Skip to content

Commit 5c5f93c

Browse files
committed
Support to run the selected script in the editor
1 parent c82766c commit 5c5f93c

5 files changed

Lines changed: 95 additions & 2 deletions

File tree

extensions/npm/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,23 @@
44

55
## Features
66

7+
### Task Running
8+
79
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'
810
are treated as build tasks.
911

1012
To run scripts as tasks, use the **Tasks** menu.
1113

1214
For more information about auto detection of Tasks, see the [documentation](https://code.visualstudio.com/Docs/editor/tasks#_task-autodetection).
1315

16+
### Script Explorer
17+
18+
The Npm Script Explorer shows the npm scripts found in your workspace. The explorer view is enabled by the setting `npm.enableScriptExplorer`.
19+
20+
### Run Scripts from the Editor
21+
22+
The extension provides commands to run the script containing the selection.
23+
1424
## Settings
1525

1626
- `npm.autoDetect` - Enable detecting scripts as tasks, the default is `on`.

extensions/npm/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
"dark": "resources/dark/continue.svg"
6060
}
6161
},
62+
{
63+
"command": "npm.runScriptFromSource",
64+
"title": "%command.runScriptFromSource%"
65+
},
6266
{
6367
"command": "npm.debugScript",
6468
"title": "%command.debug%",
@@ -94,6 +98,10 @@
9498
"command": "npm.runScript",
9599
"when": "false"
96100
},
101+
{
102+
"command": "npm.runScriptFromSource",
103+
"when": "false"
104+
},
97105
{
98106
"command": "npm.debugScript",
99107
"when": "false"
@@ -114,6 +122,13 @@
114122
"group": "navigation"
115123
}
116124
],
125+
"editor/context": [
126+
{
127+
"command": "npm.runScriptFromSource",
128+
"when": "resourceFilename == 'package.json'",
129+
"group": "navigation@+1"
130+
}
131+
],
117132
"view/item/context": [
118133
{
119134
"command": "npm.openScript",

extensions/npm/package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"command.run": "Run",
1616
"command.debug": "Debug",
1717
"command.openScript": "Open",
18-
"command.runInstall": "Run Install"
18+
"command.runInstall": "Run Install",
19+
"command.runScriptFromSource": "Run Script"
1920
}

extensions/npm/src/main.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ import * as vscode from 'vscode';
99

1010
import { addJSONProviders } from './features/jsonContributions';
1111
import { NpmScriptsTreeDataProvider } from './npmView';
12-
import { provideNpmScripts, invalidateScriptsCache } from './tasks';
12+
import { provideNpmScripts, invalidateScriptsCache, findScriptAtPosition, createTask } from './tasks';
13+
14+
import * as nls from 'vscode-nls';
1315

1416
let taskProvider: vscode.Disposable | undefined;
1517

18+
const localize = nls.loadMessageBundle();
19+
1620
export async function activate(context: vscode.ExtensionContext): Promise<void> {
1721
taskProvider = registerTaskProvider(context);
1822
const treeDataProvider = registerExplorer(context);
@@ -32,6 +36,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
3236
}
3337
});
3438
context.subscriptions.push(addJSONProviders(httpRequest.xhr));
39+
context.subscriptions.push(vscode.commands.registerCommand('npm.runScriptFromSource', runScriptFromSource));
3540
}
3641

3742
function registerTaskProvider(context: vscode.ExtensionContext): vscode.Disposable | undefined {
@@ -70,6 +75,29 @@ function configureHttpRequest() {
7075
httpRequest.configure(httpSettings.get<string>('proxy', ''), httpSettings.get<boolean>('proxyStrictSSL', true));
7176
}
7277

78+
async function runScriptFromSource() {
79+
let editor = vscode.window.activeTextEditor;
80+
if (!editor) {
81+
return;
82+
}
83+
let document = editor.document;
84+
let contents = document.getText();
85+
let selection = editor.selection;
86+
let offset = document.offsetAt(selection.anchor);
87+
let script = findScriptAtPosition(contents, offset);
88+
if (script) {
89+
let uri = document.uri;
90+
let folder = vscode.workspace.getWorkspaceFolder(uri);
91+
if (folder) {
92+
let task = createTask(script, `run ${script}`, folder, uri);
93+
vscode.tasks.executeTask(task);
94+
}
95+
} else {
96+
let message = localize('noScriptFound', 'Could not find a script at the selection.');
97+
vscode.window.showErrorMessage(message);
98+
}
99+
}
100+
73101
export function deactivate(): void {
74102
if (taskProvider) {
75103
taskProvider.dispose();

extensions/npm/src/tasks.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,45 @@ async function findAllScripts(buffer: string): Promise<StringMap> {
304304
return scripts;
305305
}
306306

307+
export function findScriptAtPosition(buffer: string, offset: number): string | undefined {
308+
let script: string | undefined = undefined;
309+
let inScripts = false;
310+
let scriptStart: number | undefined;
311+
312+
let visitor: JSONVisitor = {
313+
onError(_error: ParseErrorCode, _offset: number, _length: number) {
314+
// TODO: inform user about the parse error
315+
},
316+
onObjectEnd() {
317+
if (inScripts) {
318+
inScripts = false;
319+
scriptStart = undefined;
320+
}
321+
},
322+
onLiteralValue(value: any, nodeOffset: number, nodeLength: number) {
323+
if (inScripts && scriptStart) {
324+
if (offset >= scriptStart && offset < nodeOffset + nodeLength) {
325+
// found the script
326+
inScripts = false;
327+
} else {
328+
script = undefined;
329+
}
330+
}
331+
},
332+
onObjectProperty(property: string, nodeOffset: number, nodeLength: number) {
333+
if (property === 'scripts') {
334+
inScripts = true;
335+
}
336+
else if (inScripts) {
337+
scriptStart = nodeOffset;
338+
script = property;
339+
}
340+
}
341+
};
342+
visit(buffer, visitor);
343+
return script;
344+
}
345+
307346
export async function getScripts(packageJsonUri: Uri): Promise<StringMap | undefined> {
308347

309348
if (packageJsonUri.scheme !== 'file') {

0 commit comments

Comments
 (0)