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
|
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorAction, ServicesAccessor, IActionOptions } from 'vs/editor/browser/editorExtensions';
import { grammarsExtPoint, ITMSyntaxExtensionPoint } from 'vs/workbench/services/textMate/common/TMGrammars';
import { IExtensionService, ExtensionPointContribution } from 'vs/workbench/services/extensions/common/extensions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
interface ModeScopeMap {
[key: string]: string;
}
export interface IGrammarContributions {
getGrammar(mode: string): string;
}
class GrammarContributions implements IGrammarContributions {
private static _grammars: ModeScopeMap = {};
constructor(contributions: ExtensionPointContribution<ITMSyntaxExtensionPoint[]>[]) {
if (!Object.keys(GrammarContributions._grammars).length) {
this.fillModeScopeMap(contributions);
}
}
private fillModeScopeMap(contributions: ExtensionPointContribution<ITMSyntaxExtensionPoint[]>[]) {
contributions.forEach((contribution) => {
contribution.value.forEach((grammar) => {
if (grammar.language && grammar.scopeName) {
GrammarContributions._grammars[grammar.language] = grammar.scopeName;
}
});
});
}
public getGrammar(mode: string): string {
return GrammarContributions._grammars[mode];
}
}
export interface IEmmetActionOptions extends IActionOptions {
actionName: string;
}
export abstract class EmmetEditorAction extends EditorAction {
protected emmetActionName: string;
constructor(opts: IEmmetActionOptions) {
super(opts);
this.emmetActionName = opts.actionName;
}
private static readonly emmetSupportedModes = ['html', 'css', 'xml', 'xsl', 'haml', 'jade', 'jsx', 'slim', 'scss', 'sass', 'less', 'stylus', 'styl', 'svg'];
private _lastGrammarContributions: Promise<GrammarContributions> | null = null;
private _lastExtensionService: IExtensionService | null = null;
private _withGrammarContributions(extensionService: IExtensionService): Promise<GrammarContributions | null> {
if (this._lastExtensionService !== extensionService) {
this._lastExtensionService = extensionService;
this._lastGrammarContributions = extensionService.readExtensionPointContributions(grammarsExtPoint).then((contributions) => {
return new GrammarContributions(contributions);
});
}
return this._lastGrammarContributions || Promise.resolve(null);
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
const extensionService = accessor.get(IExtensionService);
const commandService = accessor.get(ICommandService);
return this._withGrammarContributions(extensionService).then((grammarContributions) => {
if (this.id === 'editor.emmet.action.expandAbbreviation' && grammarContributions) {
return commandService.executeCommand<void>('emmet.expandAbbreviation', EmmetEditorAction.getLanguage(editor, grammarContributions));
}
return undefined;
});
}
public static getLanguage(editor: ICodeEditor, grammars: IGrammarContributions) {
const model = editor.getModel();
const selection = editor.getSelection();
if (!model || !selection) {
return null;
}
const position = selection.getStartPosition();
model.tokenization.tokenizeIfCheap(position.lineNumber);
const languageId = model.getLanguageIdAtPosition(position.lineNumber, position.column);
const syntax = languageId.split('.').pop();
if (!syntax) {
return null;
}
let checkParentMode = (): string => {
let languageGrammar = grammars.getGrammar(syntax);
if (!languageGrammar) {
return syntax;
}
let languages = languageGrammar.split('.');
if (languages.length < 2) {
return syntax;
}
for (let i = 1; i < languages.length; i++) {
const language = languages[languages.length - i];
if (this.emmetSupportedModes.indexOf(language) !== -1) {
return language;
}
}
return syntax;
};
return {
language: syntax,
parentMode: checkParentMode()
};
}
}
|