1 var __create = Object.create;
2 var __defProp = Object.defineProperty;
3 var __getProtoOf = Object.getPrototypeOf;
4 var __hasOwnProp = Object.prototype.hasOwnProperty;
5 var __getOwnPropNames = Object.getOwnPropertyNames;
6 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7 var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
8 var __commonJS = (callback, module2) => () => {
10 module2 = {exports: {}};
11 callback(module2.exports, module2);
13 return module2.exports;
15 var __export = (target, all) => {
16 __markAsModule(target);
18 __defProp(target, name, {get: all[name], enumerable: true});
20 var __exportStar = (target, module2, desc) => {
21 __markAsModule(target);
22 if (module2 && typeof module2 === "object" || typeof module2 === "function") {
23 for (let key of __getOwnPropNames(module2))
24 if (!__hasOwnProp.call(target, key) && key !== "default")
25 __defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
29 var __toModule = (module2) => {
30 if (module2 && module2.__esModule)
32 return __exportStar(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", {value: module2, enumerable: true}), module2);
35 // node_modules/pify/index.js
36 var require_pify = __commonJS((exports2, module2) => {
38 var processFn = (fn, options, proxy, unwrapped) => function(...arguments_) {
39 const P = options.promiseModule;
40 return new P((resolve, reject) => {
41 if (options.multiArgs) {
42 arguments_.push((...result) => {
43 if (options.errorFirst) {
54 } else if (options.errorFirst) {
55 arguments_.push((error, result) => {
63 arguments_.push(resolve);
65 const self = this === proxy ? unwrapped : this;
66 Reflect.apply(fn, self, arguments_);
69 var filterCache = new WeakMap();
70 module2.exports = (input, options) => {
72 exclude: [/.+(?:Sync|Stream)$/],
74 promiseModule: Promise,
77 const objectType = typeof input;
78 if (!(input !== null && (objectType === "object" || objectType === "function"))) {
79 throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? "null" : objectType}\``);
81 const filter = (target, key) => {
82 let cached = filterCache.get(target);
85 filterCache.set(target, cached);
90 const match = (pattern) => typeof pattern === "string" || typeof key === "symbol" ? key === pattern : pattern.test(key);
91 const desc = Reflect.getOwnPropertyDescriptor(target, key);
92 const writableOrConfigurableOwn = desc === void 0 || desc.writable || desc.configurable;
93 const included = options.include ? options.include.some(match) : !options.exclude.some(match);
94 const shouldFilter = included && writableOrConfigurableOwn;
95 cached[key] = shouldFilter;
98 const cache = new WeakMap();
99 const proxy = new Proxy(input, {
100 apply(target, thisArg, args) {
101 const cached = cache.get(target);
103 return Reflect.apply(cached, thisArg, args);
105 const pified = options.excludeMain ? target : processFn(target, options, proxy, target);
106 cache.set(target, pified);
107 return Reflect.apply(pified, thisArg, args);
110 const property = target[key];
111 if (!filter(target, key) || property === Function.prototype[key]) {
114 const cached = cache.get(property);
118 if (typeof property === "function") {
119 const pified = processFn(property, options, proxy, target);
120 cache.set(property, pified);
132 activate: () => activate
134 var import_coc10 = __toModule(require("coc.nvim"));
135 var import_fs6 = __toModule(require("fs"));
136 var import_os4 = __toModule(require("os"));
137 var import_path5 = __toModule(require("path"));
138 var import_util9 = __toModule(require("util"));
141 var import_coc = __toModule(require("coc.nvim"));
144 var import_pify = __toModule(require_pify());
145 var import_fs = __toModule(require("fs"));
146 var import_crypto = __toModule(require("crypto"));
147 var BASE64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
148 function tostr(bytes) {
151 for (i = 0; i < bytes.length; i++) {
152 r.push(BASE64[bytes[i] % 64]);
157 return tostr(import_crypto.default.randomBytes(10));
159 async function statAsync(filepath) {
161 return await import_pify.default(import_fs.default.stat)(filepath);
166 async function readFileAsync(fullpath, encoding = "utf8") {
167 return await import_pify.default(import_fs.default.readFile)(fullpath, encoding);
169 async function readdirAsync(filepath) {
171 return await import_pify.default(import_fs.default.readdir)(filepath);
176 function headTail(line) {
178 let ms = line.match(/^(\S+)\s+(.*)/);
181 return [ms[1], ms[2]];
183 function distinct(array, keyFn) {
185 return array.filter((element, position) => {
186 return array.indexOf(element) === position;
189 const seen = Object.create(null);
190 return array.filter((elem) => {
191 const key = keyFn(elem);
199 var conditionRe = /\(\?\(\?:\w+\).+\|/;
201 var commentRe = /\(\?#.*?\)/;
202 var stringStartRe = /\\A/;
203 var namedCaptureRe = /\(\?P<\w+>.*?\)/;
204 var namedReferenceRe = /\(\?P=(\w+)\)/;
205 var braceRe = /\^\]/;
206 var regex = new RegExp(`${bellRe.source}|${commentRe.source}|${stringStartRe.source}|${namedCaptureRe.source}|${namedReferenceRe.source}|${braceRe}`, "g");
207 function convertRegex(str) {
208 if (str.indexOf("\\z") !== -1) {
209 throw new Error("pattern \\z not supported");
211 if (str.indexOf("(?s)") !== -1) {
212 throw new Error("pattern (?s) not supported");
214 if (str.indexOf("(?x)") !== -1) {
215 throw new Error("pattern (?x) not supported");
217 if (str.indexOf("\n") !== -1) {
218 throw new Error("multiple line pattern not supported");
220 if (conditionRe.test(str)) {
221 throw new Error("condition pattern not supported");
223 return str.replace(regex, (match, p1) => {
228 if (match.startsWith("(?#"))
232 if (match.startsWith("(?P<"))
233 return "(?" + match.slice(3);
234 if (match.startsWith("(?P="))
239 function getRegexText(prefix) {
240 if (prefix.startsWith("^"))
241 prefix = prefix.slice(1);
242 if (prefix.endsWith("$"))
243 prefix = prefix.slice(0, -1);
244 let content = prefix.replace(/\(.*\)\??/g, "");
245 content = content.replace(/\\/g, "");
248 function markdownBlock(code, filetype) {
249 filetype = filetype == "javascriptreact" ? "javascript" : filetype;
250 filetype = filetype == "typescriptreact" ? "typescript" : filetype;
251 return "``` " + filetype + "\n" + code + "\n```";
255 var codesMap = new Map();
256 codesMap.set(1, "invalid snippet line, trigger requried.");
257 codesMap.set(2, 'invalid snippet option, option "$1" not supported.');
258 codesMap.set(3, "invalid python expression, $1");
259 codesMap.set(4, "invalid code interpolation, #! not supported.");
260 var validOptions = ["b", "i", "w", "r", "e", "A"];
261 var LanguageProvider = class {
262 constructor(channel, trace = "error") {
263 this.channel = channel;
265 this.disposables = [];
266 this.collection = import_coc.languages.createDiagnosticCollection("snippets");
267 for (let doc of import_coc.workspace.documents) {
268 if (this.shouldValidate(doc.uri)) {
269 this.validate(doc.uri, doc.getDocumentContent()).catch((e) => {
270 channel.appendLine(`[Error ${new Date().toLocaleTimeString()}]: ${e.message}`);
274 import_coc.workspace.onDidOpenTextDocument(async (textDocument) => {
275 let doc = import_coc.workspace.getDocument(textDocument.uri);
276 if (!this.shouldValidate(doc.uri))
278 await this.validate(doc.uri, doc.getDocumentContent());
279 }, null, this.disposables);
280 import_coc.workspace.onDidChangeTextDocument(async (ev) => {
281 let doc = import_coc.workspace.getDocument(ev.textDocument.uri);
282 if (!doc || !this.shouldValidate(doc.uri))
284 await this.validate(doc.uri, doc.getDocumentContent());
285 }, null, this.disposables);
286 import_coc.workspace.onDidCloseTextDocument((e) => {
287 this.collection.delete(e.uri);
288 }, null, this.disposables);
290 shouldValidate(uri) {
291 return uri.endsWith(".snippets");
293 async validate(uri, content) {
294 let lines = content.split("\n");
295 let diagnostics = [];
297 for (let line of lines) {
298 if (/^snippet\s*$/.test(line)) {
299 let range = import_coc.Range.create(curr, 0, curr, line.length);
300 diagnostics.push(import_coc.Diagnostic.create(range, codesMap.get(1), import_coc.DiagnosticSeverity.Error, 1));
303 if (line.startsWith("snippet ")) {
304 let content2 = headTail(line)[1];
305 let ms = content2.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?$/);
307 if (prefix.length > 2 && prefix[0] == prefix[prefix.length - 1] && !/\w/.test(prefix[0])) {
308 prefix = prefix.slice(1, prefix.length - 1);
310 let option = ms[4] || "";
311 let isExpression = option.indexOf("r") !== -1;
312 let startCharacter = line.length - option.length;
313 for (let ch of option) {
314 if (validOptions.indexOf(ch) == -1) {
315 let range = import_coc.Range.create(curr, startCharacter, curr, startCharacter + 1);
316 let message = codesMap.get(2).replace("$1", ch);
317 diagnostics.push(import_coc.Diagnostic.create(range, message, import_coc.DiagnosticSeverity.Error, 2));
319 startCharacter = startCharacter + 1;
323 convertRegex(prefix);
325 let start = line.indexOf(prefix);
326 let range = import_coc.Range.create(curr, start, curr, start + prefix.length);
327 let message = codesMap.get(3).replace("$1", e.message);
328 diagnostics.push(import_coc.Diagnostic.create(range, message, import_coc.DiagnosticSeverity.Error, 3));
332 let idx = line.indexOf("`#!");
334 let range = import_coc.Range.create(curr, idx, curr, idx + 3);
335 let message = codesMap.get(4);
336 diagnostics.push(import_coc.Diagnostic.create(range, message, import_coc.DiagnosticSeverity.Error, 4));
341 if (this.trace == "verbose") {
342 this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] diagnostics of ${uri} -> ${JSON.stringify(diagnostics)}`);
344 this.collection.set(uri, diagnostics);
346 provideCompletionItems(_document, position, _token, context) {
347 let {input, col} = context.option;
348 if (context.triggerCharacter == "$") {
351 kind: import_coc.CompletionItemKind.Snippet,
353 insertTextFormat: import_coc.InsertTextFormat.Snippet,
355 range: import_coc.Range.create(position.line, position.character - 1, position.line, position.character),
356 newText: "\\${VISUAL${1::default}\\}"
360 if (col == 0 && "snippet".startsWith(input)) {
363 kind: import_coc.CompletionItemKind.Snippet,
364 detail: "Snippet definition",
365 insertTextFormat: import_coc.InsertTextFormat.Snippet,
366 insertText: 'snippet ${1:Tab_trigger} "${2:Description}" ${3:b}\n$0\nendsnippet'
371 async resolveCompletionItem(item) {
372 let text = item.insertText || item.textEdit.newText;
373 let snip = await Promise.resolve(import_coc.snippetManager.resolveSnippet(text));
374 item.documentation = {
376 value: markdownBlock(snip.toString(), "snippets")
381 var languages_default = LanguageProvider;
383 // src/list/snippet.ts
384 var import_coc2 = __toModule(require("coc.nvim"));
385 var import_os = __toModule(require("os"));
386 var SnippetsList = class extends import_coc2.BasicList {
387 constructor(nvim, manager, mru) {
389 this.manager = manager;
391 this.name = "snippets";
392 this.description = "snippets list";
393 this.addLocationActions();
395 async loadItems(context) {
396 let {window: window4} = context;
397 let valid = await window4.valid;
400 let buf = await window4.buffer;
401 let doc = import_coc2.workspace.getDocument(buf.id);
404 let snippets = await this.manager.getSnippets(doc.filetype);
406 for (let snip of snippets) {
407 let pos = import_coc2.Position.create(snip.lnum, 0);
408 let location = import_coc2.Location.create(import_coc2.Uri.file(snip.filepath).toString(), import_coc2.Range.create(pos, pos));
409 let prefix = snip.prefix;
410 if (prefix.length < 20) {
411 prefix = `${prefix}${" ".repeat(20 - prefix.length)}`;
414 label: `${prefix} ${snip.description} ${snip.filepath.replace(import_os.default.homedir(), "~")}`,
415 filterText: `${snip.prefix} ${snip.description}`,
421 async doHighlight() {
422 let {nvim} = import_coc2.workspace;
423 nvim.pauseNotification();
424 nvim.command("syntax match CocSnippetsPrefix /\\v^\\S+/ contained containedin=CocSnippetsLine", true);
425 nvim.command("syntax match CocSnippetsFile /\\v\\t\\S+$/ contained containedin=CocSnippetsLine", true);
426 nvim.command("highlight default link CocSnippetsPrefix Identifier", true);
427 nvim.command("highlight default link CocSnippetsFile Comment", true);
428 await nvim.resumeNotification();
431 var snippet_default = SnippetsList;
434 var import_coc3 = __toModule(require("coc.nvim"));
435 var import_path = __toModule(require("path"));
439 (function(TriggerKind2) {
440 TriggerKind2[TriggerKind2["SpaceBefore"] = 0] = "SpaceBefore";
441 TriggerKind2[TriggerKind2["LineBegin"] = 1] = "LineBegin";
442 TriggerKind2[TriggerKind2["WordBoundary"] = 2] = "WordBoundary";
443 TriggerKind2[TriggerKind2["InWord"] = 3] = "InWord";
444 })(TriggerKind || (TriggerKind = {}));
447 var ProviderManager = class {
448 constructor(channel) {
449 this.channel = channel;
450 this.providers = new Map();
452 regist(provider, name) {
453 this.providers.set(name, provider);
454 return import_coc3.Disposable.create(() => {
455 this.providers.delete(name);
459 return this.providers.size > 0;
462 let providers = Array.from(this.providers.values());
463 await Promise.all(providers.map((provider) => {
464 return provider.init();
466 this.appendError("init", e);
469 async getSnippets(filetype) {
470 let names = Array.from(this.providers.keys());
472 for (let name of names) {
473 let provider = this.providers.get(name);
475 let snippets = await provider.getSnippets(filetype);
476 snippets.map((s) => s.provider = name);
477 list.push(...snippets);
479 this.appendError(`getSnippets of ${name}`, e);
484 async getSnippetFiles(filetype) {
486 for (let [name, provider] of this.providers.entries()) {
488 let res = await provider.getSnippetFiles(filetype);
489 files = files.concat(res);
491 this.appendError(`getSnippetFiles of ${name}`, e);
496 async getTriggerSnippets(bufnr, autoTrigger = false) {
497 let doc = import_coc3.workspace.getDocument(bufnr);
500 let position = await import_coc3.window.getCursorPosition();
501 let names = Array.from(this.providers.keys());
503 for (let name of names) {
504 let provider = this.providers.get(name);
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) {
513 this.appendError(`getTriggerSnippets of ${name}`, e);
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);
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);
528 async provideCompletionItems(document, position, _token, context) {
529 let doc = import_coc3.workspace.getDocument(document.uri);
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);
538 let contextPrefixes = [];
539 for (let snip of snippets) {
540 let contentBehind = before_content;
541 if (contextPrefixes.indexOf(snip.prefix) !== -1)
543 if (snip.regex != null && snip.prefix == "")
546 let provider = this.providers.get(snip.provider);
549 valid = await provider.checkContext(snip.context);
551 this.appendError(`checkContext of ${snip.provider}`, e);
556 contextPrefixes.push(snip.prefix);
558 let head = this.getPrefixHead(doc, snip.prefix);
559 if (input.length == 0 && !before_content.endsWith(snip.prefix))
563 kind: import_coc3.CompletionItemKind.Snippet,
564 filterText: snip.prefix,
565 detail: snip.description,
566 insertTextFormat: import_coc3.InsertTextFormat.Snippet
570 provider: snip.provider,
571 filepath: `${import_path.default.basename(snip.filepath)}:${snip.lnum}`
574 if (!input.length || snip.prefix && input[0] != snip.prefix[0])
576 let content = before_content + snip.prefix;
577 let ms = content.match(snip.regex);
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, {
585 range: import_coc3.Range.create({line: position.line, character: character - head.length}, position),
589 } else if (input.length == 0) {
591 contentBehind = before_content.slice(0, -prefix.length);
592 Object.assign(item, {
595 range: import_coc3.Range.create({line: position.line, character: character - prefix.length}, position),
600 if (snip.triggerKind == TriggerKind.LineBegin && contentBehind.trim().length)
602 if (snip.triggerKind == TriggerKind.SpaceBefore) {
603 if (contentBehind.length && !/\s/.test(contentBehind[contentBehind.length - 1])) {
607 if (!item.textEdit) {
609 range: import_coc3.Range.create({line: position.line, character}, position),
613 item.data.location = `${snip.filepath}:${snip.lnum}`;
614 item.data.line = contentBehind + snip.prefix;
619 async resolveCompletionItem(item) {
620 let provider = this.providers.get(item.data.provider);
622 let filetype = await import_coc3.workspace.nvim.eval("&filetype");
625 insertSnippet = await provider.resolveSnippetBody(item.data.snip, item.textEdit.range, item.data.line);
627 this.appendError(`resolveSnippetBody of ${item.data.provider}`, e);
630 item.textEdit.newText = insertSnippet;
631 if (import_coc3.snippetManager) {
632 let snip = await Promise.resolve(import_coc3.snippetManager.resolveSnippet(insertSnippet));
633 item.documentation = {
635 value: markdownBlock(snip.toString(), filetype.match(/^\w+/)[0])
641 getPrefixHead(doc, prefix) {
643 for (let idx = prefix.length - 1; idx >= 0; idx--) {
644 if (!doc.isWord(prefix[idx])) {
649 return res == 0 ? "" : prefix.slice(0, res + 1);
652 function characterIndex(content, byteIndex) {
653 let buf = Buffer.from(content, "utf8");
654 return buf.slice(0, byteIndex).toString("utf8").length;
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"));
663 // src/baseProvider.ts
664 var import_coc4 = __toModule(require("coc.nvim"));
665 var BaseProvider = class {
666 constructor(config) {
667 this.config = config;
669 async checkContext(_context) {
672 getExtendsFiletypes(filetype, exists = new Set()) {
673 if (exists.has(filetype))
675 let extend = this.config.extends ? this.config.extends[filetype] : null;
676 exists.add(filetype);
677 if (!extend || extend.length == 0)
679 return extend.reduce((arr, curr) => {
680 return arr.concat([curr], this.getExtendsFiletypes(curr, exists));
683 getFiletypes(filetype) {
684 let filetypes = [filetype];
685 if (filetype.indexOf(".") !== -1) {
686 filetypes.push(...filetype.split("."));
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]);
696 if (filetype == "javascriptreact" && !filetypes.includes("javascript")) {
697 filetypes.push("javascript");
699 if (filetype == "typescriptreact" && !filetypes.includes("typescript")) {
700 filetypes.push("typescript");
702 let extendFiletypes = filetypes.reduce((arr, curr) => {
703 return arr.concat(this.getExtendsFiletypes(curr));
705 filetypes.push(...extendFiletypes);
707 return distinct(filetypes);
710 var baseProvider_default = BaseProvider;
714 constructor(_content) {
715 this._content = _content;
719 return this._curr >= this._content.length;
722 for (let i = this._curr; i <= this._content.length; i++) {
723 let ch = this._content[i];
724 if (!ch || /\S/.test(ch)) {
734 return this._content[this._curr] || "";
737 return this._content.length;
740 return this._content.slice(this._curr + 1, this._curr + 1 + count);
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 !== "\\")) {
755 if (!allowEnd && i == this.len - 1 && character != this._content[i]) {
761 return this._content[this._curr - 1] || "";
764 while (this._curr < this._content.length) {
765 let fine = fn(this.curr, this._curr);
766 if (fine === false) {
769 this._curr = this._curr + 1;
773 let end = this._curr + count;
774 end = Math.min(end, this.len);
775 let str = this._content.slice(this._curr, end);
780 if (index == this._curr)
782 let str = this._content.slice(this._curr, index);
787 var parser_default = Parser;
789 // src/snipmateProvider.ts
790 var SnipmateProvider = class extends baseProvider_default {
791 constructor(channel, trace, config) {
793 this.channel = channel;
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")
801 let filepath = uri.fsPath;
802 if (!import_fs2.default.existsSync(filepath))
804 let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
806 await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
807 }, null, this.disposables);
810 let arr = await this.getAllSnippetFiles();
811 let {nvim} = import_coc5.workspace;
812 let author = await nvim.getVar("snips_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);
819 async loadSnippetsFromFile(filetype, directory, filepath) {
820 let snippets = await this.parseSnippetsFile(filepath);
821 let idx = this.snippetFiles.findIndex((o) => o.filepath == filepath);
823 this.snippetFiles.splice(idx, 1);
824 this.snippetFiles.push({
830 this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} snipmate snippets from: ${filepath}`);
832 async resolveSnippetBody(snippet, _range, _line) {
833 let parser2 = new parser_default(snippet.body);
835 let {nvim} = import_coc5.workspace;
836 while (!parser2.eof()) {
837 if (parser2.curr == "`") {
838 let idx = parser2.nextIndex("`", true, false);
840 resolved = resolved + parser2.eatTo(parser2.len);
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");
849 resolved = resolved + await nvim.eval(code);
851 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Error on eval: ${code}`);
856 parser2.iterate((ch) => {
860 resolved = resolved + ch;
867 parseSnippetsFile(filepath) {
869 const rl = import_readline.default.createInterface({
870 input: import_fs2.default.createReadStream(filepath, "utf8"),
876 let description = "";
877 rl.on("line", (line) => {
879 if (line.startsWith("#"))
881 if (line.startsWith("snippet")) {
882 line = line.replace(/\s*$/, "");
883 if (lines.length && prefix) {
886 lnum: lnum - lines.length - 1,
887 body: lines.join("\n").replace(/\s+$/, ""),
890 triggerKind: TriggerKind.SpaceBefore
894 let ms = line.match(/^snippet\s+(\S+)(?:\s(.+))?$/);
897 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] Broken line on ${filepath}:${lnum}`);
901 description = ms[2] || "";
905 if (line.indexOf("VISUAL") !== -1) {
906 line = line.replace(/\$(\{?)VISUAL\b(:[^\}])?(\}?)/g, "$$$1TM_SELECTED_TEXT$2$3");
908 if (line.startsWith(" ")) {
909 lines.push(line.slice(1));
915 return new Promise((resolve) => {
916 rl.on("close", async () => {
920 lnum: lnum - lines.length - 1,
921 body: lines.join("\n"),
924 triggerKind: TriggerKind.SpaceBefore
931 async getTriggerSnippets(document, position, autoTrigger) {
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] == " ")
939 snippets = snippets.filter((s) => {
941 if (!line.endsWith(prefix))
943 let pre = line.slice(0, line.length - prefix.length);
944 return pre.length == 0 || /\s/.test(pre[pre.length - 1]);
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);
953 description: s.description,
954 location: s.filepath,
962 async getSnippetFiles(filetype) {
963 let filetypes = this.getFiletypes(filetype);
965 for (let s of this.snippetFiles) {
966 if (filetypes.indexOf(s.filetype) !== -1) {
967 res.push(s.filepath);
972 async getSnippets(filetype) {
973 let filetypes = this.getFiletypes(filetype);
975 let snippetFiles = this.snippetFiles.filter((o) => filetypes.indexOf(o.filetype) !== -1);
977 snippetFiles.sort((a, b) => {
978 if (a.filetype == b.filetype)
980 if (a.filetype == filetype)
984 for (let file of snippetFiles) {
985 let {snippets} = file;
986 for (let snip of snippets) {
992 async getAllSnippetFiles() {
993 let {nvim} = import_coc5.workspace;
994 let opt = await nvim.eval("&rtp");
995 let rtps = opt.split(",");
997 for (let rtp of rtps) {
998 let items = await this.getSnippetFileItems(import_path2.default.join(rtp, "snippets"));
1003 async getSnippetFileItems(directory) {
1005 let stat = await statAsync(directory);
1006 if (stat && stat.isDirectory()) {
1007 let files = await readdirAsync(directory);
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});
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});
1033 // src/textmateProvider.ts
1034 var import_coc6 = __toModule(require("coc.nvim"));
1035 var import_fs3 = __toModule(require("fs"));
1037 // node_modules/jsonc-parser/lib/esm/impl/scanner.js
1039 function createScanner(text, ignoreTrivia) {
1040 if (ignoreTrivia === void 0) {
1041 ignoreTrivia = false;
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) {
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;
1062 if (digits < count) {
1067 function setPosition(newPosition) {
1074 function scanNumber() {
1076 if (text.charCodeAt(pos) === 48) {
1080 while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1084 if (pos < text.length && text.charCodeAt(pos) === 46) {
1086 if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1088 while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1093 return text.substring(start, pos);
1097 if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
1099 if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
1102 if (pos < text.length && isDigit(text.charCodeAt(pos))) {
1104 while (pos < text.length && isDigit(text.charCodeAt(pos))) {
1112 return text.substring(start, end);
1114 function scanString() {
1115 var result = "", start = pos;
1118 result += text.substring(start, pos);
1122 var ch = text.charCodeAt(pos);
1124 result += text.substring(start, pos);
1129 result += text.substring(start, pos);
1135 var ch2 = text.charCodeAt(pos++);
1162 var ch3 = scanHexDigits(4, true);
1164 result += String.fromCharCode(ch3);
1175 if (ch >= 0 && ch <= 31) {
1176 if (isLineBreak(ch)) {
1177 result += text.substring(start, pos);
1188 function scanNext() {
1192 lineStartOffset = lineNumber;
1193 prevTokenLineStartOffset = tokenLineStartOffset;
1198 var code = text.charCodeAt(pos);
1199 if (isWhiteSpace(code)) {
1202 value += String.fromCharCode(code);
1203 code = text.charCodeAt(pos);
1204 } while (isWhiteSpace(code));
1207 if (isLineBreak(code)) {
1209 value += String.fromCharCode(code);
1210 if (code === 13 && text.charCodeAt(pos) === 10) {
1215 tokenLineStartOffset = pos;
1239 value = scanString();
1242 var start = pos - 1;
1243 if (text.charCodeAt(pos + 1) === 47) {
1246 if (isLineBreak(text.charCodeAt(pos))) {
1251 value = text.substring(start, pos);
1254 if (text.charCodeAt(pos + 1) === 42) {
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) {
1262 commentClosed = true;
1266 if (isLineBreak(ch)) {
1267 if (ch === 13 && text.charCodeAt(pos) === 10) {
1271 tokenLineStartOffset = pos;
1274 if (!commentClosed) {
1278 value = text.substring(start, pos);
1281 value += String.fromCharCode(code);
1285 value += String.fromCharCode(code);
1287 if (pos === len || !isDigit(text.charCodeAt(pos))) {
1300 value += scanNumber();
1303 while (pos < len && isUnknownContentCharacter(code)) {
1305 code = text.charCodeAt(pos);
1307 if (tokenOffset !== pos) {
1308 value = text.substring(tokenOffset, pos);
1319 value += String.fromCharCode(code);
1324 function isUnknownContentCharacter(code) {
1325 if (isWhiteSpace(code) || isLineBreak(code)) {
1341 function scanNextNonTrivia() {
1344 result = scanNext();
1345 } while (result >= 12 && result <= 15);
1350 getPosition: function() {
1353 scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
1354 getToken: function() {
1357 getTokenValue: function() {
1360 getTokenOffset: function() {
1363 getTokenLength: function() {
1364 return pos - tokenOffset;
1366 getTokenStartLine: function() {
1367 return lineStartOffset;
1369 getTokenStartCharacter: function() {
1370 return tokenOffset - prevTokenLineStartOffset;
1372 getTokenError: function() {
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;
1380 function isLineBreak(ch) {
1381 return ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
1383 function isDigit(ch) {
1384 return ch >= 48 && ch <= 57;
1387 // node_modules/jsonc-parser/lib/esm/impl/format.js
1390 // node_modules/jsonc-parser/lib/esm/impl/parser.js
1393 (function(ParseOptions2) {
1394 ParseOptions2.DEFAULT = {
1395 allowTrailingComma: false
1397 })(ParseOptions || (ParseOptions = {}));
1398 function parse(text, errors, options) {
1399 if (errors === void 0) {
1402 if (options === void 0) {
1403 options = ParseOptions.DEFAULT;
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;
1416 onObjectBegin: function() {
1419 previousParents.push(currentParent);
1420 currentParent = object;
1421 currentProperty = null;
1423 onObjectProperty: function(name) {
1424 currentProperty = name;
1426 onObjectEnd: function() {
1427 currentParent = previousParents.pop();
1429 onArrayBegin: function() {
1432 previousParents.push(currentParent);
1433 currentParent = array;
1434 currentProperty = null;
1436 onArrayEnd: function() {
1437 currentParent = previousParents.pop();
1439 onLiteralValue: onValue,
1440 onError: function(error, offset, length) {
1441 errors.push({error, offset, length});
1444 visit(text, visitor, options);
1445 return currentParent[0];
1447 function visit(text, visitor, options) {
1448 if (options === void 0) {
1449 options = ParseOptions.DEFAULT;
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());
1459 function toOneArgVisit(visitFunction) {
1460 return visitFunction ? function(arg) {
1461 return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
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() {
1471 var token = _scanner.scan();
1472 switch (_scanner.getTokenError()) {
1483 if (!disallowComments) {
1497 if (disallowComments) {
1514 function handleError(error, skipUntilAfter, skipUntil) {
1515 if (skipUntilAfter === void 0) {
1516 skipUntilAfter = [];
1518 if (skipUntil === void 0) {
1522 if (skipUntilAfter.length + skipUntil.length > 0) {
1523 var token = _scanner.getToken();
1524 while (token !== 17) {
1525 if (skipUntilAfter.indexOf(token) !== -1) {
1528 } else if (skipUntil.indexOf(token) !== -1) {
1535 function parseString(isValue) {
1536 var value = _scanner.getTokenValue();
1538 onLiteralValue(value);
1540 onObjectProperty(value);
1545 function parseLiteral() {
1546 switch (_scanner.getToken()) {
1548 var tokenValue = _scanner.getTokenValue();
1549 var value = Number(tokenValue);
1554 onLiteralValue(value);
1557 onLiteralValue(null);
1560 onLiteralValue(true);
1563 onLiteralValue(false);
1571 function parseProperty() {
1572 if (_scanner.getToken() !== 10) {
1573 handleError(3, [], [2, 5]);
1577 if (_scanner.getToken() === 6) {
1580 if (!parseValue()) {
1581 handleError(4, [], [2, 5]);
1584 handleError(5, [], [2, 5]);
1588 function parseObject() {
1591 var needsComma = false;
1592 while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
1593 if (_scanner.getToken() === 5) {
1595 handleError(4, [], []);
1599 if (_scanner.getToken() === 2 && allowTrailingComma) {
1602 } else if (needsComma) {
1603 handleError(6, [], []);
1605 if (!parseProperty()) {
1606 handleError(4, [], [2, 5]);
1611 if (_scanner.getToken() !== 2) {
1612 handleError(7, [2], []);
1618 function parseArray() {
1621 var needsComma = false;
1622 while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
1623 if (_scanner.getToken() === 5) {
1625 handleError(4, [], []);
1629 if (_scanner.getToken() === 4 && allowTrailingComma) {
1632 } else if (needsComma) {
1633 handleError(6, [], []);
1635 if (!parseValue()) {
1636 handleError(4, [], [4, 5]);
1641 if (_scanner.getToken() !== 4) {
1642 handleError(8, [4], []);
1648 function parseValue() {
1649 switch (_scanner.getToken()) {
1651 return parseArray();
1653 return parseObject();
1655 return parseString(true);
1657 return parseLiteral();
1661 if (_scanner.getToken() === 17) {
1662 if (options.allowEmptyContent) {
1665 handleError(4, [], []);
1668 if (!parseValue()) {
1669 handleError(4, [], []);
1672 if (_scanner.getToken() !== 17) {
1673 handleError(9, [], []);
1678 // node_modules/jsonc-parser/lib/esm/impl/edit.js
1681 // node_modules/jsonc-parser/lib/esm/main.js
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) {
1692 this.channel = channel;
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}`);
1702 import_coc6.extensions.onDidUnloadExtension((id) => {
1703 delete this._snippetCache[id];
1708 if (this.config.loadFromExtensions) {
1709 for (let extension of import_coc6.extensions.all) {
1710 await this.loadSnippetsFromExtension(extension);
1713 let paths = this.config.snippetsRoots;
1714 if (paths && paths.length) {
1715 for (let dir of paths) {
1716 await this.loadSnippetsFromRoot(dir);
1720 async getSnippetFiles(filetype) {
1721 let filetypes = this.getFiletypes(filetype);
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);
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);
1745 return distinct(filepaths);
1747 async getTriggerSnippets(document, position, autoTrigger) {
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)
1756 for (let snip of snippets) {
1757 let {prefix} = snip;
1758 if (!line.endsWith(prefix))
1760 let pre = line.slice(0, line.length - prefix.length);
1761 if (pre.length && /\w/.test(pre[pre.length - 1]))
1765 range: import_coc6.Range.create(position.line, position.character - prefix.length, position.line, position.character),
1767 location: snip.filepath,
1768 description: snip.description,
1774 async getSnippets(filetype) {
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];
1783 for (let snip of snippets) {
1784 if (!added.has(snip.prefix)) {
1785 added.add(snip.prefix);
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);
1805 async resolveSnippetBody(snip, _range) {
1808 async loadSnippetsFromExtension(extension) {
1809 let {packageJSON} = extension;
1810 if (packageJSON.contributes && packageJSON.contributes.snippets) {
1811 let {snippets} = packageJSON.contributes;
1813 extensionId: extension.id,
1816 for (let item of snippets) {
1817 let p = import_path3.default.join(extension.extensionPath, item.path);
1818 let {language} = item;
1820 languageId: language,
1824 if (snippets && snippets.length) {
1825 await this.loadSnippetsFromDefinition(def);
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;
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))
1851 let arr = await this.loadSnippetsFromFile(item.filepath);
1852 let exists = cache[languageId] || [];
1853 cache[languageId] = [...exists, ...arr];
1856 async loadSnippetsFromFile(snippetFilePath) {
1857 const contents = await new Promise((resolve, reject) => {
1858 import_fs3.default.readFile(snippetFilePath, "utf8", (err, data) => {
1864 const snippets = this.loadSnippetsFromText(snippetFilePath, contents);
1865 this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} textmate snippets from ${snippetFilePath}`);
1868 loadSnippetsFromText(filepath, contents) {
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)}`);
1876 if (snippetObject) {
1877 for (let key of Object.keys(snippetObject)) {
1878 snippets.push(snippetObject[key]);
1882 this.channel.appendLine(`[Error ${new Date().toLocaleDateString()}] ${ex.stack}`);
1885 const normalizedSnippets = snippets.map((snip) => {
1886 let prefix = Array.isArray(snip.prefix) ? snip.prefix[0] : snip.prefix;
1890 body: typeof snip.body === "string" ? snip.body : snip.body.join("\n"),
1892 description: typeof snip.description === "string" ? snip.description : typeof snip.description !== "undefined" ? snip.description.join("\n") : "",
1893 triggerKind: TriggerKind.WordBoundary
1896 return normalizedSnippets;
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"));
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;
1919 parseUltisnipsFile(filepath) {
1920 const rl = import_readline2.default.createInterface({
1921 input: import_fs4.default.createReadStream(filepath, "utf8"),
1931 let clearsnippets = null;
1932 let parsedContext = null;
1933 let extendFiletypes = [];
1934 rl.on("line", (line) => {
1936 if (!block && (line.startsWith("#") || line.length == 0))
1938 const [head, tail] = headTail(line);
1942 let n = parseInt(tail.trim(), 10);
1947 let fts = tail.trim().split(/,\s+/);
1948 for (let ft of fts) {
1949 if (extendFiletypes.indexOf(ft) == -1) {
1950 extendFiletypes.push(ft);
1954 case "clearsnippets":
1955 clearsnippets = priority;
1958 parsedContext = tail.replace(/^"(.+)"$/, "$1");
1968 if (head == "endglobal" && block == "global") {
1970 pycodes.push(...preLines);
1974 if (head == "endsnippet" && block == "snippet") {
1978 let body = preLines.join("\n");
1979 body = body.replace(/((?:[^\\]?\$\{\w+?)\/)([^\n]*?[^\\])(?=\/)/g, (_match, p1, p2) => {
1980 return p1 + convertRegex(p2);
1982 let ms = first.match(/^(.+?)(?:\s+(?:"(.*?)")?(?:\s+"(.*?)")?(?:\s+(\w+))?)?\s*$/);
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);
1990 let isExpression = option.indexOf("r") !== -1;
1993 originRegex = prefix;
1994 prefix = convertRegex(prefix);
1995 prefix = prefix.endsWith("$") ? prefix : prefix + "$";
1997 regex2 = new RegExp(prefix);
1998 prefix = getRegexText(prefix);
2000 this.error(`Convert regex error for: ${prefix}`);
2003 if (parsedContext) {
2004 context = parsedContext;
2005 } else if (option.indexOf("e") == -1) {
2012 autoTrigger: option.indexOf("A") !== -1,
2013 lnum: lnum - preLines.length - 2,
2014 triggerKind: getTriggerKind(option),
2021 snippets.push(snippet);
2023 this.error(`Create snippet error on: ${filepath}:${lnum - preLines.length - 1} ${e.message}`);
2025 parsedContext = null;
2029 if (block == "snippet" || block == "global") {
2030 preLines.push(line);
2034 return new Promise((resolve) => {
2035 rl.on("close", async () => {
2036 resolve({snippets, clearsnippets, pythonCode: pycodes.join("\n"), extendFiletypes});
2040 async resolveUltisnipsBody(body) {
2041 let {pyMethod} = this;
2042 let parser2 = new parser_default(body);
2044 while (!parser2.eof()) {
2045 let p = parser2.prev();
2046 if (parser2.curr == "`" && (!p || p != "\\")) {
2047 let idx = parser2.nextIndex("`", true, false);
2049 resolved = resolved + parser2.eatTo(parser2.len);
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);
2057 } else if (parser2.curr == "$") {
2058 let text = parser2.next(7);
2059 if (text.startsWith("VISUAL") || text.startsWith("{VISUAL")) {
2061 resolved += "$" + text.replace("VISUAL", "TM_SELECTED_TEXT");
2062 } else if (!/^\d/.test(text) && !text.startsWith("{") && p != "\\") {
2063 resolved += "\\" + parser2.eat(1);
2065 resolved += parser2.eat(1);
2068 let prev = parser2.prev() || "";
2069 parser2.iterate((ch) => {
2070 if (prev !== "\\" && (ch == "`" || ch == "$")) {
2073 resolved = resolved + ch;
2079 resolved = decode(resolved);
2080 this.debug(`resolved: ${resolved}`);
2083 async execute(code, pyMethod, indent) {
2084 let {nvim} = import_coc7.workspace;
2086 if (code.startsWith("!")) {
2087 code = code.trim().slice(1);
2088 if (code.startsWith("p")) {
2089 code = code.slice(1).trim();
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*/, "");
2103 res = await nvim.eval(code);
2105 res = `Error: ${e.message}`;
2106 this.error(e.stack);
2111 res = await import_pify2.default(import_child_process.exec)(code);
2113 res = `Error: ${e.message}`;
2114 this.error(`Error on eval ${code}: ` + e.stack);
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)
2124 return `${indent}${s}`;
2132 this.channel.appendLine(`[Error ${new Date().toLocaleTimeString()}] ${str}`);
2135 if (!this.channel || this.trace == "error")
2137 this.channel.appendLine(`[Debug ${new Date().toLocaleTimeString()}] ${str}`);
2140 var ultisnipsParser_default = UltiSnipsParser;
2141 function decode(str) {
2142 return str.replace(/\\`/g, "`").replace(/\\{/g, "{");
2144 function getTriggerKind(option) {
2145 if (option.indexOf("w") !== -1) {
2146 return TriggerKind.WordBoundary;
2148 if (option.indexOf("b") !== -1) {
2149 return TriggerKind.LineBegin;
2151 if (option.indexOf("i") !== -1) {
2152 return TriggerKind.InWord;
2154 return TriggerKind.SpaceBefore;
2157 // src/ultisnipsProvider.ts
2158 var pythonCodes = new Map();
2159 var UltiSnippetsProvider = class extends baseProvider_default {
2160 constructor(channel, trace, config, context) {
2162 this.channel = channel;
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();
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);
2183 await Promise.all(items.map(({filepath, directory, filetype}) => {
2184 return this.loadSnippetsFromFile(filetype, directory, filepath);
2186 let files = items.map((o) => o.filepath);
2187 let pythonCode = "";
2188 for (let file of files) {
2189 let code = pythonCodes.get(file);
2191 pythonCode += `# ${file}
2196 pythonCodes.clear();
2197 await this.executePythonCode(pythonCode);
2200 }, this.disposables);
2202 checkLoaded(filepath) {
2203 return this.snippetFiles.findIndex((o) => o.filepath == filepath) !== -1;
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);
2214 this.directories.push(dir);
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";
2223 this.pyMethod = config.pythonVersion == 3 ? "py3" : "py";
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);
2232 for (let file of files) {
2233 let code = pythonCodes.get(file);
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"))
2245 let filepath = uri.fsPath;
2246 if (!import_fs5.default.existsSync(filepath))
2248 let snippetFile = this.snippetFiles.find((s) => s.filepath == filepath);
2250 await this.loadSnippetsFromFile(snippetFile.filetype, snippetFile.directory, filepath);
2252 let filetype = import_path4.default.basename(filepath, ".snippets");
2253 await this.loadSnippetsFromFile(filetype, import_path4.default.dirname(filepath), filepath);
2255 }, null, this.disposables);
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);
2261 this.snippetFiles.splice(idx, 1);
2262 this.snippetFiles.push({
2270 if (extendFiletypes) {
2271 let filetypes = this.config.extends[filetype] || [];
2272 filetypes = filetypes.concat(extendFiletypes);
2273 this.config.extends[filetype] = distinct(filetypes);
2275 this.channel.appendLine(`[Info ${new Date().toISOString()}] Loaded ${snippets.length} UltiSnip snippets from: ${filepath}`);
2276 pythonCodes.set(filepath, pythonCode);
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;
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")) {
2297 val = await this.parser.execute(code, this.pyMethod, ind);
2300 val = val.replace(/'/g, "\\'").replace(/\n/g, "\\n");
2301 values.set(idx, "r'" + val + "'");
2305 while (r = re.exec(body)) {
2306 let idx = parseInt(r[1], 10);
2307 if (!values.has(idx)) {
2308 values.set(idx, "''");
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()) {
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 ""`
2323 pyCodes.push(`snip = ContextSnippet()`);
2324 pyCodes.push(`context = ${context}`);
2326 pyCodes.push(`context = {}`);
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)`);
2332 pyCodes.push(`pattern = re.compile(r"${originRegex.replace(/"/g, '\\"')}")`);
2333 pyCodes.push(`match = pattern.search("${line.replace(/"/g, '\\"')}")`);
2335 await nvim.command(`${this.pyMethod} ${this.addPythonTryCatch(pyCodes.join("\n"))}`);
2337 return this.parser.resolveUltisnipsBody(body);
2339 addPythonTryCatch(code) {
2340 if (!import_coc8.workspace.isVim)
2343 "import traceback, vim",
2344 `vim.vars['errmsg'] = ''`,
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");
2352 async checkContext(context) {
2353 let {nvim} = import_coc8.workspace;
2355 "import re, os, vim, string, random",
2356 "snip = ContextSnippet()",
2357 `context = ${context}`
2359 await nvim.command(`${this.pyMethod} ${this.addPythonTryCatch(pyCodes.join("\n"))}`);
2360 return await nvim.call(`${this.pyMethod}eval`, "True if context else False");
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] == " ")
2368 snippets = snippets.filter((s) => {
2369 let {prefix, regex: regex2} = s;
2370 if (autoTrigger && !s.autoTrigger)
2373 let ms = line.match(regex2);
2378 if (!line.endsWith(prefix))
2380 if (s.triggerKind == TriggerKind.InWord)
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]);
2391 snippets.sort((a, b) => {
2392 if (a.context && !b.context)
2394 if (b.context && !a.context)
2399 let contextPrefixes = [];
2400 for (let s of snippets) {
2403 let valid = await this.checkContext(s.context);
2406 contextPrefixes.push(s.context);
2407 } else if (contextPrefixes.indexOf(s.prefix) !== -1) {
2410 if (s.regex == null) {
2411 character = position.character - s.prefix.length;
2413 let len = line.match(s.regex)[0].length;
2414 character = position.character - len;
2416 let range = import_coc9.Range.create(position.line, character, position.line, position.character);
2417 let newText = await this.resolveSnippetBody(s, range, line);
2420 description: s.description,
2421 location: s.filepath,
2422 priority: s.priority,
2429 async getSnippetFiles(filetype) {
2430 let filetypes = this.getFiletypes(filetype);
2432 for (let s of this.snippetFiles) {
2433 if (filetypes.indexOf(s.filetype) !== -1) {
2434 res.push(s.filepath);
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);
2445 snippetFiles.sort((a, b) => {
2446 if (a.filetype == b.filetype)
2448 if (a.filetype == filetype)
2452 for (let file of snippetFiles) {
2453 let {snippets, clearsnippets} = file;
2454 if (typeof clearsnippets == "number") {
2455 min = min ? Math.max(min, clearsnippets) : clearsnippets;
2457 for (let snip of snippets) {
2458 if (snip.regex || snip.context) {
2461 let idx = result.findIndex((o) => o.prefix == snip.prefix && o.triggerKind == snip.triggerKind);
2465 let item = result[idx];
2466 if (snip.priority > item.priority) {
2474 result = result.filter((o) => o.priority >= min);
2475 result.sort((a, b) => {
2476 if (a.context && !b.context)
2478 if (b.context && !a.context)
2484 async getAllSnippetFiles(runtimepath) {
2485 let {directories} = this;
2487 for (let directory of directories) {
2488 if (import_path4.default.isAbsolute(directory)) {
2489 let items = await this.getSnippetFileItems(directory);
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);
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);
2513 async getSnippetsFromPlugin(directory, subFolders) {
2515 for (let folder of subFolders) {
2516 let items = await this.getSnippetFileItems(import_path4.default.join(directory, folder));
2521 async getSnippetFileItems(directory) {
2523 let stat = await statAsync(directory);
2524 if (stat && stat.isDirectory()) {
2525 let files = await readdirAsync(directory);
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});
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});
2549 async executePythonCode(pythonCode) {
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();
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");
2566 import_coc8.disposeAll(this.disposables);
2571 var documentation = `# A valid snippet should starts with:
2573 # snippet trigger_word [ "description" [ options ] ]
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.
2590 # snippet emitter "emitter properties" b
2591 # private readonly \${1} = new Emitter<$2>()
2592 # public readonly \${1/^_(.*)/$1/}: Event<$2> = this.$1.event
2595 # Online reference: https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt
2597 async function waitDocument(doc, changedtick) {
2598 if (import_coc10.workspace.isNvim)
2600 return new Promise((resolve) => {
2601 let timeout = setTimeout(() => {
2602 disposable.dispose();
2603 resolve(doc.changedtick == changedtick);
2605 let disposable = doc.onDocumentChange(() => {
2606 clearTimeout(timeout);
2607 disposable.dispose();
2608 if (doc.changedtick == changedtick) {
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");
2627 snippetsDir = snippetsDir.replace(/^~/, import_os4.default.homedir());
2628 if (snippetsDir.indexOf("$") !== -1) {
2629 snippetsDir = snippetsDir.replace(/\$(\w+)/g, (match, p1) => {
2631 return (_a = process.env[p1]) != null ? _a : match;
2634 if (!import_path5.default.isAbsolute(snippetsDir)) {
2635 import_coc10.window.showMessage(`snippets.userSnippetsDirectory => ${snippetsDir} should be absolute path`, "warning");
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);
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);
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);
2655 await buffer.setOption("filetype", "snippets");
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)
2663 c.directories = c.directories ? c.directories.slice() : [];
2664 if (c.directories.indexOf(snippetsDir) == -1) {
2665 c.directories.push(snippetsDir);
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)));
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);
2687 loadFromExtensions: configuration.get("loadFromExtensions", true),
2688 snippetsRoots: configuration.get("textmateSnippetsRoots", []),
2689 extends: Object.assign({}, filetypeExtends)
2691 let provider = new TextmateProvider(channel, trace, config);
2692 manager.regist(provider, "snippets");
2693 if (configuration.get("snipmate.enable", true)) {
2695 author: configuration.get("snipmate.author", ""),
2696 extends: Object.assign({}, filetypeExtends)
2698 let provider2 = new SnipmateProvider(channel, trace, config2);
2699 manager.regist(provider2, "snipmate");
2701 if (configuration.get("autoTrigger", true)) {
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;
2717 let doc = import_coc10.workspace.getDocument(bufnr);
2718 if (!doc || doc.isCommandLine || !doc.attached)
2720 let now = Date.now();
2721 if (!lastInsertTs || now - lastInsertTs > 100 || !pre.endsWith(lastInsert))
2723 let res = await waitDocument(doc, changedtick);
2726 let edits = await manager.getTriggerSnippets(bufnr, true);
2727 if (edits.length == 0)
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");
2733 if (insertLeaveTs > now || insertTs > now || inserting)
2737 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2738 await mru.add(edits[0].prefix);
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);
2752 if (configuration.get("enableStatusItem", true)) {
2753 statusItem = import_coc10.window.createStatusBarItem(90, {progress: true});
2754 statusItem.text = "loading snippets";
2757 manager.init().then(() => {
2758 statusItem == null ? void 0 : statusItem.hide();
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);
2764 async function fallback() {
2765 await nvim.call("coc#start", [{source: "snippets"}]);
2767 async function doExpand(bufnr) {
2768 let edits = await manager.getTriggerSnippets(bufnr);
2769 if (edits.length == 0)
2771 if (edits.length == 1) {
2772 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[0]);
2773 await mru.add(edits[0].prefix);
2775 let idx = await import_coc10.window.showQuickpick(edits.map((e) => e.description || e.prefix), "choose snippet:");
2778 await import_coc10.commands.executeCommand("editor.action.insertSnippet", edits[idx]);
2779 await mru.add(edits[idx].prefix);
2783 subscriptions.push(import_coc10.workspace.registerKeymap(["x"], "convert-snippet", async () => {
2784 let mode = await import_coc10.workspace.nvim.call("visualmode");
2787 let doc = await import_coc10.workspace.document;
2790 let range = await import_coc10.workspace.getSelectedRange(mode, doc);
2791 let text = doc.textDocument.getText(range);
2793 await import_coc10.commands.executeCommand("snippets.editSnippets", text);
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);
2799 import_coc10.window.showMessage("Document not found", "error");
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");
2806 let uri = import_coc10.Uri.file(file).toString();
2807 await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
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);
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);
2824 import_coc10.window.showMessage("Document not found", "error");
2827 let files = await manager.getSnippetFiles(doc.filetype);
2828 if (!files.length) {
2829 import_coc10.window.showMessage("No related snippet file found", "warning");
2832 let idx = await import_coc10.window.showQuickpick(files, "choose snippet file:");
2835 let uri = import_coc10.Uri.file(files[idx]).toString();
2836 await import_coc10.workspace.jumpTo(uri, null, configuration.get("editSnippetsCommand"));
2838 subscriptions.push(import_coc10.workspace.registerKeymap(["i"], "snippets-expand", async () => {
2839 let bufnr = await nvim.eval('bufnr("%")');
2840 let expanded = await doExpand(bufnr);
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);
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();
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;
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");
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"]);
2875 await doc.applyEdits([{range, newText: ""}]);
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: ""}]);
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)));
2894 expandable: async () => {
2895 let bufnr = await nvim.eval('bufnr("%")');
2896 let edits = await manager.getTriggerSnippets(bufnr);
2897 return edits && edits.length > 0;
2901 //# sourceMappingURL=index.js.map