1 var __create = Object.create;
2 var __defProp = Object.defineProperty;
3 var __getProtoOf = Object.getPrototypeOf;
4 var __hasOwnProp = Object.prototype.hasOwnProperty;
5 var __getOwnPropNames = Object.getOwnPropertyNames;
6 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7 var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
8 var __commonJS = (callback, module2) => () => {
10 module2 = {exports: {}};
11 callback(module2.exports, module2);
13 return module2.exports;
15 var __export = (target, all) => {
16 __markAsModule(target);
18 __defProp(target, name, {get: all[name], enumerable: true});
20 var __exportStar = (target, module2, desc) => {
21 __markAsModule(target);
22 if (module2 && typeof module2 === "object" || typeof module2 === "function") {
23 for (let key of __getOwnPropNames(module2))
24 if (!__hasOwnProp.call(target, key) && key !== "default")
25 __defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
29 var __toModule = (module2) => {
30 if (module2 && module2.__esModule)
32 return __exportStar(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", {value: module2, enumerable: true}), module2);
35 // node_modules/pify/index.js
36 var require_pify = __commonJS((exports2, module2) => {
38 var processFn = (fn, options, proxy, unwrapped) => function(...arguments_) {
39 const P = options.promiseModule;
40 return new P((resolve, reject) => {
41 if (options.multiArgs) {
42 arguments_.push((...result) => {
43 if (options.errorFirst) {
54 } else if (options.errorFirst) {
55 arguments_.push((error, result) => {
63 arguments_.push(resolve);
65 const self = this === proxy ? unwrapped : this;
66 Reflect.apply(fn, self, arguments_);
69 var filterCache = new WeakMap();
70 module2.exports = (input, options) => {
72 exclude: [/.+(?:Sync|Stream)$/],
74 promiseModule: Promise,
77 const objectType = typeof input;
78 if (!(input !== null && (objectType === "object" || objectType === "function"))) {
79 throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? "null" : objectType}\``);
81 const filter = (target, key) => {
82 let cached = filterCache.get(target);
85 filterCache.set(target, cached);
90 const match = (pattern) => typeof pattern === "string" || typeof key === "symbol" ? key === pattern : pattern.test(key);
91 const desc = Reflect.getOwnPropertyDescriptor(target, key);
92 const writableOrConfigurableOwn = desc === void 0 || desc.writable || desc.configurable;
93 const included = options.include ? options.include.some(match) : !options.exclude.some(match);
94 const shouldFilter = included && writableOrConfigurableOwn;
95 cached[key] = shouldFilter;
98 const cache = new WeakMap();
99 const proxy = new Proxy(input, {
100 apply(target, thisArg, args) {
101 const cached = cache.get(target);
103 return Reflect.apply(cached, thisArg, args);
105 const pified = options.excludeMain ? target : processFn(target, options, proxy, target);
106 cache.set(target, pified);
107 return Reflect.apply(pified, thisArg, args);
110 const property = target[key];
111 if (!filter(target, key) || property === Function.prototype[key]) {
114 const cached = cache.get(property);
118 if (typeof property === "function") {
119 const pified = processFn(property, options, proxy, target);
120 cache.set(property, pified);
132 activate: () => activate
134 var import_coc10 = __toModule(require("coc.nvim"));
135 var import_fs6 = __toModule(require("fs"));
136 var import_os4 = __toModule(require("os"));
137 var import_path5 = __toModule(require("path"));
138 var import_util9 = __toModule(require("util"));
141 var import_coc = __toModule(require("coc.nvim"));
144 var import_pify = __toModule(require_pify());
145 var import_fs = __toModule(require("fs"));
146 var import_crypto = __toModule(require("crypto"));
147 var BASE64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
148 function tostr(bytes) {
151 for (i = 0; i < bytes.length; i++) {
152 r.push(BASE64[bytes[i] % 64]);
157 return tostr(import_crypto.default.randomBytes(10));
159 async function statAsync(filepath) {
161 return await import_pify.default(import_fs.default.stat)(filepath);
166 async function readFileAsync(fullpath, encoding = "utf8") {
167 return await import_pify.default(import_fs.default.readFile)(fullpath, encoding);
169 async function readdirAsync(filepath) {
171 return await import_pify.default(import_fs.default.readdir)(filepath);
176 function headTail(line) {
178 let ms = line.match(/^(\S+)\s+(.*)/);
181 return [ms[1], ms[2]];
183 function distinct(array, keyFn) {
185 return array.filter((element, position) => {
186 return array.indexOf(element) === position;
189 const seen = Object.create(null);
190 return array.filter((elem) => {
191 const key = keyFn(elem);
199 var conditionRe = /\(\?\(\?:\w+\).+\|/;
201 var commentRe = /\(\?#.*?\)/;
202 var stringStartRe = /\\A/;
203 var namedCaptureRe = /\(\?P<\w+>.*?\)/;
204 var namedReferenceRe = /\(\?P=(\w+)\)/;
205 var braceRe = /\^\]/;
206 var regex = new RegExp(`${bellRe.source}|${commentRe.source}|${stringStartRe.source}|${namedCaptureRe.source}|${namedReferenceRe.source}|${braceRe}`, "g");
207 function convertRegex(str) {
208 if (str.indexOf("\\z") !== -1) {
209 throw new Error("pattern \\z not supported");
211 if (str.indexOf("(?s)") !== -1) {
212 throw new Error("pattern (?s) not supported");
214 if (str.indexOf("(?x)") !== -1) {
215 throw new Error("pattern (?x) not supported");
217 if (str.indexOf("\n") !== -1) {
218 throw new Error("multiple line pattern not supported");
220 if (conditionRe.test(str)) {
221 throw new Error("condition pattern not supported");
223 return str.replace(regex, (match, p1) => {
228 if (match.startsWith("(?#"))
232 if (match.startsWith("(?P<"))
233 return "(?" + match.slice(3);
234 if (match.startsWith("(?P="))
239 function getRegexText(prefix) {
240 if (prefix.startsWith("^"))
241 prefix = prefix.slice(1);
242 if (prefix.endsWith("$"))
243 prefix = prefix.slice(0, -1);
244 let content = prefix.replace(/\(.*\)\??/g, "");
245 content = content.replace(/\\/g, "");
248 function markdownBlock(code, filetype) {
249 filetype = filetype == "javascriptreact" ? "javascript" : filetype;
250 filetype = filetype == "typescriptreact" ? "typescript" : filetype;
251 return "``` " + filetype + "\n" + code + "\n```";
255 var codesMap = new Map();
256 codesMap.set(1, "invalid snippet line, trigger requried.");
257 codesMap.set(2, 'invalid snippet option, option "$1" not supported.');
258 codesMap.set(3, "invalid python expression, $1");
259 codesMap.set(4, "invalid code interpolation, #! not supported.");
260 var validOptions = ["b", "i", "w", "r", "e", "A"];
261 var LanguageProvider = class {
262 constructor(channel, trace = "error") {
263 this.channel = channel;
265 this.disposables = [];
266 this.collection = import_coc.languages.createDiagnosticCollection("snippets");
267 for (let doc of import_coc.workspace.documents) {
268 if (this.shouldValidate(doc.uri)) {
269 this.validate(doc.uri, doc.getDocumentContent()).catch((e) => {
270 channel.appendLine(`[Error ${new Date().toLocaleTimeString()}]: ${e.message}`);
274 import_coc.workspace.onDidOpenTextDocument(async (textDocument) => {
275 let doc = import_coc.workspace.getDocument(textDocument.uri);
276 if (!this.shouldValidate(doc.uri))
278 await this.validate(doc.uri, doc.getDocumentContent());
279 }, null, this.disposables);
280 import_coc.workspace.onDidChangeTextDocument(async (ev) => {
281 let doc = import_coc.workspace.getDocument(ev.textDocument.uri);
282 if (!doc || !this.shouldValidate(doc.uri))
284 await this.validate(doc.uri, doc.getDocumentContent());
285 }, null, this.disposables);
286 import_coc.workspace.onDidCloseTextDocument((e) => {
287 this.collection.delete(e.uri);
288 }, null, this.disposables);
290 shouldValidate(uri) {
291 return uri.endsWith(".snippets");
293 async validate(uri, content) {
294 let lines = content.split("\n");
295 let diagnostics = [];
297 for (let line of lines) {
298 if (/^snippet\s*$/.test(line)) {
299 let range = import_coc.Range.create(curr, 0, curr, line.length);
300 diagnostics.push(import_coc.Diagnostic.create(range, codesMap.get(1), import_coc.DiagnosticSeverity.Error, 1));
303 if (line.startsWith("snippet ")) {
304 let content2 = headTail(line)[1];
305 let ms = content2.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?$/);
307 if (prefix.length > 2 && prefix[0] == prefix[prefix.length - 1] && !/\w/.test(prefix[0])) {
308 prefix = prefix.slice(1, prefix.length - 1);
310 let option = ms[4] || "";
311 let isExpression = option.indexOf("r") !== -1;
312 let startCharacter = line.length - option.length;
313 for (let ch of option) {
314 if (validOptions.indexOf(ch) == -1) {
315 let range = import_coc.Range.create(curr, startCharacter, curr, startCharacter + 1);
316 let message = codesMap.get(2).replace("$1", ch);
317 diagnostics.push(import_coc.Diagnostic.create(range, message, import_coc.DiagnosticSeverity.Error, 2));
319 startCharacter = startCharacter + 1;
323 convertRegex(prefix);
325 let start = line.indexOf(prefix);
326 let range = import_coc.Range.create(curr, start, curr, start + prefix.length);
327 let message = codesMap.get(3).replace("$1", e.message);
328 diagnostics.push(import_coc.Diagnostic.create(range, message, import_coc.DiagnosticSeverity.Error, 3));
332 let idx = line.indexOf("`#!");
334 let range = import_coc.Range.create(curr, idx, curr, idx + 3);
335 let message = codesMap.get(4);
336 diagnostics.push(import_coc.Diagnostic.create(range, message, import_coc.DiagnosticSeverity.Error, 4));
341 if (this.trace == "verbose") {
342 this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] diagnostics of ${uri} -> ${JSON.stringify(diagnostics)}`);
344 this.collection.set(uri, diagnostics);
346 provideCompletionItems(_document, position, _token, context) {
347 let {input, col} = context.option;
348 if (context.triggerCharacter == "$") {
351 kind: import_coc.CompletionItemKind.Snippet,
353 insertTextFormat: import_coc.InsertTextFormat.Snippet,
355 range: import_coc.Range.create(position.line, position.character - 1, position.line, position.character),
356 newText: "\\${VISUAL${1::default}\\}"
360 if (col == 0 && "snippet".startsWith(input)) {
363 kind: import_coc.CompletionItemKind.Snippet,
364 detail: "Snippet definition",
365 insertTextFormat: import_coc.InsertTextFormat.Snippet,
366 insertText: 'snippet ${1:Tab_trigger} "${2:Description}" ${3:b}\n$0\nendsnippet'
371 async resolveCompletionItem(item) {
372 let text = item.insertText || item.textEdit.newText;
373 let snip = await Promise.resolve(import_coc.snippetManager.resolveSnippet(text));
374 item.documentation = {
376 value: markdownBlock(snip.toString(), "snippets")
381 var languages_default = LanguageProvider;
383 // src/list/snippet.ts
384 var import_coc2 = __toModule(require("coc.nvim"));
385 var import_os = __toModule(require("os"));
386 var SnippetsList = class extends import_coc2.BasicList {
387 constructor(nvim, manager, mru) {
389 this.manager = manager;
391 this.name = "snippets";
392 this.description = "snippets list";
393 this.addLocationActions();
395 async loadItems(context) {
396 let {window: window4} = context;
397 let valid = await window4.valid;
400 let buf = await window4.buffer;
401 let doc = import_coc2.workspace.getDocument(buf.id);
404 let snippets = await this.manager.getSnippets(doc.filetype);
406 for (let snip of snippets) {
407 let pos = import_coc2.Position.create(snip.lnum, 0);
408 let location = import_coc2.Location.create(import_coc2.Uri.file(snip.filepath).toString(), import_coc2.Range.create(pos, pos));
409 let prefix = snip.prefix;
410 if (prefix.length < 20) {
411 prefix = `${prefix}${" ".repeat(20 - prefix.length)}`;
414 label: `${prefix} ${snip.description} ${snip.filepath.replace(import_os.default.homedir(), "~")}`,
415 filterText: `${snip.prefix} ${snip.description}`,
421 async doHighlight() {
422 let {nvim} = import_coc2.workspace;
423 nvim.pauseNotification();
424 nvim.command("syntax match CocSnippetsPrefix /\\v^\\S+/ contained containedin=CocSnippetsLine", true);
425 nvim.command("syntax match CocSnippetsFile /\\v\\t\\S+$/ contained containedin=CocSnippetsLine", true);
426 nvim.command("highlight default link CocSnippetsPrefix Identifier", true);
427 nvim.command("highlight default link CocSnippetsFile Comment", true);
428 await nvim.resumeNotification();
431 var snippet_default = SnippetsList;
434 var import_coc3 = __toModule(require("coc.nvim"));
435 var import_path = __toModule(require("path"));
439 (function(TriggerKind2) {
440 TriggerKind2[TriggerKind2["SpaceBefore"] = 0] = "SpaceBefore";
441 TriggerKind2[TriggerKind2["LineBegin"] = 1] = "LineBegin";
442 TriggerKind2[TriggerKind2["WordBoundary"] = 2] = "WordBoundary";
443 TriggerKind2[TriggerKind2["InWord"] = 3] = "InWord";
444 })(TriggerKind || (TriggerKind = {}));
447 var ProviderManager = class {
449 this.providers = new Map();
451 regist(provider, name) {
452 this.providers.set(name, provider);
453 return import_coc3.Disposable.create(() => {
454 this.providers.delete(name);
458 return this.providers.size > 0;
461 let providers = Array.from(this.providers.values());
462 await Promise.all(providers.map((provider) => {
463 return provider.init();
466 async getSnippets(filetype) {
467 let names = Array.from(this.providers.keys());
469 for (let name of names) {
470 let provider = this.providers.get(name);
471 let snippets = await provider.getSnippets(filetype);
472 snippets.map((s) => s.provider = name);
473 list.push(...snippets);
477 async getSnippetFiles(filetype) {
479 for (let provider of this.providers.values()) {
480 let res = await provider.getSnippetFiles(filetype);
481 files = files.concat(res);
485 async getTriggerSnippets(autoTrigger = false) {
486 let bufnr = await import_coc3.workspace.nvim.call("bufnr", "%");
487 let doc = import_coc3.workspace.getDocument(bufnr);
491 let position = await import_coc3.window.getCursorPosition();
492 let names = Array.from(this.providers.keys());
494 for (let name of names) {
495 let provider = this.providers.get(name);
496 let items = await provider.getTriggerSnippets(doc, position, autoTrigger);
497 for (let item of items) {
498 if (list.findIndex((o) => o.prefix == item.prefix) == -1) {
503 list.sort((a, b) => b.priority - a.priority);
504 if (list.length > 1 && list[0].priority > 0) {
505 list = list.filter((o) => o.priority > 0);
509 async provideCompletionItems(document, position, _token, context) {
510 let doc = import_coc3.workspace.getDocument(document.uri);
513 let snippets = await this.getSnippets(doc.filetype);
514 let currline = doc.getline(position.line, true);
515 let {input, col} = context.option;
516 let character = characterIndex(currline, col);
517 let before_content = currline.slice(0, character);
519 let contextPrefixes = [];
520 for (let snip of snippets) {
521 let contentBehind = before_content;
522 if (contextPrefixes.indexOf(snip.prefix) !== -1)
524 if (snip.regex != null && snip.prefix == "")
527 let provider = this.providers.get(snip.provider);
528 let valid = await provider.checkContext(snip.context);
531 contextPrefixes.push(snip.prefix);
533 let head = this.getPrefixHead(doc, snip.prefix);
534 if (input.length == 0 && !before_content.endsWith(snip.prefix))
538 kind: import_coc3.CompletionItemKind.Snippet,
539 filterText: snip.prefix,
540 detail: snip.description,
541 insertTextFormat: import_coc3.InsertTextFormat.Snippet
545 provider: snip.provider,
546 filepath: `${import_path.default.basename(snip.filepath)}:${snip.lnum}`
549 if (!input.length || snip.prefix && input[0] != snip.prefix[0])
551 let content = before_content + snip.prefix;
552 let ms = content.match(snip.regex);
555 } else if (head && before_content.endsWith(head)) {
556 contentBehind = before_content.slice(0, -head.length);
557 let prefix = snip.prefix.slice(head.length);
558 Object.assign(item, {
560 range: import_coc3.Range.create({line: position.line, character: character - head.length}, position),
564 } else if (input.length == 0) {
566 contentBehind = before_content.slice(0, -prefix.length);
567 Object.assign(item, {
570 range: import_coc3.Range.create({line: position.line, character: character - prefix.length}, position),
575 if (snip.triggerKind == TriggerKind.LineBegin && contentBehind.trim().length)
577 if (snip.triggerKind == TriggerKind.SpaceBefore) {
578 if (contentBehind.length && !/\s/.test(contentBehind[contentBehind.length - 1])) {
582 if (!item.textEdit) {
584 range: import_coc3.Range.create({line: position.line, character}, position),
588 item.data.location = `${snip.filepath}:${snip.lnum}`;
589 item.data.line = contentBehind + snip.prefix;
594 async resolveCompletionItem(item) {
595 let provider = this.providers.get(item.data.provider);
597 let filetype = await import_coc3.workspace.nvim.eval("&filetype");
598 let insertSnippet = await provider.resolveSnippetBody(item.data.snip, item.textEdit.range, item.data.line);
599 item.textEdit.newText = insertSnippet;
600 if (import_coc3.snippetManager) {
601 let snip = await Promise.resolve(import_coc3.snippetManager.resolveSnippet(insertSnippet));
602 item.documentation = {
604 value: markdownBlock(snip.toString(), filetype.match(/^\w+/)[0])
610 getPrefixHead(doc, prefix) {
612 for (let idx = prefix.length - 1; idx >= 0; idx--) {
613 if (!doc.isWord(prefix[idx])) {
618 return res == 0 ? "" : prefix.slice(0, res + 1);
621 function characterIndex(content, byteIndex) {
622 let buf = Buffer.from(content, "utf8");
623 return buf.slice(0, byteIndex).toString("utf8").length;
626 // src/snipmateProvider.ts
627 var import_coc5 = __toModule(require("coc.nvim"));
628 var import_fs2 = __toModule(require("fs"));
629 var import_path2 = __toModule(require("path"));
630 var import_readline = __toModule(require("readline"));
632 // src/baseProvider.ts
633 var import_coc4 = __toModule(require("coc.nvim"));
634 var BaseProvider = class {
635 constructor(config) {
636 this.config = config;
638 async checkContext(_context) {
641 getExtendsFiletypes(filetype, exists = new Set()) {
642 if (exists.has(filetype))
644 let extend = this.config.extends ? this.config.extends[filetype] : null;
645 exists.add(filetype);
646 if (!extend || extend.length == 0)
648 return extend.reduce((arr, curr) => {
649 return arr.concat([curr], this.getExtendsFiletypes(curr, exists));
652 getFiletypes(filetype) {
653 let filetypes = [filetype];
654 if (filetype.indexOf(".") !== -1) {
655 filetypes.push(...filetype.split("."));
657 if (filetype == "javascript.jsx")
658 filetypes.push("javascriptreact");
659 if (filetype == "typescript.jsx" || filetype == "typescript.tsx")
660 filetypes.push("typescriptreact");
661 let map = import_coc4.workspace.env.filetypeMap;
662 if (map && map[filetype]) {
663 filetypes.push(map[filetype]);
665 let extendFiletypes = filetypes.reduce((arr, curr) => {
666 return arr.concat(this.getExtendsFiletypes(curr));
668 filetypes.push(...extendFiletypes);
670 return distinct(filetypes);
673 var baseProvider_default = BaseProvider;
677 constructor(_content) {
678 this._content = _content;
682 return this._curr >= this._content.length;
685 for (let i = this._curr; i <= this._content.length; i++) {
686 let ch = this._content[i];
687 if (!ch || /\S/.test(ch)) {
697 return this._content[this._curr] || "";
700 return this._content.length;
703 return this._content.slice(this._curr + 1, this._curr + 1 + count);
705 nextIndex(character, checkEscape = true, allowEnd = true) {
706 if (this._curr >= this.len - 1)
707 return allowEnd ? this.len - 1 : -1;
708 let i = this._curr + 1;
709 let pre = this.curr || "";
710 while (i != this.len - 1) {
711 let ch = this._content[i];
712 if (ch == character && (!checkEscape || pre !== "\\")) {
718 if (!allowEnd && i == this.len - 1 && character != this._content[i]) {
724 return this._content[this._curr - 1] || "";
727 while (this._curr < this._content.length) {
728 let fine = fn(this.curr, this._curr);
729 if (fine === false) {
732 this._curr = this._curr + 1;
736 let end = this._curr + count;
737 end = Math.min(end, this.len);
738 let str = this._content.slice(this._curr, end);
743 if (index == this._curr)
745 let str = this._content.slice(this._curr, index);
750 var parser_default = Parser;
752 // src/snipmateProvider.ts
753 var SnipmateProvider = class extends baseProvider_default {
754 constructor(channel, trace, config) {
756 this.channel = channel;
758 this.snippetFiles = [];
759 this.disposables = [];
760 import_coc5.workspace.onDidSaveTextDocument(async (doc) => {
761 let uri = import_coc5.Uri.parse(doc.uri);
762 if (uri.scheme != "file")
764 let filepath = uri.fsPath;
765 if (!import_fs2.default.existsSync(filepath))
767 let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
769 await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
770 }, null, this.disposables);
773 let arr = await this.getAllSnippetFiles();
774 let {nvim} = import_coc5.workspace;
775 let author = await nvim.getVar("snips_author");
777 await nvim.setVar("snips_author", this.config.author);
778 await Promise.all(arr.map(({filepath, directory, filetype}) => {
779 return this.loadSnippetsFromFile(filetype, directory, filepath);
782 async loadSnippetsFromFile(filetype, directory, filepath) {
783 let snippets = await this.parseSnippetsFile(filepath);
784 let idx = this.snippetFiles.findIndex((o) => o.filepath == filepath);
786 this.snippetFiles.splice(idx, 1);
787 this.snippetFiles.push({
793 this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} snipmate snippets from: ${filepath}`);
795 async resolveSnippetBody(snippet, _range, _line) {
796 let parser2 = new parser_default(snippet.body);
798 let {nvim} = import_coc5.workspace;
799 while (!parser2.eof()) {
800 if (parser2.curr == "`") {
801 let idx = parser2.nextIndex("`", true, false);
803 resolved = resolved + parser2.eatTo(parser2.len);
806 let code = parser2.eatTo(idx + 1);
807 code = code.slice(1, -1);
808 if (code.startsWith("Filename")) {
809 resolved = resolved + await nvim.call("expand", "%:p:t");
812 resolved = resolved + await nvim.eval(code);
814 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on eval: ${code}`);
819 parser2.iterate((ch) => {
823 resolved = resolved + ch;
830 parseSnippetsFile(filepath) {
832 const rl = import_readline.default.createInterface({
833 input: import_fs2.default.createReadStream(filepath, "utf8"),
839 let description = "";
840 rl.on("line", (line) => {
842 if (line.startsWith("#"))
844 if (line.startsWith("snippet")) {
845 line = line.replace(/\s*$/, "");
846 if (lines.length && prefix) {
849 lnum: lnum - lines.length - 1,
850 body: lines.join("\n").replace(/\s+$/, ""),
853 triggerKind: TriggerKind.SpaceBefore
857 let ms = line.match(/^snippet\s+(\S+)(?:\s(.+))?$/);
860 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Broken line on ${filepath}:${lnum}`);
864 description = ms[2] || "";
868 if (line.indexOf("VISUAL") !== -1) {
869 line = line.replace(/\$(\{?)VISUAL\b(:[^\}])?(\}?)/g, "$$$1TM_SELECTED_TEXT$2$3");
871 if (line.startsWith(" ")) {
872 lines.push(line.slice(1));
878 return new Promise((resolve) => {
879 rl.on("close", async () => {
883 lnum: lnum - lines.length - 1,
884 body: lines.join("\n"),
887 triggerKind: TriggerKind.SpaceBefore
894 async getTriggerSnippets(document, position, autoTrigger) {
897 let snippets = await this.getSnippets(document.filetype);
898 let line = document.getline(position.line);
899 line = line.slice(0, position.character);
900 if (!line || line[line.length - 1] == " ")
902 snippets = snippets.filter((s) => {
904 if (!line.endsWith(prefix))
906 let pre = line.slice(0, line.length - prefix.length);
907 return pre.length == 0 || /\s/.test(pre[pre.length - 1]);
910 for (let s of snippets) {
911 let character = position.character - s.prefix.length;
912 let range = import_coc5.Range.create(position.line, character, position.line, position.character);
913 let newText = await this.resolveSnippetBody(s, range, line);
916 description: s.description,
917 location: s.filepath,
925 async getSnippetFiles(filetype) {
926 let filetypes = this.getFiletypes(filetype);
928 for (let s of this.snippetFiles) {
929 if (filetypes.indexOf(s.filetype) !== -1) {
930 res.push(s.filepath);
935 async getSnippets(filetype) {
936 let filetypes = this.getFiletypes(filetype);
938 let snippetFiles = this.snippetFiles.filter((o) => filetypes.indexOf(o.filetype) !== -1);
940 snippetFiles.sort((a, b) => {
941 if (a.filetype == b.filetype)
943 if (a.filetype == filetype)
947 for (let file of snippetFiles) {
948 let {snippets} = file;
949 for (let snip of snippets) {
955 async getAllSnippetFiles() {
956 let {nvim} = import_coc5.workspace;
957 let opt = await nvim.eval("&rtp");
958 let rtps = opt.split(",");
960 for (let rtp of rtps) {
961 let items = await this.getSnippetFileItems(import_path2.default.join(rtp, "snippets"));
966 async getSnippetFileItems(directory) {
968 let stat = await statAsync(directory);
969 if (stat && stat.isDirectory()) {
970 let files = await readdirAsync(directory);
972 for (let f of files) {
973 let file = import_path2.default.join(directory, f);
974 if (file.endsWith(".snippets")) {
975 let basename = import_path2.default.basename(f, ".snippets");
976 let filetype = basename.split("-", 2)[0];
977 res.push({filepath: file, directory, filetype});
979 let stat2 = await statAsync(file);
980 if (stat2 && stat2.isDirectory()) {
981 let files2 = await readdirAsync(file);
982 for (let filename of files2) {
983 if (filename.endsWith(".snippets")) {
984 res.push({filepath: import_path2.default.join(file, filename), directory, filetype: f});
996 // src/textmateProvider.ts
997 var import_coc6 = __toModule(require("coc.nvim"));
998 var import_fs3 = __toModule(require("fs"));
1000 // node_modules/jsonc-parser/lib/esm/impl/scanner.js
1002 function createScanner(text, ignoreTrivia) {
1003 if (ignoreTrivia === void 0) {
1004 ignoreTrivia = false;
1006 var len = text.length;
1007 var pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
1008 function scanHexDigits(count, exact) {
1011 while (digits < count || !exact) {
1012 var ch = text.charCodeAt(pos);
1013 if (ch >= 48 && ch <= 57) {
1014 value2 = value2 * 16 + ch - 48;
1015 } else if (ch >= 65 && ch <= 70) {
1016 value2 = value2 * 16 + ch - 65 + 10;
1017 } else if (ch >= 97 && ch <= 102) {
1018 value2 = value2 * 16 + ch - 97 + 10;
1025 if (digits < count) {
1030 function setPosition(newPosition) {
1037 function scanNumber() {
1039 if (text.charCodeAt(pos) === 48) {
1043 while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1047 if (pos < text.length && text.charCodeAt(pos) === 46) {
1049 if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1051 while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1056 return text.substring(start, pos);
1060 if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
1062 if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
1065 if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1067 while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1075 return text.substring(start, end);
1077 function scanString() {
1078 var result = "", start = pos;
1081 result += text.substring(start, pos);
1085 var ch = text.charCodeAt(pos);
1087 result += text.substring(start, pos);
1092 result += text.substring(start, pos);
1098 var ch2 = text.charCodeAt(pos++);
1125 var ch3 = scanHexDigits(4, true);
1127 result += String.fromCharCode(ch3);
1138 if (ch >= 0 && ch <= 31) {
1139 if (isLineBreak(ch)) {
1140 result += text.substring(start, pos);
1151 function scanNext() {
1155 lineStartOffset = lineNumber;
1156 prevTokenLineStartOffset = tokenLineStartOffset;
1161 var code = text.charCodeAt(pos);
1162 if (isWhiteSpace(code)) {
1165 value += String.fromCharCode(code);
1166 code = text.charCodeAt(pos);
1167 } while (isWhiteSpace(code));
1170 if (isLineBreak(code)) {
1172 value += String.fromCharCode(code);
1173 if (code === 13 && text.charCodeAt(pos) === 10) {
1178 tokenLineStartOffset = pos;
1202 value = scanString();
1205 var start = pos - 1;
1206 if (text.charCodeAt(pos + 1) === 47) {
1209 if (isLineBreak(text.charCodeAt(pos))) {
1214 value = text.substring(start, pos);
1217 if (text.charCodeAt(pos + 1) === 42) {
1219 var safeLength = len - 1;
1220 var commentClosed = false;
1221 while (pos < safeLength) {
1222 var ch = text.charCodeAt(pos);
1223 if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
1225 commentClosed = true;
1229 if (isLineBreak(ch)) {
1230 if (ch === 13 && text.charCodeAt(pos) === 10) {
1234 tokenLineStartOffset = pos;
1237 if (!commentClosed) {
1241 value = text.substring(start, pos);
1244 value += String.fromCharCode(code);
1248 value += String.fromCharCode(code);
1250 if (pos === len || !isDigit(text.charCodeAt(pos))) {
1263 value += scanNumber();
1266 while (pos < len && isUnknownContentCharacter(code)) {
1268 code = text.charCodeAt(pos);
1270 if (tokenOffset !== pos) {
1271 value = text.substring(tokenOffset, pos);
1282 value += String.fromCharCode(code);
1287 function isUnknownContentCharacter(code) {
1288 if (isWhiteSpace(code) || isLineBreak(code)) {
1304 function scanNextNonTrivia() {
1307 result = scanNext();
1308 } while (result >= 12 && result <= 15);
1313 getPosition: function() {
1316 scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
1317 getToken: function() {
1320 getTokenValue: function() {
1323 getTokenOffset: function() {
1326 getTokenLength: function() {
1327 return pos - tokenOffset;
1329 getTokenStartLine: function() {
1330 return lineStartOffset;
1332 getTokenStartCharacter: function() {
1333 return tokenOffset - prevTokenLineStartOffset;
1335 getTokenError: function() {
1340 function isWhiteSpace(ch) {
1341 return ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 5760 || ch >= 8192 && ch <= 8203 || ch === 8239 || ch === 8287 || ch === 12288 || ch === 65279;
1343 function isLineBreak(ch) {
1344 return ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
1346 function isDigit(ch) {
1347 return ch >= 48 && ch <= 57;
1350 // node_modules/jsonc-parser/lib/esm/impl/format.js
1353 // node_modules/jsonc-parser/lib/esm/impl/parser.js
1356 (function(ParseOptions2) {
1357 ParseOptions2.DEFAULT = {
1358 allowTrailingComma: false
1360 })(ParseOptions || (ParseOptions = {}));
1361 function parse(text, errors, options) {
1362 if (errors === void 0) {
1365 if (options === void 0) {
1366 options = ParseOptions.DEFAULT;
1368 var currentProperty = null;
1369 var currentParent = [];
1370 var previousParents = [];
1371 function onValue(value) {
1372 if (Array.isArray(currentParent)) {
1373 currentParent.push(value);
1374 } else if (currentProperty !== null) {
1375 currentParent[currentProperty] = value;
1379 onObjectBegin: function() {
1382 previousParents.push(currentParent);
1383 currentParent = object;
1384 currentProperty = null;
1386 onObjectProperty: function(name) {
1387 currentProperty = name;
1389 onObjectEnd: function() {
1390 currentParent = previousParents.pop();
1392 onArrayBegin: function() {
1395 previousParents.push(currentParent);
1396 currentParent = array;
1397 currentProperty = null;
1399 onArrayEnd: function() {
1400 currentParent = previousParents.pop();
1402 onLiteralValue: onValue,
1403 onError: function(error, offset, length) {
1404 errors.push({error, offset, length});
1407 visit(text, visitor, options);
1408 return currentParent[0];
1410 function visit(text, visitor, options) {
1411 if (options === void 0) {
1412 options = ParseOptions.DEFAULT;
1414 var _scanner = createScanner(text, false);
1415 function toNoArgVisit(visitFunction) {
1416 return visitFunction ? function() {
1417 return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
1422 function toOneArgVisit(visitFunction) {
1423 return visitFunction ? function(arg) {
1424 return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
1429 var onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), onArrayEnd = toNoArgVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisit(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
1430 var disallowComments = options && options.disallowComments;
1431 var allowTrailingComma = options && options.allowTrailingComma;
1432 function scanNext() {
1434 var token = _scanner.scan();
1435 switch (_scanner.getTokenError()) {
1446 if (!disallowComments) {
1460 if (disallowComments) {
1477 function handleError(error, skipUntilAfter, skipUntil) {
1478 if (skipUntilAfter === void 0) {
1479 skipUntilAfter = [];
1481 if (skipUntil === void 0) {
1485 if (skipUntilAfter.length + skipUntil.length > 0) {
1486 var token = _scanner.getToken();
1487 while (token !== 17) {
1488 if (skipUntilAfter.indexOf(token) !== -1) {
1491 } else if (skipUntil.indexOf(token) !== -1) {
1498 function parseString(isValue) {
1499 var value = _scanner.getTokenValue();
1501 onLiteralValue(value);
1503 onObjectProperty(value);
1508 function parseLiteral() {
1509 switch (_scanner.getToken()) {
1511 var tokenValue = _scanner.getTokenValue();
1512 var value = Number(tokenValue);
1517 onLiteralValue(value);
1520 onLiteralValue(null);
1523 onLiteralValue(true);
1526 onLiteralValue(false);
1534 function parseProperty() {
1535 if (_scanner.getToken() !== 10) {
1536 handleError(3, [], [2, 5]);
1540 if (_scanner.getToken() === 6) {
1543 if (!parseValue()) {
1544 handleError(4, [], [2, 5]);
1547 handleError(5, [], [2, 5]);
1551 function parseObject() {
1554 var needsComma = false;
1555 while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
1556 if (_scanner.getToken() === 5) {
1558 handleError(4, [], []);
1562 if (_scanner.getToken() === 2 && allowTrailingComma) {
1565 } else if (needsComma) {
1566 handleError(6, [], []);
1568 if (!parseProperty()) {
1569 handleError(4, [], [2, 5]);
1574 if (_scanner.getToken() !== 2) {
1575 handleError(7, [2], []);
1581 function parseArray() {
1584 var needsComma = false;
1585 while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
1586 if (_scanner.getToken() === 5) {
1588 handleError(4, [], []);
1592 if (_scanner.getToken() === 4 && allowTrailingComma) {
1595 } else if (needsComma) {
1596 handleError(6, [], []);
1598 if (!parseValue()) {
1599 handleError(4, [], [4, 5]);
1604 if (_scanner.getToken() !== 4) {
1605 handleError(8, [4], []);
1611 function parseValue() {
1612 switch (_scanner.getToken()) {
1614 return parseArray();
1616 return parseObject();
1618 return parseString(true);
1620 return parseLiteral();
1624 if (_scanner.getToken() === 17) {
1625 if (options.allowEmptyContent) {
1628 handleError(4, [], []);
1631 if (!parseValue()) {
1632 handleError(4, [], []);
1635 if (_scanner.getToken() !== 17) {
1636 handleError(9, [], []);
1641 // node_modules/jsonc-parser/lib/esm/impl/edit.js
1644 // node_modules/jsonc-parser/lib/esm/main.js
1648 // src/textmateProvider.ts
1649 var import_os2 = __toModule(require("os"));
1650 var import_path3 = __toModule(require("path"));
1651 var import_util5 = __toModule(require("util"));
1652 var TextmateProvider = class extends baseProvider_default {
1653 constructor(channel, trace, config) {
1655 this.channel = channel;
1657 this._snippetCache = {};
1658 this._userSnippets = {};
1659 if (config.loadFromExtensions) {
1660 import_coc6.extensions.onDidLoadExtension((extension) => {
1661 this.loadSnippetsFromExtension(extension).catch((e) => {
1662 channel.appendLine(`[Error] ${e.message}`);
1665 import_coc6.extensions.onDidUnloadExtension((id) => {
1666 delete this._snippetCache[id];
1671 if (this.config.loadFromExtensions) {
1672 for (let extension of import_coc6.extensions.all) {
1673 await this.loadSnippetsFromExtension(extension);
1676 let paths = this.config.snippetsRoots;
1677 if (paths && paths.length) {
1678 for (let dir of paths) {
1679 await this.loadSnippetsFromRoot(dir);
1683 async getSnippetFiles(filetype) {
1684 let filetypes = this.getFiletypes(filetype);
1686 if (this.config.loadFromExtensions) {
1687 for (let key of Object.keys(this._snippetCache)) {
1688 let cache = this._snippetCache[key];
1689 for (let filetype2 of filetypes) {
1690 let snippets = cache[filetype2];
1691 if (snippets && snippets.length) {
1692 filepaths.push(snippets[0].filepath);
1697 for (let filetype2 of filetypes) {
1698 let snippets = this._userSnippets[filetype2];
1699 if (snippets && snippets.length) {
1700 for (let snip of snippets) {
1701 let {filepath} = snip;
1702 if (filepaths.indexOf(filepath) == -1) {
1703 filepaths.push(filepath);
1708 return distinct(filepaths);
1710 async getTriggerSnippets(document, position, autoTrigger) {
1713 let line = document.getline(position.line);
1714 line = line.slice(0, position.character);
1715 let snippets = await this.getSnippets(document.filetype);
1716 if (!snippets || !snippets.length)
1719 for (let snip of snippets) {
1720 let {prefix} = snip;
1721 if (!line.endsWith(prefix))
1723 let pre = line.slice(0, line.length - prefix.length);
1724 if (pre.length && /\w/.test(pre[pre.length - 1]))
1728 range: import_coc6.Range.create(position.line, position.character - prefix.length, position.line, position.character),
1730 location: snip.filepath,
1731 description: snip.description,
1737 async getSnippets(filetype) {
1739 let filetypes = this.getFiletypes(filetype);
1740 let added = new Set();
1741 for (let key of Object.keys(this._snippetCache)) {
1742 let cache = this._snippetCache[key];
1743 for (let filetype2 of filetypes) {
1744 let snippets = cache[filetype2];
1746 for (let snip of snippets) {
1747 if (!added.has(snip.prefix)) {
1748 added.add(snip.prefix);
1755 for (let filetype2 of filetypes) {
1756 let snippets = this._userSnippets[filetype2];
1757 if (snippets && snippets.length) {
1758 for (let snip of snippets) {
1759 if (!added.has(snip.prefix)) {
1760 added.add(snip.prefix);
1768 async resolveSnippetBody(snip, _range) {
1771 async loadSnippetsFromExtension(extension) {
1772 let {packageJSON} = extension;
1773 if (packageJSON.contributes && packageJSON.contributes.snippets) {
1774 let {snippets} = packageJSON.contributes;
1776 extensionId: extension.id,
1779 for (let item of snippets) {
1780 let p = import_path3.default.join(extension.extensionPath, item.path);
1781 let {language} = item;
1783 languageId: language,
1787 if (snippets && snippets.length) {
1788 await this.loadSnippetsFromDefinition(def);
1792 async loadSnippetsFromRoot(root) {
1793 let {_userSnippets} = this;
1794 if (root.startsWith("~"))
1795 root = root.replace(/^~/, import_os2.default.homedir());
1796 let files = await import_util5.default.promisify(import_fs3.default.readdir)(root, "utf8");
1797 files = files.filter((f) => f.endsWith(".json") || f.endsWith(".code-snippets"));
1798 await Promise.all(files.map((file) => {
1799 file = import_path3.default.join(root, file);
1800 let basename = import_path3.default.basename(file, ".json");
1801 basename = basename.replace(/\.code-snippets$/, "");
1802 return this.loadSnippetsFromFile(file).then((snippets) => {
1803 _userSnippets[basename] = snippets;
1807 async loadSnippetsFromDefinition(def) {
1808 let {extensionId, snippets} = def;
1809 let cache = this._snippetCache[extensionId] = {};
1810 for (let item of snippets) {
1811 let {languageId} = item;
1812 if (!import_fs3.default.existsSync(item.filepath))
1814 let arr = await this.loadSnippetsFromFile(item.filepath);
1815 let exists = cache[languageId] || [];
1816 cache[languageId] = [...exists, ...arr];
1819 async loadSnippetsFromFile(snippetFilePath) {
1820 const contents = await new Promise((resolve, reject) => {
1821 import_fs3.default.readFile(snippetFilePath, "utf8", (err, data) => {
1827 const snippets = this.loadSnippetsFromText(snippetFilePath, contents);
1828 this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} textmate snippets from ${snippetFilePath}`);
1831 loadSnippetsFromText(filepath, contents) {
1835 let snippetObject = parse2(contents, errors, {allowTrailingComma: true});
1836 if (errors.length) {
1837 this.channel.appendLine(`[Error ${new Date().toLocaleDateString()}] parser error of ${filepath}: ${JSON.stringify(errors, null, 2)}`);
1839 if (snippetObject) {
1840 for (let key of Object.keys(snippetObject)) {
1841 snippets.push(snippetObject[key]);
1845 this.channel.appendLine(`[Error ${new Date().toLocaleDateString()}] ${ex.stack}`);
1848 const normalizedSnippets = snippets.map((snip) => {
1849 let prefix = Array.isArray(snip.prefix) ? snip.prefix[0] : snip.prefix;
1853 body: typeof snip.body === "string" ? snip.body : snip.body.join("\n"),
1855 description: typeof snip.description === "string" ? snip.description : typeof snip.description !== "undefined" ? snip.description.join("\n") : "",
1856 triggerKind: TriggerKind.WordBoundary
1859 return normalizedSnippets;
1863 // src/ultisnipsProvider.ts
1864 var import_coc8 = __toModule(require("coc.nvim"));
1865 var import_fs5 = __toModule(require("fs"));
1866 var import_os3 = __toModule(require("os"));
1867 var import_path4 = __toModule(require("path"));
1868 var import_coc9 = __toModule(require("coc.nvim"));
1870 // src/ultisnipsParser.ts
1871 var import_child_process = __toModule(require("child_process"));
1872 var import_coc7 = __toModule(require("coc.nvim"));
1873 var import_fs4 = __toModule(require("fs"));
1874 var import_pify2 = __toModule(require_pify());
1875 var import_readline2 = __toModule(require("readline"));
1876 var UltiSnipsParser = class {
1877 constructor(pyMethod, channel, trace = "error") {
1878 this.pyMethod = pyMethod;
1879 this.channel = channel;
1882 parseUltisnipsFile(filepath) {
1883 const rl = import_readline2.default.createInterface({
1884 input: import_fs4.default.createReadStream(filepath, "utf8"),
1894 let clearsnippets = null;
1895 let parsedContext = null;
1896 let extendFiletypes = [];
1897 rl.on("line", (line) => {
1899 if (!block && (line.startsWith("#") || line.length == 0))
1901 const [head, tail] = headTail(line);
1905 let n = parseInt(tail.trim(), 10);
1910 let fts = tail.trim().split(/,\s+/);
1911 for (let ft of fts) {
1912 if (extendFiletypes.indexOf(ft) == -1) {
1913 extendFiletypes.push(ft);
1917 case "clearsnippets":
1918 clearsnippets = priority;
1921 parsedContext = tail.replace(/^"(.+)"$/, "$1");
1931 if (head == "endglobal" && block == "global") {
1933 pycodes.push(...preLines);
1937 if (head == "endsnippet" && block == "snippet") {
1941 let body = preLines.join("\n");
1942 body = body.replace(/((?:[^\\]?\$\{\w+?)\/)([^\n]*?[^\\])(?=\/)/g, (_match, p1, p2) => {
1943 return p1 + convertRegex(p2);
1945 let ms = first.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?\s*$/);
1947 let description = ms[2] || "";
1948 let context = ms[3];
1949 let option = ms[4] || "";
1950 if (prefix.length > 2 && prefix[1] != prefix[0] && prefix[0] == prefix[prefix.length - 1] && !/\w/.test(prefix[0])) {
1951 prefix = prefix.slice(1, prefix.length - 1);
1953 let isExpression = option.indexOf("r") !== -1;
1956 originRegex = prefix;
1957 prefix = convertRegex(prefix);
1958 prefix = prefix.endsWith("$") ? prefix : prefix + "$";
1960 regex2 = new RegExp(prefix);
1961 prefix = getRegexText(prefix);
1963 this.error(`Convert regex error for: ${prefix}`);
1966 if (parsedContext) {
1967 context = parsedContext;
1968 } else if (option.indexOf("e") == -1) {
1975 autoTrigger: option.indexOf("A") !== -1,
1976 lnum: lnum - preLines.length - 2,
1977 triggerKind: getTriggerKind(option),
1984 snippets.push(snippet);
1986 this.error(`Create snippet error on: ${filepath}:${lnum - preLines.length - 1} ${e.message}`);
1988 parsedContext = null;
1992 if (block == "snippet" || block == "global") {
1993 preLines.push(line);
1997 return new Promise((resolve) => {
1998 rl.on("close", async () => {
1999 resolve({snippets, clearsnippets, pythonCode: pycodes.join("\n"), extendFiletypes});
2003 async resolveUltisnipsBody(body) {
2004 let {pyMethod} = this;
2005 let parser2 = new parser_default(body);
2007 while (!parser2.eof()) {
2008 let p = parser2.prev();
2009 if (parser2.curr == "`" && (!p || p != "\\")) {
2010 let idx = parser2.nextIndex("`", true, false);
2012 resolved = resolved + parser2.eatTo(parser2.len);
2015 let code = parser2.eatTo(idx + 1);
2016 code = code.slice(1, -1);
2017 let indent = resolved.split(/\n/).slice(-1)[0].match(/^\s*/)[0];
2018 resolved = resolved + await this.execute(code, pyMethod, indent);
2020 } else if (parser2.curr == "$") {
2021 let text = parser2.next(7);
2022 if (text.startsWith("VISUAL") || text.startsWith("{VISUAL")) {
2024 resolved += "$" + text.replace("VISUAL", "TM_SELECTED_TEXT");
2025 } else if (!/^\d/.test(text) && !text.startsWith("{") && p != "\\") {
2026 resolved += "\\" + parser2.eat(1);
2028 resolved += parser2.eat(1);
2031 let prev = parser2.prev() || "";
2032 parser2.iterate((ch) => {
2033 if (prev !== "\\" && (ch == "`" || ch == "$")) {
2036 resolved = resolved + ch;
2042 resolved = decode(resolved);
2043 this.debug(`resolved: ${resolved}`);
2046 async execute(code, pyMethod, indent) {
2047 let {nvim} = import_coc7.workspace;
2049 if (code.startsWith("!")) {
2050 code = code.trim().slice(1);
2051 if (code.startsWith("p")) {
2052 code = code.slice(1).trim();
2053 let lines = code.split("\n");
2054 lines = lines.map((line) => line.replace(/\t/g, " "));
2055 lines = lines.map((line) => ` ${line}`);
2056 lines.unshift("try:");
2057 lines.unshift("import traceback");
2058 lines.push("except Exception as e:");
2059 lines.push(" snip.rv = traceback.format_exc()");
2060 await nvim.command(`${pyMethod} ${lines.join("\n")}`);
2061 res = await nvim.call(`${pyMethod}eval`, "snip.rv");
2062 } else if (code.startsWith("v")) {
2063 code = code.replace(/^v\s*/, "");
2065 res = await nvim.eval(code);
2067 res = `Error: ${e.message}`;
2068 this.error(e.stack);
2073 res = await import_pify2.default(import_child_process.exec)(code);
2075 res = `Error: ${e.message}`;
2076 this.error(`Error on eval ${code}: ` + e.stack);
2079 res = res.toString();
2080 res = res.replace(/\r?\n$/, "");
2081 let parts = res.split(/\r?\n/);
2082 if (parts.length > 1) {
2083 res = parts.map((s, idx) => {
2084 if (idx == 0 || s.length == 0)
2086 return `${indent}${s}`;
2094 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] ${str}`);
2097 if (!this.channel || this.trace == "error")
2099 this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] ${str}`);
2102 var ultisnipsParser_default = UltiSnipsParser;
2103 function decode(str) {
2104 return str.replace(/\\`/g, "`").replace(/\\{/g, "{");
2106 function getTriggerKind(option) {
2107 if (option.indexOf("w") !== -1) {
2108 return TriggerKind.WordBoundary;
2110 if (option.indexOf("b") !== -1) {
2111 return TriggerKind.LineBegin;
2113 if (option.indexOf("i") !== -1) {
2114 return TriggerKind.InWord;
2116 return TriggerKind.SpaceBefore;
2119 // src/ultisnipsProvider.ts
2120 var pythonCodes = new Map();
2121 var UltiSnippetsProvider = class extends baseProvider_default {
2122 constructor(channel, trace, config, context) {
2124 this.channel = channel;
2126 this.config = config;
2127 this.context = context;
2128 this.snippetFiles = [];
2129 this.disposables = [];
2130 this.directories = [];
2131 this.runtimeDirs = [];
2132 this.runtimeDirs = import_coc8.workspace.env.runtimepath.split(",");
2133 import_coc8.workspace.watchOption("runtimepath", async (_, newValue) => {
2134 let parts = newValue.split(",");
2135 let subFolders = await this.getSubFolders();
2137 for (let dir of parts) {
2138 if (this.runtimeDirs.indexOf(dir) == -1) {
2139 this.runtimeDirs.push(dir);
2140 let res = await this.getSnippetsFromPlugin(dir, subFolders);
2145 await Promise.all(items.map(({filepath, directory, filetype}) => {
2146 return this.loadSnippetsFromFile(filetype, directory, filepath);
2148 let files = items.map((o) => o.filepath);
2149 let pythonCode = "";
2150 for (let file of files) {
2151 let code = pythonCodes.get(file);
2153 pythonCode += `# ${file}
2158 pythonCodes.clear();
2159 await this.executePythonCode(pythonCode);
2162 }, this.disposables);
2164 checkLoaded(filepath) {
2165 return this.snippetFiles.findIndex((o) => o.filepath == filepath) !== -1;
2168 let {nvim, env} = import_coc8.workspace;
2169 let {runtimepath} = env;
2170 let {config} = this;
2171 for (let dir of config.directories) {
2172 if (dir.startsWith("~") || dir.indexOf("$") !== -1) {
2173 let res = await import_coc8.workspace.nvim.call("expand", [dir]);
2174 this.directories.push(res);
2176 this.directories.push(dir);
2179 this.channel.appendLine(`[Info ${new Date().toISOString()}] Using ultisnips directories: ${this.directories.join(" ")}`);
2180 let hasPythonx = await nvim.call("has", ["pythonx"]);
2181 let pythonCode = await readFileAsync(this.context.asAbsolutePath("python/ultisnips.py"), "utf8");
2182 if (hasPythonx && config.usePythonx) {
2183 this.pyMethod = "pyx";
2185 this.pyMethod = config.pythonVersion == 3 ? "py3" : "py";
2187 this.channel.appendLine(`[Info ${new Date().toLocaleTimeString()}] Using ultisnips python command: ${this.pyMethod}`);
2188 this.parser = new ultisnipsParser_default(this.pyMethod, this.channel, this.trace);
2189 let arr = await this.getAllSnippetFiles(runtimepath);
2190 let files = arr.map((o) => o.filepath);
2191 await Promise.all(arr.map(({filepath, directory, filetype}) => {
2192 return this.loadSnippetsFromFile(filetype, directory, filepath);
2194 for (let file of files) {
2195 let code = pythonCodes.get(file);
2202 await this.executePythonCode(pythonCode);
2203 import_coc8.workspace.onDidSaveTextDocument(async (doc) => {
2204 let uri = import_coc8.Uri.parse(doc.uri);
2205 if (uri.scheme != "file" || !doc.uri.endsWith(".snippets"))
2207 let filepath = uri.fsPath;
2208 if (!import_fs5.default.existsSync(filepath))
2210 let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
2212 await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
2214 let filetype = import_path4.default.basename(filepath, ".snippets");
2215 await this.loadSnippetsFromFile(filetype, import_path4.default.dirname(filepath), filepath);
2217 }, null, this.disposables);
2219 async loadSnippetsFromFile(filetype, directory, filepath) {
2220 let {snippets, pythonCode, extendFiletypes, clearsnippets} = await this.parser.parseUltisnipsFile(filepath);
2221 let idx = this.snippetFiles.findIndex((o) => o.filepath == filepath);
2223 this.snippetFiles.splice(idx, 1);
2224 this.snippetFiles.push({
2232 if (extendFiletypes) {
2233 let filetypes = this.config.extends[filetype] || [];
2234 filetypes = filetypes.concat(extendFiletypes);
2235 this.config.extends[filetype] = distinct(filetypes);
2237 this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} UltiSnip snippets from: ${filepath}`);
2238 pythonCodes.set(filepath, pythonCode);
2240 async resolveSnippetBody(snippet, range, line) {
2241 let {nvim} = import_coc8.workspace;
2242 let {body, context, originRegex} = snippet;
2243 let buf = await nvim.buffer;
2244 let filepath = await buf.name;
2245 let indentCount = await nvim.call("indent", ".");
2246 let ind = " ".repeat(indentCount);
2247 if (body.indexOf("`!p") !== -1) {
2248 let values = new Map();
2249 let re = /\$\{(\d+)(?::([^}]+))?\}/g;
2251 while (r = re.exec(body)) {
2252 let idx = parseInt(r[1], 10);
2253 let val = r[2] || "";
2254 let exists = values.get(idx);
2255 if (exists == null || val && exists == "''") {
2256 if (/^`!\w/.test(val) && val.endsWith("`")) {
2257 let code = val.slice(1).slice(0, -1);
2258 if (code.startsWith("!p")) {
2261 val = await this.parser.execute(code, this.pyMethod, ind);
2264 val = val.replace(/'/g, "\\'").replace(/\n/g, "\\n");
2265 values.set(idx, "r'" + val + "'");
2269 while (r = re.exec(body)) {
2270 let idx = parseInt(r[1], 10);
2271 if (!values.has(idx)) {
2272 values.set(idx, "''");
2275 let len = values.size == 0 ? 0 : Math.max.apply(null, Array.from(values.keys()));
2276 let vals = new Array(len).fill('""');
2277 for (let [idx, val] of values.entries()) {
2281 pyCodes.push("import re, os, vim, string, random");
2282 pyCodes.push(`t = ('', ${vals.join(",")})`);
2283 pyCodes.push(`fn = r'${import_path4.default.basename(filepath)}'`);
2284 pyCodes.push(`path = r'${filepath}'`);
2286 pyCodes.push(`snip = ContextSnippet()`);
2287 pyCodes.push(`context = ${context}`);
2289 pyCodes.push(`context = {}`);
2291 let start = `(${range.start.line},${Buffer.byteLength(line.slice(0, range.start.character))})`;
2292 let end = `(${range.end.line},${Buffer.byteLength(line.slice(0, range.end.character))})`;
2293 pyCodes.push(`snip = SnippetUtil('${ind}', ${start}, ${end}, context)`);
2295 pyCodes.push(`pattern = re.compile(r"${originRegex.replace(/"/g, '\\"')}")`);
2296 pyCodes.push(`match = pattern.search("${line.replace(/"/g, '\\"')}")`);
2299 await nvim.command(`${this.pyMethod} ${pyCodes.join("\n")}`);
2301 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}]: ${e.message}`);
2302 this.channel.appendLine(`code: ${pyCodes.join("\n")}`);
2305 return this.parser.resolveUltisnipsBody(body);
2307 async checkContext(context) {
2308 let {nvim} = import_coc8.workspace;
2310 pyCodes.push("import re, os, vim, string, random");
2311 pyCodes.push(`snip = ContextSnippet()`);
2312 pyCodes.push(`context = ${context}`);
2313 await nvim.command(`${this.pyMethod} ${pyCodes.join("\n")}`);
2314 let res = await nvim.call(`${this.pyMethod}eval`, "True if context else False");
2317 async getTriggerSnippets(document, position, autoTrigger) {
2318 let snippets = await this.getSnippets(document.filetype);
2319 let line = document.getline(position.line);
2320 line = line.slice(0, position.character);
2321 if (!line || line[line.length - 1] == " ")
2323 snippets = snippets.filter((s) => {
2324 let {prefix, regex: regex2} = s;
2325 if (autoTrigger && !s.autoTrigger)
2328 let ms = line.match(regex2);
2333 if (!line.endsWith(prefix))
2335 if (s.triggerKind == TriggerKind.InWord)
2337 let pre = line.slice(0, line.length - prefix.length);
2338 if (s.triggerKind == TriggerKind.LineBegin)
2339 return pre.trim() == "";
2340 if (s.triggerKind == TriggerKind.SpaceBefore)
2341 return pre.length == 0 || /\s/.test(pre[pre.length - 1]);
2342 if (s.triggerKind == TriggerKind.WordBoundary)
2343 return pre.length == 0 || !document.isWord(pre[pre.length - 1]);
2346 snippets.sort((a, b) => {
2347 if (a.context && !b.context)
2349 if (b.context && !a.context)
2354 let contextPrefixes = [];
2355 for (let s of snippets) {
2358 let valid = await this.checkContext(s.context);
2361 contextPrefixes.push(s.context);
2362 } else if (contextPrefixes.indexOf(s.prefix) !== -1) {
2365 if (s.regex == null) {
2366 character = position.character - s.prefix.length;
2368 let len = line.match(s.regex)[0].length;
2369 character = position.character - len;
2371 let range = import_coc9.Range.create(position.line, character, position.line, position.character);
2372 let newText = await this.resolveSnippetBody(s, range, line);
2375 description: s.description,
2376 location: s.filepath,
2377 priority: s.priority,
2384 async getSnippetFiles(filetype) {
2385 let filetypes = this.getFiletypes(filetype);
2387 for (let s of this.snippetFiles) {
2388 if (filetypes.indexOf(s.filetype) !== -1) {
2389 res.push(s.filepath);
2394 async getSnippets(filetype) {
2395 let filetypes = this.getFiletypes(filetype);
2396 filetypes.push("all");
2397 let snippetFiles = this.snippetFiles.filter((o) => filetypes.indexOf(o.filetype) !== -1);
2400 snippetFiles.sort((a, b) => {
2401 if (a.filetype == b.filetype)
2403 if (a.filetype == filetype)
2407 for (let file of snippetFiles) {
2408 let {snippets, clearsnippets} = file;
2409 if (typeof clearsnippets == "number") {
2410 min = min ? Math.max(min, clearsnippets) : clearsnippets;
2412 for (let snip of snippets) {
2413 if (snip.regex || snip.context) {
2416 let idx = result.findIndex((o) => o.prefix == snip.prefix && o.triggerKind == snip.triggerKind);
2420 let item = result[idx];
2421 if (snip.priority > item.priority) {
2429 result = result.filter((o) => o.priority >= min);
2430 result.sort((a, b) => {
2431 if (a.context && !b.context)
2433 if (b.context && !a.context)
2439 async getAllSnippetFiles(runtimepath) {
2440 let {directories} = this;
2442 for (let directory of directories) {
2443 if (import_path4.default.isAbsolute(directory)) {
2444 let items = await this.getSnippetFileItems(directory);
2448 let subFolders = await this.getSubFolders();
2449 let rtps = runtimepath.split(",");
2450 this.runtimeDirs = rtps;
2451 for (let rtp of rtps) {
2452 let items = await this.getSnippetsFromPlugin(rtp, subFolders);
2457 async getSubFolders() {
2458 let {directories} = this;
2459 directories = directories.filter((s) => !import_path4.default.isAbsolute(s));
2460 let dirs = await import_coc8.workspace.nvim.eval('get(g:, "UltiSnipsSnippetDirectories", [])');
2461 for (let dir of dirs) {
2462 if (directories.indexOf(dir) == -1) {
2463 directories.push(dir);
2468 async getSnippetsFromPlugin(directory, subFolders) {
2470 for (let folder of subFolders) {
2471 let items = await this.getSnippetFileItems(import_path4.default.join(directory, folder));
2476 async getSnippetFileItems(directory) {
2478 let stat = await statAsync(directory);
2479 if (stat && stat.isDirectory()) {
2480 let files = await readdirAsync(directory);
2482 for (let f of files) {
2483 let file = import_path4.default.join(directory, f);
2484 if (file.endsWith(".snippets")) {
2485 let basename = import_path4.default.basename(f, ".snippets");
2486 let filetype = basename.split("_", 2)[0];
2487 res.push({filepath: file, directory, filetype});
2489 let stat2 = await statAsync(file);
2490 if (stat2 && stat2.isDirectory()) {
2491 let files2 = await readdirAsync(file);
2492 for (let filename of files2) {
2493 if (filename.endsWith(".snippets")) {
2494 res.push({filepath: import_path4.default.join(file, filename), directory, filetype: f});
2504 async executePythonCode(pythonCode) {
2506 let dir = import_path4.default.join(import_os3.default.tmpdir(), `coc.nvim-${process.pid}`);
2507 if (!import_fs5.default.existsSync(dir))
2508 import_fs5.default.mkdirSync(dir);
2509 let tmpfile = import_path4.default.join(import_os3.default.tmpdir(), `coc.nvim-${process.pid}`, `coc-ultisnips-${uid()}.py`);
2510 import_fs5.default.writeFileSync(tmpfile, "# -*- coding: utf-8 -*-\n" + pythonCode, "utf8");
2511 await import_coc8.workspace.nvim.command(`exe '${this.pyMethod}file '.fnameescape('${tmpfile}')`);
2512 pythonCodes.clear();
2514 this.channel.appendLine(`Error on execute python script:`);
2515 this.channel.append(e.message);
2516 import_coc8.window.showMessage(`Error on execute python script: ${e.message}`, "error");
2520 import_coc8.disposeAll(this.disposables);
2525 var documentation = `# A valid snippet should starts with:
2527 # snippet trigger_word [ "description" [ options ] ]
2535 # b - Beginning of line.
2536 # i - In-word expansion.
2537 # w - Word boundary.
2538 # r - Regular expression
2539 # e - Custom context snippet
2540 # A - Snippet will be triggered automatically, when condition matches.
2544 # snippet emitter "emitter properties" b
2545 # private readonly \${1} = new Emitter<$2>()
2546 # public readonly \${1/^_(.*)/$1/}: Event<$2> = this.$1.event
2549 # Online reference: https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt
2551 async function activate(context) {
2552 let {subscriptions} = context;
2553 const {nvim} = import_coc10.workspace;
2554 const configuration = import_coc10.workspace.getConfiguration("snippets");
2555 const filetypeExtends = configuration.get("extends", {});
2556 const manager = new ProviderManager();
2557 const trace = configuration.get("trace", "error");
2558 let mru = import_coc10.workspace.createMru("snippets-mru");
2559 const channel = import_coc10.window.createOutputChannel("snippets");
2560 let snippetsDir = configuration.get("userSnippetsDirectory");
2562 snippetsDir = snippetsDir.replace(/^~/, import_os4.default.homedir());
2563 if (snippetsDir.indexOf("$") !== -1) {
2564 snippetsDir = snippetsDir.replace(/\$(\w+)/g, (match, p1) => {
2566 return (_a = process.env[p1]) != null ? _a : match;
2569 if (!import_path5.default.isAbsolute(snippetsDir)) {
2570 import_coc10.window.showMessage(`snippets.userSnippetsDirectory => ${snippetsDir} should be absolute path`, "warning");
2575 snippetsDir = import_path5.default.join(import_path5.default.dirname(import_coc10.workspace.env.extensionRoot), "ultisnips");
2576 if (!import_fs6.default.existsSync(snippetsDir)) {
2577 await import_util9.default.promisify(import_fs6.default.mkdir)(snippetsDir);
2579 import_coc10.events.on("CompleteDone", async (item) => {
2580 if (typeof item.user_data === "string" && item.user_data.indexOf("snippets") !== -1) {
2581 await mru.add(item.word);
2583 }, null, subscriptions);
2584 import_coc10.workspace.onDidOpenTextDocument(async (document) => {
2585 if (document.uri.endsWith(".snippets")) {
2586 let doc = import_coc10.workspace.getDocument(document.uri);
2590 await buffer.setOption("filetype", "snippets");
2592 }, null, subscriptions);
2593 if (configuration.get("ultisnips.enable", true)) {
2594 let config2 = configuration.get("ultisnips", {});
2595 let c = Object.assign({}, config2, {
2596 extends: Object.assign({}, filetypeExtends)
2598 c.directories = c.directories ? c.directories.slice() : [];
2599 if (c.directories.indexOf(snippetsDir) == -1) {
2600 c.directories.push(snippetsDir);
2602 let provider2 = new UltiSnippetsProvider(channel, trace, c, context);
2603 manager.regist(provider2, "ultisnips");
2604 subscriptions.push(provider2);
2605 nvim.getOption("runtimepath").then(async (rtp) => {
2606 let paths = rtp.split(",");
2607 let idx = paths.findIndex((s) => /^ultisnips$/i.test(import_path5.default.basename(s)));
2610 let directory = import_path5.default.resolve(__dirname, "..");
2611 nvim.command("autocmd BufNewFile,BufRead *.snippets setf snippets", true);
2612 nvim.command(`execute 'noa set rtp+='.fnameescape('${directory.replace(/'/g, "''")}')`, true);
2613 import_coc10.workspace.documents.forEach((doc) => {
2614 if (doc.uri.endsWith(".snippets")) {
2615 doc.buffer.setOption("filetype", "snippets", true);
2622 loadFromExtensions: configuration.get("loadFromExtensions", true),
2623 snippetsRoots: configuration.get("textmateSnippetsRoots", []),
2624 extends: Object.assign({}, filetypeExtends)
2626 let provider = new TextmateProvider(channel, trace, config);
2627 manager.regist(provider, "snippets");
2628 if (configuration.get("snipmate.enable", true)) {
2630 author: configuration.get("snipmate.author", ""),
2631 extends: Object.assign({}, filetypeExtends)
2633 let provider2 = new SnipmateProvider(channel, trace, config2);
2634 manager.regist(provider2, "snipmate");
2636 if (configuration.get("autoTrigger", true)) {
2640 import_coc10.events.on("InsertCharPre", (character) => {
2641 insertTs = Date.now();
2642 lastInsert = character;
2643 }, null, subscriptions);
2644 import_coc10.events.on("InsertLeave", () => {
2645 insertLeaveTs = Date.now();
2646 }, null, subscriptions);
2647 let inserting = false;
2648 const handleTextChange = async (bufnr, pre) => {
2649 let lastInsertTs = insertTs;
2653 let doc = import_coc10.workspace.getDocument(bufnr);
2654 if (!doc || doc.isCommandLine || !doc.attached)
2656 let now = Date.now();
2657 if (!lastInsertTs || now - lastInsertTs > 100 || !pre.endsWith(lastInsert))
2659 let edits = await manager.getTriggerSnippets(true);
2660 if (edits.length == 0)
2662 if (edits.length > 1) {
2663 channel.appendLine(`Multiple snippet found for auto trigger: ${edits.map((s) => s.prefix).join(", ")}`);
2664 import_coc10.window.showMessage("Multiple snippet found for auto trigger, check output by :CocCommand workspace.showOutput", "warning");
2666 if (insertLeaveTs > now || inserting)
2670 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2671 await mru.add(edits[0].prefix);
2677 import_coc10.events.on("TextChangedI", async (bufnr, info) => {
2678 await handleTextChange(bufnr, info.pre);
2679 }, null, subscriptions);
2680 import_coc10.events.on("TextChangedP", async (bufnr, info) => {
2681 await handleTextChange(bufnr, info.pre);
2682 }, null, subscriptions);
2685 if (configuration.get("enableStatusItem", true)) {
2686 statusItem = import_coc10.window.createStatusBarItem(90, {progress: true});
2687 statusItem.text = "loading snippets";
2690 manager.init().then(() => {
2691 statusItem == null ? void 0 : statusItem.hide();
2693 statusItem == null ? void 0 : statusItem.hide();
2694 import_coc10.window.showMessage(`Error on load snippets: ${e.message}`, "error");
2696 if (manager.hasProvider) {
2697 let disposable = import_coc10.languages.registerCompletionItemProvider("snippets", "S", null, manager, configuration.get("triggerCharacters", []), configuration.get("priority", 90));
2698 subscriptions.push(disposable);
2700 async function fallback() {
2701 await nvim.call("coc#start", [{source: "snippets"}]);
2703 async function doExpand() {
2704 let edits = await manager.getTriggerSnippets();
2705 if (edits.length == 0)
2707 if (edits.length == 1) {
2708 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2709 await mru.add(edits[0].prefix);
2711 let idx = await import_coc10.window.showQuickpick(edits.map((e) => e.description || e.prefix), "choose snippet:");
2714 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[idx]);
2715 await mru.add(edits[idx].prefix);
2719 subscriptions.push(import_coc10.workspace.registerKeymap(["x"], "convert-snippet", async () => {
2720 let mode = await import_coc10.workspace.nvim.call("visualmode");
2723 let doc = await import_coc10.workspace.document;
2727 let range = await import_coc10.workspace.getSelectedRange(mode, doc);
2728 let text = doc.textDocument.getText(range);
2730 await import_coc10.commands.executeCommand("snippets.editSnippets", text);
2732 subscriptions.push(import_coc10.commands.registerCommand("snippets.editSnippets", async (text) => {
2733 let buf = await nvim.buffer;
2734 let doc = import_coc10.workspace.getDocument(buf.id);
2736 import_coc10.window.showMessage("Document not found", "error");
2739 let file = import_path5.default.join(snippetsDir, `${doc.filetype}.snippets`);
2740 if (!import_fs6.default.existsSync(file)) {
2741 await import_util9.default.promisify(import_fs6.default.writeFile)(file, documentation, "utf8");
2743 let uri = import_coc10.Uri.file(file).toString();
2744 await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2746 await nvim.command("normal! G");
2747 await nvim.command("normal! 2o");
2748 let position = await import_coc10.window.getCursorPosition();
2749 let indent = text.match(/^\s*/)[0];
2750 text = text.split(/\r?\n/).map((s) => s.startsWith(indent) ? s.slice(indent.length) : s).join("\n");
2751 let escaped = text.replace(/([$}\]])/g, "\\$1");
2752 let snippet = 'snippet ${1:Tab_trigger} "${2:Description}" ${3:b}\n' + escaped + "\nendsnippet";
2753 let edit2 = import_coc10.TextEdit.insert(position, snippet);
2754 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edit2);
2757 subscriptions.push(import_coc10.commands.registerCommand("snippets.openSnippetFiles", async () => {
2758 let buf = await nvim.buffer;
2759 let doc = import_coc10.workspace.getDocument(buf.id);
2761 import_coc10.window.showMessage("Document not found", "error");
2764 let files = await manager.getSnippetFiles(doc.filetype);
2765 if (!files.length) {
2766 import_coc10.window.showMessage("No related snippet file found", "warning");
2769 let idx = await import_coc10.window.showQuickpick(files, "choose snippet file:");
2772 let uri = import_coc10.Uri.file(files[idx]).toString();
2773 await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2775 subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand", async () => {
2776 let expanded = await doExpand();
2779 }, {silent: true, sync: false, cancel: true}));
2780 subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand-jump", async () => {
2781 let expanded = await doExpand();
2783 let bufnr = await nvim.call("bufnr", "%");
2784 let session = import_coc10.snippetManager.getSession(bufnr);
2785 if (session && session.isActive) {
2786 await nvim.call("coc#_cancel", []);
2787 await import_coc10.snippetManager.nextPlaceholder();
2792 }, {silent: true, sync: false, cancel: true}));
2793 subscriptions.push(import_coc10.workspace.registerKeymap(["v"], "snippets-select", async () => {
2794 let doc = await import_coc10.workspace.document;
2797 let mode = await nvim.call("visualmode");
2798 if (["v", "V"].indexOf(mode) == -1) {
2799 import_coc10.window.showMessage(`visual mode ${mode} not supported`, "warning");
2802 await nvim.command("normal! `<");
2803 let start = await import_coc10.window.getCursorPosition();
2804 await nvim.command("normal! `>");
2805 let end = await import_coc10.window.getCursorPosition();
2806 end = import_coc10.Position.create(end.line, end.character + 1);
2807 let range = import_coc10.Range.create(start, end);
2808 let text = doc.textDocument.getText(range);
2809 await nvim.call("feedkeys", ["i", "in"]);
2811 await doc.applyEdits([{range, newText: ""}]);
2813 let currline = doc.getline(start.line);
2814 let indent = currline.match(/^\s*/)[0];
2815 let lines = text.split(/\r?\n/);
2816 lines = lines.map((s) => s.startsWith(indent) ? s.slice(indent.length) : s);
2817 text = lines.join("\n");
2818 range = import_coc10.Range.create(import_coc10.Position.create(start.line, indent.length), end);
2819 await doc.applyEdits([{range, newText: ""}]);
2821 await nvim.setVar("coc_selected_text", text);
2822 await import_coc10.window.moveTo(range.start);
2823 }, {silent: true, sync: false, cancel: true}));
2824 let languageProvider = new languages_default(channel, trace);
2825 subscriptions.push(import_coc10.languages.registerCompletionItemProvider("snippets-source", "S", ["snippets"], languageProvider, ["$"], configuration.get("priority", 90)));
2826 subscriptions.push(statusItem);
2827 subscriptions.push(channel);
2828 subscriptions.push(import_coc10.listManager.registerList(new snippet_default(import_coc10.workspace.nvim, manager, mru)));
2830 expandable: async () => {
2833 edits = await manager.getTriggerSnippets();
2835 channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on getTriggerSnippets: ${e}`);
2837 return edits && edits.length > 0;
2841 //# sourceMappingURL=index.js.map