diff --git a/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts b/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts index 0df0a7c9bfb..a8eed0c7b50 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadOutputService.ts @@ -38,11 +38,13 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostOutputService); - this._register(anyEvent(this._outputService.onActiveOutputChannel, this._panelService.onDidPanelOpen, this._panelService.onDidPanelClose)(() => { + const setVisibleChannel = () => { const panel = this._panelService.getActivePanel(); const visibleChannel: IOutputChannel = panel && panel.getId() === OUTPUT_PANEL_ID ? this._outputService.getActiveChannel() : null; this._proxy.$setVisibleChannel(visibleChannel ? visibleChannel.id : null); - })); + }; + this._register(anyEvent(this._outputService.onActiveOutputChannel, this._panelService.onDidPanelOpen, this._panelService.onDidPanelClose)(() => setVisibleChannel())); + setVisibleChannel(); } public dispose(): void { @@ -72,10 +74,10 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut return undefined; } - public $clear(channelId: string): Thenable { + public $clear(channelId: string, till: number): Thenable { const channel = this._getChannel(channelId); if (channel) { - channel.clear(); + channel.clear(till); } return undefined; } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index a7e9ea956cf..e7c980489a8 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -305,7 +305,7 @@ export interface MainThreadOutputServiceShape extends IDisposable { $register(label: string, log: boolean, file?: UriComponents): Thenable; $append(channelId: string, value: string): Thenable; $update(channelId: string): Thenable; - $clear(channelId: string): Thenable; + $clear(channelId: string, till: number): Thenable; $reveal(channelId: string, preserveFocus: boolean): Thenable; $close(channelId: string): Thenable; $dispose(channelId: string): Thenable; diff --git a/src/vs/workbench/api/node/extHostOutputService.ts b/src/vs/workbench/api/node/extHostOutputService.ts index 4d5c0f9f8b2..bae23eb8674 100644 --- a/src/vs/workbench/api/node/extHostOutputService.ts +++ b/src/vs/workbench/api/node/extHostOutputService.ts @@ -19,6 +19,7 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements private readonly _name: string; protected readonly _proxy: MainThreadOutputServiceShape; private _disposed: boolean; + private _offset: number; protected _onDidAppend: Emitter = this._register(new Emitter()); get onDidAppend(): Event { return this._onDidAppend.event; } @@ -29,13 +30,17 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements this._name = name; this._proxy = proxy; this._id = proxy.$register(this.name, log, file); + this._offset = 0; } get name(): string { return this._name; } - abstract append(value: string): void; + append(value: string): void { + this.validate(); + this._offset += value ? Buffer.from(value).byteLength : 0; + } update(): void { this._id.then(id => this._proxy.$update(id)); @@ -48,7 +53,8 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements clear(): void { this.validate(); - this._id.then(id => this._proxy.$clear(id)); + const till = this._offset; + this._id.then(id => this._proxy.$clear(id, till)); } show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void { @@ -85,7 +91,7 @@ export class ExtHostPushOutputChannel extends AbstractExtHostOutputChannel { } append(value: string): void { - this.validate(); + super.append(value); this._id.then(id => this._proxy.$append(id, value)); this._onDidAppend.fire(); } @@ -105,7 +111,7 @@ export class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChann } append(value: string): void { - this.validate(); + super.append(value); this._appender.append(value); this._onDidAppend.fire(); } diff --git a/src/vs/workbench/parts/output/common/output.ts b/src/vs/workbench/parts/output/common/output.ts index c8709c545a1..aca59d9ff7a 100644 --- a/src/vs/workbench/parts/output/common/output.ts +++ b/src/vs/workbench/parts/output/common/output.ts @@ -124,7 +124,7 @@ export interface IOutputChannel { /** * Clears all received output for this channel. */ - clear(): void; + clear(till?: number): void; /** * Disposes the output channel. diff --git a/src/vs/workbench/parts/output/electron-browser/outputServices.ts b/src/vs/workbench/parts/output/electron-browser/outputServices.ts index bc8fbc58591..8e4d8f4e1f0 100644 --- a/src/vs/workbench/parts/output/electron-browser/outputServices.ts +++ b/src/vs/workbench/parts/output/electron-browser/outputServices.ts @@ -113,7 +113,7 @@ abstract class AbstractFileOutputChannel extends Disposable { return this.outputChannelDescriptor.label; } - clear(): void { + clear(till?: number): void { if (this.modelUpdater.isScheduled()) { this.modelUpdater.cancel(); this.onUpdateModelCancelled(); @@ -121,6 +121,7 @@ abstract class AbstractFileOutputChannel extends Disposable { if (this.model) { this.model.setValue(''); } + this.endOffset = isNumber(till) ? till : this.endOffset; this.startOffset = this.endOffset; } @@ -208,8 +209,8 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out } } - clear(): void { - super.clear(); + clear(till?: number): void { + super.clear(till); this.appendedMessage = ''; } @@ -338,6 +339,7 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann private updateInProgress: boolean = false; private etag: string = ''; + private loadModelPromise: TPromise = TPromise.as(null); constructor( outputChannelDescriptor: IOutputChannelDescriptor, @@ -354,12 +356,20 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann } loadModel(): TPromise { - return this.fileService.resolveContent(this.file, { position: this.startOffset, encoding: 'utf8' }) + this.loadModelPromise = this.fileService.resolveContent(this.file, { position: this.startOffset, encoding: 'utf8' }) .then(content => { this.endOffset = this.startOffset + Buffer.from(content.value).byteLength; this.etag = content.etag; return this.createModel(content.value); }); + return this.loadModelPromise; + } + + clear(till?: number): void { + this.loadModelPromise.then(() => { + super.clear(till); + this.update(); + }); } append(message: string): void {