提交 f91e05b5 编写于 作者: D Dirk Baeumer

Fixes #11204: Provide Restart Current Task action

上级 2af4a3ad
/*---------------------------------------------------------------------------------------------
* 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 Filters = require('vs/base/common/filters');
import { TPromise } from 'vs/base/common/winjs.base';
import Quickopen = require('vs/workbench/browser/quickopen');
import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { Task } from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
export class TaskEntry extends Model.QuickOpenEntry {
constructor(protected taskService: ITaskService, protected task: Task, highlights: Model.IHighlight[] = []) {
super(highlights);
this.task = task;
}
public getLabel(): string {
return this.task.name;
}
public getAriaLabel(): string {
return nls.localize('entryAriaLabel', "{0}, tasks", this.getLabel());
}
}
export abstract class QuickOpenHandler extends Quickopen.QuickOpenHandler {
constructor(
@IQuickOpenService protected quickOpenService: IQuickOpenService,
@ITaskService protected taskService: ITaskService
) {
super();
this.quickOpenService = quickOpenService;
this.taskService = taskService;
}
public getResults(input: string): TPromise<Model.QuickOpenModel> {
return this.getTasks().then(tasks => tasks
.sort((a, b) => a.name.localeCompare(b.name))
.map(task => ({ task: task, highlights: Filters.matchesContiguousSubString(input, task.name) }))
.filter(({ highlights }) => !!highlights)
.map(({ task, highlights }) => this.createEntry(this.taskService, task, highlights))
, _ => []).then(e => new Model.QuickOpenModel(e));
}
protected abstract getTasks(): TPromise<Task[]>;
protected abstract createEntry(taskService: ITaskService, task: Task, highlights: Model.IHighlight[]): TaskEntry;
public getClass(): string {
return null;
}
public canRun(): boolean {
return true;
}
public getAutoFocus(input: string): QuickOpen.IAutoFocus {
return {
autoFocusFirstEntry: !!input
};
}
public onClose(canceled: boolean): void {
return;
}
public getGroupLabel(): string {
return null;
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 { TPromise } from 'vs/base/common/winjs.base';
import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { Task } from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
import * as base from './quickOpen';
class TaskEntry extends base.TaskEntry {
constructor(taskService: ITaskService, task: Task, highlights: Model.IHighlight[] = []) {
super(taskService, task, highlights);
}
public getAriaLabel(): string {
return nls.localize('entryAriaLabel', "{0}, tasks", this.getLabel());
}
public run(mode: QuickOpen.Mode, context: Model.IContext): boolean {
if (mode === QuickOpen.Mode.PREVIEW) {
return false;
}
this.taskService.restart(this.task._id);
return true;
}
}
export class QuickOpenHandler extends base.QuickOpenHandler {
constructor(
@IQuickOpenService quickOpenService: IQuickOpenService,
@ITaskService taskService: ITaskService
) {
super(quickOpenService, taskService);
}
public getAriaLabel(): string {
return nls.localize('tasksAriaLabel', "Type the name of a task to restart");
}
protected getTasks(): TPromise<Task[]> {
return this.taskService.getActiveTasks();
}
protected createEntry(taskService: ITaskService, task: Task, highlights: Model.IHighlight[]): base.TaskEntry {
return new TaskEntry(taskService, task, highlights);
}
public getEmptyLabel(searchString: string): string {
if (searchString.length > 0) {
return nls.localize('noTasksMatching', "No tasks matching");
}
return nls.localize('noTasksFound', "No tasks to restart found");
}
}
......@@ -5,9 +5,7 @@
'use strict';
import nls = require('vs/nls');
import Filters = require('vs/base/common/filters');
import { TPromise } from 'vs/base/common/winjs.base';
import Quickopen = require('vs/workbench/browser/quickopen');
import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
......@@ -15,19 +13,11 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { Task } from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
class TaskEntry extends Model.QuickOpenEntry {
private taskService: ITaskService;
private task: Task;
import * as base from './quickOpen';
class TaskEntry extends base.TaskEntry {
constructor(taskService: ITaskService, task: Task, highlights: Model.IHighlight[] = []) {
super(highlights);
this.taskService = taskService;
this.task = task;
}
public getLabel(): string {
return this.task.name;
super(taskService, task, highlights);
}
public getAriaLabel(): string {
......@@ -43,54 +33,24 @@ class TaskEntry extends Model.QuickOpenEntry {
}
}
export class QuickOpenHandler extends Quickopen.QuickOpenHandler {
private quickOpenService: IQuickOpenService;
private taskService: ITaskService;
export class QuickOpenHandler extends base.QuickOpenHandler {
constructor(
@IQuickOpenService quickOpenService: IQuickOpenService,
@ITaskService taskService: ITaskService
) {
super();
this.quickOpenService = quickOpenService;
this.taskService = taskService;
super(quickOpenService, taskService);
}
public getAriaLabel(): string {
return nls.localize('tasksAriaLabel', "Type the name of a task to run");
}
public getResults(input: string): TPromise<Model.QuickOpenModel> {
return this.taskService.tasks().then(tasks => tasks
.sort((a, b) => a.name.localeCompare(b.name))
.map(task => ({ task: task, highlights: Filters.matchesContiguousSubString(input, task.name) }))
.filter(({ highlights }) => !!highlights)
.map(({ task, highlights }) => new TaskEntry(this.taskService, task, highlights))
, _ => []).then(e => new Model.QuickOpenModel(e));
}
public getClass(): string {
return null;
protected getTasks(): TPromise<Task[]> {
return this.taskService.tasks();
}
public canRun(): boolean {
return true;
}
public getAutoFocus(input: string): QuickOpen.IAutoFocus {
return {
autoFocusFirstEntry: !!input
};
}
public onClose(canceled: boolean): void {
return;
}
public getGroupLabel(): string {
return null;
protected createEntry(taskService: ITaskService, task: Task, highlights: Model.IHighlight[]): base.TaskEntry {
return new TaskEntry(taskService, task, highlights);
}
public getEmptyLabel(searchString: string): string {
......@@ -99,4 +59,4 @@ export class QuickOpenHandler extends Quickopen.QuickOpenHandler {
}
return nls.localize('noTasksFound', "No tasks found");
}
}
}
\ No newline at end of file
......@@ -5,9 +5,7 @@
'use strict';
import nls = require('vs/nls');
import Filters = require('vs/base/common/filters');
import { TPromise } from 'vs/base/common/winjs.base';
import Quickopen = require('vs/workbench/browser/quickopen');
import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
......@@ -15,23 +13,11 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { Task } from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
class TaskEntry extends Model.QuickOpenEntry {
private taskService: ITaskService;
private task: Task;
import * as base from './quickOpen';
class TaskEntry extends base.TaskEntry {
constructor(taskService: ITaskService, task: Task, highlights: Model.IHighlight[] = []) {
super(highlights);
this.taskService = taskService;
this.task = task;
}
public getLabel(): string {
return this.task.name;
}
public getAriaLabel(): string {
return nls.localize('entryAriaLabel', "{0}, tasks", this.getLabel());
super(taskService, task, highlights);
}
public run(mode: QuickOpen.Mode, context: Model.IContext): boolean {
......@@ -43,54 +29,24 @@ class TaskEntry extends Model.QuickOpenEntry {
}
}
export class QuickOpenHandler extends Quickopen.QuickOpenHandler {
private quickOpenService: IQuickOpenService;
private taskService: ITaskService;
export class QuickOpenHandler extends base.QuickOpenHandler {
constructor(
@IQuickOpenService quickOpenService: IQuickOpenService,
@ITaskService taskService: ITaskService
) {
super();
this.quickOpenService = quickOpenService;
this.taskService = taskService;
super(quickOpenService, taskService);
}
public getAriaLabel(): string {
return nls.localize('tasksAriaLabel', "Type the name of a task to terminate");
}
public getResults(input: string): TPromise<Model.QuickOpenModel> {
return this.taskService.getActiveTasks().then(tasks => tasks
.sort((a, b) => a.name.localeCompare(b.name))
.map(task => ({ task: task, highlights: Filters.matchesContiguousSubString(input, task.name) }))
.filter(({ highlights }) => !!highlights)
.map(({ task, highlights }) => new TaskEntry(this.taskService, task, highlights))
, _ => []).then(e => new Model.QuickOpenModel(e));
}
public getClass(): string {
return null;
}
public canRun(): boolean {
return true;
}
public getAutoFocus(input: string): QuickOpen.IAutoFocus {
return {
autoFocusFirstEntry: !!input
};
}
public onClose(canceled: boolean): void {
return;
protected getTasks(): TPromise<Task[]> {
return this.taskService.getActiveTasks();
}
public getGroupLabel(): string {
return null;
protected createEntry(taskService: ITaskService, task: Task, highlights: Model.IHighlight[]): base.TaskEntry {
return new TaskEntry(taskService, task, highlights);
}
public getEmptyLabel(searchString: string): string {
......
......@@ -38,7 +38,8 @@ export interface ITaskService extends IEventEmitter {
inTerminal(): boolean;
isActive(): TPromise<boolean>;
getActiveTasks(): TPromise<Task[]>;
terminate(id: string): TPromise<TerminateResponse>;
restart(task: string | Task): void;
terminate(task: string | Task): TPromise<TerminateResponse>;
terminateAll(): TPromise<TerminateResponse>;
tasks(): TPromise<Task[]>;
......
......@@ -11,7 +11,7 @@ import 'vs/workbench/parts/tasks/browser/terminateQuickOpen';
import * as nls from 'vs/nls';
import { TPromise, Promise } from 'vs/base/common/winjs.base';
import { TPromise } from 'vs/base/common/winjs.base';
import Severity from 'vs/base/common/severity';
import * as Objects from 'vs/base/common/objects';
import { IStringDictionary } from 'vs/base/common/collections';
......@@ -562,6 +562,10 @@ class TaskService extends EventEmitter implements ITaskService {
this.runTaskCommand(accessor, arg);
});
CommandsRegistry.registerCommand('workbench.action.tasks.restartTask', (accessor, arg) => {
this.runRestartTaskCommand(accessor, arg);
});
CommandsRegistry.registerCommand('workbench.action.tasks.terminate', (accessor, arg) => {
this.runTerminateCommand();
});
......@@ -775,13 +779,31 @@ class TaskService extends EventEmitter implements ITaskService {
});
}
public restart(task: string | Task): void {
if (!this._taskSystem) {
return;
}
const id: string = Types.isString(task) ? task : task._id;
this._taskSystem.terminate(id).then((response) => {
if (response.success) {
this.emit(TaskServiceEvents.Terminated, {});
this.run(task);
} else {
this.messageService.show(Severity.Warning, nls.localize('TaskSystem.restartFailed', 'Failed to terminate and restart task {0}', Types.isString(task) ? task : task.name));
}
return response;
});
}
public terminate(task: string | Task): TPromise<TerminateResponse> {
if (!this._taskSystem) {
return TPromise.as({ success: true });
}
const id: string = Types.isString(task) ? task : task._id;
return this._taskSystem.terminate(id).then((response) => {
this.emit(TaskServiceEvents.Terminated, {});
if (response.success) {
this.emit(TaskServiceEvents.Terminated, {});
}
return response;
});
}
......@@ -1095,35 +1117,59 @@ class TaskService extends EventEmitter implements ITaskService {
return;
}
if (this.inTerminal()) {
if (!this._taskSystem) {
return;
}
let activeTasks = this._taskSystem.getActiveTasks();
if (activeTasks.length === 0) {
return;
}
if (activeTasks.length === 1) {
this._taskSystem.terminate(activeTasks[0]._id);
} else {
this.quickOpenService.show('terminate task ');
}
this.getActiveTasks().then((activeTasks) => {
if (activeTasks.length === 0) {
return;
}
if (activeTasks.length === 1) {
this.terminate(activeTasks[0]);
} else {
this.quickOpenService.show('terminate task ');
}
});
} else {
this.isActive().then((active) => {
if (active) {
this.terminateAll().then((response) => {
if (response.success) {
return undefined;
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
return;
}
if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
this.messageService.show(Severity.Error, nls.localize('TerminateAction.noProcess', 'The launched process doesn\'t exist anymore. If the task spawned background tasks exiting VS Code might result in orphaned processes.'));
return undefined;
} else {
return Promise.wrapError(nls.localize('TerminateAction.failed', 'Failed to terminate running task'));
this.messageService.show(Severity.Error, nls.localize('TerminateAction.failed', 'Failed to terminate running task'));
}
});
}
});
}
}
private runRestartTaskCommand(accessor: ServicesAccessor, arg: any): void {
if (!this.canRunCommand()) {
return;
}
if (this.inTerminal()) {
this.getActiveTasks().then((activeTasks) => {
if (activeTasks.length === 0) {
return;
}
if (activeTasks.length === 1) {
this.restart(activeTasks[0]);
} else {
this.quickOpenService.show('restart task ');
}
});
} else {
this.getActiveTasks().then((activeTasks) => {
if (activeTasks.length === 0) {
return;
}
let task = activeTasks[0];
this.restart(task);
});
}
}
}
......@@ -1132,6 +1178,7 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(Config
MenuRegistry.addCommand({ id: 'workbench.action.tasks.showLog', title: nls.localize('ShowLogAction.label', "Show Task Log"), alias: 'Tasks: Show Task Log', category: tasksCategory });
MenuRegistry.addCommand({ id: 'workbench.action.tasks.runTask', title: nls.localize('RunTaskAction.label', "Run Task"), alias: 'Tasks: Run Task', category: tasksCategory });
MenuRegistry.addCommand({ id: 'workbench.action.tasks.restartTask', title: nls.localize('RestartTaskAction.label', "Restart Task"), alias: 'Tasks: Restart Task', category: tasksCategory });
MenuRegistry.addCommand({ id: 'workbench.action.tasks.terminate', title: nls.localize('TerminateAction.label', "Terminate Running Task"), alias: 'Tasks: Terminate Running Task', category: tasksCategory });
MenuRegistry.addCommand({ id: 'workbench.action.tasks.build', title: nls.localize('BuildAction.label', "Run Build Task"), alias: 'Tasks: Run Build Task', category: tasksCategory });
MenuRegistry.addCommand({ id: 'workbench.action.tasks.test', title: nls.localize('TestAction.label', "Run Test Task"), alias: 'Tasks: Run Test Task', category: tasksCategory });
......@@ -1162,6 +1209,15 @@ quickOpenRegistry.registerQuickOpenHandler(
)
);
quickOpenRegistry.registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
'vs/workbench/parts/tasks/browser/restartQuickOpen',
'QuickOpenHandler',
'restart task ',
nls.localize('quickOpen.restartTask', "Restart Task")
)
);
// Status bar
let statusbarRegistry = <IStatusbarRegistry>Registry.as(StatusbarExtensions.Statusbar);
statusbarRegistry.registerStatusbarItem(new StatusbarItemDescriptor(StatusBarItem, StatusbarAlignment.LEFT, 50 /* Medium Priority */));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册