mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-19 14:22:19 +01:00
Merge pull request #189720 from microsoft/tyriar/187082_2
Improve management of events/memory in terminal
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IBufferMarkCapability, TerminalCapability, IMarkProperties } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
// Importing types is safe in any layer
|
||||
// eslint-disable-next-line local/code-import-patterns
|
||||
@@ -13,19 +14,20 @@ import type { IMarker, Terminal } from 'xterm-headless';
|
||||
* Manages "marks" in the buffer which are lines that are tracked when lines are added to or removed
|
||||
* from the buffer.
|
||||
*/
|
||||
export class BufferMarkCapability implements IBufferMarkCapability {
|
||||
export class BufferMarkCapability extends Disposable implements IBufferMarkCapability {
|
||||
|
||||
readonly type = TerminalCapability.BufferMarkDetection;
|
||||
|
||||
private _idToMarkerMap: Map<string, IMarker> = new Map();
|
||||
private _anonymousMarkers: Map<number, IMarker> = new Map();
|
||||
|
||||
private readonly _onMarkAdded = new Emitter<IMarkProperties>();
|
||||
private readonly _onMarkAdded = this._register(new Emitter<IMarkProperties>());
|
||||
readonly onMarkAdded = this._onMarkAdded.event;
|
||||
|
||||
constructor(
|
||||
private readonly _terminal: Terminal
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
*markers(): IterableIterator<IMarker> {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand, IHandleCommandOptions, ICommandInvalidationRequest, CommandInvalidationReason, ISerializedTerminalCommand, ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalOutputMatch, ITerminalOutputMatcher } from 'vs/platform/terminal/common/terminal';
|
||||
@@ -55,7 +56,7 @@ interface ITerminalDimensions {
|
||||
rows: number;
|
||||
}
|
||||
|
||||
export class CommandDetectionCapability implements ICommandDetectionCapability {
|
||||
export class CommandDetectionCapability extends Disposable implements ICommandDetectionCapability {
|
||||
readonly type = TerminalCapability.CommandDetection;
|
||||
|
||||
protected _commands: ITerminalCommand[] = [];
|
||||
@@ -97,29 +98,30 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
|
||||
return true;
|
||||
}
|
||||
|
||||
private readonly _onCommandStarted = new Emitter<ITerminalCommand>();
|
||||
private readonly _onCommandStarted = this._register(new Emitter<ITerminalCommand>());
|
||||
readonly onCommandStarted = this._onCommandStarted.event;
|
||||
private readonly _onBeforeCommandFinished = new Emitter<ITerminalCommand>();
|
||||
private readonly _onBeforeCommandFinished = this._register(new Emitter<ITerminalCommand>());
|
||||
readonly onBeforeCommandFinished = this._onBeforeCommandFinished.event;
|
||||
private readonly _onCommandFinished = new Emitter<ITerminalCommand>();
|
||||
private readonly _onCommandFinished = this._register(new Emitter<ITerminalCommand>());
|
||||
readonly onCommandFinished = this._onCommandFinished.event;
|
||||
private readonly _onCommandExecuted = new Emitter<void>();
|
||||
private readonly _onCommandExecuted = this._register(new Emitter<void>());
|
||||
readonly onCommandExecuted = this._onCommandExecuted.event;
|
||||
private readonly _onCommandInvalidated = new Emitter<ITerminalCommand[]>();
|
||||
private readonly _onCommandInvalidated = this._register(new Emitter<ITerminalCommand[]>());
|
||||
readonly onCommandInvalidated = this._onCommandInvalidated.event;
|
||||
private readonly _onCurrentCommandInvalidated = new Emitter<ICommandInvalidationRequest>();
|
||||
private readonly _onCurrentCommandInvalidated = this._register(new Emitter<ICommandInvalidationRequest>());
|
||||
readonly onCurrentCommandInvalidated = this._onCurrentCommandInvalidated.event;
|
||||
|
||||
constructor(
|
||||
private readonly _terminal: Terminal,
|
||||
private readonly _logService: ILogService
|
||||
) {
|
||||
super();
|
||||
this._dimensions = {
|
||||
cols: this._terminal.cols,
|
||||
rows: this._terminal.rows
|
||||
};
|
||||
this._terminal.onResize(e => this._handleResize(e));
|
||||
this._terminal.onCursorMove(() => this._handleCursorMove());
|
||||
this._register(this._terminal.onResize(e => this._handleResize(e)));
|
||||
this._register(this._terminal.onCursorMove(() => this._handleCursorMove()));
|
||||
this._setupClearListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ICwdDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
export class CwdDetectionCapability implements ICwdDetectionCapability {
|
||||
export class CwdDetectionCapability extends Disposable implements ICwdDetectionCapability {
|
||||
readonly type = TerminalCapability.CwdDetection;
|
||||
private _cwd = '';
|
||||
private _cwds = new Map</*cwd*/string, /*frequency*/number>();
|
||||
@@ -18,7 +19,7 @@ export class CwdDetectionCapability implements ICwdDetectionCapability {
|
||||
return Array.from(this._cwds.keys());
|
||||
}
|
||||
|
||||
private readonly _onDidChangeCwd = new Emitter<string>();
|
||||
private readonly _onDidChangeCwd = this._register(new Emitter<string>());
|
||||
readonly onDidChangeCwd = this._onDidChangeCwd.event;
|
||||
|
||||
getCwd(): string {
|
||||
|
||||
@@ -500,7 +500,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
|
||||
protected _createOrGetCwdDetection(): ICwdDetectionCapability {
|
||||
let cwdDetection = this.capabilities.get(TerminalCapability.CwdDetection);
|
||||
if (!cwdDetection) {
|
||||
cwdDetection = new CwdDetectionCapability();
|
||||
cwdDetection = this._register(new CwdDetectionCapability());
|
||||
this.capabilities.add(TerminalCapability.CwdDetection, cwdDetection);
|
||||
}
|
||||
return cwdDetection;
|
||||
@@ -509,7 +509,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
|
||||
protected _createOrGetCommandDetection(terminal: Terminal): ICommandDetectionCapability {
|
||||
let commandDetection = this.capabilities.get(TerminalCapability.CommandDetection);
|
||||
if (!commandDetection) {
|
||||
commandDetection = new CommandDetectionCapability(terminal, this._logService);
|
||||
commandDetection = this._register(new CommandDetectionCapability(terminal, this._logService));
|
||||
this.capabilities.add(TerminalCapability.CommandDetection, commandDetection);
|
||||
}
|
||||
return commandDetection;
|
||||
@@ -518,7 +518,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
|
||||
protected _createOrGetBufferMarkDetection(terminal: Terminal): IBufferMarkCapability {
|
||||
let bufferMarkDetection = this.capabilities.get(TerminalCapability.BufferMarkDetection);
|
||||
if (!bufferMarkDetection) {
|
||||
bufferMarkDetection = new BufferMarkCapability(terminal);
|
||||
bufferMarkDetection = this._register(new BufferMarkCapability(terminal));
|
||||
this.capabilities.add(TerminalCapability.BufferMarkDetection, bufferMarkDetection);
|
||||
}
|
||||
return bufferMarkDetection;
|
||||
|
||||
@@ -19,6 +19,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
|
||||
import { IShellLaunchConfig } from 'vs/platform/terminal/common/terminal';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
const enum FontConstants {
|
||||
MinimumFontSize = 6,
|
||||
@@ -29,7 +30,7 @@ const enum FontConstants {
|
||||
* Encapsulates terminal configuration logic, the primary purpose of this file is so that platform
|
||||
* specific test cases can be written.
|
||||
*/
|
||||
export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
|
||||
export class TerminalConfigHelper extends Disposable implements IBrowserTerminalConfigHelper {
|
||||
panelContainer: HTMLElement | undefined;
|
||||
|
||||
private _charMeasureElement: HTMLElement | undefined;
|
||||
@@ -37,7 +38,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
|
||||
protected _linuxDistro: LinuxDistro = LinuxDistro.Unknown;
|
||||
config!: ITerminalConfiguration;
|
||||
|
||||
private readonly _onConfigChanged = new Emitter<void>();
|
||||
private readonly _onConfigChanged = this._register(new Emitter<void>());
|
||||
get onConfigChanged(): Event<void> { return this._onConfigChanged.event; }
|
||||
|
||||
constructor(
|
||||
@@ -47,6 +48,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IProductService private readonly _productService: IProductService,
|
||||
) {
|
||||
super();
|
||||
this._updateConfig();
|
||||
this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(TERMINAL_CONFIG_SECTION)) {
|
||||
|
||||
@@ -33,15 +33,15 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor
|
||||
private _editorInputs: Map</*resource*/string, TerminalEditorInput> = new Map();
|
||||
private _instanceDisposables: Map</*resource*/string, IDisposable[]> = new Map();
|
||||
|
||||
private readonly _onDidDisposeInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidDisposeInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onDidDisposeInstance = this._onDidDisposeInstance.event;
|
||||
private readonly _onDidFocusInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidFocusInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onDidFocusInstance = this._onDidFocusInstance.event;
|
||||
private readonly _onDidChangeInstanceCapability = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidChangeInstanceCapability = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onDidChangeInstanceCapability = this._onDidChangeInstanceCapability.event;
|
||||
private readonly _onDidChangeActiveInstance = new Emitter<ITerminalInstance | undefined>();
|
||||
private readonly _onDidChangeActiveInstance = this._register(new Emitter<ITerminalInstance | undefined>());
|
||||
readonly onDidChangeActiveInstance = this._onDidChangeActiveInstance.event;
|
||||
private readonly _onDidChangeInstances = new Emitter<void>();
|
||||
private readonly _onDidChangeInstances = this._register(new Emitter<void>());
|
||||
readonly onDidChangeInstances = this._onDidChangeInstances.event;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -278,9 +278,9 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
|
||||
readonly onDisposed = this._onDisposed.event;
|
||||
private readonly _onInstancesChanged: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onInstancesChanged = this._onInstancesChanged.event;
|
||||
private readonly _onDidChangeActiveInstance = new Emitter<ITerminalInstance | undefined>();
|
||||
private readonly _onDidChangeActiveInstance = this._register(new Emitter<ITerminalInstance | undefined>());
|
||||
readonly onDidChangeActiveInstance = this._onDidChangeActiveInstance.event;
|
||||
private readonly _onPanelOrientationChanged = new Emitter<Orientation>();
|
||||
private readonly _onPanelOrientationChanged = this._register(new Emitter<Orientation>());
|
||||
readonly onPanelOrientationChanged = this._onPanelOrientationChanged.event;
|
||||
|
||||
constructor(
|
||||
@@ -380,13 +380,6 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
|
||||
|
||||
removeInstance(instance: ITerminalInstance) {
|
||||
this._removeInstance(instance);
|
||||
|
||||
// Dispose instance event listeners
|
||||
const disposables = this._instanceDisposables.get(instance.instanceId);
|
||||
if (disposables) {
|
||||
dispose(disposables);
|
||||
this._instanceDisposables.delete(instance.instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
private _removeInstance(instance: ITerminalInstance) {
|
||||
@@ -418,6 +411,13 @@ export class TerminalGroup extends Disposable implements ITerminalGroup {
|
||||
} else {
|
||||
this._onInstancesChanged.fire();
|
||||
}
|
||||
|
||||
// Dispose instance event listeners
|
||||
const disposables = this._instanceDisposables.get(instance.instanceId);
|
||||
if (disposables) {
|
||||
dispose(disposables);
|
||||
this._instanceDisposables.delete(instance.instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
moveInstance(instance: ITerminalInstance, index: number): void {
|
||||
|
||||
@@ -33,27 +33,27 @@ export class TerminalGroupService extends Disposable implements ITerminalGroupSe
|
||||
|
||||
private _container: HTMLElement | undefined;
|
||||
|
||||
private readonly _onDidChangeActiveGroup = new Emitter<ITerminalGroup | undefined>();
|
||||
private readonly _onDidChangeActiveGroup = this._register(new Emitter<ITerminalGroup | undefined>());
|
||||
readonly onDidChangeActiveGroup = this._onDidChangeActiveGroup.event;
|
||||
private readonly _onDidDisposeGroup = new Emitter<ITerminalGroup>();
|
||||
private readonly _onDidDisposeGroup = this._register(new Emitter<ITerminalGroup>());
|
||||
readonly onDidDisposeGroup = this._onDidDisposeGroup.event;
|
||||
private readonly _onDidChangeGroups = new Emitter<void>();
|
||||
private readonly _onDidChangeGroups = this._register(new Emitter<void>());
|
||||
readonly onDidChangeGroups = this._onDidChangeGroups.event;
|
||||
private readonly _onDidShow = new Emitter<void>();
|
||||
private readonly _onDidShow = this._register(new Emitter<void>());
|
||||
readonly onDidShow = this._onDidShow.event;
|
||||
|
||||
private readonly _onDidDisposeInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidDisposeInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onDidDisposeInstance = this._onDidDisposeInstance.event;
|
||||
private readonly _onDidFocusInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidFocusInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onDidFocusInstance = this._onDidFocusInstance.event;
|
||||
private readonly _onDidChangeActiveInstance = new Emitter<ITerminalInstance | undefined>();
|
||||
private readonly _onDidChangeActiveInstance = this._register(new Emitter<ITerminalInstance | undefined>());
|
||||
readonly onDidChangeActiveInstance = this._onDidChangeActiveInstance.event;
|
||||
private readonly _onDidChangeInstances = new Emitter<void>();
|
||||
private readonly _onDidChangeInstances = this._register(new Emitter<void>());
|
||||
readonly onDidChangeInstances = this._onDidChangeInstances.event;
|
||||
private readonly _onDidChangeInstanceCapability = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidChangeInstanceCapability = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onDidChangeInstanceCapability = this._onDidChangeInstanceCapability.event;
|
||||
|
||||
private readonly _onDidChangePanelOrientation = new Emitter<Orientation>();
|
||||
private readonly _onDidChangePanelOrientation = this._register(new Emitter<Orientation>());
|
||||
readonly onDidChangePanelOrientation = this._onDidChangePanelOrientation.event;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ErrorNoTelemetry, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ISeparator, template } from 'vs/base/common/labels';
|
||||
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, MutableDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { OS, OperatingSystem, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
@@ -168,9 +168,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
private _containerReadyBarrier: AutoOpenBarrier;
|
||||
private _attachBarrier: AutoOpenBarrier;
|
||||
private _icon: TerminalIcon | undefined;
|
||||
private _messageTitleDisposable: IDisposable | undefined;
|
||||
private _messageTitleDisposable: MutableDisposable<IDisposable> = this._register(new MutableDisposable());
|
||||
private _widgetManager: TerminalWidgetManager = new TerminalWidgetManager();
|
||||
private _dndObserver: IDisposable | undefined;
|
||||
private _dndObserver: MutableDisposable<IDisposable> = this._register(new MutableDisposable());
|
||||
private _lastLayoutDimensions: dom.Dimension | undefined;
|
||||
private _hasHadInput: boolean;
|
||||
private _description?: string;
|
||||
@@ -245,7 +245,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
get exitCode(): number | undefined { return this._exitCode; }
|
||||
get exitReason(): TerminalExitReason | undefined { return this._exitReason; }
|
||||
get hadFocusOnExit(): boolean { return this._hadFocusOnExit; }
|
||||
get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable; }
|
||||
get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable.value; }
|
||||
get shellLaunchConfig(): IShellLaunchConfig { return this._shellLaunchConfig; }
|
||||
get shellType(): TerminalShellType | undefined { return this._shellType; }
|
||||
get os(): OperatingSystem | undefined { return this._processManager.os; }
|
||||
@@ -450,8 +450,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._initDimensions();
|
||||
this._processManager = this._createProcessManager();
|
||||
|
||||
this._register(toDisposable(() => this._dndObserver?.dispose()));
|
||||
|
||||
this._containerReadyBarrier = new AutoOpenBarrier(Constants.WaitForContainerThreshold);
|
||||
this._attachBarrier = new AutoOpenBarrier(1000);
|
||||
this._xtermReadyPromise = this._createXterm();
|
||||
@@ -527,10 +525,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
e.affectsConfiguration(TerminalSettingId.TerminalTitle) ||
|
||||
e.affectsConfiguration(TerminalSettingId.TerminalTitleSeparator) ||
|
||||
e.affectsConfiguration(TerminalSettingId.TerminalDescription)) {
|
||||
this._labelComputer?.refreshLabel();
|
||||
this._labelComputer?.refreshLabel(this);
|
||||
}
|
||||
}));
|
||||
this._register(this._workspaceContextService.onDidChangeWorkspaceFolders(() => this._labelComputer?.refreshLabel()));
|
||||
this._register(this._workspaceContextService.onDidChangeWorkspaceFolders(() => this._labelComputer?.refreshLabel(this)));
|
||||
this._register(this.onDidBlur(() => this.xterm?.suggestController?.hideSuggestWidget()));
|
||||
|
||||
// Clear out initial data events after 10 seconds, hopefully extension hosts are up and
|
||||
@@ -564,6 +562,14 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
});
|
||||
this.onDisposed(() => {
|
||||
contribution.dispose();
|
||||
this._contributions.delete(desc.id);
|
||||
// Just in case to prevent potential future memory leaks due to cyclic dependency.
|
||||
if ('instance' in contribution) {
|
||||
delete contribution.instance;
|
||||
}
|
||||
if ('_instance' in contribution) {
|
||||
delete contribution._instance;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -745,13 +751,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// Write initial text, deferring onLineFeed listener when applicable to avoid firing
|
||||
// onLineData events containing initialText
|
||||
const initialTextWrittenPromise = this._shellLaunchConfig.initialText ? new Promise<void>(r => this._writeInitialText(xterm, r)) : undefined;
|
||||
const lineDataEventAddon = new LineDataEventAddon(initialTextWrittenPromise);
|
||||
const lineDataEventAddon = this._register(new LineDataEventAddon(initialTextWrittenPromise));
|
||||
lineDataEventAddon.onLineData(e => this._onLineData.fire(e));
|
||||
this._lineDataEventAddon = lineDataEventAddon;
|
||||
// Delay the creation of the bell listener to avoid showing the bell when the terminal
|
||||
// starts up or reconnects
|
||||
setTimeout(() => {
|
||||
xterm.raw.onBell(() => {
|
||||
this._register(xterm.raw.onBell(() => {
|
||||
if (this._configHelper.config.enableBell) {
|
||||
this.statusList.add({
|
||||
id: TerminalStatus.Bell,
|
||||
@@ -761,17 +767,17 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}, this._configHelper.config.bellDuration);
|
||||
this._audioCueService.playSound(AudioCue.terminalBell.sound.getSound());
|
||||
}
|
||||
});
|
||||
}));
|
||||
}, 1000);
|
||||
xterm.raw.onSelectionChange(async () => this._onSelectionChange());
|
||||
xterm.raw.buffer.onBufferChange(() => this._refreshAltBufferContextKey());
|
||||
this._register(xterm.raw.onSelectionChange(async () => this._onSelectionChange()));
|
||||
this._register(xterm.raw.buffer.onBufferChange(() => this._refreshAltBufferContextKey()));
|
||||
|
||||
this._processManager.onProcessData(e => this._onProcessData(e));
|
||||
xterm.raw.onData(async data => {
|
||||
this._register(xterm.raw.onData(async data => {
|
||||
await this._processManager.write(data);
|
||||
this._onDidInputData.fire(this);
|
||||
});
|
||||
xterm.raw.onBinary(data => this._processManager.processBinary(data));
|
||||
}));
|
||||
this._register(xterm.raw.onBinary(data => this._processManager.processBinary(data)));
|
||||
// Init winpty compat and link handler after process creation as they rely on the
|
||||
// underlying process OS
|
||||
this._processManager.onProcessReady(async (processTraits) => {
|
||||
@@ -1046,14 +1052,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
|
||||
private _initDragAndDrop(container: HTMLElement) {
|
||||
this._dndObserver?.dispose();
|
||||
const dndController = this._scopedInstantiationService.createInstance(TerminalInstanceDragAndDropController, container);
|
||||
const dndController = this._register(this._scopedInstantiationService.createInstance(TerminalInstanceDragAndDropController, container));
|
||||
dndController.onDropTerminal(e => this._onRequestAddInstanceToGroup.fire(e));
|
||||
dndController.onDropFile(async path => {
|
||||
this.focus();
|
||||
await this.sendPath(path, false);
|
||||
});
|
||||
this._dndObserver = new dom.DragAndDropObserver(container, dndController);
|
||||
this._dndObserver.value = new dom.DragAndDropObserver(container, dndController);
|
||||
}
|
||||
|
||||
hasSelection(): boolean {
|
||||
@@ -1339,12 +1344,12 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// Set the initial name based on the _resolved_ shell launch config, this will also
|
||||
// ensure the resolved icon gets shown
|
||||
if (!this._labelComputer) {
|
||||
this._labelComputer = this._register(this._scopedInstantiationService.createInstance(TerminalLabelComputer, this._configHelper, this));
|
||||
this._labelComputer.onDidChangeLabel(e => {
|
||||
this._labelComputer = this._register(this._scopedInstantiationService.createInstance(TerminalLabelComputer, this._configHelper));
|
||||
this._register(this._labelComputer.onDidChangeLabel(e => {
|
||||
this._title = e.title;
|
||||
this._description = e.description;
|
||||
this._onTitleChanged.fire(this);
|
||||
});
|
||||
}));
|
||||
}
|
||||
if (this._shellLaunchConfig.name) {
|
||||
this._setTitle(this._shellLaunchConfig.name, TitleEventSource.Api);
|
||||
@@ -1353,7 +1358,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// _xtermReadyPromise is ready constructed since this is called from the ctor
|
||||
setTimeout(() => {
|
||||
this._xtermReadyPromise.then(xterm => {
|
||||
this._messageTitleDisposable = xterm.raw.onTitleChange(e => this._onTitleChange(e));
|
||||
this._messageTitleDisposable.value = xterm.raw.onTitleChange(e => this._onTitleChange(e));
|
||||
});
|
||||
});
|
||||
this._setTitle(this._shellLaunchConfig.executable, TitleEventSource.Process);
|
||||
@@ -1364,7 +1369,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
switch (type) {
|
||||
case ProcessPropertyType.Cwd:
|
||||
this._cwd = value;
|
||||
this._labelComputer?.refreshLabel();
|
||||
this._labelComputer?.refreshLabel(this);
|
||||
break;
|
||||
case ProcessPropertyType.InitialCwd:
|
||||
this._initialCwd = value;
|
||||
@@ -1912,8 +1917,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// If the title has not been set by the API or the rename command, unregister the handler that
|
||||
// automatically updates the terminal name
|
||||
this._staticTitle = title;
|
||||
dispose(this._messageTitleDisposable);
|
||||
this._messageTitleDisposable = undefined;
|
||||
this._messageTitleDisposable.value = undefined;
|
||||
break;
|
||||
case TitleEventSource.Sequence:
|
||||
// On Windows, some shells will fire this with the full path which we want to trim
|
||||
@@ -1958,7 +1962,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
return;
|
||||
}
|
||||
this._fixedCols = this._parseFixedDimension(cols);
|
||||
this._labelComputer?.refreshLabel();
|
||||
this._labelComputer?.refreshLabel(this);
|
||||
this._terminalHasFixedWidth.set(!!this._fixedCols);
|
||||
const rows = await this._quickInputService.input({
|
||||
title: nls.localize('setTerminalDimensionsRow', "Set Fixed Dimensions: Row"),
|
||||
@@ -1969,7 +1973,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
return;
|
||||
}
|
||||
this._fixedRows = this._parseFixedDimension(rows);
|
||||
this._labelComputer?.refreshLabel();
|
||||
this._labelComputer?.refreshLabel(this);
|
||||
await this._refreshScrollbar();
|
||||
this._resize();
|
||||
this.focus();
|
||||
@@ -2007,7 +2011,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
}
|
||||
await this._refreshScrollbar();
|
||||
this._labelComputer?.refreshLabel();
|
||||
this._labelComputer?.refreshLabel(this);
|
||||
this.focus();
|
||||
}
|
||||
|
||||
@@ -2151,7 +2155,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
title = this._updateTitleProperties(title, eventSource);
|
||||
const titleChanged = title !== this._title;
|
||||
this._title = title;
|
||||
this._labelComputer?.refreshLabel(reset);
|
||||
this._labelComputer?.refreshLabel(this, reset);
|
||||
this._setAriaLabel(this.xterm?.raw, this._instanceId, this._title);
|
||||
|
||||
if (titleChanged) {
|
||||
@@ -2250,9 +2254,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
class TerminalInstanceDragAndDropController extends Disposable implements dom.IDragAndDropObserverCallbacks {
|
||||
private _dropOverlay?: HTMLElement;
|
||||
|
||||
private readonly _onDropFile = new Emitter<string | URI>();
|
||||
private readonly _onDropFile = this._register(new Emitter<string | URI>());
|
||||
get onDropFile(): Event<string | URI> { return this._onDropFile.event; }
|
||||
private readonly _onDropTerminal = new Emitter<IRequestAddInstanceToGroupEvent>();
|
||||
private readonly _onDropTerminal = this._register(new Emitter<IRequestAddInstanceToGroupEvent>());
|
||||
get onDropTerminal(): Event<IRequestAddInstanceToGroupEvent> { return this._onDropTerminal.event; }
|
||||
|
||||
constructor(
|
||||
@@ -2404,65 +2408,65 @@ export class TerminalLabelComputer extends Disposable {
|
||||
|
||||
constructor(
|
||||
private readonly _configHelper: TerminalConfigHelper,
|
||||
private readonly _instance: Pick<ITerminalInstance, 'shellLaunchConfig' | 'cwd' | 'fixedCols' | 'fixedRows' | 'initialCwd' | 'processName' | 'sequence' | 'userHome' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'>,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
refreshLabel(reset?: boolean): void {
|
||||
this._title = this.computeLabel(this._configHelper.config.tabs.title, TerminalLabelType.Title, reset);
|
||||
this._description = this.computeLabel(this._configHelper.config.tabs.description, TerminalLabelType.Description);
|
||||
if (this._title !== this._instance.title || this._description !== this._instance.description || reset) {
|
||||
refreshLabel(instance: Pick<ITerminalInstance, 'shellLaunchConfig' | 'cwd' | 'fixedCols' | 'fixedRows' | 'initialCwd' | 'processName' | 'sequence' | 'userHome' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'>, reset?: boolean): void {
|
||||
this._title = this.computeLabel(instance, this._configHelper.config.tabs.title, TerminalLabelType.Title, reset);
|
||||
this._description = this.computeLabel(instance, this._configHelper.config.tabs.description, TerminalLabelType.Description);
|
||||
if (this._title !== instance.title || this._description !== instance.description || reset) {
|
||||
this._onDidChangeLabel.fire({ title: this._title, description: this._description });
|
||||
}
|
||||
}
|
||||
|
||||
computeLabel(
|
||||
instance: Pick<ITerminalInstance, 'shellLaunchConfig' | 'cwd' | 'fixedCols' | 'fixedRows' | 'initialCwd' | 'processName' | 'sequence' | 'userHome' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'>,
|
||||
labelTemplate: string,
|
||||
labelType: TerminalLabelType,
|
||||
reset?: boolean
|
||||
) {
|
||||
const type = this._instance.shellLaunchConfig.attachPersistentProcess?.type || this._instance.shellLaunchConfig.type;
|
||||
const type = instance.shellLaunchConfig.attachPersistentProcess?.type || instance.shellLaunchConfig.type;
|
||||
const templateProperties: ITerminalLabelTemplateProperties = {
|
||||
cwd: this._instance.cwd || this._instance.initialCwd || '',
|
||||
cwd: instance.cwd || instance.initialCwd || '',
|
||||
cwdFolder: '',
|
||||
workspaceFolder: this._instance.workspaceFolder ? path.basename(this._instance.workspaceFolder.uri.fsPath) : undefined,
|
||||
workspaceFolder: instance.workspaceFolder ? path.basename(instance.workspaceFolder.uri.fsPath) : undefined,
|
||||
local: type === 'Local' ? type : undefined,
|
||||
process: this._instance.processName,
|
||||
sequence: this._instance.sequence,
|
||||
process: instance.processName,
|
||||
sequence: instance.sequence,
|
||||
task: type === 'Task' ? type : undefined,
|
||||
fixedDimensions: this._instance.fixedCols
|
||||
? (this._instance.fixedRows ? `\u2194${this._instance.fixedCols} \u2195${this._instance.fixedRows}` : `\u2194${this._instance.fixedCols}`)
|
||||
: (this._instance.fixedRows ? `\u2195${this._instance.fixedRows}` : ''),
|
||||
fixedDimensions: instance.fixedCols
|
||||
? (instance.fixedRows ? `\u2194${instance.fixedCols} \u2195${instance.fixedRows}` : `\u2194${instance.fixedCols}`)
|
||||
: (instance.fixedRows ? `\u2195${instance.fixedRows}` : ''),
|
||||
separator: { label: this._configHelper.config.tabs.separator }
|
||||
};
|
||||
labelTemplate = labelTemplate.trim();
|
||||
if (!labelTemplate) {
|
||||
return labelType === TerminalLabelType.Title ? (this._instance.processName || '') : '';
|
||||
return labelType === TerminalLabelType.Title ? (instance.processName || '') : '';
|
||||
}
|
||||
if (!reset && this._instance.staticTitle && labelType === TerminalLabelType.Title) {
|
||||
return this._instance.staticTitle.replace(/[\n\r\t]/g, '') || templateProperties.process?.replace(/[\n\r\t]/g, '') || '';
|
||||
if (!reset && instance.staticTitle && labelType === TerminalLabelType.Title) {
|
||||
return instance.staticTitle.replace(/[\n\r\t]/g, '') || templateProperties.process?.replace(/[\n\r\t]/g, '') || '';
|
||||
}
|
||||
const detection = this._instance.capabilities.has(TerminalCapability.CwdDetection) || this._instance.capabilities.has(TerminalCapability.NaiveCwdDetection);
|
||||
const detection = instance.capabilities.has(TerminalCapability.CwdDetection) || instance.capabilities.has(TerminalCapability.NaiveCwdDetection);
|
||||
const folders = this._workspaceContextService.getWorkspace().folders;
|
||||
const multiRootWorkspace = folders.length > 1;
|
||||
|
||||
// Only set cwdFolder if detection is on
|
||||
if (templateProperties.cwd && detection && (!this._instance.shellLaunchConfig.isFeatureTerminal || labelType === TerminalLabelType.Title)) {
|
||||
if (templateProperties.cwd && detection && (!instance.shellLaunchConfig.isFeatureTerminal || labelType === TerminalLabelType.Title)) {
|
||||
const cwdUri = URI.from({
|
||||
scheme: this._instance.workspaceFolder?.uri.scheme || Schemas.file,
|
||||
path: this._instance.cwd ? path.resolve(this._instance.cwd) : undefined
|
||||
scheme: instance.workspaceFolder?.uri.scheme || Schemas.file,
|
||||
path: instance.cwd ? path.resolve(instance.cwd) : undefined
|
||||
});
|
||||
// Multi-root workspaces always show cwdFolder to disambiguate them, otherwise only show
|
||||
// when it differs from the workspace folder in which it was launched from
|
||||
let showCwd = false;
|
||||
if (multiRootWorkspace) {
|
||||
showCwd = true;
|
||||
} else if (this._instance.workspaceFolder?.uri) {
|
||||
const caseSensitive = this._fileService.hasCapability(this._instance.workspaceFolder.uri, FileSystemProviderCapabilities.PathCaseSensitive);
|
||||
showCwd = cwdUri.fsPath.localeCompare(this._instance.workspaceFolder.uri.fsPath, undefined, { sensitivity: caseSensitive ? 'case' : 'base' }) !== 0;
|
||||
} else if (instance.workspaceFolder?.uri) {
|
||||
const caseSensitive = this._fileService.hasCapability(instance.workspaceFolder.uri, FileSystemProviderCapabilities.PathCaseSensitive);
|
||||
showCwd = cwdUri.fsPath.localeCompare(instance.workspaceFolder.uri.fsPath, undefined, { sensitivity: caseSensitive ? 'case' : 'base' }) !== 0;
|
||||
}
|
||||
if (showCwd) {
|
||||
|
||||
@@ -2472,7 +2476,7 @@ export class TerminalLabelComputer extends Disposable {
|
||||
|
||||
// Remove special characters that could mess with rendering
|
||||
const label = template(labelTemplate, (templateProperties as unknown) as { [key: string]: string | ISeparator | undefined | null }).replace(/[\n\r\t]/g, '').trim();
|
||||
return label === '' && labelType === TerminalLabelType.Title ? (this._instance.processName || '') : label;
|
||||
return label === '' && labelType === TerminalLabelType.Title ? (instance.processName || '') : label;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
|
||||
private _configHelper: TerminalConfigHelper;
|
||||
private _backendRegistration = new Map<string | undefined, { promise: Promise<void>; resolve: () => void }>();
|
||||
|
||||
private readonly _onDidCreateInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidCreateInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidCreateInstance(): Event<ITerminalInstance> { return this._onDidCreateInstance.event; }
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -7,7 +7,7 @@ import { equals } from 'vs/base/common/arrays';
|
||||
import { AutoOpenBarrier } from 'vs/base/common/async';
|
||||
import { throttle } from 'vs/base/common/decorators';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isMacintosh, isWeb, isWindows, OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -27,7 +27,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA
|
||||
* Links TerminalService with TerminalProfileResolverService
|
||||
* and keeps the available terminal profiles updated
|
||||
*/
|
||||
export class TerminalProfileService implements ITerminalProfileService {
|
||||
export class TerminalProfileService extends Disposable implements ITerminalProfileService {
|
||||
declare _serviceBrand: undefined;
|
||||
|
||||
private _webExtensionContributedProfileContextKey: IContextKey<boolean>;
|
||||
@@ -39,7 +39,7 @@ export class TerminalProfileService implements ITerminalProfileService {
|
||||
private _platformConfigJustRefreshed = false;
|
||||
private readonly _profileProviders: Map</*ext id*/string, Map</*provider id*/string, ITerminalProfileProvider>> = new Map();
|
||||
|
||||
private readonly _onDidChangeAvailableProfiles = new Emitter<ITerminalProfile[]>();
|
||||
private readonly _onDidChangeAvailableProfiles = this._register(new Emitter<ITerminalProfile[]>());
|
||||
get onDidChangeAvailableProfiles(): Event<ITerminalProfile[]> { return this._onDidChangeAvailableProfiles.event; }
|
||||
|
||||
get profilesReady(): Promise<void> { return this._profilesReadyPromise; }
|
||||
@@ -62,6 +62,8 @@ export class TerminalProfileService implements ITerminalProfileService {
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService
|
||||
) {
|
||||
super();
|
||||
|
||||
// in web, we don't want to show the dropdown unless there's a web extension
|
||||
// that contributes a profile
|
||||
this._extensionService.onDidChangeExtensions(() => this.refreshAvailableProfiles());
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { DeferredPromise, timeout } from 'vs/base/common/async';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isMacintosh, isWeb } from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -53,7 +53,7 @@ import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilitie
|
||||
import { ITimerService } from 'vs/workbench/services/timer/browser/timerService';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
|
||||
export class TerminalService implements ITerminalService {
|
||||
export class TerminalService extends Disposable implements ITerminalService {
|
||||
declare _serviceBrand: undefined;
|
||||
|
||||
private _hostActiveTerminals: Map<ITerminalInstanceHost, ITerminalInstance | undefined> = new Map();
|
||||
@@ -120,47 +120,47 @@ export class TerminalService implements ITerminalService {
|
||||
|
||||
private _editingTerminal: ITerminalInstance | undefined;
|
||||
|
||||
private readonly _onDidChangeActiveGroup = new Emitter<ITerminalGroup | undefined>();
|
||||
private readonly _onDidChangeActiveGroup = this._register(new Emitter<ITerminalGroup | undefined>());
|
||||
get onDidChangeActiveGroup(): Event<ITerminalGroup | undefined> { return this._onDidChangeActiveGroup.event; }
|
||||
private readonly _onDidCreateInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidCreateInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidCreateInstance(): Event<ITerminalInstance> { return this._onDidCreateInstance.event; }
|
||||
private readonly _onDidDisposeInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidDisposeInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidDisposeInstance(): Event<ITerminalInstance> { return this._onDidDisposeInstance.event; }
|
||||
private readonly _onDidFocusInstance = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidFocusInstance = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidFocusInstance(): Event<ITerminalInstance> { return this._onDidFocusInstance.event; }
|
||||
private readonly _onDidReceiveProcessId = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidReceiveProcessId = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidReceiveProcessId(): Event<ITerminalInstance> { return this._onDidReceiveProcessId.event; }
|
||||
private readonly _onDidRequestStartExtensionTerminal = new Emitter<IStartExtensionTerminalRequest>();
|
||||
private readonly _onDidRequestStartExtensionTerminal = this._register(new Emitter<IStartExtensionTerminalRequest>());
|
||||
get onDidRequestStartExtensionTerminal(): Event<IStartExtensionTerminalRequest> { return this._onDidRequestStartExtensionTerminal.event; }
|
||||
private readonly _onDidChangeInstanceDimensions = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidChangeInstanceDimensions = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidChangeInstanceDimensions(): Event<ITerminalInstance> { return this._onDidChangeInstanceDimensions.event; }
|
||||
private readonly _onDidMaxiumumDimensionsChange = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidMaxiumumDimensionsChange = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidMaximumDimensionsChange(): Event<ITerminalInstance> { return this._onDidMaxiumumDimensionsChange.event; }
|
||||
private readonly _onDidChangeInstanceCapability = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidChangeInstanceCapability = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidChangeInstanceCapability(): Event<ITerminalInstance> { return this._onDidChangeInstanceCapability.event; }
|
||||
private readonly _onDidChangeInstances = new Emitter<void>();
|
||||
private readonly _onDidChangeInstances = this._register(new Emitter<void>());
|
||||
get onDidChangeInstances(): Event<void> { return this._onDidChangeInstances.event; }
|
||||
private readonly _onDidChangeInstanceTitle = new Emitter<ITerminalInstance | undefined>();
|
||||
private readonly _onDidChangeInstanceTitle = this._register(new Emitter<ITerminalInstance | undefined>());
|
||||
get onDidChangeInstanceTitle(): Event<ITerminalInstance | undefined> { return this._onDidChangeInstanceTitle.event; }
|
||||
private readonly _onDidChangeInstanceIcon = new Emitter<{ instance: ITerminalInstance; userInitiated: boolean }>();
|
||||
private readonly _onDidChangeInstanceIcon = this._register(new Emitter<{ instance: ITerminalInstance; userInitiated: boolean }>());
|
||||
get onDidChangeInstanceIcon(): Event<{ instance: ITerminalInstance; userInitiated: boolean }> { return this._onDidChangeInstanceIcon.event; }
|
||||
private readonly _onDidChangeInstanceColor = new Emitter<{ instance: ITerminalInstance; userInitiated: boolean }>();
|
||||
private readonly _onDidChangeInstanceColor = this._register(new Emitter<{ instance: ITerminalInstance; userInitiated: boolean }>());
|
||||
get onDidChangeInstanceColor(): Event<{ instance: ITerminalInstance; userInitiated: boolean }> { return this._onDidChangeInstanceColor.event; }
|
||||
private readonly _onDidChangeActiveInstance = new Emitter<ITerminalInstance | undefined>();
|
||||
private readonly _onDidChangeActiveInstance = this._register(new Emitter<ITerminalInstance | undefined>());
|
||||
get onDidChangeActiveInstance(): Event<ITerminalInstance | undefined> { return this._onDidChangeActiveInstance.event; }
|
||||
private readonly _onDidChangeInstancePrimaryStatus = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidChangeInstancePrimaryStatus = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidChangeInstancePrimaryStatus(): Event<ITerminalInstance> { return this._onDidChangeInstancePrimaryStatus.event; }
|
||||
private readonly _onDidInputInstanceData = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidInputInstanceData = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidInputInstanceData(): Event<ITerminalInstance> { return this._onDidInputInstanceData.event; }
|
||||
private readonly _onDidChangeSelection = new Emitter<ITerminalInstance>();
|
||||
private readonly _onDidChangeSelection = this._register(new Emitter<ITerminalInstance>());
|
||||
get onDidChangeSelection(): Event<ITerminalInstance> { return this._onDidChangeSelection.event; }
|
||||
private readonly _onDidDisposeGroup = new Emitter<ITerminalGroup>();
|
||||
private readonly _onDidDisposeGroup = this._register(new Emitter<ITerminalGroup>());
|
||||
get onDidDisposeGroup(): Event<ITerminalGroup> { return this._onDidDisposeGroup.event; }
|
||||
private readonly _onDidChangeGroups = new Emitter<void>();
|
||||
private readonly _onDidChangeGroups = this._register(new Emitter<void>());
|
||||
get onDidChangeGroups(): Event<void> { return this._onDidChangeGroups.event; }
|
||||
private readonly _onDidRegisterProcessSupport = new Emitter<void>();
|
||||
private readonly _onDidRegisterProcessSupport = this._register(new Emitter<void>());
|
||||
get onDidRegisterProcessSupport(): Event<void> { return this._onDidRegisterProcessSupport.event; }
|
||||
private readonly _onDidChangeConnectionState = new Emitter<void>();
|
||||
private readonly _onDidChangeConnectionState = this._register(new Emitter<void>());
|
||||
get onDidChangeConnectionState(): Event<void> { return this._onDidChangeConnectionState.event; }
|
||||
|
||||
constructor(
|
||||
@@ -185,7 +185,9 @@ export class TerminalService implements ITerminalService {
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@ITimerService private readonly _timerService: ITimerService
|
||||
) {
|
||||
this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper);
|
||||
super();
|
||||
|
||||
this._configHelper = this._register(this._instantiationService.createInstance(TerminalConfigHelper));
|
||||
// the below avoids having to poll routinely.
|
||||
// we update detected profiles when an instance is created so that,
|
||||
// for example, we detect if you've installed a pwsh
|
||||
|
||||
@@ -46,7 +46,7 @@ import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/termin
|
||||
import { getTerminalResourcesFromDragEvent, parseTerminalUri } from 'vs/workbench/contrib/terminal/browser/terminalUri';
|
||||
import { getInstanceHoverInfo } from 'vs/workbench/contrib/terminal/browser/terminalTooltip';
|
||||
import { defaultInputBoxStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { getColorForSeverity } from 'vs/workbench/contrib/terminal/browser/terminalStatusList';
|
||||
|
||||
@@ -196,8 +196,8 @@ export class TerminalTabList extends WorkbenchList<ITerminalInstance> {
|
||||
}
|
||||
});
|
||||
if (!this._decorationsProvider) {
|
||||
this._decorationsProvider = instantiationService.createInstance(TabDecorationsProvider);
|
||||
decorationsService.registerDecorationsProvider(this._decorationsProvider);
|
||||
this._decorationsProvider = this.disposables.add(instantiationService.createInstance(TabDecorationsProvider));
|
||||
this.disposables.add(decorationsService.registerDecorationsProvider(this._decorationsProvider));
|
||||
}
|
||||
this.refresh();
|
||||
}
|
||||
@@ -737,18 +737,17 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
|
||||
}
|
||||
}
|
||||
|
||||
class TabDecorationsProvider implements IDecorationsProvider {
|
||||
class TabDecorationsProvider extends Disposable implements IDecorationsProvider {
|
||||
readonly label: string = localize('label', "Terminal");
|
||||
private readonly _onDidChange = new Emitter<URI[]>();
|
||||
|
||||
private readonly _onDidChange = this._register(new Emitter<URI[]>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
) {
|
||||
this._terminalService.onDidChangeInstancePrimaryStatus(e => this._onDidChange.fire([e.resource]));
|
||||
}
|
||||
|
||||
get onDidChange(): Event<URI[]> {
|
||||
return this._onDidChange.event;
|
||||
super();
|
||||
this._register(this._terminalService.onDidChangeInstancePrimaryStatus(e => this._onDidChange.fire([e.resource])));
|
||||
}
|
||||
|
||||
provideDecorations(resource: URI): IDecorationData | undefined {
|
||||
@@ -772,8 +771,4 @@ class TabDecorationsProvider implements IDecorationsProvider {
|
||||
tooltip: primaryStatus.tooltip
|
||||
};
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
|
||||
private _cursorIndexDelta: number = 0;
|
||||
private _inputQueue?: string[];
|
||||
|
||||
private readonly _onBell = new Emitter<void>();
|
||||
private readonly _onBell = this._register(new Emitter<void>());
|
||||
readonly onBell = this._onBell.event;
|
||||
private readonly _onAcceptedCompletion = new Emitter<string>();
|
||||
private readonly _onAcceptedCompletion = this._register(new Emitter<string>());
|
||||
readonly onAcceptedCompletion = this._onAcceptedCompletion.event;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -146,21 +146,21 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal, ID
|
||||
|
||||
get isStdinDisabled(): boolean { return !!this.raw.options.disableStdin; }
|
||||
|
||||
private readonly _onDidRequestRunCommand = new Emitter<{ command: ITerminalCommand; copyAsHtml?: boolean; noNewLine?: boolean }>();
|
||||
private readonly _onDidRequestRunCommand = this.add(new Emitter<{ command: ITerminalCommand; copyAsHtml?: boolean; noNewLine?: boolean }>());
|
||||
readonly onDidRequestRunCommand = this._onDidRequestRunCommand.event;
|
||||
private readonly _onDidRequestFocus = new Emitter<void>();
|
||||
private readonly _onDidRequestFocus = this.add(new Emitter<void>());
|
||||
readonly onDidRequestFocus = this._onDidRequestFocus.event;
|
||||
private readonly _onDidRequestSendText = new Emitter<string>();
|
||||
private readonly _onDidRequestSendText = this.add(new Emitter<string>());
|
||||
readonly onDidRequestSendText = this._onDidRequestSendText.event;
|
||||
private readonly _onDidRequestFreePort = new Emitter<string>();
|
||||
private readonly _onDidRequestFreePort = this.add(new Emitter<string>());
|
||||
readonly onDidRequestFreePort = this._onDidRequestFreePort.event;
|
||||
private readonly _onDidChangeFindResults = new Emitter<{ resultIndex: number; resultCount: number }>();
|
||||
private readonly _onDidChangeFindResults = this.add(new Emitter<{ resultIndex: number; resultCount: number }>());
|
||||
readonly onDidChangeFindResults = this._onDidChangeFindResults.event;
|
||||
private readonly _onDidChangeSelection = new Emitter<void>();
|
||||
private readonly _onDidChangeSelection = this.add(new Emitter<void>());
|
||||
readonly onDidChangeSelection = this._onDidChangeSelection.event;
|
||||
private readonly _onDidChangeFocus = new Emitter<boolean>();
|
||||
private readonly _onDidChangeFocus = this.add(new Emitter<boolean>());
|
||||
readonly onDidChangeFocus = this._onDidChangeFocus.event;
|
||||
private readonly _onDidDispose = new Emitter<void>();
|
||||
private readonly _onDidDispose = this.add(new Emitter<void>());
|
||||
readonly onDidDispose = this._onDidDispose.event;
|
||||
|
||||
get markTracker(): IMarkTracker { return this._markNavigationAddon; }
|
||||
|
||||
@@ -12,6 +12,7 @@ import { deserializeEnvironmentDescriptionMap, deserializeEnvironmentVariableCol
|
||||
import { IEnvironmentVariableCollectionWithPersistence, IEnvironmentVariableService } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { TerminalStorageKeys } from 'vs/workbench/contrib/terminal/common/terminalStorageKeys';
|
||||
import { IMergedEnvironmentVariableCollection, ISerializableEnvironmentDescriptionMap, ISerializableEnvironmentVariableCollection } from 'vs/platform/terminal/common/environmentVariable';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
interface ISerializableExtensionEnvironmentVariableCollection {
|
||||
extensionIdentifier: string;
|
||||
@@ -22,19 +23,21 @@ interface ISerializableExtensionEnvironmentVariableCollection {
|
||||
/**
|
||||
* Tracks and persists environment variable collections as defined by extensions.
|
||||
*/
|
||||
export class EnvironmentVariableService implements IEnvironmentVariableService {
|
||||
export class EnvironmentVariableService extends Disposable implements IEnvironmentVariableService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
collections: Map<string, IEnvironmentVariableCollectionWithPersistence> = new Map();
|
||||
mergedCollection: IMergedEnvironmentVariableCollection;
|
||||
|
||||
private readonly _onDidChangeCollections = new Emitter<IMergedEnvironmentVariableCollection>();
|
||||
private readonly _onDidChangeCollections = this._register(new Emitter<IMergedEnvironmentVariableCollection>());
|
||||
get onDidChangeCollections(): Event<IMergedEnvironmentVariableCollection> { return this._onDidChangeCollections.event; }
|
||||
|
||||
constructor(
|
||||
@IExtensionService private readonly _extensionService: IExtensionService,
|
||||
@IStorageService private readonly _storageService: IStorageService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._storageService.remove(TerminalStorageKeys.DeprecatedEnvironmentVariableCollections, StorageScope.WORKSPACE);
|
||||
const serializedPersistedCollections = this._storageService.get(TerminalStorageKeys.EnvironmentVariableCollections, StorageScope.WORKSPACE);
|
||||
if (serializedPersistedCollections) {
|
||||
|
||||
@@ -197,8 +197,8 @@ suite('Workbench - TerminalInstance', () => {
|
||||
test('should resolve to "" when the template variables are empty', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '', description: '' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: '' }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: '' }));
|
||||
// TODO:
|
||||
// terminalLabelComputer.onLabelChanged(e => {
|
||||
// strictEqual(e.title, '');
|
||||
@@ -210,80 +210,80 @@ suite('Workbench - TerminalInstance', () => {
|
||||
test('should resolve cwd', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${cwd}', description: '${cwd}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, cwd: ROOT_1 }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, cwd: ROOT_1 }));
|
||||
strictEqual(terminalLabelComputer.title, ROOT_1);
|
||||
strictEqual(terminalLabelComputer.description, ROOT_1);
|
||||
});
|
||||
test('should resolve workspaceFolder', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${workspaceFolder}', description: '${workspaceFolder}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'zsh', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: 'folder' }) } as IWorkspaceFolder }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: 'folder' }) } as IWorkspaceFolder }));
|
||||
strictEqual(terminalLabelComputer.title, 'folder');
|
||||
strictEqual(terminalLabelComputer.description, 'folder');
|
||||
});
|
||||
test('should resolve local', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${local}', description: '${local}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Local' } }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Local' } }));
|
||||
strictEqual(terminalLabelComputer.title, 'Local');
|
||||
strictEqual(terminalLabelComputer.description, 'Local');
|
||||
});
|
||||
test('should resolve process', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${process}', description: '${process}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'zsh' }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh' }));
|
||||
strictEqual(terminalLabelComputer.title, 'zsh');
|
||||
strictEqual(terminalLabelComputer.description, 'zsh');
|
||||
});
|
||||
test('should resolve sequence', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' - ', title: '${sequence}', description: '${sequence}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, sequence: 'sequence' }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, sequence: 'sequence' }));
|
||||
strictEqual(terminalLabelComputer.title, 'sequence');
|
||||
strictEqual(terminalLabelComputer.description, 'sequence');
|
||||
});
|
||||
test('should resolve task', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${task}', description: '${task}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Task' } }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Task' } }));
|
||||
strictEqual(terminalLabelComputer.title, 'zsh ~ Task');
|
||||
strictEqual(terminalLabelComputer.description, 'Task');
|
||||
});
|
||||
test('should resolve separator', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${separator}', description: '${separator}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Task' } }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'zsh', shellLaunchConfig: { type: 'Task' } }));
|
||||
strictEqual(terminalLabelComputer.title, 'zsh');
|
||||
strictEqual(terminalLabelComputer.description, '');
|
||||
});
|
||||
test('should always return static title when specified', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}', description: '${workspaceFolder}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: 'folder' }) } as IWorkspaceFolder, staticTitle: 'my-title' }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: 'folder' }) } as IWorkspaceFolder, staticTitle: 'my-title' }));
|
||||
strictEqual(terminalLabelComputer.title, 'my-title');
|
||||
strictEqual(terminalLabelComputer.description, 'folder');
|
||||
});
|
||||
test('should provide cwdFolder for all cwds only when in multi-root', () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_1 }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_1 }));
|
||||
// single-root, cwd is same as root
|
||||
strictEqual(terminalLabelComputer.title, 'process');
|
||||
strictEqual(terminalLabelComputer.description, '');
|
||||
// multi-root
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_2 }), new TestFileService(), mockMultiRootContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockMultiRootContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_2 }));
|
||||
if (isWindows) {
|
||||
strictEqual(terminalLabelComputer.title, 'process');
|
||||
strictEqual(terminalLabelComputer.description, '');
|
||||
@@ -295,13 +295,13 @@ suite('Workbench - TerminalInstance', () => {
|
||||
test('should hide cwdFolder in single folder workspaces when cwd matches the workspace\'s default cwd even when slashes differ', async () => {
|
||||
configurationService = new TestConfigurationService({ terminal: { integrated: { tabs: { separator: ' ~ ', title: '${process}${separator}${cwdFolder}', description: '${cwdFolder}' } } } });
|
||||
configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!);
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_1 }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_1 }));
|
||||
strictEqual(terminalLabelComputer.title, 'process');
|
||||
strictEqual(terminalLabelComputer.description, '');
|
||||
if (!isWindows) {
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_2 }), new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel();
|
||||
terminalLabelComputer = new TerminalLabelComputer(configHelper, new TestFileService(), mockContextService);
|
||||
terminalLabelComputer.refreshLabel(createInstance({ capabilities, processName: 'process', workspaceFolder: { uri: URI.from({ scheme: Schemas.file, path: ROOT_1 }) } as IWorkspaceFolder, cwd: ROOT_2 }));
|
||||
strictEqual(terminalLabelComputer.title, 'process ~ root2');
|
||||
strictEqual(terminalLabelComputer.description, 'root2');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user