diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index d7548243b347368032e7cd8142cc1d193a84a58f..021264c4cf1e23a1de438604e7cd621d7eaee781 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2443,8 +2443,7 @@ declare namespace vscode { /** * Reveal this channel in the UI. - * - * @param column The column in which to show the channel, default in [one](#ViewColumn.One). + * @param column @deprecated **This argument is deprecated.** The column in which to show the channel, default in [one](#ViewColumn.One). * @param preserveFocus When `true` the channel will not take focus. */ show(column?: ViewColumn, preserveFocus?: boolean): void; diff --git a/src/vs/workbench/api/node/extHostOutputService.ts b/src/vs/workbench/api/node/extHostOutputService.ts index 90fb7faeaffb8b20218c6a7e4aaacc50ff6ca7d8..6712976624d028b9b91883bd3c1e24dc635aeb30 100644 --- a/src/vs/workbench/api/node/extHostOutputService.ts +++ b/src/vs/workbench/api/node/extHostOutputService.ts @@ -48,7 +48,7 @@ export class ExtHostOutputChannel implements vscode.OutputChannel { } show(column?: vscode.ViewColumn, preserveFocus?: boolean): void { - this._proxy.reveal(this._name, TypeConverters.fromViewColumn(column), preserveFocus); + this._proxy.reveal(this._name, preserveFocus); } hide(): void { @@ -95,8 +95,8 @@ export class MainThreadOutputService { return undefined; } - public reveal(channel: string, position: Position, preserveFocus: boolean): TPromise { - this._outputService.showOutput(channel, position, preserveFocus); + public reveal(channel: string, preserveFocus: boolean): TPromise { + this._outputService.showOutput(channel, preserveFocus); return undefined; } diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index 3b2c9daaf951790cba88ca8e9f8d821b33ed8a04..66761ad5f5a6d7e811aa0f0dd02ca63f26ec78be 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -13,7 +13,11 @@ export abstract class Panel extends Composite implements IPanel { } /** * A panel descriptor is a leightweight descriptor of a panel in the monaco workbench. */ -export class PanelDescriptor extends CompositeDescriptor { } +export class PanelDescriptor extends CompositeDescriptor { + constructor(moduleId: string, ctorName: string, id: string, name: string, cssClass?: string) { + super(moduleId, ctorName, id, name, cssClass); + } +} export class PanelRegistry extends CompositeRegistry { private defaultPanelId: string; diff --git a/src/vs/workbench/browser/parts/editor/baseEditor.ts b/src/vs/workbench/browser/parts/editor/baseEditor.ts index c1d22ff54e253ae07d3ca15a953186ad76cfbe26..7cc94906671d3bce9a154ea1fe0c9868657bf5fd 100644 --- a/src/vs/workbench/browser/parts/editor/baseEditor.ts +++ b/src/vs/workbench/browser/parts/editor/baseEditor.ts @@ -11,7 +11,7 @@ import types = require('vs/base/common/types'); import {Builder} from 'vs/base/browser/builder'; import {EventType, EditorEvent} from 'vs/workbench/common/events'; import {Registry} from 'vs/platform/platform'; -import {Viewlet} from 'vs/workbench/browser/viewlet'; +import {Panel} from 'vs/workbench/browser/panel'; import {EditorInput, IFileEditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {IEditor, Position, POSITIONS} from 'vs/platform/editor/common/editor'; import {IInstantiationService, IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation'; @@ -30,7 +30,7 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; * * This class is only intended to be subclassed and not instantiated. */ -export abstract class BaseEditor extends Viewlet implements IEditor { +export abstract class BaseEditor extends Panel implements IEditor { private _input: EditorInput; private _options: EditorOptions; private _position: Position; diff --git a/src/vs/workbench/browser/parts/editor/stringEditor.ts b/src/vs/workbench/browser/parts/editor/stringEditor.ts index 8d1d7c0edd56d959c4973c6b46332e8a1fc28d93..fb11b5c88c66b445a197142df8a26336ff03ec0d 100644 --- a/src/vs/workbench/browser/parts/editor/stringEditor.ts +++ b/src/vs/workbench/browser/parts/editor/stringEditor.ts @@ -13,7 +13,6 @@ import {DefaultConfig} from 'vs/editor/common/config/defaultConfig'; import {EditorConfiguration} from 'vs/editor/common/config/commonEditorConfig'; import {TextEditorOptions, EditorModel, EditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {BaseTextEditorModel} from 'vs/workbench/common/editor/textEditorModel'; -import {LogEditorInput} from 'vs/workbench/common/editor/logEditorInput'; import {UntitledEditorInput} from 'vs/workbench/common/editor/untitledEditorInput'; import {BaseTextEditor} from 'vs/workbench/browser/parts/editor/textEditor'; import {UntitledEditorEvent, EventType} from 'vs/workbench/common/events'; @@ -35,8 +34,6 @@ export class StringEditor extends BaseTextEditor { public static ID = 'workbench.editors.stringEditor'; - private defaultWrappingColumn: number; - private defaultLineNumbers: boolean; private mapResourceToEditorViewState: { [resource: string]: IEditorViewState; }; constructor( @@ -50,12 +47,8 @@ export class StringEditor extends BaseTextEditor { @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IModeService modeService: IModeService ) { - super(StringEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService); - this.defaultWrappingColumn = DefaultConfig.editor.wrappingColumn; - this.defaultLineNumbers = DefaultConfig.editor.lineNumbers; - this.mapResourceToEditorViewState = Object.create(null); this.toUnbind.push(this.eventService.addListener(EventType.UNTITLED_FILE_DELETED, (e: UntitledEditorEvent) => this.onUntitledDeletedEvent(e))); @@ -132,43 +125,17 @@ export class StringEditor extends BaseTextEditor { // Apply options again because input has changed textEditor.updateOptions(this.getCodeEditorOptions()); - - // Auto reveal last line for log editors - if (input instanceof LogEditorInput) { - this.revealLastLine(); - } }); } - protected applyConfiguration(configuration: any): void { - - // Remember some settings that we overwrite from #getCodeEditorOptions() - let editorConfig = configuration && configuration[EditorConfiguration.EDITOR_SECTION]; - if (editorConfig) { - this.defaultWrappingColumn = editorConfig.wrappingColumn; - this.defaultLineNumbers = editorConfig.lineNumbers; - } - - super.applyConfiguration(configuration); - } - protected getCodeEditorOptions(): IEditorOptions { let options = super.getCodeEditorOptions(); let input = this.getInput(); - let isLog = input instanceof LogEditorInput; let isUntitled = input instanceof UntitledEditorInput; options.readOnly = !isUntitled; // all string editors are readonly except for the untitled one - if (isLog) { - options.wrappingColumn = 0; // all log editors wrap - options.lineNumbers = false; // all log editors hide line numbers - } else { - options.wrappingColumn = this.defaultWrappingColumn; // otherwise make sure to restore the defaults - options.lineNumbers = this.defaultLineNumbers; // otherwise make sure to restore the defaults - } - return options; } @@ -188,15 +155,6 @@ export class StringEditor extends BaseTextEditor { return true; } - public focus(): void { - super.focus(); - - // Auto reveal last line for log editors - if (this.getInput() instanceof LogEditorInput) { - this.revealLastLine(); - } - } - public clearInput(): void { // Keep editor view state in settings to restore when coming back diff --git a/src/vs/workbench/buildfile.js b/src/vs/workbench/buildfile.js index 79c0ce7cb4d4994e3a4ffecb5670ae87b0e4a86e..7836998fe0ac13b7753b91a445f1661398eaa988 100644 --- a/src/vs/workbench/buildfile.js +++ b/src/vs/workbench/buildfile.js @@ -31,6 +31,7 @@ exports.collectModules= function(excludes) { createModuleDescription('vs/workbench/parts/output/common/outputMode', languageMainExcludes), createModuleDescription('vs/workbench/parts/output/common/outputWorker', languageWorkerExcludes), + createModuleDescription('vs/workbench/parts/output/browser/outputPanel', excludes), createModuleDescription('vs/workbench/parts/debug/browser/debugViewlet', excludes), createModuleDescription('vs/workbench/parts/debug/browser/repl', excludes), diff --git a/src/vs/workbench/common/editor/logEditorInput.ts b/src/vs/workbench/common/editor/logEditorInput.ts deleted file mode 100644 index ca28644ae634a7cfe3055ee87fef3b4c23aa709b..0000000000000000000000000000000000000000 --- a/src/vs/workbench/common/editor/logEditorInput.ts +++ /dev/null @@ -1,79 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 {IEditor, ITextModel} from 'vs/editor/common/editorCommon'; -import {StringEditorInput} from 'vs/workbench/common/editor/stringEditorInput'; -import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; -import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; - -/** - * A read-only text editor input whos contents are made of the provided value and mime type. As a subclass of StringEditorInput - * it adds additional functionality suitable for using it to show output or logs. - */ -export class LogEditorInput extends StringEditorInput { - - public static ID = 'workbench.editors.logEditorInput'; - - constructor( - name: string, - description: string, - value: string, - mime: string, - singleton: boolean, - @IInstantiationService instantiationService: IInstantiationService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService - ) { - super(name, description, value, mime, singleton, instantiationService); - } - - public getId(): string { - return LogEditorInput.ID; - } - - /** - * Appends text to the end of this input and automatically reveals the last line if an editor is visible with this input. - */ - public append(value: string): void { - super.append(value); - - this.revealLastLine(); - } - - /** - * Removes all lines from the top if the line number exceeds the given line count. Returns the new value if lines got trimmed. - * Automatically reveals the last line if an editor is visible with this input. - * - * Note: This method is a no-op if the input has not yet been resolved. - */ - public trim(linecount: number): string { - let newValue = super.trim(linecount); - if (newValue !== null) { - this.revealLastLine(); - } - - return newValue; - } - - /** - * Reveals the last line on any editor that has this output set. - */ - public revealLastLine(): void { - let editors = this.editorService.getVisibleEditors(); - for (let i = 0; i < editors.length; i++) { - let editor = editors[i]; - if (editor.input === this) { - let editorControl = editor.getControl(); - if (editorControl) { - let model = editorControl.getModel(); - if (model) { - let lastLine = model.getLineCount(); - editorControl.revealLine(lastLine); - } - } - } - } - } -} \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index f86f9483b008b1bafabcde0e50e2db84d5b364c3..483151ee8a96368f0711b2ac8e995504b23a24bb 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -12,10 +12,10 @@ import editor = require('vs/editor/common/editorCommon'); import editorbrowser = require('vs/editor/browser/editorBrowser'); import { Source } from 'vs/workbench/parts/debug/common/debugSource'; -export var VIEWLET_ID = 'workbench.view.debug'; -export var REPL_ID = 'workbench.panel.repl'; -export var DEBUG_SERVICE_ID = 'debugService'; -export var CONTEXT_IN_DEBUG_MODE = 'inDebugMode'; +export const VIEWLET_ID = 'workbench.view.debug'; +export const REPL_ID = 'workbench.panel.repl'; +export const DEBUG_SERVICE_ID = 'debugService'; +export const CONTEXT_IN_DEBUG_MODE = 'inDebugMode'; // raw diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index 24f02321aedd5f05a0fcd7b0609f656007ea9d3e..1319cf49b5e2c77865cd331572a79d34ffd4d68d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -76,8 +76,7 @@ const openViewletKb: IKeybindings = { 'Repl', debug.REPL_ID, nls.localize('debugConsole', "Debug Console"), - 'repl', - 40 + 'repl' )); (platform.Registry.as(panel.Extensions.Panels)).setDefaultPanelId(debug.REPL_ID); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 5f0a2044275a1922956199889b56a2866cfac457..35c5d47db3c35080b44758513de1f477fec9f039 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -564,7 +564,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } // no task running, execute the preLaunchTask. - this.outputService.showOutput('Tasks', true, true); + this.outputService.showOutput('Tasks', true); const taskPromise = this.taskService.run(filteredTasks[0].id).then(result => { this.lastTaskEvent = null; diff --git a/src/vs/workbench/parts/output/browser/media/Clearoutput.svg b/src/vs/workbench/parts/output/browser/media/clear_output.svg similarity index 100% rename from src/vs/workbench/parts/output/browser/media/Clearoutput.svg rename to src/vs/workbench/parts/output/browser/media/clear_output.svg diff --git a/src/vs/workbench/parts/output/browser/media/Clearoutput_inverse.svg b/src/vs/workbench/parts/output/browser/media/clear_output_inverse.svg similarity index 100% rename from src/vs/workbench/parts/output/browser/media/Clearoutput_inverse.svg rename to src/vs/workbench/parts/output/browser/media/clear_output_inverse.svg diff --git a/src/vs/workbench/parts/output/browser/media/output-global-toggled.svg b/src/vs/workbench/parts/output/browser/media/output-global-toggled.svg deleted file mode 100644 index 146b882ca9e573de8ca8d0662285ad95eea2cc76..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/media/output-global-toggled.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/media/output-global.svg b/src/vs/workbench/parts/output/browser/media/output-global.svg deleted file mode 100644 index bc97f3140cbf1f962a8b2c858f851bee2d55663d..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/media/output-global.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/media/output.contribution.css b/src/vs/workbench/parts/output/browser/media/output.contribution.css new file mode 100644 index 0000000000000000000000000000000000000000..8f4a3472ec671029f5b62d38f276dd6f04ad950c --- /dev/null +++ b/src/vs/workbench/parts/output/browser/media/output.contribution.css @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-workbench .output-action.clear-output { + background: url('clear_output.svg') center center no-repeat; +} + +.monaco-workbench.vs-dark .output-action.clear-output { + background: url('clear_output_inverse.svg') center center no-repeat; +} + +/* High Contrast Theming */ + +.monaco-workbench.hc-black .output-action.clear-output { + background: none; +} + +.monaco-workbench.hc-black .output-action.clear-output:before { + content: url('clear_output_inverse.svg'); + position: absolute; + top: 12px; + left: 8px; + height: 16px; + width: 16px; +} diff --git a/src/vs/workbench/parts/output/browser/media/outputactions.contribution.css b/src/vs/workbench/parts/output/browser/media/outputactions.contribution.css deleted file mode 100644 index 74295c251ab4da172f45db833ac6e0baf8e0ffba..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/media/outputactions.contribution.css +++ /dev/null @@ -1,98 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.monaco-workbench > .activitybar .monaco-action-bar .output-action.runworkspace { - background-image: url('runworkspace-global.svg'); -} - -.monaco-workbench > .activitybar .monaco-action-bar .output-action.showoutput { - background-image: url('output-global.svg'); -} - -.monaco-workbench > .activitybar .monaco-action-bar .output-action.showoutput.active { - background-image: url('output-global-toggled.svg'); -} - -.monaco-workbench > .activitybar .monaco-action-bar .badge.global-output-error .badge-content { - background-color: #E02020; -} - -.monaco-workbench .output-action.clear-output { - background: url('Clearoutput.svg') center center no-repeat; -} - -.monaco-workbench.vs-dark .output-action.clear-output { - background: url('Clearoutput_inverse.svg') center center no-repeat; -} - -/* High Contrast Theming */ -.monaco-workbench.hc-black > .activitybar .monaco-action-bar .output-action.runworkspace:before { - content: url('runworkspace-global.svg'); -} - -.monaco-workbench.hc-black > .activitybar .monaco-action-bar .output-action.showoutput:before { - content: url('output-global.svg'); -} - -.monaco-workbench.hc-black > .activitybar .monaco-action-bar .output-action.showoutput.active:before { - content: url('output-global-toggled.svg'); -} - -.monaco-workbench.hc-black .output-action.clear-output { - background: none; -} - -.monaco-workbench.hc-black .output-action.clear-output:before { - content: url('Clearoutput_inverse.svg'); - position: absolute; - top: 12px; - left: 8px; - height: 16px; - width: 16px; -} - -/* Switch Output Channel */ - -.monaco-workbench .output-action.switch-to-output { - display: inline-block; - padding: 0; - -ms-transition: -ms-transform 100ms ease; - -webkit-transition: -webkit-transform 100ms ease; - -moz-transition: -moz-transform 100ms ease; - -o-transition: -o-transform 100ms ease; - transition: transform 100ms ease; -} - -.monaco-workbench.vs .output-action.switch-to-output.active { - -ms-transform: translate(0, -3px); - -webkit-transform: translate(0, -3px); - -moz-transform: translate(0, -3px); - -o-transform: translate(0, -3px); - transform: translate(0, -3px); -} - -.monaco-workbench.vs .output-action.switch-to-output { - background: url('switch-to-output.svg') center center no-repeat; -} - -.monaco-workbench.vs-dark .output-action.switch-to-output { - background: url('switch-to-output-inverse.svg') center center no-repeat; -} - -.monaco-workbench.hc-black .output-action.switch-to-output { - background: none; -} - -.monaco-workbench.hc-black .output-action.switch-to-output:before { - position: absolute; - top: 12px; - left: 8px; - height: 16px; - width: 16px; -} - -.monaco-workbench.hc-black .output-action.switch-to-output:before { - content: url('switch-to-output-inverse.svg'); -} \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/media/runworkspace-global.svg b/src/vs/workbench/parts/output/browser/media/runworkspace-global.svg deleted file mode 100644 index 3721ee6fa03812a9809e2ec860dc857d475e6380..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/media/runworkspace-global.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/media/switch-to-output-inverse.svg b/src/vs/workbench/parts/output/browser/media/switch-to-output-inverse.svg deleted file mode 100644 index aa75f6db6e3c931a8fecadcb36f3929ff15fae9e..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/media/switch-to-output-inverse.svg +++ /dev/null @@ -1,3 +0,0 @@ - -]> \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/media/switch-to-output.svg b/src/vs/workbench/parts/output/browser/media/switch-to-output.svg deleted file mode 100644 index e620b93d06604415a245da549a2043f2c1d1e3bb..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/media/switch-to-output.svg +++ /dev/null @@ -1,3 +0,0 @@ - -]> \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/output.contribution.ts b/src/vs/workbench/parts/output/browser/output.contribution.ts index b1e8d2fa53dda3cc1de3a8b1348866a448473df1..d4dfd406b1d3e18af30e959c28a105968e81d3cc 100644 --- a/src/vs/workbench/parts/output/browser/output.contribution.ts +++ b/src/vs/workbench/parts/output/browser/output.contribution.ts @@ -2,40 +2,24 @@ * 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 {Registry} from 'vs/platform/platform'; +import 'vs/css!../browser/media/output.contribution'; +import nls = require('vs/nls'); +import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; +import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {registerMode} from 'vs/editor/common/modes/modesRegistry'; -import {OutputService} from 'vs/workbench/parts/output/common/outputServices'; -import {OUTPUT_MIME, OUTPUT_MODE_ID, OUTPUT_EDITOR_INPUT_ID, IOutputService} from 'vs/workbench/parts/output/common/output'; -import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorInput'; -import {IEditorRegistry, Extensions, IEditorInputFactory} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {EditorInput} from 'vs/workbench/common/editor'; -import {IInstantiationService, INullService} from 'vs/platform/instantiation/common/instantiation'; +import platform = require('vs/platform/platform'); +import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; import {registerSingleton} from 'vs/platform/instantiation/common/extensions'; - -// Register Editor Input Factory -class OutputInputFactory implements IEditorInputFactory { - - constructor(@INullService ns) {} - - public serialize(editorInput: EditorInput): string { - let outputEditoInput = editorInput; - - return outputEditoInput.getChannel(); // use the channel to distinguish different output editor inputs - } - - public deserialize(instantiationService: IInstantiationService, channel: string): EditorInput { - return OutputEditorInput.getInstance(instantiationService, channel); - } -} +import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry'; +import {OutputService} from 'vs/workbench/parts/output/common/outputServices'; +import {ClearOutputEditorAction, ToggleOutputAction} from 'vs/workbench/parts/output/browser/outputActions'; +import {OUTPUT_MIME, OUTPUT_MODE_ID, OUTPUT_PANEL_ID, IOutputService} from 'vs/workbench/parts/output/common/output'; +import panel = require('vs/workbench/browser/panel'); // Register Service registerSingleton(IOutputService, OutputService); -// Register Output Input Factory -(Registry.as(Extensions.Editors)).registerEditorInputFactory(OUTPUT_EDITOR_INPUT_ID, OutputInputFactory); - // Register Output Mode registerMode({ id: OUTPUT_MODE_ID, @@ -45,3 +29,24 @@ registerMode({ moduleId: 'vs/workbench/parts/output/common/outputMode', ctorName: 'OutputMode' }); + +// Register Output Panel +(platform.Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( + 'vs/workbench/parts/output/browser/outputPanel', + 'OutputPanel', + OUTPUT_PANEL_ID, + nls.localize('output', "Output"), + 'output' +)); + +// register toggle output action globally +let actionRegistry = platform.Registry.as(ActionExtensions.WorkbenchActions); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleOutputAction, ToggleOutputAction.ID, ToggleOutputAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_U, + linux: { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H // On Ubuntu Ctrl+Shift+U is taken by some global OS command + } +}), nls.localize('viewCategory', "View")); + +// Contribute to Context Menu of Output Window +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ClearOutputEditorAction, ClearOutputEditorAction.ID, nls.localize('clearOutput.label', "Clear Output"))); diff --git a/src/vs/workbench/parts/output/browser/outputActions.contribution.ts b/src/vs/workbench/parts/output/browser/outputActions.contribution.ts deleted file mode 100644 index 1dc78de1dbbfa9d92fee40ab6d91f0c57e0b16b4..0000000000000000000000000000000000000000 --- a/src/vs/workbench/parts/output/browser/outputActions.contribution.ts +++ /dev/null @@ -1,68 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 'vs/css!./media/outputactions.contribution'; -import nls = require('vs/nls'); -import {BaseActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; -import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; -import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry'; -import {Registry} from 'vs/platform/platform'; -import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {Scope, IActionBarRegistry, Extensions as ActionBarExtensions} from 'vs/workbench/browser/actionBarRegistry'; -import {Action} from 'vs/base/common/actions'; -import {IEditorInputAction, IEditorInputActionContext, EditorInputActionContributor} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorInput'; -import {ClearOutputEditorAction, ToggleOutputAction, GlobalShowOutputAction, SwitchOutputActionItem, SwitchOutputAction, ClearOutputAction} from 'vs/workbench/parts/output/browser/outputActions'; -import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; -import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; - -class OutputEditorActionContributor extends EditorInputActionContributor { - - constructor( @IInstantiationService private instantiationService: IInstantiationService) { - super(); - } - - public hasActionsForEditorInput(context: IEditorInputActionContext): boolean { - return context.input instanceof OutputEditorInput; - } - - public getActionsForEditorInput(context: IEditorInputActionContext): IEditorInputAction[] { - let actions: IEditorInputAction[] = []; - - actions.push(this.instantiationService.createInstance(SwitchOutputAction)); - actions.push(this.instantiationService.createInstance(ClearOutputAction)); - - return actions; - } - - public getActionItem(context: any, action: Action): BaseActionItem { - if (action.id === SwitchOutputAction.ID) { - return this.instantiationService.createInstance(SwitchOutputActionItem, action, context.input); - } - - return super.getActionItem(context, action); - } -} - -let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); -let actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); - -// register show output action globally -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalShowOutputAction, GlobalShowOutputAction.ID, GlobalShowOutputAction.LABEL), nls.localize('viewCategory', "View")); - -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleOutputAction, ToggleOutputAction.ID, ToggleOutputAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_U, - linux: { - primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H // On Ubuntu Ctrl+Shift+U is taken by some global OS command - } -}), nls.localize('viewCategory', "View")); - -// Contribute Output Editor Contributor -actionBarRegistry.registerActionBarContributor(Scope.EDITOR, OutputEditorActionContributor); - -// Contribute to Context Menu of Output Window -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ClearOutputEditorAction, ClearOutputEditorAction.ID, nls.localize('clearOutput.label', "Clear Output"))); diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index 74025236792c91aaadc45c77410b424f1b3c3380..6271e2cf4753257c40ebcaf5966111b562f06301 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -7,73 +7,16 @@ import {Promise, TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); import {Registry} from 'vs/platform/platform'; -import errors = require('vs/base/common/errors'); import arrays = require('vs/base/common/arrays'); import {IDisposable} from 'vs/base/common/lifecycle'; import {IAction, Action} from 'vs/base/common/actions'; import {EditorAction, Behaviour} from 'vs/editor/common/editorAction'; import {ICommonCodeEditor, IEditorActionDescriptorData} from 'vs/editor/common/editorCommon'; -import {EditorInputAction} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {IOutputChannelRegistry, Extensions, IOutputService, OUTPUT_EDITOR_INPUT_ID, OUTPUT_MODE_ID} from 'vs/workbench/parts/output/common/output'; +import {IOutputChannelRegistry, Extensions, IOutputService, OUTPUT_MODE_ID, OUTPUT_PANEL_ID} from 'vs/workbench/parts/output/common/output'; import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorInput'; import {SelectActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; -import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; -import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpenService'; -import {IInstantiationService, INullService} from 'vs/platform/instantiation/common/instantiation'; - -export class GlobalShowOutputAction extends Action { - - public static ID = 'workbench.action.output.showOutput'; - public static LABEL = nls.localize('showOutput', "Show Output"); - - constructor( - id: string, - label: string, - @IOutputService private outputService: IOutputService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IQuickOpenService private quickOpenService: IQuickOpenService - ) { - super(id, label); - - this.order = 20; // Allow other actions to position before or after - this.class = 'output-action showoutput'; - } - - public run(event?: any): Promise { - let channelToOpen: string = null; - - // Check for previously opened output - let channels = this.quickOpenService.getEditorHistory().filter((i) => i instanceof OutputEditorInput); - if (channels.length > 0) { - - // See if output is already opened and just focus it - let editors = this.editorService.getVisibleEditors(); - if (editors.some((e) => { - if (e.input instanceof OutputEditorInput) { - this.editorService.focusEditor(e); - - return true; - } - - return false; - })) { - return Promise.as(null); - } - - // Otherwise pick a channel from the list - channelToOpen = channels[0].getChannel(); - } - - // Fallback to any contributed channel otherwise if we don't have history - else { - channelToOpen = (Registry.as(Extensions.OutputChannels)).getChannels()[0]; - } - - let sideBySide = !!(event && (event.ctrlKey || event.metaKey)); - - return this.outputService.showOutput(channelToOpen, sideBySide, false /* Do not preserve Focus */); - } -} +import {IPartService} from 'vs/workbench/services/part/common/partService'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; export class ToggleOutputAction extends Action { @@ -82,46 +25,33 @@ export class ToggleOutputAction extends Action { constructor( id: string, label: string, - @IQuickOpenService private quickOpenService: IQuickOpenService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IInstantiationService private instantiationService: IInstantiationService + @IPartService private partService: IPartService, + @IPanelService private panelService: IPanelService, + @IOutputService private outputService: IOutputService ) { super(id, label); } public run(event?: any): Promise { - let activeInput = this.editorService.getActiveEditorInput(); - - // Restore Previous Non-Output Editor - if (activeInput instanceof OutputEditorInput) { - let history = this.quickOpenService.getEditorHistory(); - for (let i = 1; i < history.length; i++) { - if (!(history[i] instanceof OutputEditorInput)) { - return this.editorService.openEditor(history[i]); - } - } - } + const panel = this.panelService.getActivePanel(); + if (panel && panel.getId() === OUTPUT_PANEL_ID) { + this.partService.setPanelHidden(true); - // Show Output - else { - let action = this.instantiationService.createInstance(GlobalShowOutputAction, GlobalShowOutputAction.ID, GlobalShowOutputAction.LABEL); - action.run().done(() => action.dispose(), errors.onUnexpectedError); + return Promise.as(null); } - return Promise.as(true); + return this.outputService.showOutput(this.outputService.getActiveChannel()); } } -export class ClearOutputAction extends EditorInputAction { +export class ClearOutputAction extends Action { - constructor( @INullService ns) { + constructor(@IOutputService private outputService: IOutputService) { super('workbench.output.action.clearOutput', nls.localize('clearOutput', "Clear Output"), 'output-action clear-output'); } public run(): Promise { - let outputEditorInput = this.input; - outputEditorInput.clearOutput(); - + this.outputService.clearOutput(this.outputService.getActiveChannel()); return Promise.as(true); } } @@ -133,7 +63,7 @@ export class ClearOutputEditorAction extends EditorAction { constructor( descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, - @IWorkbenchEditorService private myEditorService: IWorkbenchEditorService + @IOutputService private outputService: IOutputService ) { super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.ShowInContextMenu); } @@ -150,32 +80,21 @@ export class ClearOutputEditorAction extends EditorAction { } public run(): TPromise { - let input = this.myEditorService.getActiveEditorInput(); - if (input && input.getId() === OUTPUT_EDITOR_INPUT_ID) { - let outputEditorInput = input; - outputEditorInput.clearOutput(); - - return Promise.as(true); - } - + this.outputService.clearOutput(this.outputService.getActiveChannel()); return TPromise.as(false); } } -export class SwitchOutputAction extends EditorInputAction { +export class SwitchOutputAction extends Action { public static ID = 'workbench.output.action.switchBetweenOutputs'; - constructor( @IOutputService private outputService: IOutputService) { + constructor(@IOutputService private outputService: IOutputService) { super(SwitchOutputAction.ID, nls.localize('switchToOutput.label', "Switch to Output")); this.class = 'output-action switch-to-output'; } - public isEnabled(): boolean { - return super.isEnabled() && this.input instanceof OutputEditorInput; - } - public run(channel?: string): Promise { return this.outputService.showOutput(channel); } @@ -187,27 +106,23 @@ export class SwitchOutputActionItem extends SelectActionItem { constructor( action: IAction, - input: OutputEditorInput, @IOutputService private outputService: IOutputService ) { - super(null, action, SwitchOutputActionItem.getChannels(outputService, input), SwitchOutputActionItem.getChannels(outputService, input).indexOf(input.getChannel())); - - this.input = input; + super(null, action, SwitchOutputActionItem.getChannels(outputService), Math.max(0, SwitchOutputActionItem.getChannels(outputService).indexOf(outputService.getActiveChannel()))); this.outputListenerDispose = this.outputService.onOutputChannel(this.onOutputChannel, this); } private onOutputChannel(): void { - let channels = SwitchOutputActionItem.getChannels(this.outputService, this.input); - let selected = channels.indexOf(this.input.getChannel()); + let channels = SwitchOutputActionItem.getChannels(this.outputService); + let selected = Math.max(0, channels.indexOf(this.outputService.getActiveChannel())); this.setOptions(channels, selected); } - private static getChannels(outputService: IOutputService, input: OutputEditorInput): string[] { + private static getChannels(outputService: IOutputService): string[] { const contributedChannels = (Registry.as(Extensions.OutputChannels)).getChannels(); const usedChannels = outputService.getChannels(); - usedChannels.push(input.getChannel()); return arrays.distinct(contributedChannels.concat(usedChannels)).sort(); // sort by name } diff --git a/src/vs/workbench/parts/output/browser/outputPanel.ts b/src/vs/workbench/parts/output/browser/outputPanel.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d797c10b2f11d0765833e57e391e5b0af5f6988 --- /dev/null +++ b/src/vs/workbench/parts/output/browser/outputPanel.ts @@ -0,0 +1,104 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import lifecycle = require('vs/base/common/lifecycle'); +import {TPromise} from 'vs/base/common/winjs.base'; +import {Action, IAction} from 'vs/base/common/actions'; +import {Builder} from 'vs/base/browser/builder'; +import {IActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; +import {IEditorOptions} from 'vs/editor/common/editorCommon'; +import {IModeService} from 'vs/editor/common/services/modeService'; +import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {IStorageService} from 'vs/platform/storage/common/storage'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import {IEventService} from 'vs/platform/event/common/event'; +import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; +import {IMessageService} from 'vs/platform/message/common/message'; +import {EditorInput, EditorOptions} from 'vs/workbench/common/editor'; +import {StringEditor} from 'vs/workbench/browser/parts/editor/stringEditor'; +import {OUTPUT_PANEL_ID, IOutputService} from 'vs/workbench/parts/output/common/output'; +import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorInput'; +import {SwitchOutputAction, SwitchOutputActionItem, ClearOutputAction} from 'vs/workbench/parts/output/browser/outputActions'; +import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; +import {ClosePanelAction} from 'vs/workbench/browser/parts/panel/panelPart'; +import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; + +export class OutputPanel extends StringEditor { + + private toDispose: lifecycle.IDisposable[]; + private actions: IAction[]; + + constructor( + @ITelemetryService telemetryService: ITelemetryService, + @IInstantiationService instantiationService: IInstantiationService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService storageService: IStorageService, + @IMessageService messageService: IMessageService, + @IConfigurationService configurationService: IConfigurationService, + @IEventService eventService: IEventService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IModeService modeService: IModeService, + @IOutputService private outputService: IOutputService + ) { + super(telemetryService, instantiationService, contextService, storageService, + messageService, configurationService, eventService, editorService, modeService); + this.toDispose = []; + } + + public getId(): string { + return OUTPUT_PANEL_ID; + } + + public getActions(): IAction[] { + if (!this.actions) { + this.actions = [ + this.instantiationService.createInstance(SwitchOutputAction), + this.instantiationService.createInstance(ClearOutputAction), + this.instantiationService.createInstance(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL) + ]; + + this.actions.forEach(a => { + this.toDispose.push(a); + }); + } + + return this.actions; + } + + public getActionItem(action: Action): IActionItem { + if (action.id === SwitchOutputAction.ID) { + return this.instantiationService.createInstance(SwitchOutputActionItem, action); + } + + return super.getActionItem(action); + } + + protected getCodeEditorOptions(): IEditorOptions { + const options = super.getCodeEditorOptions(); + options.wrappingColumn = 0; // all log editors wrap + options.lineNumbers = false; // all log editors hide line numbers + + return options; + } + + public setInput(input: EditorInput, options: EditorOptions): TPromise { + return super.setInput(input, options).then(() => this.revealLastLine()); + } + + public create(parent: Builder): TPromise { + return super.create(parent) + .then(() => this.setInput(OutputEditorInput.getInstance(this.instantiationService, this.outputService.getActiveChannel()), null)); + } + + public focus(): void { + super.focus(); + this.revealLastLine(); + } + + public dispose(): void { + this.toDispose = lifecycle.disposeAll(this.toDispose); + super.dispose(); + } +} diff --git a/src/vs/workbench/parts/output/common/output.ts b/src/vs/workbench/parts/output/common/output.ts index cd22ad9ceb797237bdc60fb46c6a13fa11a22b58..4ddcc63b7b89fc5a974fd97054dce2f885229bf3 100644 --- a/src/vs/workbench/parts/output/common/output.ts +++ b/src/vs/workbench/parts/output/common/output.ts @@ -26,9 +26,9 @@ export const OUTPUT_MODE_ID = 'Log'; export const OUTPUT_EDITOR_INPUT_ID = 'vs.output'; /** - * Output from any not defined channel is here + * Output panel id */ -export const DEFAULT_OUTPUT_CHANNEL = ''; +export const OUTPUT_PANEL_ID = 'workbench.panel.output'; export const Extensions = { OutputChannels: 'workbench.contributions.outputChannels' @@ -54,7 +54,6 @@ export interface IOutputService { /** * Appends output to the given channel. */ - append(output: string): void; append(channel: string, output: string): void; /** @@ -63,20 +62,25 @@ export interface IOutputService { * The optional channel allows to ask for output for a specific channel. If you leave the * channel out, you get the default channels output. */ - getOutput(channel?: string): string; + getOutput(channel: string): string; /** * Returns all channels that received output in the current session. */ getChannels(): string[]; + /** + * Returns the name of the currently opened channel. + */ + getActiveChannel(): string; + /** * Clears all received output. * * The optional channel allows to clear the output for a specific channel. If you leave the * channel out, you get clear the default channels output. */ - clearOutput(channel?: string): void; + clearOutput(channel: string): void; /** * Opens the output for the given channel @@ -84,7 +88,7 @@ export interface IOutputService { * The optional channel allows to show the output for a specific channel. If you leave the * channel out, you show the default channels output. */ - showOutput(channel?: string, sideBySide?: boolean|Position, preserveFocus?: boolean): TPromise; + showOutput(channel: string, preserveFocus?: boolean): TPromise; /** * Allows to register on Output events diff --git a/src/vs/workbench/parts/output/common/outputEditorInput.ts b/src/vs/workbench/parts/output/common/outputEditorInput.ts index 6f1e2db4f52c1f764e6f925a4baa24523234c6cb..c09221e9aef381493351819f1c8505bf5b881d9b 100644 --- a/src/vs/workbench/parts/output/common/outputEditorInput.ts +++ b/src/vs/workbench/parts/output/common/outputEditorInput.ts @@ -7,15 +7,16 @@ import {TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); import {EditorModel} from 'vs/workbench/common/editor'; -import {LogEditorInput} from 'vs/workbench/common/editor/logEditorInput'; -import {OUTPUT_EDITOR_INPUT_ID, IOutputEvent, OUTPUT_MIME, IOutputService} from 'vs/workbench/parts/output/common/output'; +import {StringEditorInput} from 'vs/workbench/common/editor/stringEditorInput'; +import {OUTPUT_EDITOR_INPUT_ID, OUTPUT_PANEL_ID, IOutputEvent, OUTPUT_MIME, IOutputService} from 'vs/workbench/parts/output/common/output'; +import {OutputPanel} from 'vs/workbench/parts/output/browser/outputPanel'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; -import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; /** * Output Editor Input */ -export class OutputEditorInput extends LogEditorInput { +export class OutputEditorInput extends StringEditorInput { private static instances: { [channel: string]: OutputEditorInput; } = Object.create(null); private static MAX_OUTPUT_LINES = 10000; // Max. number of output lines to show in output @@ -41,10 +42,10 @@ export class OutputEditorInput extends LogEditorInput { constructor( channel: string, @IInstantiationService instantiationService: IInstantiationService, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, - @IOutputService private outputService: IOutputService + @IOutputService private outputService: IOutputService, + @IPanelService private panelService: IPanelService ) { - super(nls.localize('output', "Output"), channel ? nls.localize('outputChannel', "for '{0}'", channel) : '', '', OUTPUT_MIME, true, instantiationService, editorService); + super(nls.localize('output', "Output"), channel ? nls.localize('outputChannel', "for '{0}'", channel) : '', '', OUTPUT_MIME, true, instantiationService); this.channel = channel; this.toUnbind = []; @@ -58,6 +59,10 @@ export class OutputEditorInput extends LogEditorInput { if (e.output) { this.append(e.output); this.trim(OutputEditorInput.MAX_OUTPUT_LINES); + const panel = this.panelService.getActivePanel(); + if (panel.getId() === OUTPUT_PANEL_ID && this.outputService.getActiveChannel() === this.channel) { + (panel).revealLastLine(); + } } else if (e.output === null) { this.clearValue(); // special output indicates we should clear } @@ -83,12 +88,6 @@ export class OutputEditorInput extends LogEditorInput { }); } - public clearOutput(): void { - if (this.outputService) { - this.outputService.clearOutput(this.channel); - } - } - public getChannel(): string { return this.channel; } diff --git a/src/vs/workbench/parts/output/common/outputServices.ts b/src/vs/workbench/parts/output/common/outputServices.ts index 558ecb8b98a679b3007675ab5b30f7450af3c339..4cd49a55b880bff6db2a5d652310aca68b68cb79 100644 --- a/src/vs/workbench/parts/output/common/outputServices.ts +++ b/src/vs/workbench/parts/output/common/outputServices.ts @@ -2,19 +2,23 @@ * 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 {Promise, TPromise} from 'vs/base/common/winjs.base'; import strings = require('vs/base/common/strings'); import Event, {Emitter} from 'vs/base/common/event'; -import {EditorOptions} from 'vs/workbench/common/editor'; -import {OUTPUT_MIME, DEFAULT_OUTPUT_CHANNEL, IOutputEvent, IOutputService} from 'vs/workbench/parts/output/common/output'; -import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorInput'; -import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IEditor, Position} from 'vs/platform/editor/common/editor'; import {IEventService} from 'vs/platform/event/common/event'; import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; +import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'; +import {Registry} from 'vs/platform/platform'; +import {EditorOptions} from 'vs/workbench/common/editor'; +import {IOutputEvent, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry} from 'vs/workbench/parts/output/common/output'; +import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorInput'; +import {OutputPanel} from 'vs/workbench/parts/output/browser/outputPanel'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; + +const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel'; export class OutputService implements IOutputService { public serviceId = IOutputService; @@ -27,25 +31,29 @@ export class OutputService implements IOutputService { private sendOutputEventsTimerId: number; private lastSentOutputEventsTime: number; private bufferedOutput: { [channel: string]: string; }; + private activeChannel: string; private _onOutput: Emitter; private _onOutputChannel: Emitter; constructor( + @IStorageService private storageService: IStorageService, @IInstantiationService private instantiationService: IInstantiationService, @IEventService private eventService: IEventService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @ILifecycleService private lifecycleService: ILifecycleService + @ILifecycleService private lifecycleService: ILifecycleService, + @IPanelService private panelService: IPanelService ) { this._onOutput = new Emitter(); this._onOutputChannel = new Emitter(); this.receivedOutput = Object.create(null); - this.bufferedOutput = Object.create(null); this.sendOutputEventsTimerId = -1; this.lastSentOutputEventsTime = -1; + const channels = (Registry.as(Extensions.OutputChannels)).getChannels(); + this.activeChannel = this.storageService.get(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE, channels && channels.length > 0 ? channels[0] : null); + this.registerListeners(); } @@ -61,18 +69,7 @@ export class OutputService implements IOutputService { this.lifecycleService.onShutdown(this.dispose, this); } - public append(channelOrOutput: string, output?: string): void { - let channel: string = DEFAULT_OUTPUT_CHANNEL; - if (output) { - channel = channelOrOutput; - } else { - output = channelOrOutput; - } - - this.doAppend(channel, output); - } - - private doAppend(channel: string, output: string): void { + public append(channel: string, output: string): void { // Initialize if (!this.receivedOutput[channel]) { @@ -147,7 +144,7 @@ export class OutputService implements IOutputService { this.bufferedOutput = Object.create(null); } - public getOutput(channel = DEFAULT_OUTPUT_CHANNEL): string { + public getOutput(channel: string): string { return this.receivedOutput[channel] || ''; } @@ -155,41 +152,24 @@ export class OutputService implements IOutputService { return Object.keys(this.receivedOutput); } - public clearOutput(channel = DEFAULT_OUTPUT_CHANNEL): void { - this.receivedOutput[channel] = ''; - - this._onOutput.fire({ channel: channel, output: null /* indicator to clear output */ }); + public getActiveChannel(): string { + return this.activeChannel; } - public showOutput(channel: string = DEFAULT_OUTPUT_CHANNEL, sideBySide?: boolean | Position, preserveFocus?: boolean): TPromise { - - // If already opened, focus it unless we want to preserve focus - let existingOutputEditor = this.findOutputEditor(channel); - if (existingOutputEditor) { - if (!preserveFocus) { - return this.editorService.focusEditor(existingOutputEditor); - } - - // Still reveal last line - (existingOutputEditor.input).revealLastLine(); - - return Promise.as(existingOutputEditor); - } + public clearOutput(channel: string): void { + this.receivedOutput[channel] = ''; - // Otherwise open new - return this.editorService.openEditor(OutputEditorInput.getInstance(this.instantiationService, channel), preserveFocus ? EditorOptions.create({ preserveFocus: true }) : null, sideBySide); + this._onOutput.fire({ channel: channel, output: null /* indicator to clear output */ }); } - private findOutputEditor(channel: string): IEditor { - let editors = this.editorService.getVisibleEditors(); - for (let i = 0; i < editors.length; i++) { - let editor = editors[i]; - if (editor.input instanceof OutputEditorInput && (editor.input).getChannel() === channel && (editor.input).getMime() === OUTPUT_MIME) { - return editor; - } - } + public showOutput(channel: string, preserveFocus?: boolean): TPromise { + this.activeChannel = channel; + this.storageService.store(OUTPUT_ACTIVE_CHANNEL_KEY, this.activeChannel, StorageScope.WORKSPACE); - return null; + return this.panelService.openPanel(OUTPUT_PANEL_ID, !preserveFocus).then((outputPanel: OutputPanel) => { + return outputPanel.setInput(OutputEditorInput.getInstance(this.instantiationService, channel), EditorOptions.create({ preserveFocus: preserveFocus })). + then(() => outputPanel); + }); } public dispose(): void { 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 a5cc94314ad16d05b5aa063174b83c90eaa4e68c..f2875ff79ef0f29a8eaad9c939ac49fc847745d2 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -214,7 +214,7 @@ class ConfigureTaskRunnerAction extends Action { forceOpen: true } }, sideBySide).then((value) => { - this.outputService.showOutput(TaskService.OutputChannel, true, true); + this.outputService.showOutput(TaskService.OutputChannel, true); return value; }); }, (error) => { @@ -531,7 +531,7 @@ class TaskService extends EventEmitter implements ITaskService { } if (isAffected) { this.outputService.append(TaskService.OutputChannel, nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.\n')); - this.outputService.showOutput(TaskService.OutputChannel, true, true); + this.outputService.showOutput(TaskService.OutputChannel, true); return TPromise.wrapError({}); } } @@ -605,7 +605,7 @@ class TaskService extends EventEmitter implements ITaskService { result = false; this.outputService.append(TaskService.OutputChannel, line + '\n'); }); - this.outputService.showOutput(TaskService.OutputChannel, true, true); + this.outputService.showOutput(TaskService.OutputChannel, true); } return result; } @@ -761,7 +761,7 @@ class TaskService extends EventEmitter implements ITaskService { this.messageService.show(Severity.Error, nls.localize('TaskSystem.unknownError', 'An error has occurred while running a task. See task log for details.')); } if (showOutput) { - this.outputService.showOutput(TaskService.OutputChannel, false, true); + this.outputService.showOutput(TaskService.OutputChannel, true); } } } diff --git a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts index 42f65c9b04a5f3b54118b217eb86982e6b1201a8..1a5f767391c2e9d2f8756ef1409b7df6e6d3f75b 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts @@ -76,7 +76,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { this.defaultTestTaskIdentifier = parseResult.defaultTestTaskIdentifier; if (!this.validationStatus.isOK()) { - this.outputService.showOutput(this.outputChannel, false, true); + this.outputService.showOutput(this.outputChannel, true); } } @@ -394,7 +394,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { } private showOutput(): void { - this.outputService.showOutput(this.outputChannel, true, true); + this.outputService.showOutput(this.outputChannel, true); } private clearOutput(): void { diff --git a/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts index 141710061eb02a6d39a5264ab52d2c70b632cac1..bf9b5bca86b8ee1e73fde6186fdd67aa831831ab 100644 --- a/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts @@ -10,7 +10,6 @@ import {Promise } from 'vs/base/common/winjs.base'; import * as Strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; import {StringEditorInput} from 'vs/workbench/common/editor/stringEditorInput'; -import {LogEditorInput} from 'vs/workbench/common/editor/logEditorInput'; import {ResourceEditorInput} from 'vs/workbench/common/editor/resourceEditorInput'; import {ResourceEditorModel} from 'vs/workbench/common/editor/resourceEditorModel'; import {TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/browser/servicesTestUtils'; @@ -111,17 +110,6 @@ suite("Workbench - StringEditorInput", () => { assert.strictEqual(stringEditorInput.matches(stringEditorInput2), true); }); - test("LogEditorInput", function() { - let inst = InstantiationService.create({}); - - let logEditorInput = inst.createInstance(LogEditorInput, "name", 'description', "value\nvalue\nvalue", "mime", false); - let logEditorInput2 = inst.createInstance(LogEditorInput, "name", 'description', "value\nvalue\nvalue", "mime", false); - let stringEditorInput = inst.createInstance(StringEditorInput, "name", 'description', "value", "mime", false); - - assert.strictEqual(logEditorInput.matches(stringEditorInput), false); - assert.strictEqual(logEditorInput.matches(logEditorInput2), true); - }); - test("ResourceEditorInput", function(done) { let modelService = createMockModelService(); let modeService = createMockModeService(); diff --git a/src/vs/workbench/workbench.main.js b/src/vs/workbench/workbench.main.js index 6d4c46776ee8c7b5fbeea7e1879201ca0bde8314..1bdbc5361bc9990c852a5df1b2618300ad77dc7a 100644 --- a/src/vs/workbench/workbench.main.js +++ b/src/vs/workbench/workbench.main.js @@ -53,7 +53,6 @@ define([ 'vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen', 'vs/workbench/parts/output/browser/output.contribution', - 'vs/workbench/parts/output/browser/outputActions.contribution', 'vs/workbench/parts/markdown/browser/markdown.contribution', 'vs/workbench/parts/markdown/browser/markdownActions.contribution',