mirror of
https://github.com/Microsoft/vscode
synced 2024-10-06 03:17:00 +00:00
Grunt autodetection for terminal task runner
This commit is contained in:
parent
8f67f0721c
commit
5e4d510a36
|
@ -32,7 +32,8 @@ const extensions = [
|
|||
'css',
|
||||
'html',
|
||||
'git',
|
||||
'gulp'
|
||||
'gulp',
|
||||
'grunt'
|
||||
];
|
||||
|
||||
extensions.forEach(extension => npmInstall(`extensions/${extension}`));
|
||||
|
|
48
extensions/grunt/package.json
Normal file
48
extensions/grunt/package.json
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"name": "grunt",
|
||||
"publisher": "vscode",
|
||||
"description": "Extension to add Grunt capabilities to VSCode.",
|
||||
"displayName": "Grunt support for VSCode",
|
||||
"version": "0.0.1",
|
||||
"engines": {
|
||||
"vscode": "*"
|
||||
},
|
||||
"enableProposedApi": true,
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:gulp",
|
||||
"watch": "gulp watch-extension:gulp"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-nls": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^7.0.12"
|
||||
},
|
||||
"main": "./out/main",
|
||||
"activationEvents": [
|
||||
"onCommand:workbench.action.tasks.runTask",
|
||||
"onCommand:workbench.action.tasks.build",
|
||||
"onCommand:workbench.action.tasks.test"
|
||||
],
|
||||
"contributes": {
|
||||
"configuration": {
|
||||
"id": "grunt",
|
||||
"type": "object",
|
||||
"title": "Grunt",
|
||||
"properties": {
|
||||
"grunt.autoDetect": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"off",
|
||||
"on"
|
||||
],
|
||||
"default": "on",
|
||||
"description": "%config.grunt.autoDetect%"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
extensions/grunt/package.nls.json
Normal file
3
extensions/grunt/package.nls.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"config.grunt.autoDetect": "Controls whether auto detection of Grunt tasks is on or off. Default is on."
|
||||
}
|
176
extensions/grunt/src/main.ts
Normal file
176
extensions/grunt/src/main.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as cp from 'child_process';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
const localize = nls.config(process.env.VSCODE_NLS_CONFIG)();
|
||||
|
||||
type AutoDetect = 'on' | 'off';
|
||||
let taskProvider: vscode.Disposable | undefined;
|
||||
|
||||
export function activate(_context: vscode.ExtensionContext): void {
|
||||
let workspaceRoot = vscode.workspace.rootPath;
|
||||
if (!workspaceRoot) {
|
||||
return;
|
||||
}
|
||||
let pattern = path.join(workspaceRoot, 'Gruntfile.js');
|
||||
let detectorPromise: Thenable<vscode.Task[]> | undefined = undefined;
|
||||
let fileWatcher = vscode.workspace.createFileSystemWatcher(pattern);
|
||||
fileWatcher.onDidChange(() => detectorPromise = undefined);
|
||||
fileWatcher.onDidCreate(() => detectorPromise = undefined);
|
||||
fileWatcher.onDidDelete(() => detectorPromise = undefined);
|
||||
|
||||
function onConfigurationChanged() {
|
||||
let autoDetect = vscode.workspace.getConfiguration('grunt').get<AutoDetect>('autoDetect');
|
||||
if (taskProvider && autoDetect === 'off') {
|
||||
detectorPromise = undefined;
|
||||
taskProvider.dispose();
|
||||
taskProvider = undefined;
|
||||
} else if (!taskProvider && autoDetect === 'on') {
|
||||
taskProvider = vscode.workspace.registerTaskProvider({
|
||||
provideTasks: () => {
|
||||
if (!detectorPromise) {
|
||||
detectorPromise = getGruntTasks();
|
||||
}
|
||||
return detectorPromise;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
vscode.workspace.onDidChangeConfiguration(onConfigurationChanged);
|
||||
onConfigurationChanged();
|
||||
}
|
||||
|
||||
export function deactivate(): void {
|
||||
if (taskProvider) {
|
||||
taskProvider.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
function exists(file: string): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve, _reject) => {
|
||||
fs.exists(file, (value) => {
|
||||
resolve(value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function exec(command: string, options: cp.ExecOptions): Promise<{ stdout: string; stderr: string }> {
|
||||
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
|
||||
cp.exec(command, options, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject({ error, stdout, stderr });
|
||||
}
|
||||
resolve({ stdout, stderr });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function getGruntTasks(): Promise<vscode.Task[]> {
|
||||
let workspaceRoot = vscode.workspace.rootPath;
|
||||
let emptyTasks: vscode.Task[] = [];
|
||||
if (!workspaceRoot) {
|
||||
return emptyTasks;
|
||||
}
|
||||
let gruntfile = path.join(workspaceRoot, 'Gruntfile.js');
|
||||
if (!await exists(gruntfile)) {
|
||||
return emptyTasks;
|
||||
}
|
||||
|
||||
let command: string;
|
||||
let platform = process.platform;
|
||||
if (platform === 'win32' && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'grunt.cmd'))) {
|
||||
command = path.join('.', 'node_modules', '.bin', 'grunt.cmd');
|
||||
} else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'grunt'))) {
|
||||
command = path.join('.', 'node_modules', '.bin', 'grunt');
|
||||
} else {
|
||||
command = 'grunt';
|
||||
}
|
||||
|
||||
let commandLine = `${command} --help --no-color`;
|
||||
let channel = vscode.window.createOutputChannel('tasks');
|
||||
try {
|
||||
let { stdout, stderr } = await exec(commandLine, { cwd: workspaceRoot });
|
||||
if (stderr) {
|
||||
channel.appendLine(stderr);
|
||||
channel.show(true);
|
||||
}
|
||||
let result: vscode.Task[] = [];
|
||||
if (stdout) {
|
||||
let buildTask: { task: vscode.Task | undefined, rank: number } = { task: undefined, rank: 0 };
|
||||
let testTask: { task: vscode.Task | undefined, rank: number } = { task: undefined, rank: 0 };
|
||||
|
||||
// grunt lists tasks as follows (description is wrapped into a new line if too long):
|
||||
// ...
|
||||
// Available tasks
|
||||
// uglify Minify files with UglifyJS. *
|
||||
// jshint Validate files with JSHint. *
|
||||
// test Alias for "jshint", "qunit" tasks.
|
||||
// default Alias for "jshint", "qunit", "concat", "uglify" tasks.
|
||||
// long Alias for "eslint", "qunit", "browserify", "sass",
|
||||
// "autoprefixer", "uglify", tasks.
|
||||
//
|
||||
// Tasks run in the order specified
|
||||
|
||||
let lines = stdout.split(/\r{0,1}\n/);
|
||||
let tasksStart = false;
|
||||
let tasksEnd = false;
|
||||
for (let line of lines) {
|
||||
if (line.length === 0) {
|
||||
continue;
|
||||
}
|
||||
if (!tasksStart && !tasksEnd) {
|
||||
if (line.indexOf('Available tasks') === 0) {
|
||||
tasksStart = true;
|
||||
}
|
||||
} else if (tasksStart && !tasksEnd) {
|
||||
if (line.indexOf('Tasks run in the order specified') === 0) {
|
||||
tasksEnd = true;
|
||||
} else {
|
||||
let regExp = /^\s*(\S.*\S) \S/g;
|
||||
let matches = regExp.exec(line);
|
||||
if (matches && matches.length === 2) {
|
||||
let taskName = matches[1];
|
||||
let task = taskName.indexOf(' ') === -1
|
||||
? new vscode.ShellTask(`grunt: ${taskName}`, `${command} ${taskName}`)
|
||||
: new vscode.ShellTask(`grunt: ${taskName}`, `${command} "${taskName}"`);
|
||||
task.identifier = `grunt.${taskName}`;
|
||||
result.push(task);
|
||||
let lowerCaseTaskName = taskName.toLowerCase();
|
||||
if (lowerCaseTaskName === 'build') {
|
||||
buildTask = { task, rank: 2 };
|
||||
} else if (lowerCaseTaskName.indexOf('build') !== -1 && buildTask.rank < 1) {
|
||||
buildTask = { task, rank: 1 };
|
||||
} else if (lowerCaseTaskName === 'test') {
|
||||
testTask = { task, rank: 2 };
|
||||
} else if (lowerCaseTaskName.indexOf('test') !== -1 && testTask.rank < 1) {
|
||||
testTask = { task, rank: 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buildTask.task) {
|
||||
buildTask.task.group = vscode.TaskGroup.Build;
|
||||
}
|
||||
if (testTask.task) {
|
||||
testTask.task.group = vscode.TaskGroup.Test;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (err.stderr) {
|
||||
channel.appendLine(err.stderr);
|
||||
channel.show(true);
|
||||
}
|
||||
channel.appendLine(localize('execFailed', 'Auto detecting Grunt failed with error: {0}', err.error ? err.error.toString() : 'unknown'));
|
||||
return emptyTasks;
|
||||
}
|
||||
}
|
8
extensions/grunt/src/typings/refs.d.ts
vendored
Normal file
8
extensions/grunt/src/typings/refs.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
|
||||
/// <reference types='@types/node'/>
|
19
extensions/grunt/tsconfig.json
Normal file
19
extensions/grunt/tsconfig.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es2016"
|
||||
],
|
||||
"outDir": "./out",
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"out"
|
||||
]
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"config.gulp.autoDetect": "Controls whether auto detection of gulp tasks in on or off. Default is on."
|
||||
"config.gulp.autoDetect": "Controls whether auto detection of Gulp tasks is on or off. Default is on."
|
||||
}
|
Loading…
Reference in a new issue