massive update, probably broken
[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(channel) {
449     this.channel = channel;
450     this.providers = new Map();
451   }
452   regist(provider, name) {
453     this.providers.set(name, provider);
454     return import_coc3.Disposable.create(() => {
455       this.providers.delete(name);
456     });
457   }
458   get hasProvider() {
459     return this.providers.size > 0;
460   }
461   async init() {
462     let providers = Array.from(this.providers.values());
463     await Promise.all(providers.map((provider) => {
464       return provider.init();
465     })).catch((e) => {
466       this.appendError("init", e);
467     });
468   }
469   async getSnippets(filetype) {
470     let names = Array.from(this.providers.keys());
471     let list = [];
472     for (let name of names) {
473       let provider = this.providers.get(name);
474       try {
475         let snippets = await provider.getSnippets(filetype);
476         snippets.map((s) => s.provider = name);
477         list.push(...snippets);
478       } catch (e) {
479         this.appendError(`getSnippets of ${name}`, e);
480       }
481     }
482     return list;
483   }
484   async getSnippetFiles(filetype) {
485     let files = [];
486     for (let [name, provider] of this.providers.entries()) {
487       try {
488         let res = await provider.getSnippetFiles(filetype);
489         files = files.concat(res);
490       } catch (e) {
491         this.appendError(`getSnippetFiles of ${name}`, e);
492       }
493     }
494     return files;
495   }
496   async getTriggerSnippets(bufnr, autoTrigger = false) {
497     let doc = import_coc3.workspace.getDocument(bufnr);
498     if (!doc)
499       return [];
500     let position = await import_coc3.window.getCursorPosition();
501     let names = Array.from(this.providers.keys());
502     let list = [];
503     for (let name of names) {
504       let provider = this.providers.get(name);
505       try {
506         let items = await provider.getTriggerSnippets(doc, position, autoTrigger);
507         for (let item of items) {
508           if (list.findIndex((o) => o.prefix == item.prefix) == -1) {
509             list.push(item);
510           }
511         }
512       } catch (e) {
513         this.appendError(`getTriggerSnippets of ${name}`, e);
514       }
515     }
516     list.sort((a, b) => b.priority - a.priority);
517     if (list.length > 1 && list[0].priority > 0) {
518       list = list.filter((o) => o.priority > 0);
519     }
520     return list;
521   }
522   appendError(name, e) {
523     this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on ${name}: ${typeof e === "string" ? e : e.message}`);
524     if (e instanceof Error) {
525       this.channel.appendLine(e.stack);
526     }
527   }
528   async provideCompletionItems(document, position, _token, context) {
529     let doc = import_coc3.workspace.getDocument(document.uri);
530     if (!doc)
531       return [];
532     let snippets = await this.getSnippets(doc.filetype);
533     let currline = doc.getline(position.line, true);
534     let {input, col} = context.option;
535     let character = characterIndex(currline, col);
536     let before_content = currline.slice(0, character);
537     let res = [];
538     let contextPrefixes = [];
539     for (let snip of snippets) {
540       let contentBehind = before_content;
541       if (contextPrefixes.indexOf(snip.prefix) !== -1)
542         continue;
543       if (snip.regex != null && snip.prefix == "")
544         continue;
545       if (snip.context) {
546         let provider = this.providers.get(snip.provider);
547         let valid;
548         try {
549           valid = await provider.checkContext(snip.context);
550         } catch (e) {
551           this.appendError(`checkContext of ${snip.provider}`, e);
552           valid = false;
553         }
554         if (!valid)
555           continue;
556         contextPrefixes.push(snip.prefix);
557       }
558       let head = this.getPrefixHead(doc, snip.prefix);
559       if (input.length == 0 && !before_content.endsWith(snip.prefix))
560         continue;
561       let item = {
562         label: snip.prefix,
563         kind: import_coc3.CompletionItemKind.Snippet,
564         filterText: snip.prefix,
565         detail: snip.description,
566         insertTextFormat: import_coc3.InsertTextFormat.Snippet
567       };
568       item.data = {
569         snip,
570         provider: snip.provider,
571         filepath: `${import_path.default.basename(snip.filepath)}:${snip.lnum}`
572       };
573       if (snip.regex) {
574         if (!input.length || snip.prefix && input[0] != snip.prefix[0])
575           continue;
576         let content = before_content + snip.prefix;
577         let ms = content.match(snip.regex);
578         if (!ms)
579           continue;
580       } else if (head && before_content.endsWith(head)) {
581         contentBehind = before_content.slice(0, -head.length);
582         let prefix = snip.prefix.slice(head.length);
583         Object.assign(item, {
584           textEdit: {
585             range: import_coc3.Range.create({line: position.line, character: character - head.length}, position),
586             newText: prefix
587           }
588         });
589       } else if (input.length == 0) {
590         let {prefix} = snip;
591         contentBehind = before_content.slice(0, -prefix.length);
592         Object.assign(item, {
593           preselect: true,
594           textEdit: {
595             range: import_coc3.Range.create({line: position.line, character: character - prefix.length}, position),
596             newText: prefix
597           }
598         });
599       }
600       if (snip.triggerKind == TriggerKind.LineBegin && contentBehind.trim().length)
601         continue;
602       if (snip.triggerKind == TriggerKind.SpaceBefore) {
603         if (contentBehind.length && !/\s/.test(contentBehind[contentBehind.length - 1])) {
604           continue;
605         }
606       }
607       if (!item.textEdit) {
608         item.textEdit = {
609           range: import_coc3.Range.create({line: position.line, character}, position),
610           newText: item.label
611         };
612       }
613       item.data.location = `${snip.filepath}:${snip.lnum}`;
614       item.data.line = contentBehind + snip.prefix;
615       res.push(item);
616     }
617     return res;
618   }
619   async resolveCompletionItem(item) {
620     let provider = this.providers.get(item.data.provider);
621     if (provider) {
622       let filetype = await import_coc3.workspace.nvim.eval("&filetype");
623       let insertSnippet;
624       try {
625         insertSnippet = await provider.resolveSnippetBody(item.data.snip, item.textEdit.range, item.data.line);
626       } catch (e) {
627         this.appendError(`resolveSnippetBody of ${item.data.provider}`, e);
628         return item;
629       }
630       item.textEdit.newText = insertSnippet;
631       if (import_coc3.snippetManager) {
632         let snip = await Promise.resolve(import_coc3.snippetManager.resolveSnippet(insertSnippet));
633         item.documentation = {
634           kind: "markdown",
635           value: markdownBlock(snip.toString(), filetype.match(/^\w+/)[0])
636         };
637       }
638     }
639     return item;
640   }
641   getPrefixHead(doc, prefix) {
642     let res = 0;
643     for (let idx = prefix.length - 1; idx >= 0; idx--) {
644       if (!doc.isWord(prefix[idx])) {
645         res = idx;
646         break;
647       }
648     }
649     return res == 0 ? "" : prefix.slice(0, res + 1);
650   }
651 };
652 function characterIndex(content, byteIndex) {
653   let buf = Buffer.from(content, "utf8");
654   return buf.slice(0, byteIndex).toString("utf8").length;
655 }
656
657 // src/snipmateProvider.ts
658 var import_coc5 = __toModule(require("coc.nvim"));
659 var import_fs2 = __toModule(require("fs"));
660 var import_path2 = __toModule(require("path"));
661 var import_readline = __toModule(require("readline"));
662
663 // src/baseProvider.ts
664 var import_coc4 = __toModule(require("coc.nvim"));
665 var BaseProvider = class {
666   constructor(config) {
667     this.config = config;
668   }
669   async checkContext(_context) {
670     return true;
671   }
672   getExtendsFiletypes(filetype, exists = new Set()) {
673     if (exists.has(filetype))
674       return [];
675     let extend = this.config.extends ? this.config.extends[filetype] : null;
676     exists.add(filetype);
677     if (!extend || extend.length == 0)
678       return [];
679     return extend.reduce((arr, curr) => {
680       return arr.concat([curr], this.getExtendsFiletypes(curr, exists));
681     }, []);
682   }
683   getFiletypes(filetype) {
684     let filetypes = [filetype];
685     if (filetype.indexOf(".") !== -1) {
686       filetypes.push(...filetype.split("."));
687     }
688     if (filetype == "javascript.jsx")
689       filetypes.push("javascriptreact");
690     if (filetype == "typescript.jsx" || filetype == "typescript.tsx")
691       filetypes.push("typescriptreact");
692     let map = import_coc4.workspace.env.filetypeMap;
693     if (map && map[filetype]) {
694       filetypes.push(map[filetype]);
695     }
696     if (filetype == "javascriptreact" && !filetypes.includes("javascript")) {
697       filetypes.push("javascript");
698     }
699     if (filetype == "typescriptreact" && !filetypes.includes("typescript")) {
700       filetypes.push("typescript");
701     }
702     let extendFiletypes = filetypes.reduce((arr, curr) => {
703       return arr.concat(this.getExtendsFiletypes(curr));
704     }, []);
705     filetypes.push(...extendFiletypes);
706     filetypes.reverse();
707     return distinct(filetypes);
708   }
709 };
710 var baseProvider_default = BaseProvider;
711
712 // src/parser.ts
713 var Parser = class {
714   constructor(_content) {
715     this._content = _content;
716     this._curr = 0;
717   }
718   eof() {
719     return this._curr >= this._content.length;
720   }
721   skipSpaces() {
722     for (let i = this._curr; i <= this._content.length; i++) {
723       let ch = this._content[i];
724       if (!ch || /\S/.test(ch)) {
725         this._curr = i;
726         break;
727       }
728     }
729   }
730   get index() {
731     return this._curr;
732   }
733   get curr() {
734     return this._content[this._curr] || "";
735   }
736   get len() {
737     return this._content.length;
738   }
739   next(count = 1) {
740     return this._content.slice(this._curr + 1, this._curr + 1 + count);
741   }
742   nextIndex(character, checkEscape = true, allowEnd = true) {
743     if (this._curr >= this.len - 1)
744       return allowEnd ? this.len - 1 : -1;
745     let i = this._curr + 1;
746     let pre = this.curr || "";
747     while (i != this.len - 1) {
748       let ch = this._content[i];
749       if (ch == character && (!checkEscape || pre !== "\\")) {
750         break;
751       }
752       pre = ch;
753       i = i + 1;
754     }
755     if (!allowEnd && i == this.len - 1 && character != this._content[i]) {
756       return -1;
757     }
758     return i;
759   }
760   prev() {
761     return this._content[this._curr - 1] || "";
762   }
763   iterate(fn) {
764     while (this._curr < this._content.length) {
765       let fine = fn(this.curr, this._curr);
766       if (fine === false) {
767         break;
768       }
769       this._curr = this._curr + 1;
770     }
771   }
772   eat(count) {
773     let end = this._curr + count;
774     end = Math.min(end, this.len);
775     let str = this._content.slice(this._curr, end);
776     this._curr = end;
777     return str;
778   }
779   eatTo(index) {
780     if (index == this._curr)
781       return "";
782     let str = this._content.slice(this._curr, index);
783     this._curr = index;
784     return str;
785   }
786 };
787 var parser_default = Parser;
788
789 // src/snipmateProvider.ts
790 var SnipmateProvider = class extends baseProvider_default {
791   constructor(channel, trace, config) {
792     super(config);
793     this.channel = channel;
794     this.trace = trace;
795     this.snippetFiles = [];
796     this.disposables = [];
797     import_coc5.workspace.onDidSaveTextDocument(async (doc) => {
798       let uri = import_coc5.Uri.parse(doc.uri);
799       if (uri.scheme != "file")
800         return;
801       let filepath = uri.fsPath;
802       if (!import_fs2.default.existsSync(filepath))
803         return;
804       let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
805       if (snippetFile)
806         await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
807     }, null, this.disposables);
808   }
809   async init() {
810     let arr = await this.getAllSnippetFiles();
811     let {nvim} = import_coc5.workspace;
812     let author = await nvim.getVar("snips_author");
813     if (!author)
814       await nvim.setVar("snips_author", this.config.author);
815     await Promise.all(arr.map(({filepath, directory, filetype}) => {
816       return this.loadSnippetsFromFile(filetype, directory, filepath);
817     }));
818   }
819   async loadSnippetsFromFile(filetype, directory, filepath) {
820     let snippets = await this.parseSnippetsFile(filepath);
821     let idx = this.snippetFiles.findIndex((o) => o.filepath == filepath);
822     if (idx !== -1)
823       this.snippetFiles.splice(idx, 1);
824     this.snippetFiles.push({
825       directory,
826       filepath,
827       filetype,
828       snippets
829     });
830     this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} snipmate snippets from: ${filepath}`);
831   }
832   async resolveSnippetBody(snippet, _range, _line) {
833     let parser2 = new parser_default(snippet.body);
834     let resolved = "";
835     let {nvim} = import_coc5.workspace;
836     while (!parser2.eof()) {
837       if (parser2.curr == "`") {
838         let idx = parser2.nextIndex("`", true, false);
839         if (idx == -1) {
840           resolved = resolved + parser2.eatTo(parser2.len);
841           break;
842         }
843         let code = parser2.eatTo(idx + 1);
844         code = code.slice(1, -1);
845         if (code.startsWith("Filename")) {
846           resolved = resolved + await nvim.call("expand", "%:p:t");
847         } else {
848           try {
849             resolved = resolved + await nvim.eval(code);
850           } catch (e) {
851             this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on eval: ${code}`);
852           }
853         }
854         continue;
855       }
856       parser2.iterate((ch) => {
857         if (ch == "`") {
858           return false;
859         } else {
860           resolved = resolved + ch;
861         }
862         return true;
863       });
864     }
865     return resolved;
866   }
867   parseSnippetsFile(filepath) {
868     let res = [];
869     const rl = import_readline.default.createInterface({
870       input: import_fs2.default.createReadStream(filepath, "utf8"),
871       crlfDelay: Infinity
872     });
873     let lnum = 0;
874     let lines = [];
875     let prefix = "";
876     let description = "";
877     rl.on("line", (line) => {
878       lnum += 1;
879       if (line.startsWith("#"))
880         return;
881       if (line.startsWith("snippet")) {
882         line = line.replace(/\s*$/, "");
883         if (lines.length && prefix) {
884           res.push({
885             filepath,
886             lnum: lnum - lines.length - 1,
887             body: lines.join("\n").replace(/\s+$/, ""),
888             prefix,
889             description,
890             triggerKind: TriggerKind.SpaceBefore
891           });
892           lines = [];
893         }
894         let ms = line.match(/^snippet\s+(\S+)(?:\s(.+))?$/);
895         if (!ms) {
896           prefix = "";
897           this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Broken line on ${filepath}:${lnum}`);
898           return;
899         }
900         prefix = ms[1];
901         description = ms[2] || "";
902         return;
903       }
904       if (prefix) {
905         if (line.indexOf("VISUAL") !== -1) {
906           line = line.replace(/\$(\{?)VISUAL\b(:[^\}])?(\}?)/g, "$$$1TM_SELECTED_TEXT$2$3");
907         }
908         if (line.startsWith("   ")) {
909           lines.push(line.slice(1));
910         } else {
911           lines.push(line);
912         }
913       }
914     });
915     return new Promise((resolve) => {
916       rl.on("close", async () => {
917         if (lines.length) {
918           res.push({
919             filepath,
920             lnum: lnum - lines.length - 1,
921             body: lines.join("\n"),
922             prefix,
923             description,
924             triggerKind: TriggerKind.SpaceBefore
925           });
926         }
927         resolve(res);
928       });
929     });
930   }
931   async getTriggerSnippets(document, position, autoTrigger) {
932     if (autoTrigger)
933       return [];
934     let snippets = await this.getSnippets(document.filetype);
935     let line = document.getline(position.line);
936     line = line.slice(0, position.character);
937     if (!line || line[line.length - 1] == " ")
938       return [];
939     snippets = snippets.filter((s) => {
940       let {prefix} = s;
941       if (!line.endsWith(prefix))
942         return false;
943       let pre = line.slice(0, line.length - prefix.length);
944       return pre.length == 0 || /\s/.test(pre[pre.length - 1]);
945     });
946     let edits = [];
947     for (let s of snippets) {
948       let character = position.character - s.prefix.length;
949       let range = import_coc5.Range.create(position.line, character, position.line, position.character);
950       let newText = await this.resolveSnippetBody(s, range, line);
951       edits.push({
952         prefix: s.prefix,
953         description: s.description,
954         location: s.filepath,
955         range,
956         newText,
957         priority: -1
958       });
959     }
960     return edits;
961   }
962   async getSnippetFiles(filetype) {
963     let filetypes = this.getFiletypes(filetype);
964     let res = [];
965     for (let s of this.snippetFiles) {
966       if (filetypes.indexOf(s.filetype) !== -1) {
967         res.push(s.filepath);
968       }
969     }
970     return res;
971   }
972   async getSnippets(filetype) {
973     let filetypes = this.getFiletypes(filetype);
974     filetypes.push("_");
975     let snippetFiles = this.snippetFiles.filter((o) => filetypes.indexOf(o.filetype) !== -1);
976     let result = [];
977     snippetFiles.sort((a, b) => {
978       if (a.filetype == b.filetype)
979         return 1;
980       if (a.filetype == filetype)
981         return -1;
982       return 1;
983     });
984     for (let file of snippetFiles) {
985       let {snippets} = file;
986       for (let snip of snippets) {
987         result.push(snip);
988       }
989     }
990     return result;
991   }
992   async getAllSnippetFiles() {
993     let {nvim} = import_coc5.workspace;
994     let opt = await nvim.eval("&rtp");
995     let rtps = opt.split(",");
996     let res = [];
997     for (let rtp of rtps) {
998       let items = await this.getSnippetFileItems(import_path2.default.join(rtp, "snippets"));
999       res.push(...items);
1000     }
1001     return res;
1002   }
1003   async getSnippetFileItems(directory) {
1004     let res = [];
1005     let stat = await statAsync(directory);
1006     if (stat && stat.isDirectory()) {
1007       let files = await readdirAsync(directory);
1008       if (files.length) {
1009         for (let f of files) {
1010           let file = import_path2.default.join(directory, f);
1011           if (file.endsWith(".snippets")) {
1012             let basename = import_path2.default.basename(f, ".snippets");
1013             let filetype = basename.split("-", 2)[0];
1014             res.push({filepath: file, directory, filetype});
1015           } else {
1016             let stat2 = await statAsync(file);
1017             if (stat2 && stat2.isDirectory()) {
1018               let files2 = await readdirAsync(file);
1019               for (let filename of files2) {
1020                 if (filename.endsWith(".snippets")) {
1021                   res.push({filepath: import_path2.default.join(file, filename), directory, filetype: f});
1022                 }
1023               }
1024             }
1025           }
1026         }
1027       }
1028     }
1029     return res;
1030   }
1031 };
1032
1033 // src/textmateProvider.ts
1034 var import_coc6 = __toModule(require("coc.nvim"));
1035 var import_fs3 = __toModule(require("fs"));
1036
1037 // node_modules/jsonc-parser/lib/esm/impl/scanner.js
1038 "use strict";
1039 function createScanner(text, ignoreTrivia) {
1040   if (ignoreTrivia === void 0) {
1041     ignoreTrivia = false;
1042   }
1043   var len = text.length;
1044   var pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
1045   function scanHexDigits(count, exact) {
1046     var digits = 0;
1047     var value2 = 0;
1048     while (digits < count || !exact) {
1049       var ch = text.charCodeAt(pos);
1050       if (ch >= 48 && ch <= 57) {
1051         value2 = value2 * 16 + ch - 48;
1052       } else if (ch >= 65 && ch <= 70) {
1053         value2 = value2 * 16 + ch - 65 + 10;
1054       } else if (ch >= 97 && ch <= 102) {
1055         value2 = value2 * 16 + ch - 97 + 10;
1056       } else {
1057         break;
1058       }
1059       pos++;
1060       digits++;
1061     }
1062     if (digits < count) {
1063       value2 = -1;
1064     }
1065     return value2;
1066   }
1067   function setPosition(newPosition) {
1068     pos = newPosition;
1069     value = "";
1070     tokenOffset = 0;
1071     token = 16;
1072     scanError = 0;
1073   }
1074   function scanNumber() {
1075     var start = pos;
1076     if (text.charCodeAt(pos) === 48) {
1077       pos++;
1078     } else {
1079       pos++;
1080       while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1081         pos++;
1082       }
1083     }
1084     if (pos < text.length && text.charCodeAt(pos) === 46) {
1085       pos++;
1086       if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1087         pos++;
1088         while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1089           pos++;
1090         }
1091       } else {
1092         scanError = 3;
1093         return text.substring(start, pos);
1094       }
1095     }
1096     var end = pos;
1097     if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
1098       pos++;
1099       if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
1100         pos++;
1101       }
1102       if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1103         pos++;
1104         while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1105           pos++;
1106         }
1107         end = pos;
1108       } else {
1109         scanError = 3;
1110       }
1111     }
1112     return text.substring(start, end);
1113   }
1114   function scanString() {
1115     var result = "", start = pos;
1116     while (true) {
1117       if (pos >= len) {
1118         result += text.substring(start, pos);
1119         scanError = 2;
1120         break;
1121       }
1122       var ch = text.charCodeAt(pos);
1123       if (ch === 34) {
1124         result += text.substring(start, pos);
1125         pos++;
1126         break;
1127       }
1128       if (ch === 92) {
1129         result += text.substring(start, pos);
1130         pos++;
1131         if (pos >= len) {
1132           scanError = 2;
1133           break;
1134         }
1135         var ch2 = text.charCodeAt(pos++);
1136         switch (ch2) {
1137           case 34:
1138             result += '"';
1139             break;
1140           case 92:
1141             result += "\\";
1142             break;
1143           case 47:
1144             result += "/";
1145             break;
1146           case 98:
1147             result += "\b";
1148             break;
1149           case 102:
1150             result += "\f";
1151             break;
1152           case 110:
1153             result += "\n";
1154             break;
1155           case 114:
1156             result += "\r";
1157             break;
1158           case 116:
1159             result += " ";
1160             break;
1161           case 117:
1162             var ch3 = scanHexDigits(4, true);
1163             if (ch3 >= 0) {
1164               result += String.fromCharCode(ch3);
1165             } else {
1166               scanError = 4;
1167             }
1168             break;
1169           default:
1170             scanError = 5;
1171         }
1172         start = pos;
1173         continue;
1174       }
1175       if (ch >= 0 && ch <= 31) {
1176         if (isLineBreak(ch)) {
1177           result += text.substring(start, pos);
1178           scanError = 2;
1179           break;
1180         } else {
1181           scanError = 6;
1182         }
1183       }
1184       pos++;
1185     }
1186     return result;
1187   }
1188   function scanNext() {
1189     value = "";
1190     scanError = 0;
1191     tokenOffset = pos;
1192     lineStartOffset = lineNumber;
1193     prevTokenLineStartOffset = tokenLineStartOffset;
1194     if (pos >= len) {
1195       tokenOffset = len;
1196       return token = 17;
1197     }
1198     var code = text.charCodeAt(pos);
1199     if (isWhiteSpace(code)) {
1200       do {
1201         pos++;
1202         value += String.fromCharCode(code);
1203         code = text.charCodeAt(pos);
1204       } while (isWhiteSpace(code));
1205       return token = 15;
1206     }
1207     if (isLineBreak(code)) {
1208       pos++;
1209       value += String.fromCharCode(code);
1210       if (code === 13 && text.charCodeAt(pos) === 10) {
1211         pos++;
1212         value += "\n";
1213       }
1214       lineNumber++;
1215       tokenLineStartOffset = pos;
1216       return token = 14;
1217     }
1218     switch (code) {
1219       case 123:
1220         pos++;
1221         return token = 1;
1222       case 125:
1223         pos++;
1224         return token = 2;
1225       case 91:
1226         pos++;
1227         return token = 3;
1228       case 93:
1229         pos++;
1230         return token = 4;
1231       case 58:
1232         pos++;
1233         return token = 6;
1234       case 44:
1235         pos++;
1236         return token = 5;
1237       case 34:
1238         pos++;
1239         value = scanString();
1240         return token = 10;
1241       case 47:
1242         var start = pos - 1;
1243         if (text.charCodeAt(pos + 1) === 47) {
1244           pos += 2;
1245           while (pos < len) {
1246             if (isLineBreak(text.charCodeAt(pos))) {
1247               break;
1248             }
1249             pos++;
1250           }
1251           value = text.substring(start, pos);
1252           return token = 12;
1253         }
1254         if (text.charCodeAt(pos + 1) === 42) {
1255           pos += 2;
1256           var safeLength = len - 1;
1257           var commentClosed = false;
1258           while (pos < safeLength) {
1259             var ch = text.charCodeAt(pos);
1260             if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
1261               pos += 2;
1262               commentClosed = true;
1263               break;
1264             }
1265             pos++;
1266             if (isLineBreak(ch)) {
1267               if (ch === 13 && text.charCodeAt(pos) === 10) {
1268                 pos++;
1269               }
1270               lineNumber++;
1271               tokenLineStartOffset = pos;
1272             }
1273           }
1274           if (!commentClosed) {
1275             pos++;
1276             scanError = 1;
1277           }
1278           value = text.substring(start, pos);
1279           return token = 13;
1280         }
1281         value += String.fromCharCode(code);
1282         pos++;
1283         return token = 16;
1284       case 45:
1285         value += String.fromCharCode(code);
1286         pos++;
1287         if (pos === len || !isDigit(text.charCodeAt(pos))) {
1288           return token = 16;
1289         }
1290       case 48:
1291       case 49:
1292       case 50:
1293       case 51:
1294       case 52:
1295       case 53:
1296       case 54:
1297       case 55:
1298       case 56:
1299       case 57:
1300         value += scanNumber();
1301         return token = 11;
1302       default:
1303         while (pos < len && isUnknownContentCharacter(code)) {
1304           pos++;
1305           code = text.charCodeAt(pos);
1306         }
1307         if (tokenOffset !== pos) {
1308           value = text.substring(tokenOffset, pos);
1309           switch (value) {
1310             case "true":
1311               return token = 8;
1312             case "false":
1313               return token = 9;
1314             case "null":
1315               return token = 7;
1316           }
1317           return token = 16;
1318         }
1319         value += String.fromCharCode(code);
1320         pos++;
1321         return token = 16;
1322     }
1323   }
1324   function isUnknownContentCharacter(code) {
1325     if (isWhiteSpace(code) || isLineBreak(code)) {
1326       return false;
1327     }
1328     switch (code) {
1329       case 125:
1330       case 93:
1331       case 123:
1332       case 91:
1333       case 34:
1334       case 58:
1335       case 44:
1336       case 47:
1337         return false;
1338     }
1339     return true;
1340   }
1341   function scanNextNonTrivia() {
1342     var result;
1343     do {
1344       result = scanNext();
1345     } while (result >= 12 && result <= 15);
1346     return result;
1347   }
1348   return {
1349     setPosition,
1350     getPosition: function() {
1351       return pos;
1352     },
1353     scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
1354     getToken: function() {
1355       return token;
1356     },
1357     getTokenValue: function() {
1358       return value;
1359     },
1360     getTokenOffset: function() {
1361       return tokenOffset;
1362     },
1363     getTokenLength: function() {
1364       return pos - tokenOffset;
1365     },
1366     getTokenStartLine: function() {
1367       return lineStartOffset;
1368     },
1369     getTokenStartCharacter: function() {
1370       return tokenOffset - prevTokenLineStartOffset;
1371     },
1372     getTokenError: function() {
1373       return scanError;
1374     }
1375   };
1376 }
1377 function isWhiteSpace(ch) {
1378   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;
1379 }
1380 function isLineBreak(ch) {
1381   return ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
1382 }
1383 function isDigit(ch) {
1384   return ch >= 48 && ch <= 57;
1385 }
1386
1387 // node_modules/jsonc-parser/lib/esm/impl/format.js
1388 "use strict";
1389
1390 // node_modules/jsonc-parser/lib/esm/impl/parser.js
1391 "use strict";
1392 var ParseOptions;
1393 (function(ParseOptions2) {
1394   ParseOptions2.DEFAULT = {
1395     allowTrailingComma: false
1396   };
1397 })(ParseOptions || (ParseOptions = {}));
1398 function parse(text, errors, options) {
1399   if (errors === void 0) {
1400     errors = [];
1401   }
1402   if (options === void 0) {
1403     options = ParseOptions.DEFAULT;
1404   }
1405   var currentProperty = null;
1406   var currentParent = [];
1407   var previousParents = [];
1408   function onValue(value) {
1409     if (Array.isArray(currentParent)) {
1410       currentParent.push(value);
1411     } else if (currentProperty !== null) {
1412       currentParent[currentProperty] = value;
1413     }
1414   }
1415   var visitor = {
1416     onObjectBegin: function() {
1417       var object = {};
1418       onValue(object);
1419       previousParents.push(currentParent);
1420       currentParent = object;
1421       currentProperty = null;
1422     },
1423     onObjectProperty: function(name) {
1424       currentProperty = name;
1425     },
1426     onObjectEnd: function() {
1427       currentParent = previousParents.pop();
1428     },
1429     onArrayBegin: function() {
1430       var array = [];
1431       onValue(array);
1432       previousParents.push(currentParent);
1433       currentParent = array;
1434       currentProperty = null;
1435     },
1436     onArrayEnd: function() {
1437       currentParent = previousParents.pop();
1438     },
1439     onLiteralValue: onValue,
1440     onError: function(error, offset, length) {
1441       errors.push({error, offset, length});
1442     }
1443   };
1444   visit(text, visitor, options);
1445   return currentParent[0];
1446 }
1447 function visit(text, visitor, options) {
1448   if (options === void 0) {
1449     options = ParseOptions.DEFAULT;
1450   }
1451   var _scanner = createScanner(text, false);
1452   function toNoArgVisit(visitFunction) {
1453     return visitFunction ? function() {
1454       return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
1455     } : function() {
1456       return true;
1457     };
1458   }
1459   function toOneArgVisit(visitFunction) {
1460     return visitFunction ? function(arg) {
1461       return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
1462     } : function() {
1463       return true;
1464     };
1465   }
1466   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);
1467   var disallowComments = options && options.disallowComments;
1468   var allowTrailingComma = options && options.allowTrailingComma;
1469   function scanNext() {
1470     while (true) {
1471       var token = _scanner.scan();
1472       switch (_scanner.getTokenError()) {
1473         case 4:
1474           handleError(14);
1475           break;
1476         case 5:
1477           handleError(15);
1478           break;
1479         case 3:
1480           handleError(13);
1481           break;
1482         case 1:
1483           if (!disallowComments) {
1484             handleError(11);
1485           }
1486           break;
1487         case 2:
1488           handleError(12);
1489           break;
1490         case 6:
1491           handleError(16);
1492           break;
1493       }
1494       switch (token) {
1495         case 12:
1496         case 13:
1497           if (disallowComments) {
1498             handleError(10);
1499           } else {
1500             onComment();
1501           }
1502           break;
1503         case 16:
1504           handleError(1);
1505           break;
1506         case 15:
1507         case 14:
1508           break;
1509         default:
1510           return token;
1511       }
1512     }
1513   }
1514   function handleError(error, skipUntilAfter, skipUntil) {
1515     if (skipUntilAfter === void 0) {
1516       skipUntilAfter = [];
1517     }
1518     if (skipUntil === void 0) {
1519       skipUntil = [];
1520     }
1521     onError(error);
1522     if (skipUntilAfter.length + skipUntil.length > 0) {
1523       var token = _scanner.getToken();
1524       while (token !== 17) {
1525         if (skipUntilAfter.indexOf(token) !== -1) {
1526           scanNext();
1527           break;
1528         } else if (skipUntil.indexOf(token) !== -1) {
1529           break;
1530         }
1531         token = scanNext();
1532       }
1533     }
1534   }
1535   function parseString(isValue) {
1536     var value = _scanner.getTokenValue();
1537     if (isValue) {
1538       onLiteralValue(value);
1539     } else {
1540       onObjectProperty(value);
1541     }
1542     scanNext();
1543     return true;
1544   }
1545   function parseLiteral() {
1546     switch (_scanner.getToken()) {
1547       case 11:
1548         var tokenValue = _scanner.getTokenValue();
1549         var value = Number(tokenValue);
1550         if (isNaN(value)) {
1551           handleError(2);
1552           value = 0;
1553         }
1554         onLiteralValue(value);
1555         break;
1556       case 7:
1557         onLiteralValue(null);
1558         break;
1559       case 8:
1560         onLiteralValue(true);
1561         break;
1562       case 9:
1563         onLiteralValue(false);
1564         break;
1565       default:
1566         return false;
1567     }
1568     scanNext();
1569     return true;
1570   }
1571   function parseProperty() {
1572     if (_scanner.getToken() !== 10) {
1573       handleError(3, [], [2, 5]);
1574       return false;
1575     }
1576     parseString(false);
1577     if (_scanner.getToken() === 6) {
1578       onSeparator(":");
1579       scanNext();
1580       if (!parseValue()) {
1581         handleError(4, [], [2, 5]);
1582       }
1583     } else {
1584       handleError(5, [], [2, 5]);
1585     }
1586     return true;
1587   }
1588   function parseObject() {
1589     onObjectBegin();
1590     scanNext();
1591     var needsComma = false;
1592     while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
1593       if (_scanner.getToken() === 5) {
1594         if (!needsComma) {
1595           handleError(4, [], []);
1596         }
1597         onSeparator(",");
1598         scanNext();
1599         if (_scanner.getToken() === 2 && allowTrailingComma) {
1600           break;
1601         }
1602       } else if (needsComma) {
1603         handleError(6, [], []);
1604       }
1605       if (!parseProperty()) {
1606         handleError(4, [], [2, 5]);
1607       }
1608       needsComma = true;
1609     }
1610     onObjectEnd();
1611     if (_scanner.getToken() !== 2) {
1612       handleError(7, [2], []);
1613     } else {
1614       scanNext();
1615     }
1616     return true;
1617   }
1618   function parseArray() {
1619     onArrayBegin();
1620     scanNext();
1621     var needsComma = false;
1622     while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
1623       if (_scanner.getToken() === 5) {
1624         if (!needsComma) {
1625           handleError(4, [], []);
1626         }
1627         onSeparator(",");
1628         scanNext();
1629         if (_scanner.getToken() === 4 && allowTrailingComma) {
1630           break;
1631         }
1632       } else if (needsComma) {
1633         handleError(6, [], []);
1634       }
1635       if (!parseValue()) {
1636         handleError(4, [], [4, 5]);
1637       }
1638       needsComma = true;
1639     }
1640     onArrayEnd();
1641     if (_scanner.getToken() !== 4) {
1642       handleError(8, [4], []);
1643     } else {
1644       scanNext();
1645     }
1646     return true;
1647   }
1648   function parseValue() {
1649     switch (_scanner.getToken()) {
1650       case 3:
1651         return parseArray();
1652       case 1:
1653         return parseObject();
1654       case 10:
1655         return parseString(true);
1656       default:
1657         return parseLiteral();
1658     }
1659   }
1660   scanNext();
1661   if (_scanner.getToken() === 17) {
1662     if (options.allowEmptyContent) {
1663       return true;
1664     }
1665     handleError(4, [], []);
1666     return false;
1667   }
1668   if (!parseValue()) {
1669     handleError(4, [], []);
1670     return false;
1671   }
1672   if (_scanner.getToken() !== 17) {
1673     handleError(9, [], []);
1674   }
1675   return true;
1676 }
1677
1678 // node_modules/jsonc-parser/lib/esm/impl/edit.js
1679 "use strict";
1680
1681 // node_modules/jsonc-parser/lib/esm/main.js
1682 "use strict";
1683 var parse2 = parse;
1684
1685 // src/textmateProvider.ts
1686 var import_os2 = __toModule(require("os"));
1687 var import_path3 = __toModule(require("path"));
1688 var import_util5 = __toModule(require("util"));
1689 var TextmateProvider = class extends baseProvider_default {
1690   constructor(channel, trace, config) {
1691     super(config);
1692     this.channel = channel;
1693     this.trace = trace;
1694     this._snippetCache = {};
1695     this._userSnippets = {};
1696     if (config.loadFromExtensions) {
1697       import_coc6.extensions.onDidLoadExtension((extension) => {
1698         this.loadSnippetsFromExtension(extension).catch((e) => {
1699           channel.appendLine(`[Error] ${e.message}`);
1700         });
1701       });
1702       import_coc6.extensions.onDidUnloadExtension((id) => {
1703         delete this._snippetCache[id];
1704       });
1705     }
1706   }
1707   async init() {
1708     if (this.config.loadFromExtensions) {
1709       for (let extension of import_coc6.extensions.all) {
1710         await this.loadSnippetsFromExtension(extension);
1711       }
1712     }
1713     let paths = this.config.snippetsRoots;
1714     if (paths && paths.length) {
1715       for (let dir of paths) {
1716         await this.loadSnippetsFromRoot(dir);
1717       }
1718     }
1719   }
1720   async getSnippetFiles(filetype) {
1721     let filetypes = this.getFiletypes(filetype);
1722     let filepaths = [];
1723     if (this.config.loadFromExtensions) {
1724       for (let key of Object.keys(this._snippetCache)) {
1725         let cache = this._snippetCache[key];
1726         for (let filetype2 of filetypes) {
1727           let snippets = cache[filetype2];
1728           if (snippets && snippets.length) {
1729             filepaths.push(snippets[0].filepath);
1730           }
1731         }
1732       }
1733     }
1734     for (let filetype2 of filetypes) {
1735       let snippets = this._userSnippets[filetype2];
1736       if (snippets && snippets.length) {
1737         for (let snip of snippets) {
1738           let {filepath} = snip;
1739           if (filepaths.indexOf(filepath) == -1) {
1740             filepaths.push(filepath);
1741           }
1742         }
1743       }
1744     }
1745     return distinct(filepaths);
1746   }
1747   async getTriggerSnippets(document, position, autoTrigger) {
1748     if (autoTrigger)
1749       return [];
1750     let line = document.getline(position.line);
1751     line = line.slice(0, position.character);
1752     let snippets = await this.getSnippets(document.filetype);
1753     if (!snippets || !snippets.length)
1754       return [];
1755     let edits = [];
1756     for (let snip of snippets) {
1757       let {prefix} = snip;
1758       if (!line.endsWith(prefix))
1759         continue;
1760       let pre = line.slice(0, line.length - prefix.length);
1761       if (pre.length && /\w/.test(pre[pre.length - 1]))
1762         continue;
1763       edits.push({
1764         prefix,
1765         range: import_coc6.Range.create(position.line, position.character - prefix.length, position.line, position.character),
1766         newText: snip.body,
1767         location: snip.filepath,
1768         description: snip.description,
1769         priority: -1
1770       });
1771     }
1772     return edits;
1773   }
1774   async getSnippets(filetype) {
1775     let res = [];
1776     let filetypes = this.getFiletypes(filetype);
1777     let added = new Set();
1778     for (let key of Object.keys(this._snippetCache)) {
1779       let cache = this._snippetCache[key];
1780       for (let filetype2 of filetypes) {
1781         let snippets = cache[filetype2];
1782         if (snippets) {
1783           for (let snip of snippets) {
1784             if (!added.has(snip.prefix)) {
1785               added.add(snip.prefix);
1786               res.push(snip);
1787             }
1788           }
1789         }
1790       }
1791     }
1792     for (let filetype2 of filetypes) {
1793       let snippets = this._userSnippets[filetype2];
1794       if (snippets && snippets.length) {
1795         for (let snip of snippets) {
1796           if (!added.has(snip.prefix)) {
1797             added.add(snip.prefix);
1798             res.push(snip);
1799           }
1800         }
1801       }
1802     }
1803     return res;
1804   }
1805   async resolveSnippetBody(snip, _range) {
1806     return snip.body;
1807   }
1808   async loadSnippetsFromExtension(extension) {
1809     let {packageJSON} = extension;
1810     if (packageJSON.contributes && packageJSON.contributes.snippets) {
1811       let {snippets} = packageJSON.contributes;
1812       let def = {
1813         extensionId: extension.id,
1814         snippets: []
1815       };
1816       for (let item of snippets) {
1817         let p = import_path3.default.join(extension.extensionPath, item.path);
1818         let {language} = item;
1819         def.snippets.push({
1820           languageId: language,
1821           filepath: p
1822         });
1823       }
1824       if (snippets && snippets.length) {
1825         await this.loadSnippetsFromDefinition(def);
1826       }
1827     }
1828   }
1829   async loadSnippetsFromRoot(root) {
1830     let {_userSnippets} = this;
1831     if (root.startsWith("~"))
1832       root = root.replace(/^~/, import_os2.default.homedir());
1833     let files = await import_util5.default.promisify(import_fs3.default.readdir)(root, "utf8");
1834     files = files.filter((f) => f.endsWith(".json") || f.endsWith(".code-snippets"));
1835     await Promise.all(files.map((file) => {
1836       file = import_path3.default.join(root, file);
1837       let basename = import_path3.default.basename(file, ".json");
1838       basename = basename.replace(/\.code-snippets$/, "");
1839       return this.loadSnippetsFromFile(file).then((snippets) => {
1840         _userSnippets[basename] = snippets;
1841       });
1842     }));
1843   }
1844   async loadSnippetsFromDefinition(def) {
1845     let {extensionId, snippets} = def;
1846     let cache = this._snippetCache[extensionId] = {};
1847     for (let item of snippets) {
1848       let {languageId} = item;
1849       if (!import_fs3.default.existsSync(item.filepath))
1850         continue;
1851       let arr = await this.loadSnippetsFromFile(item.filepath);
1852       let exists = cache[languageId] || [];
1853       cache[languageId] = [...exists, ...arr];
1854     }
1855   }
1856   async loadSnippetsFromFile(snippetFilePath) {
1857     const contents = await new Promise((resolve, reject) => {
1858       import_fs3.default.readFile(snippetFilePath, "utf8", (err, data) => {
1859         if (err)
1860           return reject(err);
1861         resolve(data);
1862       });
1863     });
1864     const snippets = this.loadSnippetsFromText(snippetFilePath, contents);
1865     this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} textmate snippets from ${snippetFilePath}`);
1866     return snippets;
1867   }
1868   loadSnippetsFromText(filepath, contents) {
1869     let snippets = [];
1870     try {
1871       let errors = [];
1872       let snippetObject = parse2(contents, errors, {allowTrailingComma: true});
1873       if (errors.length) {
1874         this.channel.appendLine(`[Error ${new Date().toLocaleDateString()}] parser error of ${filepath}: ${JSON.stringify(errors, null, 2)}`);
1875       }
1876       if (snippetObject) {
1877         for (let key of Object.keys(snippetObject)) {
1878           snippets.push(snippetObject[key]);
1879         }
1880       }
1881     } catch (ex) {
1882       this.channel.appendLine(`[Error ${new Date().toLocaleDateString()}] ${ex.stack}`);
1883       snippets = [];
1884     }
1885     const normalizedSnippets = snippets.map((snip) => {
1886       let prefix = Array.isArray(snip.prefix) ? snip.prefix[0] : snip.prefix;
1887       return {
1888         filepath,
1889         lnum: 0,
1890         body: typeof snip.body === "string" ? snip.body : snip.body.join("\n"),
1891         prefix,
1892         description: typeof snip.description === "string" ? snip.description : typeof snip.description !== "undefined" ? snip.description.join("\n") : "",
1893         triggerKind: TriggerKind.WordBoundary
1894       };
1895     });
1896     return normalizedSnippets;
1897   }
1898 };
1899
1900 // src/ultisnipsProvider.ts
1901 var import_coc8 = __toModule(require("coc.nvim"));
1902 var import_fs5 = __toModule(require("fs"));
1903 var import_os3 = __toModule(require("os"));
1904 var import_path4 = __toModule(require("path"));
1905 var import_coc9 = __toModule(require("coc.nvim"));
1906
1907 // src/ultisnipsParser.ts
1908 var import_child_process = __toModule(require("child_process"));
1909 var import_coc7 = __toModule(require("coc.nvim"));
1910 var import_fs4 = __toModule(require("fs"));
1911 var import_pify2 = __toModule(require_pify());
1912 var import_readline2 = __toModule(require("readline"));
1913 var UltiSnipsParser = class {
1914   constructor(pyMethod, channel, trace = "error") {
1915     this.pyMethod = pyMethod;
1916     this.channel = channel;
1917     this.trace = trace;
1918   }
1919   parseUltisnipsFile(filepath) {
1920     const rl = import_readline2.default.createInterface({
1921       input: import_fs4.default.createReadStream(filepath, "utf8"),
1922       crlfDelay: Infinity
1923     });
1924     let pycodes = [];
1925     let snippets = [];
1926     let block;
1927     let preLines = [];
1928     let first;
1929     let priority = 0;
1930     let lnum = 0;
1931     let clearsnippets = null;
1932     let parsedContext = null;
1933     let extendFiletypes = [];
1934     rl.on("line", (line) => {
1935       lnum += 1;
1936       if (!block && (line.startsWith("#") || line.length == 0))
1937         return;
1938       const [head, tail] = headTail(line);
1939       if (!block) {
1940         switch (head) {
1941           case "priority":
1942             let n = parseInt(tail.trim(), 10);
1943             if (!isNaN(n))
1944               priority = n;
1945             break;
1946           case "extends":
1947             let fts = tail.trim().split(/,\s+/);
1948             for (let ft of fts) {
1949               if (extendFiletypes.indexOf(ft) == -1) {
1950                 extendFiletypes.push(ft);
1951               }
1952             }
1953             break;
1954           case "clearsnippets":
1955             clearsnippets = priority;
1956             break;
1957           case "context":
1958             parsedContext = tail.replace(/^"(.+)"$/, "$1");
1959             break;
1960           case "snippet":
1961           case "global":
1962             block = head;
1963             first = tail;
1964             break;
1965         }
1966         return;
1967       }
1968       if (head == "endglobal" && block == "global") {
1969         block = null;
1970         pycodes.push(...preLines);
1971         preLines = [];
1972         return;
1973       }
1974       if (head == "endsnippet" && block == "snippet") {
1975         block = null;
1976         try {
1977           let originRegex;
1978           let body = preLines.join("\n");
1979           body = body.replace(/((?:[^\\]?\$\{\w+?)\/)([^\n]*?[^\\])(?=\/)/g, (_match, p1, p2) => {
1980             return p1 + convertRegex(p2);
1981           });
1982           let ms = first.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?\s*$/);
1983           let prefix = ms[1];
1984           let description = ms[2] || "";
1985           let context = ms[3];
1986           let option = ms[4] || "";
1987           if (prefix.length > 2 && prefix[1] != prefix[0] && prefix[0] == prefix[prefix.length - 1] && !/\w/.test(prefix[0])) {
1988             prefix = prefix.slice(1, prefix.length - 1);
1989           }
1990           let isExpression = option.indexOf("r") !== -1;
1991           let regex2 = null;
1992           if (isExpression) {
1993             originRegex = prefix;
1994             prefix = convertRegex(prefix);
1995             prefix = prefix.endsWith("$") ? prefix : prefix + "$";
1996             try {
1997               regex2 = new RegExp(prefix);
1998               prefix = getRegexText(prefix);
1999             } catch (e) {
2000               this.error(`Convert regex error for: ${prefix}`);
2001             }
2002           }
2003           if (parsedContext) {
2004             context = parsedContext;
2005           } else if (option.indexOf("e") == -1) {
2006             context = null;
2007           }
2008           let snippet = {
2009             filepath,
2010             context,
2011             originRegex,
2012             autoTrigger: option.indexOf("A") !== -1,
2013             lnum: lnum - preLines.length - 2,
2014             triggerKind: getTriggerKind(option),
2015             prefix,
2016             description,
2017             regex: regex2,
2018             body,
2019             priority
2020           };
2021           snippets.push(snippet);
2022         } catch (e) {
2023           this.error(`Create snippet error on: ${filepath}:${lnum - preLines.length - 1} ${e.message}`);
2024         } finally {
2025           parsedContext = null;
2026           preLines = [];
2027         }
2028       }
2029       if (block == "snippet" || block == "global") {
2030         preLines.push(line);
2031         return;
2032       }
2033     });
2034     return new Promise((resolve) => {
2035       rl.on("close", async () => {
2036         resolve({snippets, clearsnippets, pythonCode: pycodes.join("\n"), extendFiletypes});
2037       });
2038     });
2039   }
2040   async resolveUltisnipsBody(body) {
2041     let {pyMethod} = this;
2042     let parser2 = new parser_default(body);
2043     let resolved = "";
2044     while (!parser2.eof()) {
2045       let p = parser2.prev();
2046       if (parser2.curr == "`" && (!p || p != "\\")) {
2047         let idx = parser2.nextIndex("`", true, false);
2048         if (idx == -1) {
2049           resolved = resolved + parser2.eatTo(parser2.len);
2050           break;
2051         }
2052         let code = parser2.eatTo(idx + 1);
2053         code = code.slice(1, -1);
2054         let indent = resolved.split(/\n/).slice(-1)[0].match(/^\s*/)[0];
2055         resolved = resolved + await this.execute(code, pyMethod, indent);
2056         continue;
2057       } else if (parser2.curr == "$") {
2058         let text = parser2.next(7);
2059         if (text.startsWith("VISUAL") || text.startsWith("{VISUAL")) {
2060           parser2.eat(8);
2061           resolved += "$" + text.replace("VISUAL", "TM_SELECTED_TEXT");
2062         } else if (!/^\d/.test(text) && !text.startsWith("{") && p != "\\") {
2063           resolved += "\\" + parser2.eat(1);
2064         } else {
2065           resolved += parser2.eat(1);
2066         }
2067       }
2068       let prev = parser2.prev() || "";
2069       parser2.iterate((ch) => {
2070         if (prev !== "\\" && (ch == "`" || ch == "$")) {
2071           return false;
2072         } else {
2073           resolved = resolved + ch;
2074         }
2075         prev = ch;
2076         return true;
2077       });
2078     }
2079     resolved = decode(resolved);
2080     this.debug(`resolved: ${resolved}`);
2081     return resolved;
2082   }
2083   async execute(code, pyMethod, indent) {
2084     let {nvim} = import_coc7.workspace;
2085     let res = "";
2086     if (code.startsWith("!")) {
2087       code = code.trim().slice(1);
2088       if (code.startsWith("p")) {
2089         code = code.slice(1).trim();
2090         let lines = [
2091           "import traceback",
2092           "try:",
2093           '    snip._reset("")'
2094         ];
2095         lines.push(...code.split("\n").map((line) => "    " + line.replace(/\t/g, "    ")));
2096         lines.push("except Exception as e:");
2097         lines.push("    snip.rv = traceback.format_exc()");
2098         await nvim.command(`${pyMethod} ${lines.join("\n")}`);
2099         res = await nvim.call(`${pyMethod}eval`, "snip.rv");
2100       } else if (code.startsWith("v")) {
2101         code = code.replace(/^v\s*/, "");
2102         try {
2103           res = await nvim.eval(code);
2104         } catch (e) {
2105           res = `Error: ${e.message}`;
2106           this.error(e.stack);
2107         }
2108       }
2109     } else {
2110       try {
2111         res = await import_pify2.default(import_child_process.exec)(code);
2112       } catch (e) {
2113         res = `Error: ${e.message}`;
2114         this.error(`Error on eval ${code}: ` + e.stack);
2115       }
2116     }
2117     res = res.toString();
2118     res = res.replace(/\r?\n$/, "");
2119     let parts = res.split(/\r?\n/);
2120     if (parts.length > 1) {
2121       res = parts.map((s, idx) => {
2122         if (idx == 0 || s.length == 0)
2123           return s;
2124         return `${indent}${s}`;
2125       }).join("\n");
2126     }
2127     return res;
2128   }
2129   error(str) {
2130     if (!this.channel)
2131       return;
2132     this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] ${str}`);
2133   }
2134   debug(str) {
2135     if (!this.channel || this.trace == "error")
2136       return;
2137     this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] ${str}`);
2138   }
2139 };
2140 var ultisnipsParser_default = UltiSnipsParser;
2141 function decode(str) {
2142   return str.replace(/\\`/g, "`").replace(/\\{/g, "{");
2143 }
2144 function getTriggerKind(option) {
2145   if (option.indexOf("w") !== -1) {
2146     return TriggerKind.WordBoundary;
2147   }
2148   if (option.indexOf("b") !== -1) {
2149     return TriggerKind.LineBegin;
2150   }
2151   if (option.indexOf("i") !== -1) {
2152     return TriggerKind.InWord;
2153   }
2154   return TriggerKind.SpaceBefore;
2155 }
2156
2157 // src/ultisnipsProvider.ts
2158 var pythonCodes = new Map();
2159 var UltiSnippetsProvider = class extends baseProvider_default {
2160   constructor(channel, trace, config, context) {
2161     super(config);
2162     this.channel = channel;
2163     this.trace = trace;
2164     this.config = config;
2165     this.context = context;
2166     this.snippetFiles = [];
2167     this.disposables = [];
2168     this.directories = [];
2169     this.runtimeDirs = [];
2170     this.runtimeDirs = import_coc8.workspace.env.runtimepath.split(",");
2171     import_coc8.workspace.watchOption("runtimepath", async (_, newValue) => {
2172       let parts = newValue.split(",");
2173       let subFolders = await this.getSubFolders();
2174       let items = [];
2175       for (let dir of parts) {
2176         if (this.runtimeDirs.indexOf(dir) == -1) {
2177           this.runtimeDirs.push(dir);
2178           let res = await this.getSnippetsFromPlugin(dir, subFolders);
2179           items.push(...res);
2180         }
2181       }
2182       if (items.length) {
2183         await Promise.all(items.map(({filepath, directory, filetype}) => {
2184           return this.loadSnippetsFromFile(filetype, directory, filepath);
2185         }));
2186         let files = items.map((o) => o.filepath);
2187         let pythonCode = "";
2188         for (let file of files) {
2189           let code = pythonCodes.get(file);
2190           if (code) {
2191             pythonCode += `# ${file}
2192 ` + code + "\n";
2193           }
2194         }
2195         if (pythonCode) {
2196           pythonCodes.clear();
2197           await this.executePythonCode(pythonCode);
2198         }
2199       }
2200     }, this.disposables);
2201   }
2202   checkLoaded(filepath) {
2203     return this.snippetFiles.findIndex((o) => o.filepath == filepath) !== -1;
2204   }
2205   async init() {
2206     let {nvim, env} = import_coc8.workspace;
2207     let {runtimepath} = env;
2208     let {config} = this;
2209     for (let dir of config.directories) {
2210       if (dir.startsWith("~") || dir.indexOf("$") !== -1) {
2211         let res = await import_coc8.workspace.nvim.call("expand", [dir]);
2212         this.directories.push(res);
2213       } else {
2214         this.directories.push(dir);
2215       }
2216     }
2217     this.channel.appendLine(`[Info ${new Date().toISOString()}] Using ultisnips directories: ${this.directories.join(" ")}`);
2218     let hasPythonx = await nvim.call("has", ["pythonx"]);
2219     let pythonCode = await readFileAsync(this.context.asAbsolutePath("python/ultisnips.py"), "utf8");
2220     if (hasPythonx && config.usePythonx) {
2221       this.pyMethod = "pyx";
2222     } else {
2223       this.pyMethod = config.pythonVersion == 3 ? "py3" : "py";
2224     }
2225     this.channel.appendLine(`[Info ${new Date().toLocaleTimeString()}] Using ultisnips python command: ${this.pyMethod}`);
2226     this.parser = new ultisnipsParser_default(this.pyMethod, this.channel, this.trace);
2227     let arr = await this.getAllSnippetFiles(runtimepath);
2228     let files = arr.map((o) => o.filepath);
2229     await Promise.all(arr.map(({filepath, directory, filetype}) => {
2230       return this.loadSnippetsFromFile(filetype, directory, filepath);
2231     }));
2232     for (let file of files) {
2233       let code = pythonCodes.get(file);
2234       if (code) {
2235         pythonCode += `
2236 # ${file}
2237 ` + code + "\n";
2238       }
2239     }
2240     await this.executePythonCode(pythonCode);
2241     import_coc8.workspace.onDidSaveTextDocument(async (doc) => {
2242       let uri = import_coc8.Uri.parse(doc.uri);
2243       if (uri.scheme != "file" || !doc.uri.endsWith(".snippets"))
2244         return;
2245       let filepath = uri.fsPath;
2246       if (!import_fs5.default.existsSync(filepath))
2247         return;
2248       let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
2249       if (snippetFile) {
2250         await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
2251       } else {
2252         let filetype = import_path4.default.basename(filepath, ".snippets");
2253         await this.loadSnippetsFromFile(filetype, import_path4.default.dirname(filepath), filepath);
2254       }
2255     }, null, this.disposables);
2256   }
2257   async loadSnippetsFromFile(filetype, directory, filepath) {
2258     let {snippets, pythonCode, extendFiletypes, clearsnippets} = await this.parser.parseUltisnipsFile(filepath);
2259     let idx = this.snippetFiles.findIndex((o) => o.filepath == filepath);
2260     if (idx !== -1)
2261       this.snippetFiles.splice(idx, 1);
2262     this.snippetFiles.push({
2263       extendFiletypes,
2264       clearsnippets,
2265       directory,
2266       filepath,
2267       filetype,
2268       snippets
2269     });
2270     if (extendFiletypes) {
2271       let filetypes = this.config.extends[filetype] || [];
2272       filetypes = filetypes.concat(extendFiletypes);
2273       this.config.extends[filetype] = distinct(filetypes);
2274     }
2275     this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} UltiSnip snippets from: ${filepath}`);
2276     pythonCodes.set(filepath, pythonCode);
2277   }
2278   async resolveSnippetBody(snippet, range, line) {
2279     let {nvim} = import_coc8.workspace;
2280     let {body, context, originRegex} = snippet;
2281     let indentCount = await nvim.call("indent", ".");
2282     let ind = " ".repeat(indentCount);
2283     if (body.indexOf("`!p") !== -1) {
2284       let values = new Map();
2285       let re = /\$\{(\d+)(?::([^}]+))?\}/g;
2286       let r;
2287       while (r = re.exec(body)) {
2288         let idx = parseInt(r[1], 10);
2289         let val = r[2] || "";
2290         let exists = values.get(idx);
2291         if (exists == null || val && exists == "''") {
2292           if (/^`!\w/.test(val) && val.endsWith("`")) {
2293             let code = val.slice(1).slice(0, -1);
2294             if (code.startsWith("!p")) {
2295               val = "";
2296             } else {
2297               val = await this.parser.execute(code, this.pyMethod, ind);
2298             }
2299           }
2300           val = val.replace(/'/g, "\\'").replace(/\n/g, "\\n");
2301           values.set(idx, "r'" + val + "'");
2302         }
2303       }
2304       re = /\$(\d+)/g;
2305       while (r = re.exec(body)) {
2306         let idx = parseInt(r[1], 10);
2307         if (!values.has(idx)) {
2308           values.set(idx, "''");
2309         }
2310       }
2311       let len = values.size == 0 ? 0 : Math.max.apply(null, Array.from(values.keys()));
2312       let vals = new Array(len).fill('""');
2313       for (let [idx, val] of values.entries()) {
2314         vals[idx] = val;
2315       }
2316       let pyCodes = [
2317         "import re, os, vim, string, random",
2318         `t = (${vals.join(",")})`,
2319         `fn = vim.eval('expand("%:t")') or ""`,
2320         `path = vim.eval('expand("%:p")') or ""`
2321       ];
2322       if (context) {
2323         pyCodes.push(`snip = ContextSnippet()`);
2324         pyCodes.push(`context = ${context}`);
2325       } else {
2326         pyCodes.push(`context = {}`);
2327       }
2328       let start = `(${range.start.line},${Buffer.byteLength(line.slice(0, range.start.character))})`;
2329       let end = `(${range.end.line},${Buffer.byteLength(line.slice(0, range.end.character))})`;
2330       pyCodes.push(`snip = SnippetUtil('${ind}', ${start}, ${end}, context)`);
2331       if (originRegex) {
2332         pyCodes.push(`pattern = re.compile(r"${originRegex.replace(/"/g, '\\"')}")`);
2333         pyCodes.push(`match = pattern.search("${line.replace(/"/g, '\\"')}")`);
2334       }
2335       await nvim.command(`${this.pyMethod} ${this.addPythonTryCatch(pyCodes.join("\n"))}`);
2336     }
2337     return this.parser.resolveUltisnipsBody(body);
2338   }
2339   addPythonTryCatch(code) {
2340     if (!import_coc8.workspace.isVim)
2341       return code;
2342     let lines = [
2343       "import traceback, vim",
2344       `vim.vars['errmsg'] = ''`,
2345       "try:"
2346     ];
2347     lines.push(...code.split("\n").map((line) => "    " + line));
2348     lines.push("except Exception as e:");
2349     lines.push(`    vim.vars['errmsg'] = traceback.format_exc()`);
2350     return lines.join("\n");
2351   }
2352   async checkContext(context) {
2353     let {nvim} = import_coc8.workspace;
2354     let pyCodes = [
2355       "import re, os, vim, string, random",
2356       "snip = ContextSnippet()",
2357       `context = ${context}`
2358     ];
2359     await nvim.command(`${this.pyMethod} ${this.addPythonTryCatch(pyCodes.join("\n"))}`);
2360     return await nvim.call(`${this.pyMethod}eval`, "True if context else False");
2361   }
2362   async getTriggerSnippets(document, position, autoTrigger) {
2363     let snippets = await this.getSnippets(document.filetype);
2364     let line = document.getline(position.line);
2365     line = line.slice(0, position.character);
2366     if (!line || line[line.length - 1] == " ")
2367       return [];
2368     snippets = snippets.filter((s) => {
2369       let {prefix, regex: regex2} = s;
2370       if (autoTrigger && !s.autoTrigger)
2371         return false;
2372       if (regex2) {
2373         let ms = line.match(regex2);
2374         if (!ms)
2375           return false;
2376         prefix = ms[0];
2377       }
2378       if (!line.endsWith(prefix))
2379         return false;
2380       if (s.triggerKind == TriggerKind.InWord)
2381         return true;
2382       let pre = line.slice(0, line.length - prefix.length);
2383       if (s.triggerKind == TriggerKind.LineBegin)
2384         return pre.trim() == "";
2385       if (s.triggerKind == TriggerKind.SpaceBefore)
2386         return pre.length == 0 || /\s/.test(pre[pre.length - 1]);
2387       if (s.triggerKind == TriggerKind.WordBoundary)
2388         return pre.length == 0 || !document.isWord(pre[pre.length - 1]);
2389       return false;
2390     });
2391     snippets.sort((a, b) => {
2392       if (a.context && !b.context)
2393         return -1;
2394       if (b.context && !a.context)
2395         return 1;
2396       return 0;
2397     });
2398     let edits = [];
2399     let contextPrefixes = [];
2400     for (let s of snippets) {
2401       let character;
2402       if (s.context) {
2403         let valid = await this.checkContext(s.context);
2404         if (!valid)
2405           continue;
2406         contextPrefixes.push(s.context);
2407       } else if (contextPrefixes.indexOf(s.prefix) !== -1) {
2408         continue;
2409       }
2410       if (s.regex == null) {
2411         character = position.character - s.prefix.length;
2412       } else {
2413         let len = line.match(s.regex)[0].length;
2414         character = position.character - len;
2415       }
2416       let range = import_coc9.Range.create(position.line, character, position.line, position.character);
2417       let newText = await this.resolveSnippetBody(s, range, line);
2418       edits.push({
2419         prefix: s.prefix,
2420         description: s.description,
2421         location: s.filepath,
2422         priority: s.priority,
2423         range,
2424         newText
2425       });
2426     }
2427     return edits;
2428   }
2429   async getSnippetFiles(filetype) {
2430     let filetypes = this.getFiletypes(filetype);
2431     let res = [];
2432     for (let s of this.snippetFiles) {
2433       if (filetypes.indexOf(s.filetype) !== -1) {
2434         res.push(s.filepath);
2435       }
2436     }
2437     return res;
2438   }
2439   async getSnippets(filetype) {
2440     let filetypes = this.getFiletypes(filetype);
2441     filetypes.push("all");
2442     let snippetFiles = this.snippetFiles.filter((o) => filetypes.indexOf(o.filetype) !== -1);
2443     let min = null;
2444     let result = [];
2445     snippetFiles.sort((a, b) => {
2446       if (a.filetype == b.filetype)
2447         return 1;
2448       if (a.filetype == filetype)
2449         return -1;
2450       return 1;
2451     });
2452     for (let file of snippetFiles) {
2453       let {snippets, clearsnippets} = file;
2454       if (typeof clearsnippets == "number") {
2455         min = min ? Math.max(min, clearsnippets) : clearsnippets;
2456       }
2457       for (let snip of snippets) {
2458         if (snip.regex || snip.context) {
2459           result.push(snip);
2460         } else {
2461           let idx = result.findIndex((o) => o.prefix == snip.prefix && o.triggerKind == snip.triggerKind);
2462           if (idx == -1) {
2463             result.push(snip);
2464           } else {
2465             let item = result[idx];
2466             if (snip.priority > item.priority) {
2467               result[idx] = item;
2468             }
2469           }
2470         }
2471       }
2472     }
2473     if (min != null)
2474       result = result.filter((o) => o.priority >= min);
2475     result.sort((a, b) => {
2476       if (a.context && !b.context)
2477         return -1;
2478       if (b.context && !a.context)
2479         return 1;
2480       return 0;
2481     });
2482     return result;
2483   }
2484   async getAllSnippetFiles(runtimepath) {
2485     let {directories} = this;
2486     let res = [];
2487     for (let directory of directories) {
2488       if (import_path4.default.isAbsolute(directory)) {
2489         let items = await this.getSnippetFileItems(directory);
2490         res.push(...items);
2491       }
2492     }
2493     let subFolders = await this.getSubFolders();
2494     let rtps = runtimepath.split(",");
2495     this.runtimeDirs = rtps;
2496     for (let rtp of rtps) {
2497       let items = await this.getSnippetsFromPlugin(rtp, subFolders);
2498       res.push(...items);
2499     }
2500     return res;
2501   }
2502   async getSubFolders() {
2503     let {directories} = this;
2504     directories = directories.filter((s) => !import_path4.default.isAbsolute(s));
2505     let dirs = await import_coc8.workspace.nvim.eval('get(g:, "UltiSnipsSnippetDirectories", [])');
2506     for (let dir of dirs) {
2507       if (directories.indexOf(dir) == -1) {
2508         directories.push(dir);
2509       }
2510     }
2511     return directories;
2512   }
2513   async getSnippetsFromPlugin(directory, subFolders) {
2514     let res = [];
2515     for (let folder of subFolders) {
2516       let items = await this.getSnippetFileItems(import_path4.default.join(directory, folder));
2517       res.push(...items);
2518     }
2519     return res;
2520   }
2521   async getSnippetFileItems(directory) {
2522     let res = [];
2523     let stat = await statAsync(directory);
2524     if (stat && stat.isDirectory()) {
2525       let files = await readdirAsync(directory);
2526       if (files.length) {
2527         for (let f of files) {
2528           let file = import_path4.default.join(directory, f);
2529           if (file.endsWith(".snippets")) {
2530             let basename = import_path4.default.basename(f, ".snippets");
2531             let filetype = basename.split("_", 2)[0];
2532             res.push({filepath: file, directory, filetype});
2533           } else {
2534             let stat2 = await statAsync(file);
2535             if (stat2 && stat2.isDirectory()) {
2536               let files2 = await readdirAsync(file);
2537               for (let filename of files2) {
2538                 if (filename.endsWith(".snippets")) {
2539                   res.push({filepath: import_path4.default.join(file, filename), directory, filetype: f});
2540                 }
2541               }
2542             }
2543           }
2544         }
2545       }
2546     }
2547     return res;
2548   }
2549   async executePythonCode(pythonCode) {
2550     try {
2551       let dir = import_path4.default.join(import_os3.default.tmpdir(), `coc.nvim-${process.pid}`);
2552       if (!import_fs5.default.existsSync(dir))
2553         import_fs5.default.mkdirSync(dir);
2554       let tmpfile = import_path4.default.join(import_os3.default.tmpdir(), `coc.nvim-${process.pid}`, `coc-ultisnips-${uid()}.py`);
2555       let code = this.addPythonTryCatch(pythonCode);
2556       import_fs5.default.writeFileSync(tmpfile, "# -*- coding: utf-8 -*-\n" + code, "utf8");
2557       await import_coc8.workspace.nvim.command(`exe '${this.pyMethod}file '.fnameescape('${tmpfile}')`);
2558       pythonCodes.clear();
2559     } catch (e) {
2560       this.channel.appendLine(`Error on execute python script:`);
2561       this.channel.append(e.message);
2562       import_coc8.window.showMessage(`Error on execute python script: ${e.message}`, "error");
2563     }
2564   }
2565   dispose() {
2566     import_coc8.disposeAll(this.disposables);
2567   }
2568 };
2569
2570 // src/index.ts
2571 var documentation = `# A valid snippet should starts with:
2572 #
2573 #               snippet trigger_word [ "description" [ options ] ]
2574 #
2575 # and end with:
2576 #
2577 #               endsnippet
2578 #
2579 # Snippet options:
2580 #
2581 #               b - Beginning of line.
2582 #               i - In-word expansion.
2583 #               w - Word boundary.
2584 #               r - Regular expression
2585 #               e - Custom context snippet
2586 #               A - Snippet will be triggered automatically, when condition matches.
2587 #
2588 # Basic example:
2589 #
2590 #               snippet emitter "emitter properties" b
2591 #               private readonly \${1} = new Emitter<$2>()
2592 #               public readonly \${1/^_(.*)/$1/}: Event<$2> = this.$1.event
2593 #               endsnippet
2594 #
2595 # Online reference: https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt
2596 `;
2597 async function waitDocument(doc, changedtick) {
2598   if (import_coc10.workspace.isNvim)
2599     return true;
2600   return new Promise((resolve) => {
2601     let timeout = setTimeout(() => {
2602       disposable.dispose();
2603       resolve(doc.changedtick == changedtick);
2604     }, 200);
2605     let disposable = doc.onDocumentChange(() => {
2606       clearTimeout(timeout);
2607       disposable.dispose();
2608       if (doc.changedtick == changedtick) {
2609         resolve(true);
2610       } else {
2611         resolve(false);
2612       }
2613     });
2614   });
2615 }
2616 async function activate(context) {
2617   let {subscriptions} = context;
2618   const {nvim} = import_coc10.workspace;
2619   const configuration = import_coc10.workspace.getConfiguration("snippets");
2620   const filetypeExtends = configuration.get("extends", {});
2621   const trace = configuration.get("trace", "error");
2622   let mru = import_coc10.workspace.createMru("snippets-mru");
2623   const channel = import_coc10.window.createOutputChannel("snippets");
2624   const manager = new ProviderManager(channel);
2625   let snippetsDir = configuration.get("userSnippetsDirectory");
2626   if (snippetsDir) {
2627     snippetsDir = snippetsDir.replace(/^~/, import_os4.default.homedir());
2628     if (snippetsDir.indexOf("$") !== -1) {
2629       snippetsDir = snippetsDir.replace(/\$(\w+)/g, (match, p1) => {
2630         var _a;
2631         return (_a = process.env[p1]) != null ? _a : match;
2632       });
2633     }
2634     if (!import_path5.default.isAbsolute(snippetsDir)) {
2635       import_coc10.window.showMessage(`snippets.userSnippetsDirectory => ${snippetsDir} should be absolute path`, "warning");
2636       snippetsDir = null;
2637     }
2638   }
2639   if (!snippetsDir)
2640     snippetsDir = import_path5.default.join(import_path5.default.dirname(import_coc10.workspace.env.extensionRoot), "ultisnips");
2641   if (!import_fs6.default.existsSync(snippetsDir)) {
2642     await import_util9.default.promisify(import_fs6.default.mkdir)(snippetsDir);
2643   }
2644   import_coc10.events.on("CompleteDone", async (item) => {
2645     if (typeof item.user_data === "string" && item.user_data.indexOf("snippets") !== -1) {
2646       await mru.add(item.word);
2647     }
2648   }, null, subscriptions);
2649   import_coc10.workspace.onDidOpenTextDocument(async (document) => {
2650     if (document.uri.endsWith(".snippets")) {
2651       let doc = import_coc10.workspace.getDocument(document.uri);
2652       if (!doc)
2653         return;
2654       let {buffer} = doc;
2655       await buffer.setOption("filetype", "snippets");
2656     }
2657   }, null, subscriptions);
2658   if (configuration.get("ultisnips.enable", true)) {
2659     let config2 = configuration.get("ultisnips", {});
2660     let c = Object.assign({}, config2, {
2661       extends: Object.assign({}, filetypeExtends)
2662     });
2663     c.directories = c.directories ? c.directories.slice() : [];
2664     if (c.directories.indexOf(snippetsDir) == -1) {
2665       c.directories.push(snippetsDir);
2666     }
2667     let provider2 = new UltiSnippetsProvider(channel, trace, c, context);
2668     manager.regist(provider2, "ultisnips");
2669     subscriptions.push(provider2);
2670     nvim.getOption("runtimepath").then(async (rtp) => {
2671       let paths = rtp.split(",");
2672       let idx = paths.findIndex((s) => /^ultisnips$/i.test(import_path5.default.basename(s)));
2673       if (idx !== -1)
2674         return;
2675       let directory = import_path5.default.resolve(__dirname, "..");
2676       nvim.command("autocmd BufNewFile,BufRead *.snippets setf snippets", true);
2677       nvim.command(`execute 'noa set rtp+='.fnameescape('${directory.replace(/'/g, "''")}')`, true);
2678       import_coc10.workspace.documents.forEach((doc) => {
2679         if (doc.uri.endsWith(".snippets")) {
2680           doc.buffer.setOption("filetype", "snippets", true);
2681         }
2682       });
2683     }, (_e) => {
2684     });
2685   }
2686   let config = {
2687     loadFromExtensions: configuration.get("loadFromExtensions", true),
2688     snippetsRoots: configuration.get("textmateSnippetsRoots", []),
2689     extends: Object.assign({}, filetypeExtends)
2690   };
2691   let provider = new TextmateProvider(channel, trace, config);
2692   manager.regist(provider, "snippets");
2693   if (configuration.get("snipmate.enable", true)) {
2694     let config2 = {
2695       author: configuration.get("snipmate.author", ""),
2696       extends: Object.assign({}, filetypeExtends)
2697     };
2698     let provider2 = new SnipmateProvider(channel, trace, config2);
2699     manager.regist(provider2, "snipmate");
2700   }
2701   if (configuration.get("autoTrigger", true)) {
2702     let insertTs;
2703     let insertLeaveTs;
2704     let lastInsert;
2705     import_coc10.events.on("InsertCharPre", (character) => {
2706       insertTs = Date.now();
2707       lastInsert = character;
2708     }, null, subscriptions);
2709     import_coc10.events.on("InsertLeave", () => {
2710       insertLeaveTs = Date.now();
2711     }, null, subscriptions);
2712     let inserting = false;
2713     const handleTextChange = async (bufnr, pre, changedtick) => {
2714       let lastInsertTs = insertTs;
2715       if (inserting)
2716         return;
2717       let doc = import_coc10.workspace.getDocument(bufnr);
2718       if (!doc || doc.isCommandLine || !doc.attached)
2719         return;
2720       let now = Date.now();
2721       if (!lastInsertTs || now - lastInsertTs > 100 || !pre.endsWith(lastInsert))
2722         return;
2723       let res = await waitDocument(doc, changedtick);
2724       if (!res)
2725         return;
2726       let edits = await manager.getTriggerSnippets(bufnr, true);
2727       if (edits.length == 0)
2728         return;
2729       if (edits.length > 1) {
2730         channel.appendLine(`Multiple snippet found for auto trigger: ${edits.map((s) => s.prefix).join(", ")}`);
2731         import_coc10.window.showMessage("Multiple snippet found for auto trigger, check output by :CocCommand workspace.showOutput", "warning");
2732       }
2733       if (insertLeaveTs > now || insertTs > now || inserting)
2734         return;
2735       inserting = true;
2736       try {
2737         await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2738         await mru.add(edits[0].prefix);
2739       } catch (e) {
2740         console.error(e);
2741       }
2742       inserting = false;
2743     };
2744     import_coc10.events.on("TextChangedI", async (bufnr, info) => {
2745       await handleTextChange(bufnr, info.pre, info.changedtick);
2746     }, null, subscriptions);
2747     import_coc10.events.on("TextChangedP", async (bufnr, info) => {
2748       await handleTextChange(bufnr, info.pre, info.changedtick);
2749     }, null, subscriptions);
2750   }
2751   let statusItem;
2752   if (configuration.get("enableStatusItem", true)) {
2753     statusItem = import_coc10.window.createStatusBarItem(90, {progress: true});
2754     statusItem.text = "loading snippets";
2755     statusItem.show();
2756   }
2757   manager.init().then(() => {
2758     statusItem == null ? void 0 : statusItem.hide();
2759   });
2760   if (manager.hasProvider) {
2761     let disposable = import_coc10.languages.registerCompletionItemProvider("snippets", configuration.get("shortcut", "S"), null, manager, configuration.get("triggerCharacters", []), configuration.get("priority", 90));
2762     subscriptions.push(disposable);
2763   }
2764   async function fallback() {
2765     await nvim.call("coc#start", [{source: "snippets"}]);
2766   }
2767   async function doExpand(bufnr) {
2768     let edits = await manager.getTriggerSnippets(bufnr);
2769     if (edits.length == 0)
2770       return false;
2771     if (edits.length == 1) {
2772       await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2773       await mru.add(edits[0].prefix);
2774     } else {
2775       let idx = await import_coc10.window.showQuickpick(edits.map((e) => e.description || e.prefix), "choose snippet:");
2776       if (idx == -1)
2777         return;
2778       await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[idx]);
2779       await mru.add(edits[idx].prefix);
2780     }
2781     return true;
2782   }
2783   subscriptions.push(import_coc10.workspace.registerKeymap(["x"], "convert-snippet", async () => {
2784     let mode = await import_coc10.workspace.nvim.call("visualmode");
2785     if (!mode)
2786       return;
2787     let doc = await import_coc10.workspace.document;
2788     if (!doc)
2789       return;
2790     let range = await import_coc10.workspace.getSelectedRange(mode, doc);
2791     let text = doc.textDocument.getText(range);
2792     if (text)
2793       await import_coc10.commands.executeCommand("snippets.editSnippets", text);
2794   }, {sync: false}));
2795   subscriptions.push(import_coc10.commands.registerCommand("snippets.editSnippets", async (text) => {
2796     let buf = await nvim.buffer;
2797     let doc = import_coc10.workspace.getDocument(buf.id);
2798     if (!doc) {
2799       import_coc10.window.showMessage("Document not found", "error");
2800       return;
2801     }
2802     let file = import_path5.default.join(snippetsDir, `${doc.filetype}.snippets`);
2803     if (!import_fs6.default.existsSync(file)) {
2804       await import_util9.default.promisify(import_fs6.default.writeFile)(file, documentation, "utf8");
2805     }
2806     let uri = import_coc10.Uri.file(file).toString();
2807     await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2808     if (text) {
2809       await nvim.command("normal! G");
2810       await nvim.command("normal! 2o");
2811       let position = await import_coc10.window.getCursorPosition();
2812       let indent = text.match(/^\s*/)[0];
2813       text = text.split(/\r?\n/).map((s) => s.startsWith(indent) ? s.slice(indent.length) : s).join("\n");
2814       let escaped = text.replace(/([$}\]])/g, "\\$1");
2815       let snippet = 'snippet ${1:Tab_trigger} "${2:Description}" ${3:b}\n' + escaped + "\nendsnippet";
2816       let edit2 = import_coc10.TextEdit.insert(position, snippet);
2817       await import_coc10.commands.executeCommand("editor.action.insertSnippet", edit2);
2818     }
2819   }));
2820   subscriptions.push(import_coc10.commands.registerCommand("snippets.openSnippetFiles", async () => {
2821     let buf = await nvim.buffer;
2822     let doc = import_coc10.workspace.getDocument(buf.id);
2823     if (!doc) {
2824       import_coc10.window.showMessage("Document not found", "error");
2825       return;
2826     }
2827     let files = await manager.getSnippetFiles(doc.filetype);
2828     if (!files.length) {
2829       import_coc10.window.showMessage("No related snippet file found", "warning");
2830       return;
2831     }
2832     let idx = await import_coc10.window.showQuickpick(files, "choose snippet file:");
2833     if (idx == -1)
2834       return;
2835     let uri = import_coc10.Uri.file(files[idx]).toString();
2836     await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2837   }));
2838   subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand", async () => {
2839     let bufnr = await nvim.eval('bufnr("%")');
2840     let expanded = await doExpand(bufnr);
2841     if (!expanded)
2842       await fallback();
2843   }, {silent: true, sync: true, cancel: true}));
2844   subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand-jump", async () => {
2845     let bufnr = await nvim.eval('bufnr("%")');
2846     let expanded = await doExpand(bufnr);
2847     if (!expanded) {
2848       let session = import_coc10.snippetManager.getSession(bufnr);
2849       if (session && session.isActive) {
2850         await nvim.call("coc#_cancel", []);
2851         await import_coc10.snippetManager.nextPlaceholder();
2852         return;
2853       }
2854       await fallback();
2855     }
2856   }, {silent: true, sync: true, cancel: true}));
2857   subscriptions.push(import_coc10.workspace.registerKeymap(["v"], "snippets-select", async () => {
2858     let doc = await import_coc10.workspace.document;
2859     if (!doc)
2860       return;
2861     let mode = await nvim.call("visualmode");
2862     if (["v", "V"].indexOf(mode) == -1) {
2863       import_coc10.window.showMessage(`visual mode ${mode} not supported`, "warning");
2864       return;
2865     }
2866     await nvim.command("normal! `<");
2867     let start = await import_coc10.window.getCursorPosition();
2868     await nvim.command("normal! `>");
2869     let end = await import_coc10.window.getCursorPosition();
2870     end = import_coc10.Position.create(end.line, end.character + 1);
2871     let range = import_coc10.Range.create(start, end);
2872     let text = doc.textDocument.getText(range);
2873     await nvim.call("feedkeys", ["i", "in"]);
2874     if (mode == "v") {
2875       await doc.applyEdits([{range, newText: ""}]);
2876     } else {
2877       let currline = doc.getline(start.line);
2878       let indent = currline.match(/^\s*/)[0];
2879       let lines = text.split(/\r?\n/);
2880       lines = lines.map((s) => s.startsWith(indent) ? s.slice(indent.length) : s);
2881       text = lines.join("\n");
2882       range = import_coc10.Range.create(import_coc10.Position.create(start.line, indent.length), end);
2883       await doc.applyEdits([{range, newText: ""}]);
2884     }
2885     await nvim.setVar("coc_selected_text", text);
2886     await import_coc10.window.moveTo(range.start);
2887   }, {silent: true, sync: false, cancel: true}));
2888   let languageProvider = new languages_default(channel, trace);
2889   subscriptions.push(import_coc10.languages.registerCompletionItemProvider("snippets-source", configuration.get("shortcut", "S"), ["snippets"], languageProvider, ["$"], configuration.get("priority", 90)));
2890   subscriptions.push(statusItem);
2891   subscriptions.push(channel);
2892   subscriptions.push(import_coc10.listManager.registerList(new snippet_default(import_coc10.workspace.nvim, manager, mru)));
2893   return {
2894     expandable: async () => {
2895       let bufnr = await nvim.eval('bufnr("%")');
2896       let edits = await manager.getTriggerSnippets(bufnr);
2897       return edits && edits.length > 0;
2898     }
2899   };
2900 }
2901 //# sourceMappingURL=index.js.map