Skip to content

Commit 24b3caf

Browse files
committed
feat: snippet provider
1 parent 24282c2 commit 24b3caf

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { minimatch } from 'minimatch';
2+
import * as vscode from 'vscode';
3+
4+
interface Snippet {
5+
prefix: string;
6+
body: string[];
7+
description: string;
8+
}
9+
10+
interface SnippetProvider {
11+
pattern: string;
12+
snippets: Record<string, Snippet>;
13+
}
14+
15+
export class XmlSnippetProvider implements vscode.CompletionItemProvider {
16+
public static readonly TRIGGER_CHARACTERS = ['<'];
17+
18+
private readonly snippetProviders: SnippetProvider[] = [
19+
{
20+
pattern: '**/di.xml',
21+
snippets: require('./snippets/di-xml.json'),
22+
},
23+
];
24+
25+
public provideCompletionItems(
26+
document: vscode.TextDocument,
27+
position: vscode.Position,
28+
token: vscode.CancellationToken,
29+
context: vscode.CompletionContext
30+
): vscode.ProviderResult<vscode.CompletionItem[]> {
31+
const wordRange = document.getWordRangeAtPosition(position);
32+
const word = document.getText(wordRange);
33+
const snippets = this.getSnippets(document);
34+
35+
if (!snippets) {
36+
return null;
37+
}
38+
39+
const completionItems: vscode.CompletionItem[] = [];
40+
41+
for (const name in snippets) {
42+
const snippet = snippets[name];
43+
44+
// if (snippet.prefix.indexOf(word) !== 0) {
45+
// continue;
46+
// }
47+
48+
const completionItem = new vscode.CompletionItem(name, vscode.CompletionItemKind.Snippet);
49+
completionItem.insertText = new vscode.SnippetString(snippet.body.join('\n'));
50+
51+
completionItem.documentation = new vscode.MarkdownString(snippet.description);
52+
53+
completionItem.additionalTextEdits = [
54+
vscode.TextEdit.delete(
55+
new vscode.Range(position.line, position.character - 1, position.line, position.character)
56+
),
57+
];
58+
59+
completionItems.push(completionItem);
60+
}
61+
62+
return completionItems;
63+
}
64+
65+
public getSnippets(document: vscode.TextDocument): Record<string, Snippet> | undefined {
66+
for (const snippetProvider of this.snippetProviders) {
67+
if (minimatch(document.uri.fsPath, snippetProvider.pattern, { matchBase: true })) {
68+
return snippetProvider.snippets;
69+
}
70+
}
71+
72+
return undefined;
73+
}
74+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"Insert a preference element": {
3+
"prefix": "preference",
4+
"body": [
5+
"<preference for=\"${1:ClassName}\" type=\"${2:ClassName}\" />"
6+
],
7+
"description": "Insert a preference element to the current file"
8+
},
9+
"Insert a type element": {
10+
"prefix": "type",
11+
"body": [
12+
"<type name=\"${1:ClassName}\">\n</type>"
13+
],
14+
"description": "Insert a type element to the current file"
15+
},
16+
"Insert a arguments element": {
17+
"prefix": "arguments",
18+
"body": [
19+
"<arguments>\n</arguments>"
20+
],
21+
"description": "Insert an arguments element to the current file"
22+
},
23+
"Insert a argument element": {
24+
"prefix": "argument",
25+
"body": [
26+
"<argument name=\"${1:Name}\" xsi:type=\"${2:Type}\">${3:Value}</argument>"
27+
],
28+
"description": "Insert an argument element to the current file"
29+
}
30+
}

src/extension.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Magento from 'util/Magento';
1313
import { WorkspaceFolder } from 'vscode';
1414
import Logger from 'util/Logger';
1515
import { Command } from 'command/Command';
16+
import { XmlSnippetProvider } from 'completion/XmlSnippetProvider';
1617

1718
// This method is called when your extension is activated
1819
// Your extension is activated the very first time the command is executed
@@ -103,6 +104,14 @@ export async function activate(context: vscode.ExtensionContext) {
103104
vscode.languages.registerHoverProvider('xml', new XmlClasslikeHoverProvider())
104105
);
105106

107+
context.subscriptions.push(
108+
vscode.languages.registerCompletionItemProvider(
109+
'xml',
110+
new XmlSnippetProvider(),
111+
...XmlSnippetProvider.TRIGGER_CHARACTERS
112+
)
113+
);
114+
106115
await activeTextEditorChangeObserver.execute(vscode.window.activeTextEditor);
107116

108117
if (vscode.window.activeTextEditor) {

0 commit comments

Comments
 (0)