From 681ea6e18da674e30c00708c2c0b6a2b94c73430 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 13 Jan 2022 08:36:47 -0800 Subject: [PATCH 1/6] Create capability implementation objects Part of #139396 --- .../terminal/browser/terminalInstance.ts | 2 +- .../browser/terminalProcessManager.ts | 3 +- .../browser/xterm/shellIntegrationAddon.ts | 3 +- .../commandDetectionCapability.ts | 11 ++++ .../capabilities/cwdDetectionCapability.ts | 10 +++ .../naiveCwdDetectionCapability.ts | 10 +++ .../partialCommandDetectionCapability.ts | 10 +++ .../capabilities/terminalCapabilityStore.ts | 64 ++++++++++++++----- .../contrib/terminal/common/terminal.ts | 26 ++++++-- .../test/browser/terminalInstance.test.ts | 4 +- .../terminalCapabilityStore.test.ts | 62 +++++++++--------- 11 files changed, 147 insertions(+), 58 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts create mode 100644 src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts create mode 100644 src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts create mode 100644 src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 45ae6570e40..b8bd52ef416 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1174,7 +1174,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { protected _createProcessManager(): TerminalProcessManager { const processManager = this._instantiationService.createInstance(TerminalProcessManager, this._instanceId, this._configHelper); - this.capabilities.addCapabilityStore(this._processManager.capabilities); + this.capabilities.add(this._processManager.capabilities); processManager.onProcessReady(async (e) => { this._onProcessIdReady.fire(this); this._initialCwd = await this.getInitialCwd(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index bd0be54f574..f9f2b46f831 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -29,6 +29,7 @@ import { IProcessEnvironment, isMacintosh, isWindows, OperatingSystem, OS } from import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -296,7 +297,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce // Add any capabilities inherit to the backend if (this.os === OperatingSystem.Linux || this.os === OperatingSystem.Macintosh) { - this.capabilities.addCapability(TerminalCapability.NaiveCwdDetection); + this.capabilities.add(TerminalCapability.NaiveCwdDetection, new NaiveCwdDetectionCapability()); } this._dataFilter.newProcess(this._process, reset); diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts index 65dc638b52a..f55feb3825a 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts @@ -9,6 +9,7 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; /** * Shell integration is a feature that enhances the terminal's understanding of what's happening @@ -104,7 +105,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati type = ShellIntegrationInteraction.CommandFinished; break; case ShellIntegrationOscPt.EnableShellIntegration: - this.capabilities.addCapability(TerminalCapability.CommandDetection); + this.capabilities.add(TerminalCapability.CommandDetection, new CommandDetectionCapability()); return true; default: return false; diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts new file mode 100644 index 00000000000..192506ebae6 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; +import { ICommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/terminal'; + +export class CommandDetectionCapability implements ICommandDetectionCapability { + readonly type = TerminalCapability.CommandDetection; +} diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts new file mode 100644 index 00000000000..2a595990d4a --- /dev/null +++ b/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; + +export class CwdDetectionCapability { + readonly type = TerminalCapability.CwdDetection; +} diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts new file mode 100644 index 00000000000..454bc77a150 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; + +export class NaiveCwdDetectionCapability { + readonly type = TerminalCapability.NaiveCwdDetection; +} diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts new file mode 100644 index 00000000000..9d15e9488c4 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; + +export class PartialCommandDetectionCapability { + readonly type = TerminalCapability.CwdDetection; +} diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts b/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts index d28906eedae..8441c8f7bac 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts @@ -6,32 +6,40 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; -import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalCapabilityImplMap, ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/terminal'; export class TerminalCapabilityStore extends Disposable implements ITerminalCapabilityStore { - readonly items: TerminalCapability[] = []; + private _map: Map = new Map(); private readonly _onDidRemoveCapability = this._register(new Emitter()); readonly onDidRemoveCapability = this._onDidRemoveCapability.event; private readonly _onDidAddCapability = this._register(new Emitter()); readonly onDidAddCapability = this._onDidAddCapability.event; - addCapability(capability: TerminalCapability) { - this.items.push(capability); + get items(): IterableIterator { + return this._map.keys(); + } + + add(capability: T, impl: ITerminalCapabilityImplMap[T]) { + this._map.set(capability, impl); this._onDidAddCapability.fire(capability); } - removeCapability(capability: TerminalCapability) { - const index = this.items.indexOf(capability); - if (index === -1) { + get(capability: T): ITerminalCapabilityImplMap[T] | undefined { + // HACK: This isn't totally safe since the Map key and value are not connected + return this._map.get(capability) as ITerminalCapabilityImplMap[T] | undefined; + } + + remove(capability: TerminalCapability) { + if (!this._map.has(capability)) { return; } - this.items.splice(index, 1); + this._map.delete(capability); this._onDidRemoveCapability.fire(capability); } has(capability: TerminalCapability) { - return this.items.includes(capability); + return this._map.has(capability); } } @@ -43,18 +51,40 @@ export class TerminalCapabilityStoreMultiplexer extends Disposable implements IT private readonly _onDidAddCapability = this._register(new Emitter()); readonly onDidAddCapability = this._onDidAddCapability.event; - get items(): readonly TerminalCapability[] { - return this._stores.reduce((p, c) => { - p.push(...c.items); - return p; - }, []); + get items(): IterableIterator { + return this._items(); } - has(capability: TerminalCapability) { - return this.items.includes(capability); + private *_items(): IterableIterator { + for (const store of this._stores) { + for (const c of store.items) { + yield c; + } + } } - addCapabilityStore(store: ITerminalCapabilityStore) { + has(capability: TerminalCapability): boolean { + for (const store of this._stores) { + for (const c of store.items) { + if (c === capability) { + return true; + } + } + } + return false; + } + + get(capability: T): ITerminalCapabilityImplMap[T] | undefined { + for (const store of this._stores) { + const c = store.get(capability); + if (c) { + return c; + } + } + return undefined; + } + + add(store: ITerminalCapabilityStore) { this._stores.push(store); for (const capability of store.items) { this._onDidAddCapability.fire(capability); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 4059d4bb159..8093c968829 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -402,17 +402,33 @@ export interface ITerminalProcessManager extends IDisposable { updateProperty(property: T, value: IProcessPropertyMap[T]): void; } +// TODO: Move to capabilities/ export interface ITerminalCapabilityStore { - readonly items: readonly TerminalCapability[]; + readonly items: IterableIterator; readonly onDidRemoveCapability: Event; readonly onDidAddCapability: Event; has(capability: TerminalCapability): boolean; + get(capability: T): ITerminalCapabilityImplMap[T] | undefined; +} +export interface ITerminalCapabilityImplMap { + [TerminalCapability.CwdDetection]: ICwdDetectionCapability; + [TerminalCapability.CommandDetection]: ICommandDetectionCapability; + [TerminalCapability.NaiveCwdDetection]: INaiveCwdDetectionCapability; + [TerminalCapability.PartialCommandDetection]: IPartialCommandDetectionCapability; +} +export interface ICwdDetectionCapability { + readonly type: TerminalCapability.CwdDetection; +} +export interface ICommandDetectionCapability { + readonly type: TerminalCapability.CommandDetection; +} +export interface INaiveCwdDetectionCapability { + readonly type: TerminalCapability.NaiveCwdDetection; +} +export interface IPartialCommandDetectionCapability { + readonly type: TerminalCapability.PartialCommandDetection; } -export interface ITerminalCapabilityStoreController { - addCapability(capability: TerminalCapability): void; - removeCapability(capability: TerminalCapability): void; -} export const enum ProcessState { // The process has not been initialized yet. diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts index b4833a3c525..11e10d31475 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts @@ -22,7 +22,7 @@ import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/ca function createInstance(partial?: Partial): Pick { const capabilities = new TerminalCapabilityStore(); if (!isWindows) { - capabilities.addCapability(TerminalCapability.NaiveCwdDetection); + capabilities.add(TerminalCapability.NaiveCwdDetection, null!); } return { shellLaunchConfig: {}, @@ -169,7 +169,7 @@ suite('Workbench - TerminalInstance', () => { instantiationService.stub(IWorkspaceContextService, new TestContextService()); capabilities = new TerminalCapabilityStore(); if (!isWindows) { - capabilities.addCapability(TerminalCapability.NaiveCwdDetection); + capabilities.add(TerminalCapability.NaiveCwdDetection, null!); } const ROOT_1_URI = getUri(ROOT_1); diff --git a/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts b/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts index eef4165cdc6..65b6aed55cd 100644 --- a/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts @@ -24,30 +24,30 @@ suite('TerminalCapabilityStore', () => { test('should fire events when capabilities are added', () => { assertEvents(addEvents, []); - store.addCapability(TerminalCapability.CwdDetection); + store.add(TerminalCapability.CwdDetection, null!); assertEvents(addEvents, [TerminalCapability.CwdDetection]); }); test('should fire events when capabilities are removed', async () => { assertEvents(removeEvents, []); - store.addCapability(TerminalCapability.CwdDetection); + store.add(TerminalCapability.CwdDetection, null!); assertEvents(removeEvents, []); - store.removeCapability(TerminalCapability.CwdDetection); + store.remove(TerminalCapability.CwdDetection); assertEvents(removeEvents, [TerminalCapability.CwdDetection]); }); test('has should return whether a capability is present', () => { deepStrictEqual(store.has(TerminalCapability.CwdDetection), false); - store.addCapability(TerminalCapability.CwdDetection); + store.add(TerminalCapability.CwdDetection, null!); deepStrictEqual(store.has(TerminalCapability.CwdDetection), true); - store.removeCapability(TerminalCapability.CwdDetection); + store.remove(TerminalCapability.CwdDetection); deepStrictEqual(store.has(TerminalCapability.CwdDetection), false); }); test('items should reflect current state', () => { deepStrictEqual(store.items, []); - store.addCapability(TerminalCapability.CwdDetection); + store.add(TerminalCapability.CwdDetection, null!); deepStrictEqual(store.items, [TerminalCapability.CwdDetection]); - store.addCapability(TerminalCapability.NaiveCwdDetection); + store.add(TerminalCapability.NaiveCwdDetection, null!); deepStrictEqual(store.items, [TerminalCapability.CwdDetection, TerminalCapability.NaiveCwdDetection]); - store.removeCapability(TerminalCapability.CwdDetection); + store.remove(TerminalCapability.CwdDetection); deepStrictEqual(store.items, [TerminalCapability.NaiveCwdDetection]); }); }); @@ -73,52 +73,52 @@ suite('TerminalCapabilityStoreMultiplexer', () => { test('should fire events when capabilities are enabled', async () => { assertEvents(addEvents, []); - multiplexer.addCapabilityStore(store1); - multiplexer.addCapabilityStore(store2); - store1.addCapability(TerminalCapability.CwdDetection); + multiplexer.add(store1); + multiplexer.add(store2); + store1.add(TerminalCapability.CwdDetection, null!); assertEvents(addEvents, [TerminalCapability.CwdDetection]); - store2.addCapability(TerminalCapability.NaiveCwdDetection); + store2.add(TerminalCapability.NaiveCwdDetection, null!); assertEvents(addEvents, [TerminalCapability.NaiveCwdDetection]); }); test('should fire events when capabilities are disabled', async () => { assertEvents(removeEvents, []); - multiplexer.addCapabilityStore(store1); - multiplexer.addCapabilityStore(store2); - store1.addCapability(TerminalCapability.CwdDetection); - store2.addCapability(TerminalCapability.NaiveCwdDetection); + multiplexer.add(store1); + multiplexer.add(store2); + store1.add(TerminalCapability.CwdDetection, null!); + store2.add(TerminalCapability.NaiveCwdDetection, null!); assertEvents(removeEvents, []); - store1.removeCapability(TerminalCapability.CwdDetection); + store1.remove(TerminalCapability.CwdDetection); assertEvents(removeEvents, [TerminalCapability.CwdDetection]); - store2.removeCapability(TerminalCapability.NaiveCwdDetection); + store2.remove(TerminalCapability.NaiveCwdDetection); assertEvents(removeEvents, [TerminalCapability.NaiveCwdDetection]); }); test('should fire events when stores are added', async () => { assertEvents(addEvents, []); - store1.addCapability(TerminalCapability.CwdDetection); + store1.add(TerminalCapability.CwdDetection, null!); assertEvents(addEvents, []); - store2.addCapability(TerminalCapability.NaiveCwdDetection); - multiplexer.addCapabilityStore(store1); - multiplexer.addCapabilityStore(store2); + store2.add(TerminalCapability.NaiveCwdDetection, null!); + multiplexer.add(store1); + multiplexer.add(store2); assertEvents(addEvents, [TerminalCapability.CwdDetection, TerminalCapability.NaiveCwdDetection]); }); test('items should return items from all stores', () => { deepStrictEqual(multiplexer.items, []); - multiplexer.addCapabilityStore(store1); - multiplexer.addCapabilityStore(store2); - store1.addCapability(TerminalCapability.CwdDetection); + multiplexer.add(store1); + multiplexer.add(store2); + store1.add(TerminalCapability.CwdDetection, null!); deepStrictEqual(multiplexer.items, [TerminalCapability.CwdDetection]); - store1.addCapability(TerminalCapability.CommandDetection); - store2.addCapability(TerminalCapability.NaiveCwdDetection); + store1.add(TerminalCapability.CommandDetection, null!); + store2.add(TerminalCapability.NaiveCwdDetection, null!); deepStrictEqual(multiplexer.items, [TerminalCapability.CwdDetection, TerminalCapability.CommandDetection, TerminalCapability.NaiveCwdDetection]); - store2.removeCapability(TerminalCapability.NaiveCwdDetection); + store2.remove(TerminalCapability.NaiveCwdDetection); deepStrictEqual(multiplexer.items, [TerminalCapability.CwdDetection, TerminalCapability.CommandDetection]); }); test('has should return whether a capability is present', () => { deepStrictEqual(multiplexer.has(TerminalCapability.CwdDetection), false); - multiplexer.addCapabilityStore(store1); - store1.addCapability(TerminalCapability.CwdDetection); + multiplexer.add(store1); + store1.add(TerminalCapability.CwdDetection, null!); deepStrictEqual(multiplexer.has(TerminalCapability.CwdDetection), true); - store1.removeCapability(TerminalCapability.CwdDetection); + store1.remove(TerminalCapability.CwdDetection); deepStrictEqual(multiplexer.has(TerminalCapability.CwdDetection), false); }); }); From f16344fec3c09af567f2ffee1e8d1f3334a62a55 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 13 Jan 2022 08:45:22 -0800 Subject: [PATCH 2/6] Use InstanceType instead of explicit interfaces --- .../contrib/terminal/browser/terminal.ts | 3 +- .../common/capabilities/capabilities.d.ts | 26 ++++++++++++++++ .../commandDetectionCapability.ts | 3 +- .../capabilities/terminalCapabilityStore.ts | 2 +- .../contrib/terminal/common/terminal.ts | 31 ++----------------- 5 files changed, 32 insertions(+), 33 deletions(-) create mode 100644 src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index ccb32e5246d..ef8b3ba3d96 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource, TerminalShellType, IExtensionTerminalProfile, TerminalLocation, ProcessPropertyType, IProcessPropertyMap } from 'vs/platform/terminal/common/terminal'; -import { ICommandTracker, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs, IShellIntegration, ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ICommandTracker, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs, IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IEditableData } from 'vs/workbench/common/views'; @@ -17,6 +17,7 @@ import { DeserializedTerminalEditorInput } from 'vs/workbench/contrib/terminal/b import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput'; import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; import { IKeyMods } from 'vs/platform/quickinput/common/quickInput'; +import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; export const ITerminalService = createDecorator('terminalService'); export const ITerminalEditorService = createDecorator('terminalEditorService'); diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts b/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts new file mode 100644 index 00000000000..93cecb42938 --- /dev/null +++ b/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; +import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; +import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability'; +import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability'; +import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; + +export interface ITerminalCapabilityStore { + readonly items: IterableIterator; + readonly onDidRemoveCapability: Event; + readonly onDidAddCapability: Event; + has(capability: TerminalCapability): boolean; + get(capability: T): ITerminalCapabilityImplMap[T] | undefined; +} + +export interface ITerminalCapabilityImplMap { + [TerminalCapability.CwdDetection]: InstanceType; + [TerminalCapability.CommandDetection]: InstanceType; + [TerminalCapability.NaiveCwdDetection]: InstanceType; + [TerminalCapability.PartialCommandDetection]: InstanceType; +} diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts index 192506ebae6..2dc86eed713 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; -import { ICommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/terminal'; -export class CommandDetectionCapability implements ICommandDetectionCapability { +export class CommandDetectionCapability { readonly type = TerminalCapability.CommandDetection; } diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts b/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts index 8441c8f7bac..14dd644ba17 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; -import { ITerminalCapabilityImplMap, ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalCapabilityImplMap, ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; export class TerminalCapabilityStore extends Disposable implements ITerminalCapabilityStore { private _map: Map = new Map(); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 8093c968829..e613faf973b 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -8,12 +8,13 @@ import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalLocationString, IProcessProperty, TitleEventSource, ProcessPropertyType, IFixedTerminalDimensions, IExtensionTerminalProfile, ICreateContributedTerminalProfileOptions, IProcessPropertyMap, ITerminalEnvironment, TerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalLocationString, IProcessProperty, TitleEventSource, ProcessPropertyType, IFixedTerminalDimensions, IExtensionTerminalProfile, ICreateContributedTerminalProfileOptions, IProcessPropertyMap, ITerminalEnvironment, TerminalCommand } from 'vs/platform/terminal/common/terminal'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; import { IProcessDetails } from 'vs/platform/terminal/common/terminalProcess'; import { Registry } from 'vs/platform/registry/common/platform'; +import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; export const TERMINAL_VIEW_ID = 'terminal'; @@ -402,34 +403,6 @@ export interface ITerminalProcessManager extends IDisposable { updateProperty(property: T, value: IProcessPropertyMap[T]): void; } -// TODO: Move to capabilities/ -export interface ITerminalCapabilityStore { - readonly items: IterableIterator; - readonly onDidRemoveCapability: Event; - readonly onDidAddCapability: Event; - has(capability: TerminalCapability): boolean; - get(capability: T): ITerminalCapabilityImplMap[T] | undefined; -} -export interface ITerminalCapabilityImplMap { - [TerminalCapability.CwdDetection]: ICwdDetectionCapability; - [TerminalCapability.CommandDetection]: ICommandDetectionCapability; - [TerminalCapability.NaiveCwdDetection]: INaiveCwdDetectionCapability; - [TerminalCapability.PartialCommandDetection]: IPartialCommandDetectionCapability; -} -export interface ICwdDetectionCapability { - readonly type: TerminalCapability.CwdDetection; -} -export interface ICommandDetectionCapability { - readonly type: TerminalCapability.CommandDetection; -} -export interface INaiveCwdDetectionCapability { - readonly type: TerminalCapability.NaiveCwdDetection; -} -export interface IPartialCommandDetectionCapability { - readonly type: TerminalCapability.PartialCommandDetection; -} - - export const enum ProcessState { // The process has not been initialized yet. Uninitialized = 1, From ed9318820e03549b64c7c788bc21ddc914e3cf5a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 13 Jan 2022 08:51:45 -0800 Subject: [PATCH 3/6] Add jsdoc to capabilities module --- .../common/capabilities/capabilities.d.ts | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts b/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts index 93cecb42938..83cf5aa8b09 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.d.ts @@ -10,14 +10,41 @@ import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/cap import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability'; import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; +/** + * An object that keeps track of additional capabilities and their implementations for features that + * are not available for all terminals. + */ export interface ITerminalCapabilityStore { + /** + * An iterable of all capabilities in the store. + */ readonly items: IterableIterator; - readonly onDidRemoveCapability: Event; + + /** + * Fired when a capability is added. + */ readonly onDidAddCapability: Event; + + /** + * Fired when a capability is removed. + */ + readonly onDidRemoveCapability: Event; + + /** + * Gets whether the capability exists in the store. + */ has(capability: TerminalCapability): boolean; + + /** + * Gets the implementation of a capability if it has been added to the store. + */ get(capability: T): ITerminalCapabilityImplMap[T] | undefined; } +/** + * Maps capability types to their implementation, enabling strongly typed fetching of + * implementations. + */ export interface ITerminalCapabilityImplMap { [TerminalCapability.CwdDetection]: InstanceType; [TerminalCapability.CommandDetection]: InstanceType; From ee664160b6d1dd5603a2cceeae4db225f3f6e2ca Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 13 Jan 2022 10:51:56 -0800 Subject: [PATCH 4/6] Remove unused events --- .../contrib/terminal/browser/terminalProcessManager.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index f9f2b46f831..fbe8a148f51 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -104,11 +104,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit = this._onProcessExit.event; - private readonly _onCapabilityDisabled = new Emitter(); - readonly onCapabilityDisabled = this._onCapabilityDisabled.event; - private readonly _onCapabilityEnabled = new Emitter(); - readonly onCapabilityEnabled = this._onCapabilityEnabled.event; - get persistentProcessId(): number | undefined { return this._process?.id; } get shouldPersist(): boolean { return this._process ? this._process.shouldPersist : false; } get hasWrittenData(): boolean { return this._hasWrittenData; } From af1c8dfe412eefab31a5477297a882bf681ce3fa Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 13 Jan 2022 11:25:54 -0800 Subject: [PATCH 5/6] Fix tests --- .../capabilities/terminalCapabilityStore.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts b/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts index 65b6aed55cd..f6ac406206f 100644 --- a/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/capabilities/terminalCapabilityStore.test.ts @@ -42,13 +42,13 @@ suite('TerminalCapabilityStore', () => { deepStrictEqual(store.has(TerminalCapability.CwdDetection), false); }); test('items should reflect current state', () => { - deepStrictEqual(store.items, []); + deepStrictEqual(Array.from(store.items), []); store.add(TerminalCapability.CwdDetection, null!); - deepStrictEqual(store.items, [TerminalCapability.CwdDetection]); + deepStrictEqual(Array.from(store.items), [TerminalCapability.CwdDetection]); store.add(TerminalCapability.NaiveCwdDetection, null!); - deepStrictEqual(store.items, [TerminalCapability.CwdDetection, TerminalCapability.NaiveCwdDetection]); + deepStrictEqual(Array.from(store.items), [TerminalCapability.CwdDetection, TerminalCapability.NaiveCwdDetection]); store.remove(TerminalCapability.CwdDetection); - deepStrictEqual(store.items, [TerminalCapability.NaiveCwdDetection]); + deepStrictEqual(Array.from(store.items), [TerminalCapability.NaiveCwdDetection]); }); }); @@ -102,16 +102,16 @@ suite('TerminalCapabilityStoreMultiplexer', () => { assertEvents(addEvents, [TerminalCapability.CwdDetection, TerminalCapability.NaiveCwdDetection]); }); test('items should return items from all stores', () => { - deepStrictEqual(multiplexer.items, []); + deepStrictEqual(Array.from(multiplexer.items).sort(), [].sort()); multiplexer.add(store1); multiplexer.add(store2); store1.add(TerminalCapability.CwdDetection, null!); - deepStrictEqual(multiplexer.items, [TerminalCapability.CwdDetection]); + deepStrictEqual(Array.from(multiplexer.items).sort(), [TerminalCapability.CwdDetection].sort()); store1.add(TerminalCapability.CommandDetection, null!); store2.add(TerminalCapability.NaiveCwdDetection, null!); - deepStrictEqual(multiplexer.items, [TerminalCapability.CwdDetection, TerminalCapability.CommandDetection, TerminalCapability.NaiveCwdDetection]); + deepStrictEqual(Array.from(multiplexer.items).sort(), [TerminalCapability.CwdDetection, TerminalCapability.CommandDetection, TerminalCapability.NaiveCwdDetection].sort()); store2.remove(TerminalCapability.NaiveCwdDetection); - deepStrictEqual(multiplexer.items, [TerminalCapability.CwdDetection, TerminalCapability.CommandDetection]); + deepStrictEqual(Array.from(multiplexer.items).sort(), [TerminalCapability.CwdDetection, TerminalCapability.CommandDetection].sort()); }); test('has should return whether a capability is present', () => { deepStrictEqual(multiplexer.has(TerminalCapability.CwdDetection), false); From 230db92052ed343c2719389eb753fa48f038cd7b Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 13 Jan 2022 11:30:42 -0800 Subject: [PATCH 6/6] Add TODOs to fill in capability implementations --- .../terminal/common/capabilities/commandDetectionCapability.ts | 2 ++ .../terminal/common/capabilities/cwdDetectionCapability.ts | 2 ++ .../terminal/common/capabilities/naiveCwdDetectionCapability.ts | 2 ++ .../common/capabilities/partialCommandDetectionCapability.ts | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts index 2dc86eed713..24781f20aa8 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts @@ -7,4 +7,6 @@ import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; export class CommandDetectionCapability { readonly type = TerminalCapability.CommandDetection; + + // TODO: Encapsulate the functionality the capability brings here } diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts index 2a595990d4a..496485d1416 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts @@ -7,4 +7,6 @@ import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; export class CwdDetectionCapability { readonly type = TerminalCapability.CwdDetection; + + // TODO: Encapsulate the functionality the capability brings here } diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts index 454bc77a150..2a1c0bd0c4c 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts @@ -7,4 +7,6 @@ import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; export class NaiveCwdDetectionCapability { readonly type = TerminalCapability.NaiveCwdDetection; + + // TODO: Encapsulate the functionality the capability brings here } diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts index 9d15e9488c4..66b6476c6a9 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts @@ -7,4 +7,6 @@ import { TerminalCapability } from 'vs/platform/terminal/common/terminal'; export class PartialCommandDetectionCapability { readonly type = TerminalCapability.CwdDetection; + + // TODO: Encapsulate the functionality the capability brings here }