Some polish for 'Run NPM Script in Folder'
This commit is contained in:
parent
aa9a4820e6
commit
7485ffde50
5 changed files with 48 additions and 40 deletions
|
@ -22,9 +22,9 @@ The Npm Script Explorer shows the npm scripts found in your workspace. The explo
|
||||||
The extension supports to run the selected script as a task when editing the `package.json`file. You can either run a script from
|
The extension supports to run the selected script as a task when editing the `package.json`file. You can either run a script from
|
||||||
the hover shown on a script or using the command `Run Selected Npm Script`.
|
the hover shown on a script or using the command `Run Selected Npm Script`.
|
||||||
|
|
||||||
### Run Scripts from a Folder in Explorer
|
### Run Scripts from a Folder in the Explorer
|
||||||
|
|
||||||
The extension supports running a script as a task from the Explorer. Right-click a folder in Explorer and select the `Run npm Script in Folder...` option to bring up a command palette listing the scripts that the folder contains. You can run the script by selecting from the options listed in the command palette.
|
The extension supports running a script as a task from a folder in the Explorer. The command `Run NPM Script in Folder...` shown in the Explorer context menu finds all scripts in `package.json` files that are contained in this folder. You can then select the script to be executed as a task from the resulting list. You enable this support with the `npm.runScriptFromFolder` which is `false` by default.
|
||||||
|
|
||||||
### Others
|
### Others
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ The extension fetches data from https://registry.npmjs.org and https://registry.
|
||||||
- `npm.exclude` - Glob patterns for folders that should be excluded from automatic script detection. The pattern is matched against the **absolute path** of the package.json. For example, to exclude all test folders use '**/test/**'.
|
- `npm.exclude` - Glob patterns for folders that should be excluded from automatic script detection. The pattern is matched against the **absolute path** of the package.json. For example, to exclude all test folders use '**/test/**'.
|
||||||
- `npm.enableScriptExplorer` - Enable an explorer view for npm scripts.
|
- `npm.enableScriptExplorer` - Enable an explorer view for npm scripts.
|
||||||
- `npm.scriptExplorerAction` - The default click action: `open` or `run`, the default is `open`.
|
- `npm.scriptExplorerAction` - The default click action: `open` or `run`, the default is `open`.
|
||||||
- `npm.enableRunFromFolderContextMenu` - Enable running npm scripts from the context menu of folders in Explorer, the default is `false`.
|
- `npm.enableRunFromFolder` - Enable running npm scripts from the context menu of folders in Explorer, the default is `false`.
|
||||||
- `npm.scriptCodeLens.enable` - Enable/disable the code lenses to run a script, the default is `false`.
|
- `npm.scriptCodeLens.enable` - Enable/disable the code lenses to run a script, the default is `false`.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@
|
||||||
],
|
],
|
||||||
"explorer/context": [
|
"explorer/context": [
|
||||||
{
|
{
|
||||||
"when": "config.npm.enableRunFromFolderContextMenu && explorerViewletVisible && explorerResourceIsFolder",
|
"when": "config.npm.enableRunFromFolder && explorerViewletVisible && explorerResourceIsFolder",
|
||||||
"command": "npm.runScriptFromFolder",
|
"command": "npm.runScriptFromFolder",
|
||||||
"group": "2_workspace"
|
"group": "2_workspace"
|
||||||
}
|
}
|
||||||
|
@ -237,11 +237,11 @@
|
||||||
"scope": "resource",
|
"scope": "resource",
|
||||||
"description": "%config.npm.enableScriptExplorer%"
|
"description": "%config.npm.enableScriptExplorer%"
|
||||||
},
|
},
|
||||||
"npm.enableRunFromFolderContextMenu": {
|
"npm.enableRunFromFolder": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"scope": "resource",
|
"scope": "resource",
|
||||||
"description": "%config.npm.enableRunFromFolderContextMenu%"
|
"description": "%config.npm.enableRunFromFolder%"
|
||||||
},
|
},
|
||||||
"npm.scriptExplorerAction": {
|
"npm.scriptExplorerAction": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
{
|
{
|
||||||
"description": "Extension to add task support for npm scripts.",
|
"description": "Extension to add task support for npm scripts.",
|
||||||
"displayName": "Npm support for VS Code",
|
"displayName": "NPM support for VS Code",
|
||||||
"config.npm.autoDetect": "Controls whether npm scripts should be automatically detected.",
|
"config.npm.autoDetect": "Controls whether npm scripts should be automatically detected.",
|
||||||
"config.npm.runSilent": "Run npm commands with the `--silent` option.",
|
"config.npm.runSilent": "Run npm commands with the `--silent` option.",
|
||||||
"config.npm.packageManager": "The package manager used to run scripts.",
|
"config.npm.packageManager": "The package manager used to run scripts.",
|
||||||
"config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.",
|
"config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.",
|
||||||
"config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts when there is no top-level 'package.json' file.",
|
"config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts when there is no top-level 'package.json' file.",
|
||||||
"config.npm.scriptExplorerAction": "The default click action used in the scripts explorer: `open` or `run`, the default is `open`.",
|
"config.npm.scriptExplorerAction": "The default click action used in the npm scripts explorer: `open` or `run`, the default is `open`.",
|
||||||
"config.npm.enableRunFromFolderContextMenu": "Enable running scripts from the context menu of a folder in Explorer",
|
"config.npm.enableRunFromFolder": "Enable running NPM scripts contained in a folder from the Explorer context menu.",
|
||||||
"config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.",
|
"config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.",
|
||||||
"npm.parseError": "Npm task detection: failed to parse the file {0}",
|
"npm.parseError": "Npm task detection: failed to parse the file {0}",
|
||||||
"taskdef.script": "The npm script to customize.",
|
"taskdef.script": "The npm script to customize.",
|
||||||
"taskdef.path": "The path to the folder of the package.json file that provides the script. Can be omitted.",
|
"taskdef.path": "The path to the folder of the package.json file that provides the script. Can be omitted.",
|
||||||
"view.name": "Npm Scripts",
|
"view.name": "NPM Scripts",
|
||||||
"command.refresh": "Refresh",
|
"command.refresh": "Refresh",
|
||||||
"command.run": "Run",
|
"command.run": "Run",
|
||||||
"command.debug": "Debug",
|
"command.debug": "Debug",
|
||||||
"command.openScript": "Open",
|
"command.openScript": "Open",
|
||||||
"command.runInstall": "Run Install",
|
"command.runInstall": "Run Install",
|
||||||
"command.runSelectedScript": "Run Script",
|
"command.runSelectedScript": "Run Script",
|
||||||
"command.runScriptFromFolder": "Run npm Script in Folder..."
|
"command.runScriptFromFolder": "Run NPM Script in Folder..."
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ import * as vscode from 'vscode';
|
||||||
import {
|
import {
|
||||||
detectNpmScriptsForFolder,
|
detectNpmScriptsForFolder,
|
||||||
findScriptAtPosition,
|
findScriptAtPosition,
|
||||||
runScript
|
runScript,
|
||||||
|
FolderTaskItem
|
||||||
} from './tasks';
|
} from './tasks';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
@ -34,10 +35,29 @@ export function runSelectedScript() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectAndRunScriptFromFolder(selectedFolder: vscode.Uri) {
|
export async function selectAndRunScriptFromFolder(selectedFolder: vscode.Uri) {
|
||||||
let taskList: { label: string, task: vscode.Task }[] = await detectNpmScriptsForFolder(selectedFolder);
|
let taskList: FolderTaskItem[] = await detectNpmScriptsForFolder(selectedFolder);
|
||||||
|
|
||||||
if (taskList && taskList.length > 0) {
|
if (taskList && taskList.length > 0) {
|
||||||
let result = await vscode.window.showQuickPick(taskList, { placeHolder: 'Select script' });
|
const quickPick = vscode.window.createQuickPick<FolderTaskItem>();
|
||||||
|
quickPick.title = 'Run NPM script in Folder';
|
||||||
|
quickPick.placeholder = 'Select an npm script';
|
||||||
|
quickPick.items = taskList;
|
||||||
|
|
||||||
|
const toDispose: vscode.Disposable[] = [];
|
||||||
|
|
||||||
|
let pickPromise = new Promise<FolderTaskItem | undefined>((c) => {
|
||||||
|
toDispose.push(quickPick.onDidAccept(() => {
|
||||||
|
toDispose.forEach(d => d.dispose());
|
||||||
|
c(quickPick.selectedItems[0]);
|
||||||
|
}));
|
||||||
|
toDispose.push(quickPick.onDidHide(() => {
|
||||||
|
toDispose.forEach(d => d.dispose());
|
||||||
|
c(undefined);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
quickPick.show();
|
||||||
|
let result = await pickPromise;
|
||||||
|
quickPick.dispose();
|
||||||
if (result) {
|
if (result) {
|
||||||
vscode.tasks.executeTask(result.task);
|
vscode.tasks.executeTask(result.task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TaskDefinition, Task, TaskGroup, WorkspaceFolder, RelativePattern, ShellExecution, Uri, workspace,
|
TaskDefinition, Task, TaskGroup, WorkspaceFolder, RelativePattern, ShellExecution, Uri, workspace,
|
||||||
DebugConfiguration, debug, TaskProvider, TextDocument, tasks, TaskScope
|
DebugConfiguration, debug, TaskProvider, TextDocument, tasks, TaskScope, QuickPickItem
|
||||||
} from 'vscode';
|
} from 'vscode';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
@ -20,6 +20,11 @@ export interface NpmTaskDefinition extends TaskDefinition {
|
||||||
path?: string;
|
path?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FolderTaskItem extends QuickPickItem {
|
||||||
|
label: string;
|
||||||
|
task: Task;
|
||||||
|
}
|
||||||
|
|
||||||
type AutoDetect = 'on' | 'off';
|
type AutoDetect = 'on' | 'off';
|
||||||
|
|
||||||
let cachedTasks: Task[] | undefined = undefined;
|
let cachedTasks: Task[] | undefined = undefined;
|
||||||
|
@ -156,39 +161,22 @@ async function detectNpmScripts(): Promise<Task[]> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function detectNpmScriptsForFolder(folder: Uri): Promise<{ label: string, task: Task }[]> {
|
export async function detectNpmScriptsForFolder(folder: Uri): Promise<FolderTaskItem[]> {
|
||||||
|
|
||||||
let folderTasks: { label: string, task: Task }[] = [];
|
let folderTasks: FolderTaskItem[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let relativePattern = new RelativePattern(folder.fsPath, '**/package.json');
|
let relativePattern = new RelativePattern(folder.fsPath, '**/package.json');
|
||||||
let paths = await workspace.findFiles(relativePattern, '**/node_modules/**');
|
let paths = await workspace.findFiles(relativePattern, '**/node_modules/**');
|
||||||
|
|
||||||
if (cachedTasks) {
|
let visitedPackageJsonFiles: Set<string> = new Set();
|
||||||
let workspaceFolder = workspace.getWorkspaceFolder(folder);
|
for (const path of paths) {
|
||||||
if (workspaceFolder) {
|
if (!visitedPackageJsonFiles.has(path.fsPath)) {
|
||||||
let rootUri = workspaceFolder.uri.path;
|
let tasks = await provideNpmScriptsForFolder(path);
|
||||||
if (rootUri === folder.path) {
|
visitedPackageJsonFiles.add(path.fsPath);
|
||||||
return cachedTasks.map(t => ({ label: t.name, task: t }));
|
folderTasks.push(...tasks.map(t => ({ label: t.name, task: t })));
|
||||||
}
|
|
||||||
|
|
||||||
let relativePaths = paths.map(p => ' - ' + p.path.substring(rootUri.length + 1, p.path.length - '/package.json'.length));
|
|
||||||
for (const relativePath of relativePaths) {
|
|
||||||
folderTasks.push(...cachedTasks.filter(t => t.name.endsWith(relativePath)).map(t => ({ label: t.name, task: t })));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
let visitedPackageJsonFiles: Set<string> = new Set();
|
|
||||||
for (const path of paths) {
|
|
||||||
if (!visitedPackageJsonFiles.has(path.fsPath)) {
|
|
||||||
let tasks = await provideNpmScriptsForFolder(path);
|
|
||||||
visitedPackageJsonFiles.add(path.fsPath);
|
|
||||||
folderTasks.push(...tasks.map(t => ({ label: t.name, task: t })));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return folderTasks;
|
return folderTasks;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|
Loading…
Reference in a new issue