-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathextension.ts
131 lines (109 loc) · 4.79 KB
/
extension.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
'use strict';
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import * as JSON5 from 'json5';
let _snippets: { [modeId: string]: vscode.CompletionItem[] } = Object.create(null);
let _registeredProviders: { [modeId: string]: vscode.Disposable } = Object.create(null);
class CompletionProvider implements vscode.CompletionItemProvider {
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
vscode.CompletionItem[] | Thenable<vscode.CompletionItem[]> | vscode.CompletionList | Thenable<vscode.CompletionList> {
return _snippets[document.languageId];
}
public resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken):
vscode.CompletionItem | Thenable<vscode.CompletionItem> {
return item;
}
}
export function parseSnippetFile(snippetFileContent: string): vscode.CompletionItem[] {
try {
if (snippetFileContent === '') {
return [];
}
let snippetsObj = JSON5.parse(snippetFileContent);
if (!snippetsObj || typeof snippetsObj !== 'object') {
return [];
}
let topLevelProperties = Object.keys(snippetsObj);
let result: vscode.CompletionItem[] = []
let processSnippet = (snippet: any, name: string) => {
let prefix = snippet['prefix'];
let bodyStringOrArray = snippet['body'];
if (Array.isArray(bodyStringOrArray)) {
bodyStringOrArray = bodyStringOrArray.join('\n');
}
if (typeof prefix === 'string' && typeof bodyStringOrArray === 'string') {
let newSnippet = new vscode.CompletionItem(prefix);
newSnippet.kind = vscode.CompletionItemKind.Snippet;
newSnippet.detail = snippet['description'] || name,
newSnippet.documentation = snippet['description'] || name,
newSnippet.insertText = new vscode.SnippetString(bodyStringOrArray);
result.push(newSnippet);
}
}
topLevelProperties.forEach(topLevelProperty => {
let scopeOrTemplate = snippetsObj[topLevelProperty];
if (scopeOrTemplate['body'] && scopeOrTemplate['prefix']) {
processSnippet(scopeOrTemplate, topLevelProperty);
} else {
let snippetNames = Object.keys(scopeOrTemplate);
snippetNames.forEach(name => {
processSnippet(scopeOrTemplate[name], name);
});
}
});
return result;
} catch (err) {
return [];
}
}
async function readAndRegisterSnippets(filePath: vscode.Uri): Promise<vscode.CompletionItem[]> {
return new Promise<vscode.CompletionItem[]>((resolve, reject) => {
fs.readFile(filePath.fsPath, { encoding: 'utf8' }, (err, data) => {
if (err) {
reject(err);
}
let snippets = parseSnippetFile(data.toString());
resolve(snippets);
});
});
}
export async function activate(context: vscode.ExtensionContext) {
let completionItemProvider = new CompletionProvider();
let snippetFiles = await vscode.workspace.findFiles(".vscode/snippets/*.json", "");
if (snippetFiles) {
for (let i = 0; i < snippetFiles.length; i++) {
let modeId = path.basename(snippetFiles[i].path).split('\.')[0];
let snippets = await readAndRegisterSnippets(snippetFiles[i]);
_snippets[modeId] = snippets;
}
for (const modeId in _snippets) {
let disposable = vscode.languages.registerCompletionItemProvider(modeId, completionItemProvider);
_registeredProviders[modeId] = disposable;
}
}
let snippetFilesWatcher = vscode.workspace.createFileSystemWatcher("**/.vscode/snippets/*.json");
let snippetUpdate = async (e: vscode.Uri) => {
let modeId = path.basename(e.path).split('\.')[0];
let snippets = await readAndRegisterSnippets(e);
_snippets[modeId] = snippets;
if (_registeredProviders[modeId]) {
_registeredProviders[modeId].dispose();
}
let disposable = vscode.languages.registerCompletionItemProvider(modeId, completionItemProvider);
_registeredProviders[modeId] = disposable;
};
snippetFilesWatcher.onDidCreate(snippetUpdate);
snippetFilesWatcher.onDidChange(snippetUpdate);
snippetFilesWatcher.onDidDelete(async (e) => {
let modeId = path.basename(e.path).split('\.')[0];
if (_registeredProviders[modeId]) {
_registeredProviders[modeId].dispose();
}
});
}
export function deactivate() {
for (let modeId in _registeredProviders) {
_registeredProviders[modeId].dispose()
}
}