.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-snippets / lib / index.js
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) => () => {
9   if (!module2) {
10     module2 = {exports: {}};
11     callback(module2.exports, module2);
12   }
13   return module2.exports;
14 };
15 var __export = (target, all) => {
16   __markAsModule(target);
17   for (var name in all)
18     __defProp(target, name, {get: all[name], enumerable: true});
19 };
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});
26   }
27   return target;
28 };
29 var __toModule = (module2) => {
30   if (module2 && module2.__esModule)
31     return module2;
32   return __exportStar(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", {value: module2, enumerable: true}), module2);
33 };
34
35 // node_modules/pify/index.js
36 var require_pify = __commonJS((exports2, module2) => {
37   "use strict";
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) {
44             if (result[0]) {
45               reject(result);
46             } else {
47               result.shift();
48               resolve(result);
49             }
50           } else {
51             resolve(result);
52           }
53         });
54       } else if (options.errorFirst) {
55         arguments_.push((error, result) => {
56           if (error) {
57             reject(error);
58           } else {
59             resolve(result);
60           }
61         });
62       } else {
63         arguments_.push(resolve);
64       }
65       const self = this === proxy ? unwrapped : this;
66       Reflect.apply(fn, self, arguments_);
67     });
68   };
69   var filterCache = new WeakMap();
70   module2.exports = (input, options) => {
71     options = {
72       exclude: [/.+(?:Sync|Stream)$/],
73       errorFirst: true,
74       promiseModule: Promise,
75       ...options
76     };
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}\``);
80     }
81     const filter = (target, key) => {
82       let cached = filterCache.get(target);
83       if (!cached) {
84         cached = {};
85         filterCache.set(target, cached);
86       }
87       if (key in cached) {
88         return cached[key];
89       }
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;
96       return shouldFilter;
97     };
98     const cache = new WeakMap();
99     const proxy = new Proxy(input, {
100       apply(target, thisArg, args) {
101         const cached = cache.get(target);
102         if (cached) {
103           return Reflect.apply(cached, thisArg, args);
104         }
105         const pified = options.excludeMain ? target : processFn(target, options, proxy, target);
106         cache.set(target, pified);
107         return Reflect.apply(pified, thisArg, args);
108       },
109       get(target, key) {
110         const property = target[key];
111         if (!filter(target, key) || property === Function.prototype[key]) {
112           return property;
113         }
114         const cached = cache.get(property);
115         if (cached) {
116           return cached;
117         }
118         if (typeof property === "function") {
119           const pified = processFn(property, options, proxy, target);
120           cache.set(property, pified);
121           return pified;
122         }
123         return property;
124       }
125     });
126     return proxy;
127   };
128 });
129
130 // src/index.ts
131 __export(exports, {
132   activate: () => activate
133 });
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"));
139
140 // src/languages.ts
141 var import_coc = __toModule(require("coc.nvim"));
142
143 // src/util.ts
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) {
149   let r = [];
150   let i;
151   for (i = 0; i < bytes.length; i++) {
152     r.push(BASE64[bytes[i] % 64]);
153   }
154   return r.join("");
155 }
156 function uid() {
157   return tostr(import_crypto.default.randomBytes(10));
158 }
159 async function statAsync(filepath) {
160   try {
161     return await import_pify.default(import_fs.default.stat)(filepath);
162   } catch (e) {
163     return null;
164   }
165 }
166 async function readFileAsync(fullpath, encoding = "utf8") {
167   return await import_pify.default(import_fs.default.readFile)(fullpath, encoding);
168 }
169 async function readdirAsync(filepath) {
170   try {
171     return await import_pify.default(import_fs.default.readdir)(filepath);
172   } catch (e) {
173     return null;
174   }
175 }
176 function headTail(line) {
177   line = line.trim();
178   let ms = line.match(/^(\S+)\s+(.*)/);
179   if (!ms)
180     return [line, ""];
181   return [ms[1], ms[2]];
182 }
183 function distinct(array, keyFn) {
184   if (!keyFn) {
185     return array.filter((element, position) => {
186       return array.indexOf(element) === position;
187     });
188   }
189   const seen = Object.create(null);
190   return array.filter((elem) => {
191     const key = keyFn(elem);
192     if (seen[key]) {
193       return false;
194     }
195     seen[key] = true;
196     return true;
197   });
198 }
199 var conditionRe = /\(\?\(\?:\w+\).+\|/;
200 var bellRe = /\\a/;
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");
210   }
211   if (str.indexOf("(?s)") !== -1) {
212     throw new Error("pattern (?s) not supported");
213   }
214   if (str.indexOf("(?x)") !== -1) {
215     throw new Error("pattern (?x) not supported");
216   }
217   if (str.indexOf("\n") !== -1) {
218     throw new Error("multiple line pattern not supported");
219   }
220   if (conditionRe.test(str)) {
221     throw new Error("condition pattern not supported");
222   }
223   return str.replace(regex, (match, p1) => {
224     if (match == "^]")
225       return "^\\]";
226     if (match == "\\a")
227       return "";
228     if (match.startsWith("(?#"))
229       return "";
230     if (match == "\\A")
231       return "^";
232     if (match.startsWith("(?P<"))
233       return "(?" + match.slice(3);
234     if (match.startsWith("(?P="))
235       return `\\k<${p1}>`;
236     return "";
237   });
238 }
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, "");
246   return content;
247 }
248 function markdownBlock(code, filetype) {
249   filetype = filetype == "javascriptreact" ? "javascript" : filetype;
250   filetype = filetype == "typescriptreact" ? "typescript" : filetype;
251   return "``` " + filetype + "\n" + code + "\n```";
252 }
253
254 // src/languages.ts
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;
264     this.trace = trace;
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}`);
271         });
272       }
273     }
274     import_coc.workspace.onDidOpenTextDocument(async (textDocument) => {
275       let doc = import_coc.workspace.getDocument(textDocument.uri);
276       if (!this.shouldValidate(doc.uri))
277         return;
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))
283         return;
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);
289   }
290   shouldValidate(uri) {
291     return uri.endsWith(".snippets");
292   }
293   async validate(uri, content) {
294     let lines = content.split("\n");
295     let diagnostics = [];
296     let curr = 0;
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));
301         continue;
302       }
303       if (line.startsWith("snippet ")) {
304         let content2 = headTail(line)[1];
305         let ms = content2.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?$/);
306         let prefix = ms[1];
307         if (prefix.length > 2 && prefix[0] == prefix[prefix.length - 1] && !/\w/.test(prefix[0])) {
308           prefix = prefix.slice(1, prefix.length - 1);
309         }
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));
318           }
319           startCharacter = startCharacter + 1;
320         }
321         if (isExpression) {
322           try {
323             convertRegex(prefix);
324           } catch (e) {
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));
329           }
330         }
331       } else {
332         let idx = line.indexOf("`#!");
333         if (idx !== -1) {
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));
337         }
338       }
339       curr++;
340     }
341     if (this.trace == "verbose") {
342       this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] diagnostics of ${uri} -> ${JSON.stringify(diagnostics)}`);
343     }
344     this.collection.set(uri, diagnostics);
345   }
346   provideCompletionItems(_document, position, _token, context) {
347     let {input, col} = context.option;
348     if (context.triggerCharacter == "$") {
349       return [{
350         label: "$VISUAL",
351         kind: import_coc.CompletionItemKind.Snippet,
352         detail: "${VISUAL}",
353         insertTextFormat: import_coc.InsertTextFormat.Snippet,
354         textEdit: {
355           range: import_coc.Range.create(position.line, position.character - 1, position.line, position.character),
356           newText: "\\${VISUAL${1::default}\\}"
357         }
358       }];
359     }
360     if (col == 0 && "snippet".startsWith(input)) {
361       return [{
362         label: "snippet",
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'
367       }];
368     }
369     return [];
370   }
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 = {
375       kind: "markdown",
376       value: markdownBlock(snip.toString(), "snippets")
377     };
378     return item;
379   }
380 };
381 var languages_default = LanguageProvider;
382
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) {
388     super(nvim);
389     this.manager = manager;
390     this.mru = mru;
391     this.name = "snippets";
392     this.description = "snippets list";
393     this.addLocationActions();
394   }
395   async loadItems(context) {
396     let {window: window4} = context;
397     let valid = await window4.valid;
398     if (!valid)
399       return;
400     let buf = await window4.buffer;
401     let doc = import_coc2.workspace.getDocument(buf.id);
402     if (!doc)
403       return [];
404     let snippets = await this.manager.getSnippets(doc.filetype);
405     let res = [];
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)}`;
412       }
413       res.push({
414         label: `${prefix}       ${snip.description}     ${snip.filepath.replace(import_os.default.homedir(), "~")}`,
415         filterText: `${snip.prefix} ${snip.description}`,
416         location
417       });
418     }
419     return res;
420   }
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();
429   }
430 };
431 var snippet_default = SnippetsList;
432
433 // src/provider.ts
434 var import_coc3 = __toModule(require("coc.nvim"));
435 var import_path = __toModule(require("path"));
436
437 // src/types.ts
438 var TriggerKind;
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 = {}));
445
446 // src/provider.ts
447 var ProviderManager = class {
448   constructor() {
449     this.providers = new Map();
450   }
451   regist(provider, name) {
452     this.providers.set(name, provider);
453     return import_coc3.Disposable.create(() => {
454       this.providers.delete(name);
455     });
456   }
457   get hasProvider() {
458     return this.providers.size > 0;
459   }
460   async init() {
461     let providers = Array.from(this.providers.values());
462     await Promise.all(providers.map((provider) => {
463       return provider.init();
464     }));
465   }
466   async getSnippets(filetype) {
467     let names = Array.from(this.providers.keys());
468     let list = [];
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);
474     }
475     return list;
476   }
477   async getSnippetFiles(filetype) {
478     let files = [];
479     for (let provider of this.providers.values()) {
480       let res = await provider.getSnippetFiles(filetype);
481       files = files.concat(res);
482     }
483     return files;
484   }
485   async getTriggerSnippets(autoTrigger = false) {
486     let bufnr = await import_coc3.workspace.nvim.call("bufnr", "%");
487     let doc = import_coc3.workspace.getDocument(bufnr);
488     if (!doc)
489       return [];
490     doc.forceSync();
491     let position = await import_coc3.window.getCursorPosition();
492     let names = Array.from(this.providers.keys());
493     let list = [];
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) {
499           list.push(item);
500         }
501       }
502     }
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);
506     }
507     return list;
508   }
509   async provideCompletionItems(document, position, _token, context) {
510     let doc = import_coc3.workspace.getDocument(document.uri);
511     if (!doc)
512       return [];
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);
518     let res = [];
519     let contextPrefixes = [];
520     for (let snip of snippets) {
521       let contentBehind = before_content;
522       if (contextPrefixes.indexOf(snip.prefix) !== -1)
523         continue;
524       if (snip.regex != null && snip.prefix == "")
525         continue;
526       if (snip.context) {
527         let provider = this.providers.get(snip.provider);
528         let valid = await provider.checkContext(snip.context);
529         if (!valid)
530           continue;
531         contextPrefixes.push(snip.prefix);
532       }
533       let head = this.getPrefixHead(doc, snip.prefix);
534       if (input.length == 0 && !before_content.endsWith(snip.prefix))
535         continue;
536       let item = {
537         label: snip.prefix,
538         kind: import_coc3.CompletionItemKind.Snippet,
539         filterText: snip.prefix,
540         detail: snip.description,
541         insertTextFormat: import_coc3.InsertTextFormat.Snippet
542       };
543       item.data = {
544         snip,
545         provider: snip.provider,
546         filepath: `${import_path.default.basename(snip.filepath)}:${snip.lnum}`
547       };
548       if (snip.regex) {
549         if (!input.length || snip.prefix && input[0] != snip.prefix[0])
550           continue;
551         let content = before_content + snip.prefix;
552         let ms = content.match(snip.regex);
553         if (!ms)
554           continue;
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, {
559           textEdit: {
560             range: import_coc3.Range.create({line: position.line, character: character - head.length}, position),
561             newText: prefix
562           }
563         });
564       } else if (input.length == 0) {
565         let {prefix} = snip;
566         contentBehind = before_content.slice(0, -prefix.length);
567         Object.assign(item, {
568           preselect: true,
569           textEdit: {
570             range: import_coc3.Range.create({line: position.line, character: character - prefix.length}, position),
571             newText: prefix
572           }
573         });
574       }
575       if (snip.triggerKind == TriggerKind.LineBegin && contentBehind.trim().length)
576         continue;
577       if (snip.triggerKind == TriggerKind.SpaceBefore) {
578         if (contentBehind.length && !/\s/.test(contentBehind[contentBehind.length - 1])) {
579           continue;
580         }
581       }
582       if (!item.textEdit) {
583         item.textEdit = {
584           range: import_coc3.Range.create({line: position.line, character}, position),
585           newText: item.label
586         };
587       }
588       item.data.location = `${snip.filepath}:${snip.lnum}`;
589       item.data.line = contentBehind + snip.prefix;
590       res.push(item);
591     }
592     return res;
593   }
594   async resolveCompletionItem(item) {
595     let provider = this.providers.get(item.data.provider);
596     if (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 = {
603           kind: "markdown",
604           value: markdownBlock(snip.toString(), filetype.match(/^\w+/)[0])
605         };
606       }
607     }
608     return item;
609   }
610   getPrefixHead(doc, prefix) {
611     let res = 0;
612     for (let idx = prefix.length - 1; idx >= 0; idx--) {
613       if (!doc.isWord(prefix[idx])) {
614         res = idx;
615         break;
616       }
617     }
618     return res == 0 ? "" : prefix.slice(0, res + 1);
619   }
620 };
621 function characterIndex(content, byteIndex) {
622   let buf = Buffer.from(content, "utf8");
623   return buf.slice(0, byteIndex).toString("utf8").length;
624 }
625
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"));
631
632 // src/baseProvider.ts
633 var import_coc4 = __toModule(require("coc.nvim"));
634 var BaseProvider = class {
635   constructor(config) {
636     this.config = config;
637   }
638   async checkContext(_context) {
639     return true;
640   }
641   getExtendsFiletypes(filetype, exists = new Set()) {
642     if (exists.has(filetype))
643       return [];
644     let extend = this.config.extends ? this.config.extends[filetype] : null;
645     exists.add(filetype);
646     if (!extend || extend.length == 0)
647       return [];
648     return extend.reduce((arr, curr) => {
649       return arr.concat([curr], this.getExtendsFiletypes(curr, exists));
650     }, []);
651   }
652   getFiletypes(filetype) {
653     let filetypes = [filetype];
654     if (filetype.indexOf(".") !== -1) {
655       filetypes.push(...filetype.split("."));
656     }
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]);
664     }
665     let extendFiletypes = filetypes.reduce((arr, curr) => {
666       return arr.concat(this.getExtendsFiletypes(curr));
667     }, []);
668     filetypes.push(...extendFiletypes);
669     filetypes.reverse();
670     return distinct(filetypes);
671   }
672 };
673 var baseProvider_default = BaseProvider;
674
675 // src/parser.ts
676 var Parser = class {
677   constructor(_content) {
678     this._content = _content;
679     this._curr = 0;
680   }
681   eof() {
682     return this._curr >= this._content.length;
683   }
684   skipSpaces() {
685     for (let i = this._curr; i <= this._content.length; i++) {
686       let ch = this._content[i];
687       if (!ch || /\S/.test(ch)) {
688         this._curr = i;
689         break;
690       }
691     }
692   }
693   get index() {
694     return this._curr;
695   }
696   get curr() {
697     return this._content[this._curr] || "";
698   }
699   get len() {
700     return this._content.length;
701   }
702   next(count = 1) {
703     return this._content.slice(this._curr + 1, this._curr + 1 + count);
704   }
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 !== "\\")) {
713         break;
714       }
715       pre = ch;
716       i = i + 1;
717     }
718     if (!allowEnd && i == this.len - 1 && character != this._content[i]) {
719       return -1;
720     }
721     return i;
722   }
723   prev() {
724     return this._content[this._curr - 1] || "";
725   }
726   iterate(fn) {
727     while (this._curr < this._content.length) {
728       let fine = fn(this.curr, this._curr);
729       if (fine === false) {
730         break;
731       }
732       this._curr = this._curr + 1;
733     }
734   }
735   eat(count) {
736     let end = this._curr + count;
737     end = Math.min(end, this.len);
738     let str = this._content.slice(this._curr, end);
739     this._curr = end;
740     return str;
741   }
742   eatTo(index) {
743     if (index == this._curr)
744       return "";
745     let str = this._content.slice(this._curr, index);
746     this._curr = index;
747     return str;
748   }
749 };
750 var parser_default = Parser;
751
752 // src/snipmateProvider.ts
753 var SnipmateProvider = class extends baseProvider_default {
754   constructor(channel, trace, config) {
755     super(config);
756     this.channel = channel;
757     this.trace = trace;
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")
763         return;
764       let filepath = uri.fsPath;
765       if (!import_fs2.default.existsSync(filepath))
766         return;
767       let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
768       if (snippetFile)
769         await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
770     }, null, this.disposables);
771   }
772   async init() {
773     let arr = await this.getAllSnippetFiles();
774     let {nvim} = import_coc5.workspace;
775     let author = await nvim.getVar("snips_author");
776     if (!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);
780     }));
781   }
782   async loadSnippetsFromFile(filetype, directory, filepath) {
783     let snippets = await this.parseSnippetsFile(filepath);
784     let idx = this.snippetFiles.findIndex((o) => o.filepath == filepath);
785     if (idx !== -1)
786       this.snippetFiles.splice(idx, 1);
787     this.snippetFiles.push({
788       directory,
789       filepath,
790       filetype,
791       snippets
792     });
793     this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} snipmate snippets from: ${filepath}`);
794   }
795   async resolveSnippetBody(snippet, _range, _line) {
796     let parser2 = new parser_default(snippet.body);
797     let resolved = "";
798     let {nvim} = import_coc5.workspace;
799     while (!parser2.eof()) {
800       if (parser2.curr == "`") {
801         let idx = parser2.nextIndex("`", true, false);
802         if (idx == -1) {
803           resolved = resolved + parser2.eatTo(parser2.len);
804           break;
805         }
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");
810         } else {
811           try {
812             resolved = resolved + await nvim.eval(code);
813           } catch (e) {
814             this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on eval: ${code}`);
815           }
816         }
817         continue;
818       }
819       parser2.iterate((ch) => {
820         if (ch == "`") {
821           return false;
822         } else {
823           resolved = resolved + ch;
824         }
825         return true;
826       });
827     }
828     return resolved;
829   }
830   parseSnippetsFile(filepath) {
831     let res = [];
832     const rl = import_readline.default.createInterface({
833       input: import_fs2.default.createReadStream(filepath, "utf8"),
834       crlfDelay: Infinity
835     });
836     let lnum = 0;
837     let lines = [];
838     let prefix = "";
839     let description = "";
840     rl.on("line", (line) => {
841       lnum += 1;
842       if (line.startsWith("#"))
843         return;
844       if (line.startsWith("snippet")) {
845         line = line.replace(/\s*$/, "");
846         if (lines.length && prefix) {
847           res.push({
848             filepath,
849             lnum: lnum - lines.length - 1,
850             body: lines.join("\n").replace(/\s+$/, ""),
851             prefix,
852             description,
853             triggerKind: TriggerKind.SpaceBefore
854           });
855           lines = [];
856         }
857         let ms = line.match(/^snippet\s+(\S+)(?:\s(.+))?$/);
858         if (!ms) {
859           prefix = "";
860           this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Broken line on ${filepath}:${lnum}`);
861           return;
862         }
863         prefix = ms[1];
864         description = ms[2] || "";
865         return;
866       }
867       if (prefix) {
868         if (line.indexOf("VISUAL") !== -1) {
869           line = line.replace(/\$(\{?)VISUAL\b(:[^\}])?(\}?)/g, "$$$1TM_SELECTED_TEXT$2$3");
870         }
871         if (line.startsWith("   ")) {
872           lines.push(line.slice(1));
873         } else {
874           lines.push(line);
875         }
876       }
877     });
878     return new Promise((resolve) => {
879       rl.on("close", async () => {
880         if (lines.length) {
881           res.push({
882             filepath,
883             lnum: lnum - lines.length - 1,
884             body: lines.join("\n"),
885             prefix,
886             description,
887             triggerKind: TriggerKind.SpaceBefore
888           });
889         }
890         resolve(res);
891       });
892     });
893   }
894   async getTriggerSnippets(document, position, autoTrigger) {
895     if (autoTrigger)
896       return [];
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] == " ")
901       return [];
902     snippets = snippets.filter((s) => {
903       let {prefix} = s;
904       if (!line.endsWith(prefix))
905         return false;
906       let pre = line.slice(0, line.length - prefix.length);
907       return pre.length == 0 || /\s/.test(pre[pre.length - 1]);
908     });
909     let edits = [];
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);
914       edits.push({
915         prefix: s.prefix,
916         description: s.description,
917         location: s.filepath,
918         range,
919         newText,
920         priority: -1
921       });
922     }
923     return edits;
924   }
925   async getSnippetFiles(filetype) {
926     let filetypes = this.getFiletypes(filetype);
927     let res = [];
928     for (let s of this.snippetFiles) {
929       if (filetypes.indexOf(s.filetype) !== -1) {
930         res.push(s.filepath);
931       }
932     }
933     return res;
934   }
935   async getSnippets(filetype) {
936     let filetypes = this.getFiletypes(filetype);
937     filetypes.push("_");
938     let snippetFiles = this.snippetFiles.filter((o) => filetypes.indexOf(o.filetype) !== -1);
939     let result = [];
940     snippetFiles.sort((a, b) => {
941       if (a.filetype == b.filetype)
942         return 1;
943       if (a.filetype == filetype)
944         return -1;
945       return 1;
946     });
947     for (let file of snippetFiles) {
948       let {snippets} = file;
949       for (let snip of snippets) {
950         result.push(snip);
951       }
952     }
953     return result;
954   }
955   async getAllSnippetFiles() {
956     let {nvim} = import_coc5.workspace;
957     let opt = await nvim.eval("&rtp");
958     let rtps = opt.split(",");
959     let res = [];
960     for (let rtp of rtps) {
961       let items = await this.getSnippetFileItems(import_path2.default.join(rtp, "snippets"));
962       res.push(...items);
963     }
964     return res;
965   }
966   async getSnippetFileItems(directory) {
967     let res = [];
968     let stat = await statAsync(directory);
969     if (stat && stat.isDirectory()) {
970       let files = await readdirAsync(directory);
971       if (files.length) {
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});
978           } else {
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});
985                 }
986               }
987             }
988           }
989         }
990       }
991     }
992     return res;
993   }
994 };
995
996 // src/textmateProvider.ts
997 var import_coc6 = __toModule(require("coc.nvim"));
998 var import_fs3 = __toModule(require("fs"));
999
1000 // node_modules/jsonc-parser/lib/esm/impl/scanner.js
1001 "use strict";
1002 function createScanner(text, ignoreTrivia) {
1003   if (ignoreTrivia === void 0) {
1004     ignoreTrivia = false;
1005   }
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) {
1009     var digits = 0;
1010     var value2 = 0;
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;
1019       } else {
1020         break;
1021       }
1022       pos++;
1023       digits++;
1024     }
1025     if (digits < count) {
1026       value2 = -1;
1027     }
1028     return value2;
1029   }
1030   function setPosition(newPosition) {
1031     pos = newPosition;
1032     value = "";
1033     tokenOffset = 0;
1034     token = 16;
1035     scanError = 0;
1036   }
1037   function scanNumber() {
1038     var start = pos;
1039     if (text.charCodeAt(pos) === 48) {
1040       pos++;
1041     } else {
1042       pos++;
1043       while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1044         pos++;
1045       }
1046     }
1047     if (pos < text.length && text.charCodeAt(pos) === 46) {
1048       pos++;
1049       if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1050         pos++;
1051         while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1052           pos++;
1053         }
1054       } else {
1055         scanError = 3;
1056         return text.substring(start, pos);
1057       }
1058     }
1059     var end = pos;
1060     if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
1061       pos++;
1062       if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
1063         pos++;
1064       }
1065       if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1066         pos++;
1067         while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1068           pos++;
1069         }
1070         end = pos;
1071       } else {
1072         scanError = 3;
1073       }
1074     }
1075     return text.substring(start, end);
1076   }
1077   function scanString() {
1078     var result = "", start = pos;
1079     while (true) {
1080       if (pos >= len) {
1081         result += text.substring(start, pos);
1082         scanError = 2;
1083         break;
1084       }
1085       var ch = text.charCodeAt(pos);
1086       if (ch === 34) {
1087         result += text.substring(start, pos);
1088         pos++;
1089         break;
1090       }
1091       if (ch === 92) {
1092         result += text.substring(start, pos);
1093         pos++;
1094         if (pos >= len) {
1095           scanError = 2;
1096           break;
1097         }
1098         var ch2 = text.charCodeAt(pos++);
1099         switch (ch2) {
1100           case 34:
1101             result += '"';
1102             break;
1103           case 92:
1104             result += "\\";
1105             break;
1106           case 47:
1107             result += "/";
1108             break;
1109           case 98:
1110             result += "\b";
1111             break;
1112           case 102:
1113             result += "\f";
1114             break;
1115           case 110:
1116             result += "\n";
1117             break;
1118           case 114:
1119             result += "\r";
1120             break;
1121           case 116:
1122             result += " ";
1123             break;
1124           case 117:
1125             var ch3 = scanHexDigits(4, true);
1126             if (ch3 >= 0) {
1127               result += String.fromCharCode(ch3);
1128             } else {
1129               scanError = 4;
1130             }
1131             break;
1132           default:
1133             scanError = 5;
1134         }
1135         start = pos;
1136         continue;
1137       }
1138       if (ch >= 0 && ch <= 31) {
1139         if (isLineBreak(ch)) {
1140           result += text.substring(start, pos);
1141           scanError = 2;
1142           break;
1143         } else {
1144           scanError = 6;
1145         }
1146       }
1147       pos++;
1148     }
1149     return result;
1150   }
1151   function scanNext() {
1152     value = "";
1153     scanError = 0;
1154     tokenOffset = pos;
1155     lineStartOffset = lineNumber;
1156     prevTokenLineStartOffset = tokenLineStartOffset;
1157     if (pos >= len) {
1158       tokenOffset = len;
1159       return token = 17;
1160     }
1161     var code = text.charCodeAt(pos);
1162     if (isWhiteSpace(code)) {
1163       do {
1164         pos++;
1165         value += String.fromCharCode(code);
1166         code = text.charCodeAt(pos);
1167       } while (isWhiteSpace(code));
1168       return token = 15;
1169     }
1170     if (isLineBreak(code)) {
1171       pos++;
1172       value += String.fromCharCode(code);
1173       if (code === 13 && text.charCodeAt(pos) === 10) {
1174         pos++;
1175         value += "\n";
1176       }
1177       lineNumber++;
1178       tokenLineStartOffset = pos;
1179       return token = 14;
1180     }
1181     switch (code) {
1182       case 123:
1183         pos++;
1184         return token = 1;
1185       case 125:
1186         pos++;
1187         return token = 2;
1188       case 91:
1189         pos++;
1190         return token = 3;
1191       case 93:
1192         pos++;
1193         return token = 4;
1194       case 58:
1195         pos++;
1196         return token = 6;
1197       case 44:
1198         pos++;
1199         return token = 5;
1200       case 34:
1201         pos++;
1202         value = scanString();
1203         return token = 10;
1204       case 47:
1205         var start = pos - 1;
1206         if (text.charCodeAt(pos + 1) === 47) {
1207           pos += 2;
1208           while (pos < len) {
1209             if (isLineBreak(text.charCodeAt(pos))) {
1210               break;
1211             }
1212             pos++;
1213           }
1214           value = text.substring(start, pos);
1215           return token = 12;
1216         }
1217         if (text.charCodeAt(pos + 1) === 42) {
1218           pos += 2;
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) {
1224               pos += 2;
1225               commentClosed = true;
1226               break;
1227             }
1228             pos++;
1229             if (isLineBreak(ch)) {
1230               if (ch === 13 && text.charCodeAt(pos) === 10) {
1231                 pos++;
1232               }
1233               lineNumber++;
1234               tokenLineStartOffset = pos;
1235             }
1236           }
1237           if (!commentClosed) {
1238             pos++;
1239             scanError = 1;
1240           }
1241           value = text.substring(start, pos);
1242           return token = 13;
1243         }
1244         value += String.fromCharCode(code);
1245         pos++;
1246         return token = 16;
1247       case 45:
1248         value += String.fromCharCode(code);
1249         pos++;
1250         if (pos === len || !isDigit(text.charCodeAt(pos))) {
1251           return token = 16;
1252         }
1253       case 48:
1254       case 49:
1255       case 50:
1256       case 51:
1257       case 52:
1258       case 53:
1259       case 54:
1260       case 55:
1261       case 56:
1262       case 57:
1263         value += scanNumber();
1264         return token = 11;
1265       default:
1266         while (pos < len && isUnknownContentCharacter(code)) {
1267           pos++;
1268           code = text.charCodeAt(pos);
1269         }
1270         if (tokenOffset !== pos) {
1271           value = text.substring(tokenOffset, pos);
1272           switch (value) {
1273             case "true":
1274               return token = 8;
1275             case "false":
1276               return token = 9;
1277             case "null":
1278               return token = 7;
1279           }
1280           return token = 16;
1281         }
1282         value += String.fromCharCode(code);
1283         pos++;
1284         return token = 16;
1285     }
1286   }
1287   function isUnknownContentCharacter(code) {
1288     if (isWhiteSpace(code) || isLineBreak(code)) {
1289       return false;
1290     }
1291     switch (code) {
1292       case 125:
1293       case 93:
1294       case 123:
1295       case 91:
1296       case 34:
1297       case 58:
1298       case 44:
1299       case 47:
1300         return false;
1301     }
1302     return true;
1303   }
1304   function scanNextNonTrivia() {
1305     var result;
1306     do {
1307       result = scanNext();
1308     } while (result >= 12 && result <= 15);
1309     return result;
1310   }
1311   return {
1312     setPosition,
1313     getPosition: function() {
1314       return pos;
1315     },
1316     scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
1317     getToken: function() {
1318       return token;
1319     },
1320     getTokenValue: function() {
1321       return value;
1322     },
1323     getTokenOffset: function() {
1324       return tokenOffset;
1325     },
1326     getTokenLength: function() {
1327       return pos - tokenOffset;
1328     },
1329     getTokenStartLine: function() {
1330       return lineStartOffset;
1331     },
1332     getTokenStartCharacter: function() {
1333       return tokenOffset - prevTokenLineStartOffset;
1334     },
1335     getTokenError: function() {
1336       return scanError;
1337     }
1338   };
1339 }
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;
1342 }
1343 function isLineBreak(ch) {
1344   return ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
1345 }
1346 function isDigit(ch) {
1347   return ch >= 48 && ch <= 57;
1348 }
1349
1350 // node_modules/jsonc-parser/lib/esm/impl/format.js
1351 "use strict";
1352
1353 // node_modules/jsonc-parser/lib/esm/impl/parser.js
1354 "use strict";
1355 var ParseOptions;
1356 (function(ParseOptions2) {
1357   ParseOptions2.DEFAULT = {
1358     allowTrailingComma: false
1359   };
1360 })(ParseOptions || (ParseOptions = {}));
1361 function parse(text, errors, options) {
1362   if (errors === void 0) {
1363     errors = [];
1364   }
1365   if (options === void 0) {
1366     options = ParseOptions.DEFAULT;
1367   }
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;
1376     }
1377   }
1378   var visitor = {
1379     onObjectBegin: function() {
1380       var object = {};
1381       onValue(object);
1382       previousParents.push(currentParent);
1383       currentParent = object;
1384       currentProperty = null;
1385     },
1386     onObjectProperty: function(name) {
1387       currentProperty = name;
1388     },
1389     onObjectEnd: function() {
1390       currentParent = previousParents.pop();
1391     },
1392     onArrayBegin: function() {
1393       var array = [];
1394       onValue(array);
1395       previousParents.push(currentParent);
1396       currentParent = array;
1397       currentProperty = null;
1398     },
1399     onArrayEnd: function() {
1400       currentParent = previousParents.pop();
1401     },
1402     onLiteralValue: onValue,
1403     onError: function(error, offset, length) {
1404       errors.push({error, offset, length});
1405     }
1406   };
1407   visit(text, visitor, options);
1408   return currentParent[0];
1409 }
1410 function visit(text, visitor, options) {
1411   if (options === void 0) {
1412     options = ParseOptions.DEFAULT;
1413   }
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());
1418     } : function() {
1419       return true;
1420     };
1421   }
1422   function toOneArgVisit(visitFunction) {
1423     return visitFunction ? function(arg) {
1424       return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
1425     } : function() {
1426       return true;
1427     };
1428   }
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() {
1433     while (true) {
1434       var token = _scanner.scan();
1435       switch (_scanner.getTokenError()) {
1436         case 4:
1437           handleError(14);
1438           break;
1439         case 5:
1440           handleError(15);
1441           break;
1442         case 3:
1443           handleError(13);
1444           break;
1445         case 1:
1446           if (!disallowComments) {
1447             handleError(11);
1448           }
1449           break;
1450         case 2:
1451           handleError(12);
1452           break;
1453         case 6:
1454           handleError(16);
1455           break;
1456       }
1457       switch (token) {
1458         case 12:
1459         case 13:
1460           if (disallowComments) {
1461             handleError(10);
1462           } else {
1463             onComment();
1464           }
1465           break;
1466         case 16:
1467           handleError(1);
1468           break;
1469         case 15:
1470         case 14:
1471           break;
1472         default:
1473           return token;
1474       }
1475     }
1476   }
1477   function handleError(error, skipUntilAfter, skipUntil) {
1478     if (skipUntilAfter === void 0) {
1479       skipUntilAfter = [];
1480     }
1481     if (skipUntil === void 0) {
1482       skipUntil = [];
1483     }
1484     onError(error);
1485     if (skipUntilAfter.length + skipUntil.length > 0) {
1486       var token = _scanner.getToken();
1487       while (token !== 17) {
1488         if (skipUntilAfter.indexOf(token) !== -1) {
1489           scanNext();
1490           break;
1491         } else if (skipUntil.indexOf(token) !== -1) {
1492           break;
1493         }
1494         token = scanNext();
1495       }
1496     }
1497   }
1498   function parseString(isValue) {
1499     var value = _scanner.getTokenValue();
1500     if (isValue) {
1501       onLiteralValue(value);
1502     } else {
1503       onObjectProperty(value);
1504     }
1505     scanNext();
1506     return true;
1507   }
1508   function parseLiteral() {
1509     switch (_scanner.getToken()) {
1510       case 11:
1511         var tokenValue = _scanner.getTokenValue();
1512         var value = Number(tokenValue);
1513         if (isNaN(value)) {
1514           handleError(2);
1515           value = 0;
1516         }
1517         onLiteralValue(value);
1518         break;
1519       case 7:
1520         onLiteralValue(null);
1521         break;
1522       case 8:
1523         onLiteralValue(true);
1524         break;
1525       case 9:
1526         onLiteralValue(false);
1527         break;
1528       default:
1529         return false;
1530     }
1531     scanNext();
1532     return true;
1533   }
1534   function parseProperty() {
1535     if (_scanner.getToken() !== 10) {
1536       handleError(3, [], [2, 5]);
1537       return false;
1538     }
1539     parseString(false);
1540     if (_scanner.getToken() === 6) {
1541       onSeparator(":");
1542       scanNext();
1543       if (!parseValue()) {
1544         handleError(4, [], [2, 5]);
1545       }
1546     } else {
1547       handleError(5, [], [2, 5]);
1548     }
1549     return true;
1550   }
1551   function parseObject() {
1552     onObjectBegin();
1553     scanNext();
1554     var needsComma = false;
1555     while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
1556       if (_scanner.getToken() === 5) {
1557         if (!needsComma) {
1558           handleError(4, [], []);
1559         }
1560         onSeparator(",");
1561         scanNext();
1562         if (_scanner.getToken() === 2 && allowTrailingComma) {
1563           break;
1564         }
1565       } else if (needsComma) {
1566         handleError(6, [], []);
1567       }
1568       if (!parseProperty()) {
1569         handleError(4, [], [2, 5]);
1570       }
1571       needsComma = true;
1572     }
1573     onObjectEnd();
1574     if (_scanner.getToken() !== 2) {
1575       handleError(7, [2], []);
1576     } else {
1577       scanNext();
1578     }
1579     return true;
1580   }
1581   function parseArray() {
1582     onArrayBegin();
1583     scanNext();
1584     var needsComma = false;
1585     while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
1586       if (_scanner.getToken() === 5) {
1587         if (!needsComma) {
1588           handleError(4, [], []);
1589         }
1590         onSeparator(",");
1591         scanNext();
1592         if (_scanner.getToken() === 4 && allowTrailingComma) {
1593           break;
1594         }
1595       } else if (needsComma) {
1596         handleError(6, [], []);
1597       }
1598       if (!parseValue()) {
1599         handleError(4, [], [4, 5]);
1600       }
1601       needsComma = true;
1602     }
1603     onArrayEnd();
1604     if (_scanner.getToken() !== 4) {
1605       handleError(8, [4], []);
1606     } else {
1607       scanNext();
1608     }
1609     return true;
1610   }
1611   function parseValue() {
1612     switch (_scanner.getToken()) {
1613       case 3:
1614         return parseArray();
1615       case 1:
1616         return parseObject();
1617       case 10:
1618         return parseString(true);
1619       default:
1620         return parseLiteral();
1621     }
1622   }
1623   scanNext();
1624   if (_scanner.getToken() === 17) {
1625     if (options.allowEmptyContent) {
1626       return true;
1627     }
1628     handleError(4, [], []);
1629     return false;
1630   }
1631   if (!parseValue()) {
1632     handleError(4, [], []);
1633     return false;
1634   }
1635   if (_scanner.getToken() !== 17) {
1636     handleError(9, [], []);
1637   }
1638   return true;
1639 }
1640
1641 // node_modules/jsonc-parser/lib/esm/impl/edit.js
1642 "use strict";
1643
1644 // node_modules/jsonc-parser/lib/esm/main.js
1645 "use strict";
1646 var parse2 = parse;
1647
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) {
1654     super(config);
1655     this.channel = channel;
1656     this.trace = trace;
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}`);
1663         });
1664       });
1665       import_coc6.extensions.onDidUnloadExtension((id) => {
1666         delete this._snippetCache[id];
1667       });
1668     }
1669   }
1670   async init() {
1671     if (this.config.loadFromExtensions) {
1672       for (let extension of import_coc6.extensions.all) {
1673         await this.loadSnippetsFromExtension(extension);
1674       }
1675     }
1676     let paths = this.config.snippetsRoots;
1677     if (paths && paths.length) {
1678       for (let dir of paths) {
1679         await this.loadSnippetsFromRoot(dir);
1680       }
1681     }
1682   }
1683   async getSnippetFiles(filetype) {
1684     let filetypes = this.getFiletypes(filetype);
1685     let filepaths = [];
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);
1693           }
1694         }
1695       }
1696     }
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);
1704           }
1705         }
1706       }
1707     }
1708     return distinct(filepaths);
1709   }
1710   async getTriggerSnippets(document, position, autoTrigger) {
1711     if (autoTrigger)
1712       return [];
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)
1717       return [];
1718     let edits = [];
1719     for (let snip of snippets) {
1720       let {prefix} = snip;
1721       if (!line.endsWith(prefix))
1722         continue;
1723       let pre = line.slice(0, line.length - prefix.length);
1724       if (pre.length && /\w/.test(pre[pre.length - 1]))
1725         continue;
1726       edits.push({
1727         prefix,
1728         range: import_coc6.Range.create(position.line, position.character - prefix.length, position.line, position.character),
1729         newText: snip.body,
1730         location: snip.filepath,
1731         description: snip.description,
1732         priority: -1
1733       });
1734     }
1735     return edits;
1736   }
1737   async getSnippets(filetype) {
1738     let res = [];
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];
1745         if (snippets) {
1746           for (let snip of snippets) {
1747             if (!added.has(snip.prefix)) {
1748               added.add(snip.prefix);
1749               res.push(snip);
1750             }
1751           }
1752         }
1753       }
1754     }
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);
1761             res.push(snip);
1762           }
1763         }
1764       }
1765     }
1766     return res;
1767   }
1768   async resolveSnippetBody(snip, _range) {
1769     return snip.body;
1770   }
1771   async loadSnippetsFromExtension(extension) {
1772     let {packageJSON} = extension;
1773     if (packageJSON.contributes && packageJSON.contributes.snippets) {
1774       let {snippets} = packageJSON.contributes;
1775       let def = {
1776         extensionId: extension.id,
1777         snippets: []
1778       };
1779       for (let item of snippets) {
1780         let p = import_path3.default.join(extension.extensionPath, item.path);
1781         let {language} = item;
1782         def.snippets.push({
1783           languageId: language,
1784           filepath: p
1785         });
1786       }
1787       if (snippets && snippets.length) {
1788         await this.loadSnippetsFromDefinition(def);
1789       }
1790     }
1791   }
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;
1804       });
1805     }));
1806   }
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))
1813         continue;
1814       let arr = await this.loadSnippetsFromFile(item.filepath);
1815       let exists = cache[languageId] || [];
1816       cache[languageId] = [...exists, ...arr];
1817     }
1818   }
1819   async loadSnippetsFromFile(snippetFilePath) {
1820     const contents = await new Promise((resolve, reject) => {
1821       import_fs3.default.readFile(snippetFilePath, "utf8", (err, data) => {
1822         if (err)
1823           return reject(err);
1824         resolve(data);
1825       });
1826     });
1827     const snippets = this.loadSnippetsFromText(snippetFilePath, contents);
1828     this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} textmate snippets from ${snippetFilePath}`);
1829     return snippets;
1830   }
1831   loadSnippetsFromText(filepath, contents) {
1832     let snippets = [];
1833     try {
1834       let errors = [];
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)}`);
1838       }
1839       if (snippetObject) {
1840         for (let key of Object.keys(snippetObject)) {
1841           snippets.push(snippetObject[key]);
1842         }
1843       }
1844     } catch (ex) {
1845       this.channel.appendLine(`[Error ${new Date().toLocaleDateString()}] ${ex.stack}`);
1846       snippets = [];
1847     }
1848     const normalizedSnippets = snippets.map((snip) => {
1849       let prefix = Array.isArray(snip.prefix) ? snip.prefix[0] : snip.prefix;
1850       return {
1851         filepath,
1852         lnum: 0,
1853         body: typeof snip.body === "string" ? snip.body : snip.body.join("\n"),
1854         prefix,
1855         description: typeof snip.description === "string" ? snip.description : typeof snip.description !== "undefined" ? snip.description.join("\n") : "",
1856         triggerKind: TriggerKind.WordBoundary
1857       };
1858     });
1859     return normalizedSnippets;
1860   }
1861 };
1862
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"));
1869
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;
1880     this.trace = trace;
1881   }
1882   parseUltisnipsFile(filepath) {
1883     const rl = import_readline2.default.createInterface({
1884       input: import_fs4.default.createReadStream(filepath, "utf8"),
1885       crlfDelay: Infinity
1886     });
1887     let pycodes = [];
1888     let snippets = [];
1889     let block;
1890     let preLines = [];
1891     let first;
1892     let priority = 0;
1893     let lnum = 0;
1894     let clearsnippets = null;
1895     let parsedContext = null;
1896     let extendFiletypes = [];
1897     rl.on("line", (line) => {
1898       lnum += 1;
1899       if (!block && (line.startsWith("#") || line.length == 0))
1900         return;
1901       const [head, tail] = headTail(line);
1902       if (!block) {
1903         switch (head) {
1904           case "priority":
1905             let n = parseInt(tail.trim(), 10);
1906             if (!isNaN(n))
1907               priority = n;
1908             break;
1909           case "extends":
1910             let fts = tail.trim().split(/,\s+/);
1911             for (let ft of fts) {
1912               if (extendFiletypes.indexOf(ft) == -1) {
1913                 extendFiletypes.push(ft);
1914               }
1915             }
1916             break;
1917           case "clearsnippets":
1918             clearsnippets = priority;
1919             break;
1920           case "context":
1921             parsedContext = tail.replace(/^"(.+)"$/, "$1");
1922             break;
1923           case "snippet":
1924           case "global":
1925             block = head;
1926             first = tail;
1927             break;
1928         }
1929         return;
1930       }
1931       if (head == "endglobal" && block == "global") {
1932         block = null;
1933         pycodes.push(...preLines);
1934         preLines = [];
1935         return;
1936       }
1937       if (head == "endsnippet" && block == "snippet") {
1938         block = null;
1939         try {
1940           let originRegex;
1941           let body = preLines.join("\n");
1942           body = body.replace(/((?:[^\\]?\$\{\w+?)\/)([^\n]*?[^\\])(?=\/)/g, (_match, p1, p2) => {
1943             return p1 + convertRegex(p2);
1944           });
1945           let ms = first.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?\s*$/);
1946           let prefix = ms[1];
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);
1952           }
1953           let isExpression = option.indexOf("r") !== -1;
1954           let regex2 = null;
1955           if (isExpression) {
1956             originRegex = prefix;
1957             prefix = convertRegex(prefix);
1958             prefix = prefix.endsWith("$") ? prefix : prefix + "$";
1959             try {
1960               regex2 = new RegExp(prefix);
1961               prefix = getRegexText(prefix);
1962             } catch (e) {
1963               this.error(`Convert regex error for: ${prefix}`);
1964             }
1965           }
1966           if (parsedContext) {
1967             context = parsedContext;
1968           } else if (option.indexOf("e") == -1) {
1969             context = null;
1970           }
1971           let snippet = {
1972             filepath,
1973             context,
1974             originRegex,
1975             autoTrigger: option.indexOf("A") !== -1,
1976             lnum: lnum - preLines.length - 2,
1977             triggerKind: getTriggerKind(option),
1978             prefix,
1979             description,
1980             regex: regex2,
1981             body,
1982             priority
1983           };
1984           snippets.push(snippet);
1985         } catch (e) {
1986           this.error(`Create snippet error on: ${filepath}:${lnum - preLines.length - 1} ${e.message}`);
1987         } finally {
1988           parsedContext = null;
1989           preLines = [];
1990         }
1991       }
1992       if (block == "snippet" || block == "global") {
1993         preLines.push(line);
1994         return;
1995       }
1996     });
1997     return new Promise((resolve) => {
1998       rl.on("close", async () => {
1999         resolve({snippets, clearsnippets, pythonCode: pycodes.join("\n"), extendFiletypes});
2000       });
2001     });
2002   }
2003   async resolveUltisnipsBody(body) {
2004     let {pyMethod} = this;
2005     let parser2 = new parser_default(body);
2006     let resolved = "";
2007     while (!parser2.eof()) {
2008       let p = parser2.prev();
2009       if (parser2.curr == "`" && (!p || p != "\\")) {
2010         let idx = parser2.nextIndex("`", true, false);
2011         if (idx == -1) {
2012           resolved = resolved + parser2.eatTo(parser2.len);
2013           break;
2014         }
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);
2019         continue;
2020       } else if (parser2.curr == "$") {
2021         let text = parser2.next(7);
2022         if (text.startsWith("VISUAL") || text.startsWith("{VISUAL")) {
2023           parser2.eat(8);
2024           resolved += "$" + text.replace("VISUAL", "TM_SELECTED_TEXT");
2025         } else if (!/^\d/.test(text) && !text.startsWith("{") && p != "\\") {
2026           resolved += "\\" + parser2.eat(1);
2027         } else {
2028           resolved += parser2.eat(1);
2029         }
2030       }
2031       let prev = parser2.prev() || "";
2032       parser2.iterate((ch) => {
2033         if (prev !== "\\" && (ch == "`" || ch == "$")) {
2034           return false;
2035         } else {
2036           resolved = resolved + ch;
2037         }
2038         prev = ch;
2039         return true;
2040       });
2041     }
2042     resolved = decode(resolved);
2043     this.debug(`resolved: ${resolved}`);
2044     return resolved;
2045   }
2046   async execute(code, pyMethod, indent) {
2047     let {nvim} = import_coc7.workspace;
2048     let res = "";
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*/, "");
2064         try {
2065           res = await nvim.eval(code);
2066         } catch (e) {
2067           res = `Error: ${e.message}`;
2068           this.error(e.stack);
2069         }
2070       }
2071     } else {
2072       try {
2073         res = await import_pify2.default(import_child_process.exec)(code);
2074       } catch (e) {
2075         res = `Error: ${e.message}`;
2076         this.error(`Error on eval ${code}: ` + e.stack);
2077       }
2078     }
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)
2085           return s;
2086         return `${indent}${s}`;
2087       }).join("\n");
2088     }
2089     return res;
2090   }
2091   error(str) {
2092     if (!this.channel)
2093       return;
2094     this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] ${str}`);
2095   }
2096   debug(str) {
2097     if (!this.channel || this.trace == "error")
2098       return;
2099     this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] ${str}`);
2100   }
2101 };
2102 var ultisnipsParser_default = UltiSnipsParser;
2103 function decode(str) {
2104   return str.replace(/\\`/g, "`").replace(/\\{/g, "{");
2105 }
2106 function getTriggerKind(option) {
2107   if (option.indexOf("w") !== -1) {
2108     return TriggerKind.WordBoundary;
2109   }
2110   if (option.indexOf("b") !== -1) {
2111     return TriggerKind.LineBegin;
2112   }
2113   if (option.indexOf("i") !== -1) {
2114     return TriggerKind.InWord;
2115   }
2116   return TriggerKind.SpaceBefore;
2117 }
2118
2119 // src/ultisnipsProvider.ts
2120 var pythonCodes = new Map();
2121 var UltiSnippetsProvider = class extends baseProvider_default {
2122   constructor(channel, trace, config, context) {
2123     super(config);
2124     this.channel = channel;
2125     this.trace = trace;
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();
2136       let items = [];
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);
2141           items.push(...res);
2142         }
2143       }
2144       if (items.length) {
2145         await Promise.all(items.map(({filepath, directory, filetype}) => {
2146           return this.loadSnippetsFromFile(filetype, directory, filepath);
2147         }));
2148         let files = items.map((o) => o.filepath);
2149         let pythonCode = "";
2150         for (let file of files) {
2151           let code = pythonCodes.get(file);
2152           if (code) {
2153             pythonCode += `# ${file}
2154 ` + code + "\n";
2155           }
2156         }
2157         if (pythonCode) {
2158           pythonCodes.clear();
2159           await this.executePythonCode(pythonCode);
2160         }
2161       }
2162     }, this.disposables);
2163   }
2164   checkLoaded(filepath) {
2165     return this.snippetFiles.findIndex((o) => o.filepath == filepath) !== -1;
2166   }
2167   async init() {
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);
2175       } else {
2176         this.directories.push(dir);
2177       }
2178     }
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";
2184     } else {
2185       this.pyMethod = config.pythonVersion == 3 ? "py3" : "py";
2186     }
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);
2193     }));
2194     for (let file of files) {
2195       let code = pythonCodes.get(file);
2196       if (code) {
2197         pythonCode += `
2198 # ${file}
2199 ` + code + "\n";
2200       }
2201     }
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"))
2206         return;
2207       let filepath = uri.fsPath;
2208       if (!import_fs5.default.existsSync(filepath))
2209         return;
2210       let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
2211       if (snippetFile) {
2212         await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
2213       } else {
2214         let filetype = import_path4.default.basename(filepath, ".snippets");
2215         await this.loadSnippetsFromFile(filetype, import_path4.default.dirname(filepath), filepath);
2216       }
2217     }, null, this.disposables);
2218   }
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);
2222     if (idx !== -1)
2223       this.snippetFiles.splice(idx, 1);
2224     this.snippetFiles.push({
2225       extendFiletypes,
2226       clearsnippets,
2227       directory,
2228       filepath,
2229       filetype,
2230       snippets
2231     });
2232     if (extendFiletypes) {
2233       let filetypes = this.config.extends[filetype] || [];
2234       filetypes = filetypes.concat(extendFiletypes);
2235       this.config.extends[filetype] = distinct(filetypes);
2236     }
2237     this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} UltiSnip snippets from: ${filepath}`);
2238     pythonCodes.set(filepath, pythonCode);
2239   }
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;
2250       let r;
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")) {
2259               val = "";
2260             } else {
2261               val = await this.parser.execute(code, this.pyMethod, ind);
2262             }
2263           }
2264           val = val.replace(/'/g, "\\'").replace(/\n/g, "\\n");
2265           values.set(idx, "r'" + val + "'");
2266         }
2267       }
2268       re = /\$(\d+)/g;
2269       while (r = re.exec(body)) {
2270         let idx = parseInt(r[1], 10);
2271         if (!values.has(idx)) {
2272           values.set(idx, "''");
2273         }
2274       }
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()) {
2278         vals[idx] = val;
2279       }
2280       let pyCodes = [];
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}'`);
2285       if (context) {
2286         pyCodes.push(`snip = ContextSnippet()`);
2287         pyCodes.push(`context = ${context}`);
2288       } else {
2289         pyCodes.push(`context = {}`);
2290       }
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)`);
2294       if (originRegex) {
2295         pyCodes.push(`pattern = re.compile(r"${originRegex.replace(/"/g, '\\"')}")`);
2296         pyCodes.push(`match = pattern.search("${line.replace(/"/g, '\\"')}")`);
2297       }
2298       try {
2299         await nvim.command(`${this.pyMethod} ${pyCodes.join("\n")}`);
2300       } catch (e) {
2301         this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}]: ${e.message}`);
2302         this.channel.appendLine(`code: ${pyCodes.join("\n")}`);
2303       }
2304     }
2305     return this.parser.resolveUltisnipsBody(body);
2306   }
2307   async checkContext(context) {
2308     let {nvim} = import_coc8.workspace;
2309     let pyCodes = [];
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");
2315     return res;
2316   }
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] == " ")
2322       return [];
2323     snippets = snippets.filter((s) => {
2324       let {prefix, regex: regex2} = s;
2325       if (autoTrigger && !s.autoTrigger)
2326         return false;
2327       if (regex2) {
2328         let ms = line.match(regex2);
2329         if (!ms)
2330           return false;
2331         prefix = ms[0];
2332       }
2333       if (!line.endsWith(prefix))
2334         return false;
2335       if (s.triggerKind == TriggerKind.InWord)
2336         return true;
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]);
2344       return false;
2345     });
2346     snippets.sort((a, b) => {
2347       if (a.context && !b.context)
2348         return -1;
2349       if (b.context && !a.context)
2350         return 1;
2351       return 0;
2352     });
2353     let edits = [];
2354     let contextPrefixes = [];
2355     for (let s of snippets) {
2356       let character;
2357       if (s.context) {
2358         let valid = await this.checkContext(s.context);
2359         if (!valid)
2360           continue;
2361         contextPrefixes.push(s.context);
2362       } else if (contextPrefixes.indexOf(s.prefix) !== -1) {
2363         continue;
2364       }
2365       if (s.regex == null) {
2366         character = position.character - s.prefix.length;
2367       } else {
2368         let len = line.match(s.regex)[0].length;
2369         character = position.character - len;
2370       }
2371       let range = import_coc9.Range.create(position.line, character, position.line, position.character);
2372       let newText = await this.resolveSnippetBody(s, range, line);
2373       edits.push({
2374         prefix: s.prefix,
2375         description: s.description,
2376         location: s.filepath,
2377         priority: s.priority,
2378         range,
2379         newText
2380       });
2381     }
2382     return edits;
2383   }
2384   async getSnippetFiles(filetype) {
2385     let filetypes = this.getFiletypes(filetype);
2386     let res = [];
2387     for (let s of this.snippetFiles) {
2388       if (filetypes.indexOf(s.filetype) !== -1) {
2389         res.push(s.filepath);
2390       }
2391     }
2392     return res;
2393   }
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);
2398     let min = null;
2399     let result = [];
2400     snippetFiles.sort((a, b) => {
2401       if (a.filetype == b.filetype)
2402         return 1;
2403       if (a.filetype == filetype)
2404         return -1;
2405       return 1;
2406     });
2407     for (let file of snippetFiles) {
2408       let {snippets, clearsnippets} = file;
2409       if (typeof clearsnippets == "number") {
2410         min = min ? Math.max(min, clearsnippets) : clearsnippets;
2411       }
2412       for (let snip of snippets) {
2413         if (snip.regex || snip.context) {
2414           result.push(snip);
2415         } else {
2416           let idx = result.findIndex((o) => o.prefix == snip.prefix && o.triggerKind == snip.triggerKind);
2417           if (idx == -1) {
2418             result.push(snip);
2419           } else {
2420             let item = result[idx];
2421             if (snip.priority > item.priority) {
2422               result[idx] = item;
2423             }
2424           }
2425         }
2426       }
2427     }
2428     if (min != null)
2429       result = result.filter((o) => o.priority >= min);
2430     result.sort((a, b) => {
2431       if (a.context && !b.context)
2432         return -1;
2433       if (b.context && !a.context)
2434         return 1;
2435       return 0;
2436     });
2437     return result;
2438   }
2439   async getAllSnippetFiles(runtimepath) {
2440     let {directories} = this;
2441     let res = [];
2442     for (let directory of directories) {
2443       if (import_path4.default.isAbsolute(directory)) {
2444         let items = await this.getSnippetFileItems(directory);
2445         res.push(...items);
2446       }
2447     }
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);
2453       res.push(...items);
2454     }
2455     return res;
2456   }
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);
2464       }
2465     }
2466     return directories;
2467   }
2468   async getSnippetsFromPlugin(directory, subFolders) {
2469     let res = [];
2470     for (let folder of subFolders) {
2471       let items = await this.getSnippetFileItems(import_path4.default.join(directory, folder));
2472       res.push(...items);
2473     }
2474     return res;
2475   }
2476   async getSnippetFileItems(directory) {
2477     let res = [];
2478     let stat = await statAsync(directory);
2479     if (stat && stat.isDirectory()) {
2480       let files = await readdirAsync(directory);
2481       if (files.length) {
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});
2488           } else {
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});
2495                 }
2496               }
2497             }
2498           }
2499         }
2500       }
2501     }
2502     return res;
2503   }
2504   async executePythonCode(pythonCode) {
2505     try {
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();
2513     } catch (e) {
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");
2517     }
2518   }
2519   dispose() {
2520     import_coc8.disposeAll(this.disposables);
2521   }
2522 };
2523
2524 // src/index.ts
2525 var documentation = `# A valid snippet should starts with:
2526 #
2527 #               snippet trigger_word [ "description" [ options ] ]
2528 #
2529 # and end with:
2530 #
2531 #               endsnippet
2532 #
2533 # Snippet options:
2534 #
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.
2541 #
2542 # Basic example:
2543 #
2544 #               snippet emitter "emitter properties" b
2545 #               private readonly \${1} = new Emitter<$2>()
2546 #               public readonly \${1/^_(.*)/$1/}: Event<$2> = this.$1.event
2547 #               endsnippet
2548 #
2549 # Online reference: https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt
2550 `;
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");
2561   if (snippetsDir) {
2562     snippetsDir = snippetsDir.replace(/^~/, import_os4.default.homedir());
2563     if (snippetsDir.indexOf("$") !== -1) {
2564       snippetsDir = snippetsDir.replace(/\$(\w+)/g, (match, p1) => {
2565         var _a;
2566         return (_a = process.env[p1]) != null ? _a : match;
2567       });
2568     }
2569     if (!import_path5.default.isAbsolute(snippetsDir)) {
2570       import_coc10.window.showMessage(`snippets.userSnippetsDirectory => ${snippetsDir} should be absolute path`, "warning");
2571       snippetsDir = null;
2572     }
2573   }
2574   if (!snippetsDir)
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);
2578   }
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);
2582     }
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);
2587       if (!doc)
2588         return;
2589       let {buffer} = doc;
2590       await buffer.setOption("filetype", "snippets");
2591     }
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)
2597     });
2598     c.directories = c.directories ? c.directories.slice() : [];
2599     if (c.directories.indexOf(snippetsDir) == -1) {
2600       c.directories.push(snippetsDir);
2601     }
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)));
2608       if (idx !== -1)
2609         return;
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);
2616         }
2617       });
2618     }, (_e) => {
2619     });
2620   }
2621   let config = {
2622     loadFromExtensions: configuration.get("loadFromExtensions", true),
2623     snippetsRoots: configuration.get("textmateSnippetsRoots", []),
2624     extends: Object.assign({}, filetypeExtends)
2625   };
2626   let provider = new TextmateProvider(channel, trace, config);
2627   manager.regist(provider, "snippets");
2628   if (configuration.get("snipmate.enable", true)) {
2629     let config2 = {
2630       author: configuration.get("snipmate.author", ""),
2631       extends: Object.assign({}, filetypeExtends)
2632     };
2633     let provider2 = new SnipmateProvider(channel, trace, config2);
2634     manager.regist(provider2, "snipmate");
2635   }
2636   if (configuration.get("autoTrigger", true)) {
2637     let insertTs;
2638     let insertLeaveTs;
2639     let lastInsert;
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;
2650       insertTs = void 0;
2651       if (inserting)
2652         return;
2653       let doc = import_coc10.workspace.getDocument(bufnr);
2654       if (!doc || doc.isCommandLine || !doc.attached)
2655         return;
2656       let now = Date.now();
2657       if (!lastInsertTs || now - lastInsertTs > 100 || !pre.endsWith(lastInsert))
2658         return;
2659       let edits = await manager.getTriggerSnippets(true);
2660       if (edits.length == 0)
2661         return;
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");
2665       }
2666       if (insertLeaveTs > now || inserting)
2667         return;
2668       inserting = true;
2669       try {
2670         await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2671         await mru.add(edits[0].prefix);
2672       } catch (e) {
2673         console.error(e);
2674       }
2675       inserting = false;
2676     };
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);
2683   }
2684   let statusItem;
2685   if (configuration.get("enableStatusItem", true)) {
2686     statusItem = import_coc10.window.createStatusBarItem(90, {progress: true});
2687     statusItem.text = "loading snippets";
2688     statusItem.show();
2689   }
2690   manager.init().then(() => {
2691     statusItem == null ? void 0 : statusItem.hide();
2692   }, (e) => {
2693     statusItem == null ? void 0 : statusItem.hide();
2694     import_coc10.window.showMessage(`Error on load snippets: ${e.message}`, "error");
2695   });
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);
2699   }
2700   async function fallback() {
2701     await nvim.call("coc#start", [{source: "snippets"}]);
2702   }
2703   async function doExpand() {
2704     let edits = await manager.getTriggerSnippets();
2705     if (edits.length == 0)
2706       return false;
2707     if (edits.length == 1) {
2708       await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2709       await mru.add(edits[0].prefix);
2710     } else {
2711       let idx = await import_coc10.window.showQuickpick(edits.map((e) => e.description || e.prefix), "choose snippet:");
2712       if (idx == -1)
2713         return;
2714       await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[idx]);
2715       await mru.add(edits[idx].prefix);
2716     }
2717     return true;
2718   }
2719   subscriptions.push(import_coc10.workspace.registerKeymap(["x"], "convert-snippet", async () => {
2720     let mode = await import_coc10.workspace.nvim.call("visualmode");
2721     if (!mode)
2722       return;
2723     let doc = await import_coc10.workspace.document;
2724     if (!doc)
2725       return;
2726     doc.forceSync();
2727     let range = await import_coc10.workspace.getSelectedRange(mode, doc);
2728     let text = doc.textDocument.getText(range);
2729     if (text)
2730       await import_coc10.commands.executeCommand("snippets.editSnippets", text);
2731   }, {sync: false}));
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);
2735     if (!doc) {
2736       import_coc10.window.showMessage("Document not found", "error");
2737       return;
2738     }
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");
2742     }
2743     let uri = import_coc10.Uri.file(file).toString();
2744     await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2745     if (text) {
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);
2755     }
2756   }));
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);
2760     if (!doc) {
2761       import_coc10.window.showMessage("Document not found", "error");
2762       return;
2763     }
2764     let files = await manager.getSnippetFiles(doc.filetype);
2765     if (!files.length) {
2766       import_coc10.window.showMessage("No related snippet file found", "warning");
2767       return;
2768     }
2769     let idx = await import_coc10.window.showQuickpick(files, "choose snippet file:");
2770     if (idx == -1)
2771       return;
2772     let uri = import_coc10.Uri.file(files[idx]).toString();
2773     await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2774   }));
2775   subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand", async () => {
2776     let expanded = await doExpand();
2777     if (!expanded)
2778       await fallback();
2779   }, {silent: true, sync: false, cancel: true}));
2780   subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand-jump", async () => {
2781     let expanded = await doExpand();
2782     if (!expanded) {
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();
2788         return;
2789       }
2790       await fallback();
2791     }
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;
2795     if (!doc)
2796       return;
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");
2800       return;
2801     }
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"]);
2810     if (mode == "v") {
2811       await doc.applyEdits([{range, newText: ""}]);
2812     } else {
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: ""}]);
2820     }
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)));
2829   return {
2830     expandable: async () => {
2831       let edits;
2832       try {
2833         edits = await manager.getTriggerSnippets();
2834       } catch (e) {
2835         channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on getTriggerSnippets: ${e}`);
2836       }
2837       return edits && edits.length > 0;
2838     }
2839   };
2840 }
2841 //# sourceMappingURL=index.js.map