From 5c5f93cdbcc763b94ed996d73ed4e5329e60d7a8 Mon Sep 17 00:00:00 2001 From: Erich Gamma Date: Wed, 18 Jul 2018 12:57:26 +0200 Subject: [PATCH] Support to run the selected script in the editor --- extensions/npm/README.md | 10 +++++++++ extensions/npm/package.json | 15 +++++++++++++ extensions/npm/package.nls.json | 3 ++- extensions/npm/src/main.ts | 30 ++++++++++++++++++++++++- extensions/npm/src/tasks.ts | 39 +++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) diff --git a/extensions/npm/README.md b/extensions/npm/README.md index 0b3961ff716..007cb59abe6 100644 --- a/extensions/npm/README.md +++ b/extensions/npm/README.md @@ -4,6 +4,8 @@ ## Features +### Task Running + This extension supports running npm scripts defined in the `package.json` as [tasks](https://code.visualstudio.com/docs/editor/tasks). Scripts with the name 'build', 'compile', or 'watch' are treated as build tasks. @@ -11,6 +13,14 @@ To run scripts as tasks, use the **Tasks** menu. For more information about auto detection of Tasks, see the [documentation](https://code.visualstudio.com/Docs/editor/tasks#_task-autodetection). +### Script Explorer + +The Npm Script Explorer shows the npm scripts found in your workspace. The explorer view is enabled by the setting `npm.enableScriptExplorer`. + +### Run Scripts from the Editor + +The extension provides commands to run the script containing the selection. + ## Settings - `npm.autoDetect` - Enable detecting scripts as tasks, the default is `on`. diff --git a/extensions/npm/package.json b/extensions/npm/package.json index df9c903fcb4..7856f52a62c 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -59,6 +59,10 @@ "dark": "resources/dark/continue.svg" } }, + { + "command": "npm.runScriptFromSource", + "title": "%command.runScriptFromSource%" + }, { "command": "npm.debugScript", "title": "%command.debug%", @@ -94,6 +98,10 @@ "command": "npm.runScript", "when": "false" }, + { + "command": "npm.runScriptFromSource", + "when": "false" + }, { "command": "npm.debugScript", "when": "false" @@ -114,6 +122,13 @@ "group": "navigation" } ], + "editor/context": [ + { + "command": "npm.runScriptFromSource", + "when": "resourceFilename == 'package.json'", + "group": "navigation@+1" + } + ], "view/item/context": [ { "command": "npm.openScript", diff --git a/extensions/npm/package.nls.json b/extensions/npm/package.nls.json index 92665d5f65a..70e8880002c 100644 --- a/extensions/npm/package.nls.json +++ b/extensions/npm/package.nls.json @@ -15,5 +15,6 @@ "command.run": "Run", "command.debug": "Debug", "command.openScript": "Open", - "command.runInstall": "Run Install" + "command.runInstall": "Run Install", + "command.runScriptFromSource": "Run Script" } diff --git a/extensions/npm/src/main.ts b/extensions/npm/src/main.ts index 023fddbffb6..66c6cad1c28 100644 --- a/extensions/npm/src/main.ts +++ b/extensions/npm/src/main.ts @@ -9,10 +9,14 @@ import * as vscode from 'vscode'; import { addJSONProviders } from './features/jsonContributions'; import { NpmScriptsTreeDataProvider } from './npmView'; -import { provideNpmScripts, invalidateScriptsCache } from './tasks'; +import { provideNpmScripts, invalidateScriptsCache, findScriptAtPosition, createTask } from './tasks'; + +import * as nls from 'vscode-nls'; let taskProvider: vscode.Disposable | undefined; +const localize = nls.loadMessageBundle(); + export async function activate(context: vscode.ExtensionContext): Promise { taskProvider = registerTaskProvider(context); const treeDataProvider = registerExplorer(context); @@ -32,6 +36,7 @@ export async function activate(context: vscode.ExtensionContext): Promise } }); context.subscriptions.push(addJSONProviders(httpRequest.xhr)); + context.subscriptions.push(vscode.commands.registerCommand('npm.runScriptFromSource', runScriptFromSource)); } function registerTaskProvider(context: vscode.ExtensionContext): vscode.Disposable | undefined { @@ -70,6 +75,29 @@ function configureHttpRequest() { httpRequest.configure(httpSettings.get('proxy', ''), httpSettings.get('proxyStrictSSL', true)); } +async function runScriptFromSource() { + let editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + let document = editor.document; + let contents = document.getText(); + let selection = editor.selection; + let offset = document.offsetAt(selection.anchor); + let script = findScriptAtPosition(contents, offset); + if (script) { + let uri = document.uri; + let folder = vscode.workspace.getWorkspaceFolder(uri); + if (folder) { + let task = createTask(script, `run ${script}`, folder, uri); + vscode.tasks.executeTask(task); + } + } else { + let message = localize('noScriptFound', 'Could not find a script at the selection.'); + vscode.window.showErrorMessage(message); + } +} + export function deactivate(): void { if (taskProvider) { taskProvider.dispose(); diff --git a/extensions/npm/src/tasks.ts b/extensions/npm/src/tasks.ts index 2c978a15267..55d81c70500 100644 --- a/extensions/npm/src/tasks.ts +++ b/extensions/npm/src/tasks.ts @@ -304,6 +304,45 @@ async function findAllScripts(buffer: string): Promise { return scripts; } +export function findScriptAtPosition(buffer: string, offset: number): string | undefined { + let script: string | undefined = undefined; + let inScripts = false; + let scriptStart: number | undefined; + + let visitor: JSONVisitor = { + onError(_error: ParseErrorCode, _offset: number, _length: number) { + // TODO: inform user about the parse error + }, + onObjectEnd() { + if (inScripts) { + inScripts = false; + scriptStart = undefined; + } + }, + onLiteralValue(value: any, nodeOffset: number, nodeLength: number) { + if (inScripts && scriptStart) { + if (offset >= scriptStart && offset < nodeOffset + nodeLength) { + // found the script + inScripts = false; + } else { + script = undefined; + } + } + }, + onObjectProperty(property: string, nodeOffset: number, nodeLength: number) { + if (property === 'scripts') { + inScripts = true; + } + else if (inScripts) { + scriptStart = nodeOffset; + script = property; + } + } + }; + visit(buffer, visitor); + return script; +} + export async function getScripts(packageJsonUri: Uri): Promise { if (packageJsonUri.scheme !== 'file') {