diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 7d5e1983a4f..1b87df5d5d6 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -749,10 +749,14 @@ export class SelectActionItem extends BaseActionItem { private registerListeners(): void { this.toDispose.push(DOM.addStandardDisposableListener(this.select, 'change', (e) => { - this.actionRunner.run(this._action, e.target.value).done(); + this.actionRunner.run(this._action, this.getActionContext(e.target.value)).done(); })); } + protected getActionContext(option: string) { + return option; + } + public focus(): void { if (this.select) { this.select.focus(); diff --git a/src/vs/workbench/api/node/extHostOutputService.ts b/src/vs/workbench/api/node/extHostOutputService.ts index a8ef4e7f918..9dca2e375ba 100644 --- a/src/vs/workbench/api/node/extHostOutputService.ts +++ b/src/vs/workbench/api/node/extHostOutputService.ts @@ -87,7 +87,7 @@ export class MainThreadOutputService { } public getOutputChannel(channelId): IOutputChannel { - return this._outputService.getOutputChannel(channelId); + return this._outputService.getChannel(channelId); } public close(channel: string): TPromise { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts index 0cb6789a924..c12f07007d8 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts @@ -115,7 +115,7 @@ export class ExtensionsStatusbarItem implements IStatusbarItem { const name = extension && extension.name; const message = name ? `${ name }: ${ m.message }` : m.message; - const outputChannel = this.outputService.getOutputChannel(ExtensionsChannelId); + const outputChannel = this.outputService.getChannel(ExtensionsChannelId); outputChannel.append(message); outputChannel.show(true); }); diff --git a/src/vs/workbench/parts/git/browser/gitOutput.ts b/src/vs/workbench/parts/git/browser/gitOutput.ts index 9f65bf01728..59c76e209d4 100644 --- a/src/vs/workbench/parts/git/browser/gitOutput.ts +++ b/src/vs/workbench/parts/git/browser/gitOutput.ts @@ -47,7 +47,7 @@ export class GitOutput implements ext.IWorkbenchContribution { } private onOutput(output: string): void { - this.outputService.getOutputChannel('Git').append(output); + this.outputService.getChannel('Git').append(output); } public dispose(): void { diff --git a/src/vs/workbench/parts/git/browser/gitServices.ts b/src/vs/workbench/parts/git/browser/gitServices.ts index 7f64e7e2113..aa0fdf0dd35 100644 --- a/src/vs/workbench/parts/git/browser/gitServices.ts +++ b/src/vs/workbench/parts/git/browser/gitServices.ts @@ -689,7 +689,7 @@ export class GitService extends ee.EventEmitter } var error: Error; - var showOutputAction = new actions.Action('show.gitOutput', nls.localize('showOutput', "Show Output"), null, true, () => this.outputService.getOutputChannel('Git').show()); + var showOutputAction = new actions.Action('show.gitOutput', nls.localize('showOutput', "Show Output"), null, true, () => this.outputService.getChannel('Git').show()); var cancelAction = new actions.Action('close.message', nls.localize('cancel', "Cancel"), null, true, ()=>winjs.TPromise.as(true)); error = errors.create( diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts index fcc9f7a896d..eaa0046d93e 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts @@ -264,7 +264,7 @@ export class ChangesView extends EventEmitter.EventEmitter implements GitView.IV this.instantiationService.createInstance(GitActions.GlobalUnstageAction), this.instantiationService.createInstance(GitActions.GlobalUndoAction), new ActionBar.Separator(), - new Actions.Action('show.gitOutput', nls.localize('showOutput', "Show Git Output"), null, true, () => this.outputService.getOutputChannel('Git').show()) + new Actions.Action('show.gitOutput', nls.localize('showOutput', "Show Git Output"), null, true, () => this.outputService.getChannel('Git').show()) ]; this.secondaryActions.forEach(a => this.toDispose.push(a)); diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index e7ac36bc815..d3948d753db 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -38,7 +38,7 @@ export class ToggleOutputAction extends Action { return TPromise.as(null); } - return this.outputService.getOutputChannel(this.outputService.getActiveChannelId()).show(); + return this.outputService.getActiveChannel().show(); } } @@ -52,7 +52,7 @@ export class ClearOutputAction extends Action { } public run(): TPromise { - this.outputService.getOutputChannel(this.outputService.getActiveChannelId()).clear(); + this.outputService.getActiveChannel().clear(); this.panelService.getActivePanel().focus(); return TPromise.as(true); @@ -83,7 +83,7 @@ export class ClearOutputEditorAction extends EditorAction { } public run(): TPromise { - this.outputService.getOutputChannel(this.outputService.getActiveChannelId()).clear(); + this.outputService.getActiveChannel().clear(); return TPromise.as(false); } } @@ -99,7 +99,7 @@ export class SwitchOutputAction extends Action { } public run(channelId?: string): TPromise { - return this.outputService.getOutputChannel(channelId).show(); + return this.outputService.getChannel(channelId).show(); } } @@ -109,19 +109,25 @@ export class SwitchOutputActionItem extends SelectActionItem { action: IAction, @IOutputService private outputService: IOutputService ) { - super(null, action, SwitchOutputActionItem.getChannels(outputService), Math.max(0, SwitchOutputActionItem.getChannels(outputService).indexOf(outputService.getActiveChannelId()))); + super(null, action, SwitchOutputActionItem.getChannelLabels(outputService), Math.max(0, SwitchOutputActionItem.getChannelLabels(outputService).indexOf(outputService.getActiveChannel().label))); this.toDispose.push(this.outputService.onOutputChannel(this.onOutputChannel, this)); this.toDispose.push(this.outputService.onActiveOutputChannel(this.onOutputChannel, this)); } + protected getActionContext(option: string): string { + const channel = (Registry.as(Extensions.OutputChannels)).getChannels().filter(channelData => channelData.label === option).pop(); + + return channel ? channel.id : option; + } + private onOutputChannel(): void { - let channels = SwitchOutputActionItem.getChannels(this.outputService); - let selected = Math.max(0, channels.indexOf(this.outputService.getActiveChannelId())); + let channels = SwitchOutputActionItem.getChannelLabels(this.outputService); + let selected = Math.max(0, channels.indexOf(this.outputService.getActiveChannel().label)); this.setOptions(channels, selected); } - private static getChannels(outputService: IOutputService): string[] { + private static getChannelLabels(outputService: IOutputService): string[] { const contributedChannels = (Registry.as(Extensions.OutputChannels)).getChannels().map(channelData => channelData.label); return contributedChannels.sort(); // sort by name } diff --git a/src/vs/workbench/parts/output/browser/outputPanel.ts b/src/vs/workbench/parts/output/browser/outputPanel.ts index 172ee56f91c..48c56a64ea5 100644 --- a/src/vs/workbench/parts/output/browser/outputPanel.ts +++ b/src/vs/workbench/parts/output/browser/outputPanel.ts @@ -85,8 +85,8 @@ export class OutputPanel extends StringEditor { options.rulers = []; options.folding = false; - let channel = this.outputService.getActiveChannelId(); - options.ariaLabel = channel ? nls.localize('outputPanelWithInputAriaLabel', "{0}, Output panel", channel) : nls.localize('outputPanelAriaLabel', "Output panel"); + const channel = this.outputService.getActiveChannel(); + options.ariaLabel = channel ? nls.localize('outputPanelWithInputAriaLabel', "{0}, Output panel", channel.label) : nls.localize('outputPanelAriaLabel', "Output panel"); return options; } @@ -97,7 +97,7 @@ export class OutputPanel extends StringEditor { public create(parent: Builder): TPromise { return super.create(parent) - .then(() => this.setInput(OutputEditorInput.getInstance(this.instantiationService, this.outputService.getActiveChannelId()), null)); + .then(() => this.setInput(OutputEditorInput.getInstance(this.instantiationService, this.outputService.getActiveChannel()), null)); } public focus(): void { diff --git a/src/vs/workbench/parts/output/common/output.ts b/src/vs/workbench/parts/output/common/output.ts index cc7e4b42506..6c9fc50678b 100644 --- a/src/vs/workbench/parts/output/common/output.ts +++ b/src/vs/workbench/parts/output/common/output.ts @@ -56,13 +56,15 @@ export interface IOutputService { /** * Given the channel id returns the output channel instance. + * Returns null if output channel with id is not registered. */ - getOutputChannel(id: string): IOutputChannel; + getChannel(id: string): IOutputChannel; /** - * Returns the name of the currently opened channel. + * Returns the currently active channel. + * Only one channel can be active at a given moment. */ - getActiveChannelId(): string; + getActiveChannel(): IOutputChannel; /** * Allows to register on Output events. @@ -82,6 +84,16 @@ export interface IOutputService { export interface IOutputChannel { + /** + * Identifier of the output channel. + */ + id: string; + + /** + * Label of the output channel to be displayed to the user. + */ + label: string; + /** * Returns the received output content. */ diff --git a/src/vs/workbench/parts/output/common/outputEditorInput.ts b/src/vs/workbench/parts/output/common/outputEditorInput.ts index 8b71af4f805..8cdca2103f9 100644 --- a/src/vs/workbench/parts/output/common/outputEditorInput.ts +++ b/src/vs/workbench/parts/output/common/outputEditorInput.ts @@ -27,37 +27,33 @@ export class OutputEditorInput extends StringEditorInput { private static instances: { [channel: string]: OutputEditorInput; } = Object.create(null); private outputSet: boolean; - private channelId: string; private bufferedOutput: string; private toDispose: lifecycle.IDisposable[]; private appendOutputScheduler: RunOnceScheduler; - private outputChannel: IOutputChannel; public static getInstances(): OutputEditorInput[] { return Object.keys(OutputEditorInput.instances).map((key) => OutputEditorInput.instances[key]); } - public static getInstance(instantiationService: IInstantiationService, channel: string): OutputEditorInput { - if (OutputEditorInput.instances[channel]) { - return OutputEditorInput.instances[channel]; + public static getInstance(instantiationService: IInstantiationService, channel: IOutputChannel): OutputEditorInput { + if (OutputEditorInput.instances[channel.id]) { + return OutputEditorInput.instances[channel.id]; } - OutputEditorInput.instances[channel] = instantiationService.createInstance(OutputEditorInput, channel); + OutputEditorInput.instances[channel.id] = instantiationService.createInstance(OutputEditorInput, channel); - return OutputEditorInput.instances[channel]; + return OutputEditorInput.instances[channel.id]; } constructor( - channelId: string, + private outputChannel: IOutputChannel, @IInstantiationService instantiationService: IInstantiationService, @IOutputService private outputService: IOutputService, @IPanelService private panelService: IPanelService, @IEventService private eventService: IEventService ) { - super(nls.localize('output', "Output"), channelId ? nls.localize('outputChannel', "for '{0}'", channelId) : '', '', OUTPUT_MIME, true, instantiationService); + super(nls.localize('output', "Output"), outputChannel ? nls.localize('outputChannel', "for '{0}'", outputChannel.label) : '', '', OUTPUT_MIME, true, instantiationService); - this.channelId = channelId; - this.outputChannel = this.outputService.getOutputChannel(channelId); this.bufferedOutput = ''; this.toDispose = []; this.toDispose.push(this.outputService.onOutput(this.onOutputReceived, this)); @@ -88,7 +84,7 @@ export class OutputEditorInput extends StringEditorInput { } private onOutputReceived(e: IOutputEvent): void { - if (this.outputSet && e.channelId === this.channelId) { + if (this.outputSet && e.channelId === this.outputChannel.id) { if (e.output) { this.bufferedOutput = strings.appendWithLimit(this.bufferedOutput, e.output, MAX_OUTPUT_LENGTH); this.scheduleOutputAppend(); @@ -100,7 +96,7 @@ export class OutputEditorInput extends StringEditorInput { private isVisible(): boolean { const panel = this.panelService.getActivePanel(); - return panel && panel.getId() === OUTPUT_PANEL_ID && this.outputService.getActiveChannelId() === this.channelId; + return panel && panel.getId() === OUTPUT_PANEL_ID && this.outputService.getActiveChannel().id === this.outputChannel.id; } private scheduleOutputAppend(): void { @@ -127,14 +123,10 @@ export class OutputEditorInput extends StringEditorInput { }); } - public getChannel(): string { - return this.channelId; - } - public matches(otherInput: any): boolean { if (otherInput instanceof OutputEditorInput) { let otherOutputEditorInput = otherInput; - if (otherOutputEditorInput.getChannel() === this.channelId) { + if (otherOutputEditorInput.outputChannel.id === this.outputChannel.id) { return super.matches(otherInput); } } diff --git a/src/vs/workbench/parts/output/common/outputServices.ts b/src/vs/workbench/parts/output/common/outputServices.ts index b3a3768a7ec..dc3a0a39e5f 100644 --- a/src/vs/workbench/parts/output/common/outputServices.ts +++ b/src/vs/workbench/parts/output/common/outputServices.ts @@ -60,10 +60,18 @@ export class OutputService implements IOutputService { return this._onActiveOutputChannel.event; } - public getOutputChannel(id: string): IOutputChannel { + public getChannel(id: string): IOutputChannel { + const channelData = (Registry.as(Extensions.OutputChannels)).getChannels().filter(channelData => channelData.id === id).pop(); + if (!channelData) { + return null; + } + + const self = this; return { + id, + label: channelData.label, get output() { - return this.getOutput(id); + return self.getOutput(id); }, append: (output: string) => this.append(id, output), show: (preserveFocus: boolean) => this.showOutput(id, preserveFocus), @@ -91,12 +99,12 @@ export class OutputService implements IOutputService { this._onOutput.fire({ output: output, channelId: channelId }); } - private getOutput(channelId: string): string { - return this.receivedOutput[channelId] || ''; + public getActiveChannel(): IOutputChannel { + return this.getChannel(this.activeChannelId); } - public getActiveChannelId(): string { - return this.activeChannelId; + private getOutput(channelId: string): string { + return this.receivedOutput[channelId] || ''; } private clearOutput(channelId: string): void { @@ -116,7 +124,7 @@ export class OutputService implements IOutputService { this._onActiveOutputChannel.fire(channelId); // emit event that a new channel is active return this.panelService.openPanel(OUTPUT_PANEL_ID, !preserveFocus).then((outputPanel: OutputPanel) => { - return outputPanel && outputPanel.setInput(OutputEditorInput.getInstance(this.instantiationService, channelId), EditorOptions.create({ preserveFocus: preserveFocus })). + return outputPanel && outputPanel.setInput(OutputEditorInput.getInstance(this.instantiationService, this.getChannel(channelId)), EditorOptions.create({ preserveFocus: preserveFocus })). then(() => outputPanel); }); } diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 333ee0697f3..275392342fc 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -182,7 +182,7 @@ class ConfigureTaskRunnerAction extends Action { } let contentPromise: TPromise; if (selection.autoDetect) { - const outputChannel = this.outputService.getOutputChannel(TaskService.OutputChannelId); + const outputChannel = this.outputService.getChannel(TaskService.OutputChannelId); outputChannel.show(); outputChannel.append(nls.localize('ConfigureTaskRunnerAction.autoDetecting', 'Auto detecting tasks for {0}', selection.id) + '\n'); let detector = new ProcessRunnerDetector(this.fileService, this.contextService, new SystemVariables(this.editorService, this.contextService)); @@ -288,7 +288,7 @@ class ShowLogAction extends AbstractTaskAction { } public run(): Promise { - return this.outputService.getOutputChannel(TaskService.OutputChannelId).show(); + return this.outputService.getChannel(TaskService.OutputChannelId).show(); } } @@ -506,7 +506,7 @@ class TaskService extends EventEmitter implements ITaskService { this.taskSystemListeners = []; this.clearTaskSystemPromise = false; - this.outputChannel = this.outputService.getOutputChannel(TaskService.OutputChannelId); + this.outputChannel = this.outputService.getChannel(TaskService.OutputChannelId); this.configurationService.addListener(ConfigurationServiceEventTypes.UPDATED, () => { this.emit(TaskServiceEvents.ConfigChanged); if (this._taskSystem && this._taskSystem.isActiveSync()) { diff --git a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts index e99ad34f21d..c3a49d241da 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts @@ -39,7 +39,6 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { private markerService: IMarkerService; private modelService: IModelService; private outputService: IOutputService; - private outputChannelId: string; private telemetryService: ITelemetryService; private validationStatus: ValidationStatus; @@ -52,13 +51,12 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { private childProcess: LineProcess; private activeTaskIdentifier: string; - constructor(fileConfig:FileConfig.ExternalTaskRunnerConfiguration, variables:SystemVariables, markerService:IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService:IOutputService, outputChannel:string, clearOutput: boolean = true) { + constructor(fileConfig:FileConfig.ExternalTaskRunnerConfiguration, variables:SystemVariables, markerService:IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService:IOutputService, outputChannelId:string, clearOutput: boolean = true) { super(); this.fileConfig = fileConfig; this.variables = variables; this.markerService = markerService; this.modelService = modelService; - this.outputChannelId = outputChannel; this.outputService = outputService; this.telemetryService = telemetryService; @@ -66,6 +64,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { this.defaultTestTaskIdentifier = null; this.childProcess = null; this.activeTaskIdentifier = null; + this.outputChannel = this.outputService.getChannel(outputChannelId); if (clearOutput) { this.clearOutput(); @@ -76,7 +75,6 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { this.configuration = parseResult.configuration; this.defaultBuildTaskIdentifier = parseResult.defaultBuildTaskIdentifier; this.defaultTestTaskIdentifier = parseResult.defaultTestTaskIdentifier; - this.outputChannel = this.outputService.getOutputChannel(this.outputChannelId); if (!this.validationStatus.isOK()) { this.showOutput();