Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/vs/workbench/contrib/snippets/browser/commands/configureSnippets.ts')
-rw-r--r--src/vs/workbench/contrib/snippets/browser/commands/configureSnippets.ts279
1 files changed, 279 insertions, 0 deletions
diff --git a/src/vs/workbench/contrib/snippets/browser/commands/configureSnippets.ts b/src/vs/workbench/contrib/snippets/browser/commands/configureSnippets.ts
new file mode 100644
index 00000000000..3bc1b0b6b89
--- /dev/null
+++ b/src/vs/workbench/contrib/snippets/browser/commands/configureSnippets.ts
@@ -0,0 +1,279 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { isValidBasename } from 'vs/base/common/extpath';
+import { extname } from 'vs/base/common/path';
+import { basename, joinPath } from 'vs/base/common/resources';
+import { URI } from 'vs/base/common/uri';
+import { ILanguageService } from 'vs/editor/common/languages/language';
+import * as nls from 'vs/nls';
+import { MenuId } from 'vs/platform/actions/common/actions';
+import { IFileService } from 'vs/platform/files/common/files';
+import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
+import { IOpenerService } from 'vs/platform/opener/common/opener';
+import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
+import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
+import { SnippetsAction } from 'vs/workbench/contrib/snippets/browser/commands/abstractSnippetsActions';
+import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets';
+import { SnippetSource } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
+import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
+import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
+
+namespace ISnippetPick {
+ export function is(thing: object | undefined): thing is ISnippetPick {
+ return !!thing && URI.isUri((<ISnippetPick>thing).filepath);
+ }
+}
+
+interface ISnippetPick extends IQuickPickItem {
+ filepath: URI;
+ hint?: true;
+}
+
+async function computePicks(snippetService: ISnippetsService, userDataProfileService: IUserDataProfileService, languageService: ILanguageService) {
+
+ const existing: ISnippetPick[] = [];
+ const future: ISnippetPick[] = [];
+
+ const seen = new Set<string>();
+
+ for (const file of await snippetService.getSnippetFiles()) {
+
+ if (file.source === SnippetSource.Extension) {
+ // skip extension snippets
+ continue;
+ }
+
+ if (file.isGlobalSnippets) {
+
+ await file.load();
+
+ // list scopes for global snippets
+ const names = new Set<string>();
+ outer: for (const snippet of file.data) {
+ for (const scope of snippet.scopes) {
+ const name = languageService.getLanguageName(scope);
+ if (name) {
+ if (names.size >= 4) {
+ names.add(`${name}...`);
+ break outer;
+ } else {
+ names.add(name);
+ }
+ }
+ }
+ }
+
+ existing.push({
+ label: basename(file.location),
+ filepath: file.location,
+ description: names.size === 0
+ ? nls.localize('global.scope', "(global)")
+ : nls.localize('global.1', "({0})", [...names].join(', '))
+ });
+
+ } else {
+ // language snippet
+ const mode = basename(file.location).replace(/\.json$/, '');
+ existing.push({
+ label: basename(file.location),
+ description: `(${languageService.getLanguageName(mode)})`,
+ filepath: file.location
+ });
+ seen.add(mode);
+ }
+ }
+
+ const dir = userDataProfileService.currentProfile.snippetsHome;
+ for (const languageId of languageService.getRegisteredLanguageIds()) {
+ const label = languageService.getLanguageName(languageId);
+ if (label && !seen.has(languageId)) {
+ future.push({
+ label: languageId,
+ description: `(${label})`,
+ filepath: joinPath(dir, `${languageId}.json`),
+ hint: true
+ });
+ }
+ }
+
+ existing.sort((a, b) => {
+ const a_ext = extname(a.filepath.path);
+ const b_ext = extname(b.filepath.path);
+ if (a_ext === b_ext) {
+ return a.label.localeCompare(b.label);
+ } else if (a_ext === '.code-snippets') {
+ return -1;
+ } else {
+ return 1;
+ }
+ });
+
+ future.sort((a, b) => {
+ return a.label.localeCompare(b.label);
+ });
+
+ return { existing, future };
+}
+
+async function createSnippetFile(scope: string, defaultPath: URI, quickInputService: IQuickInputService, fileService: IFileService, textFileService: ITextFileService, opener: IOpenerService) {
+
+ function createSnippetUri(input: string) {
+ const filename = extname(input) !== '.code-snippets'
+ ? `${input}.code-snippets`
+ : input;
+ return joinPath(defaultPath, filename);
+ }
+
+ await fileService.createFolder(defaultPath);
+
+ const input = await quickInputService.input({
+ placeHolder: nls.localize('name', "Type snippet file name"),
+ async validateInput(input) {
+ if (!input) {
+ return nls.localize('bad_name1', "Invalid file name");
+ }
+ if (!isValidBasename(input)) {
+ return nls.localize('bad_name2', "'{0}' is not a valid file name", input);
+ }
+ if (await fileService.exists(createSnippetUri(input))) {
+ return nls.localize('bad_name3', "'{0}' already exists", input);
+ }
+ return undefined;
+ }
+ });
+
+ if (!input) {
+ return undefined;
+ }
+
+ const resource = createSnippetUri(input);
+
+ await textFileService.write(resource, [
+ '{',
+ '\t// Place your ' + scope + ' snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and ',
+ '\t// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope ',
+ '\t// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is ',
+ '\t// used to trigger the snippet and the body will be expanded and inserted. Possible variables are: ',
+ '\t// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. ',
+ '\t// Placeholders with the same ids are connected.',
+ '\t// Example:',
+ '\t// "Print to console": {',
+ '\t// \t"scope": "javascript,typescript",',
+ '\t// \t"prefix": "log",',
+ '\t// \t"body": [',
+ '\t// \t\t"console.log(\'$1\');",',
+ '\t// \t\t"$2"',
+ '\t// \t],',
+ '\t// \t"description": "Log output to console"',
+ '\t// }',
+ '}'
+ ].join('\n'));
+
+ await opener.open(resource);
+ return undefined;
+}
+
+async function createLanguageSnippetFile(pick: ISnippetPick, fileService: IFileService, textFileService: ITextFileService) {
+ if (await fileService.exists(pick.filepath)) {
+ return;
+ }
+ const contents = [
+ '{',
+ '\t// Place your snippets for ' + pick.label + ' here. Each snippet is defined under a snippet name and has a prefix, body and ',
+ '\t// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:',
+ '\t// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the ',
+ '\t// same ids are connected.',
+ '\t// Example:',
+ '\t// "Print to console": {',
+ '\t// \t"prefix": "log",',
+ '\t// \t"body": [',
+ '\t// \t\t"console.log(\'$1\');",',
+ '\t// \t\t"$2"',
+ '\t// \t],',
+ '\t// \t"description": "Log output to console"',
+ '\t// }',
+ '}'
+ ].join('\n');
+ await textFileService.write(pick.filepath, contents);
+}
+
+export class ConfigureSnippets extends SnippetsAction {
+
+ constructor() {
+ super({
+ id: 'workbench.action.openSnippets',
+ title: {
+ value: nls.localize('openSnippet.label', "Configure User Snippets"),
+ original: 'Configure User Snippets'
+ },
+ shortTitle: {
+ value: nls.localize('userSnippets', "User Snippets"),
+ mnemonicTitle: nls.localize({ key: 'miOpenSnippets', comment: ['&& denotes a mnemonic'] }, "User &&Snippets"),
+ original: 'User Snippets'
+ },
+ menu: [
+ { id: MenuId.CommandPalette },
+ { id: MenuId.MenubarPreferencesMenu, group: '3_snippets', order: 1 },
+ { id: MenuId.GlobalActivity, group: '3_snippets', order: 1 },
+ ]
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise<any> {
+
+ const snippetService = accessor.get(ISnippetsService);
+ const quickInputService = accessor.get(IQuickInputService);
+ const opener = accessor.get(IOpenerService);
+ const languageService = accessor.get(ILanguageService);
+ const userDataProfileService = accessor.get(IUserDataProfileService);
+ const workspaceService = accessor.get(IWorkspaceContextService);
+ const fileService = accessor.get(IFileService);
+ const textFileService = accessor.get(ITextFileService);
+
+ const picks = await computePicks(snippetService, userDataProfileService, languageService);
+ const existing: QuickPickInput[] = picks.existing;
+
+ type SnippetPick = IQuickPickItem & { uri: URI } & { scope: string };
+ const globalSnippetPicks: SnippetPick[] = [{
+ scope: nls.localize('new.global_scope', 'global'),
+ label: nls.localize('new.global', "New Global Snippets file..."),
+ uri: userDataProfileService.currentProfile.snippetsHome
+ }];
+
+ const workspaceSnippetPicks: SnippetPick[] = [];
+ for (const folder of workspaceService.getWorkspace().folders) {
+ workspaceSnippetPicks.push({
+ scope: nls.localize('new.workspace_scope', "{0} workspace", folder.name),
+ label: nls.localize('new.folder', "New Snippets file for '{0}'...", folder.name),
+ uri: folder.toResource('.vscode')
+ });
+ }
+
+ if (existing.length > 0) {
+ existing.unshift({ type: 'separator', label: nls.localize('group.global', "Existing Snippets") });
+ existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") });
+ } else {
+ existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") });
+ }
+
+ const pick = await quickInputService.pick(([] as QuickPickInput[]).concat(existing, globalSnippetPicks, workspaceSnippetPicks, picks.future), {
+ placeHolder: nls.localize('openSnippet.pickLanguage', "Select Snippets File or Create Snippets"),
+ matchOnDescription: true
+ });
+
+ if (globalSnippetPicks.indexOf(pick as SnippetPick) >= 0) {
+ return createSnippetFile((pick as SnippetPick).scope, (pick as SnippetPick).uri, quickInputService, fileService, textFileService, opener);
+ } else if (workspaceSnippetPicks.indexOf(pick as SnippetPick) >= 0) {
+ return createSnippetFile((pick as SnippetPick).scope, (pick as SnippetPick).uri, quickInputService, fileService, textFileService, opener);
+ } else if (ISnippetPick.is(pick)) {
+ if (pick.hint) {
+ await createLanguageSnippetFile(pick, fileService, textFileService);
+ }
+ return opener.open(pick.filepath);
+ }
+
+ }
+}