/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; import nls = require('vs/nls'); import winjs = require('vs/base/common/winjs.base'); import paths = require('vs/base/common/paths'); import actions = require('vs/base/common/actions'); import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; import platform = require('vs/platform/platform'); import workbenchActionRegistry = require('vs/workbench/browser/actionRegistry'); import workbenchContributions = require('vs/workbench/common/contributions'); import snippetsTracker = require('./snippetsTracker'); import modesExtensions = require('vs/editor/common/modes/modesRegistry'); import errors = require('vs/base/common/errors'); import {IQuickOpenService, IPickOpenEntry} from 'vs/workbench/services/quickopen/browser/quickOpenService'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import {IJSONSchema} from 'vs/base/common/jsonSchema'; import ipc = require('ipc'); import fs = require('fs'); class OpenSnippetsAction extends actions.Action { public static ID = 'workbench.action.openSnippets'; public static LABEL = nls.localize('openSnippet.label', 'Snippets'); constructor( id: string, label:string, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IQuickOpenService private quickOpenService:IQuickOpenService ) { super(id, label); } private openFile(filePath: string): void { ipc.send('vscode:windowOpen', [filePath], false /* force new window */); // handled from browser process } public run(): winjs.Promise { var modesRegistry = platform.Registry.as(modesExtensions.Extensions.EditorModes); var modeIds = modesRegistry.getRegisteredModes(); var picks: IPickOpenEntry[] = []; modeIds.forEach((modeId) => { var name = modesRegistry.getLanguageName(modeId); if (name) { picks.push({ label: name, id: modeId }); } }); picks = picks.sort((e1, e2) => e1.label.localeCompare(e2.label) ); return this.quickOpenService.pick(picks, { placeHolder: nls.localize('openSnippet.pickLanguage', "Select Language for Snippet") }).then((language) => { if (language) { var snippetPath = paths.join(this.contextService.getConfiguration().env.appSettingsHome, 'snippets', language.id + '.json'); return fileExists(snippetPath).then((success) => { if (success) { this.openFile(snippetPath); return winjs.Promise.as(null); } var defaultContent = [ '{', '/*', '\t // Place your snippets for ' + language.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, ${id} and ${id:label} and ${1:label} for variables. Variables with the same id 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'); return createFile(snippetPath, defaultContent).then(() => { this.openFile(snippetPath); }, (err) => { errors.onUnexpectedError(nls.localize('openSnippet.errorOnCreate', 'Unable to create {0}', snippetPath)); }); }); } return winjs.Promise.as(null); }); } } function fileExists(path: string): winjs.TPromise { return new winjs.TPromise((c, e, p) => { fs.stat(path,(err, stats) => { if (err) { return c(false); } if (stats.isFile()) { return c(true); } c(false); }); }); } function createFile(path: string, content: string): winjs.Promise { return new winjs.Promise((c, e, p) => { fs.writeFile(path, content, function(err) { if(err) { e(err); } c(true); }); }); } var preferencesCategory = nls.localize('preferences', "Preferences"); var workbenchActionsRegistry = platform.Registry.as(workbenchActionRegistry.Extensions.WorkbenchActions); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenSnippetsAction, OpenSnippetsAction.ID, OpenSnippetsAction.LABEL), preferencesCategory); (platform.Registry.as(workbenchContributions.Extensions.Workbench)).registerWorkbenchContribution( snippetsTracker.SnippetsTracker ); let schemaId = 'local://schemas/snippets'; let schema : IJSONSchema = { 'id': schemaId, 'default': { '{{snippetName}}': { 'prefix': '{{prefix}}', 'body': '{{snippet}}', 'description': '{{description}}' } }, 'type': 'object', 'description': nls.localize('snippetSchema.json', 'User snippet configuration'), 'additionalProperties': { 'type': 'object', 'required': ['prefix', 'body'], 'properties': { 'prefix': { 'description': nls.localize('snippetSchema.json.prefix', 'The prefix to used when selecting the snippet in intellisense'), 'type': 'string' }, 'body': { 'description': nls.localize('snippetSchema.json.body', 'The snippet content. Use \'${id}\', \'${id:label}\', \'${1:label}\' for variables and \'$0\', \'$1\' for the cursor positions'), 'type': ['string', 'array'], 'items': { 'type': 'string' } }, 'description': { 'description': nls.localize('snippetSchema.json.description', 'The snippet description.'), 'type': 'string' } }, 'additionalProperties': false } }; let schemaRegistry = platform.Registry.as(JSONContributionRegistry.Extensions.JSONContribution); schemaRegistry.registerSchema(schemaId, schema); schemaRegistry.addSchemaFileAssociation('%APP_SETTINGS_HOME%/snippets/*.json', schemaId);