From 3e345101dfd4702be875c1c13a05b8864cc2cbb4 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 5 Mar 2021 19:04:19 -0500 Subject: [PATCH] update shellType when it changes for local windows terminals (#117998) Co-authored-by: Daniel Imms --- src/vs/platform/terminal/common/terminal.ts | 9 ++ .../electron-browser/localPtyService.ts | 5 +- src/vs/platform/terminal/node/ptyService.ts | 10 +- .../platform/terminal/node/terminalProcess.ts | 43 +++++---- .../terminal/node}/windowsShellHelper.ts | 94 ++++++++++++------- .../api/common/extHostTerminalService.ts | 5 +- .../terminal/browser/remoteTerminalService.ts | 4 +- .../terminal/browser/terminal.contribution.ts | 3 +- .../contrib/terminal/browser/terminal.ts | 18 +--- .../terminal/browser/terminalInstance.ts | 57 ++--------- .../browser/terminalInstanceService.ts | 6 +- .../browser/terminalProcessExtHostProxy.ts | 4 +- .../browser/terminalProcessManager.ts | 5 +- .../terminal/browser/terminalService.ts | 4 +- .../contrib/terminal/common/terminal.ts | 15 +-- .../terminalInstanceService.ts | 12 +-- .../terminal/electron-sandbox/localPty.ts | 7 +- .../test/browser/workbenchTestServices.ts | 3 +- 18 files changed, 145 insertions(+), 159 deletions(-) rename src/vs/{workbench/contrib/terminal/electron-browser => platform/terminal/node}/windowsShellHelper.ts (56%) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 4ace7cba79b..f018b585996 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -9,6 +9,13 @@ import { IProcessEnvironment } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { IGetTerminalLayoutInfoArgs, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; +export enum WindowsShellType { + CommandPrompt = 'cmd', + PowerShell = 'pwsh', + Wsl = 'wsl', + GitBash = 'gitbash' +} +export type TerminalShellType = WindowsShellType | undefined; export interface IRawTerminalInstanceLayoutInfo { relativeSize: number; terminal: T; @@ -109,6 +116,7 @@ export interface IPtyService { readonly onProcessExit: Event<{ id: number, event: number | undefined }>; readonly onProcessReady: Event<{ id: number, event: { pid: number, cwd: string } }>; readonly onProcessTitleChanged: Event<{ id: number, event: string }>; + readonly onProcessShellTypeChanged: Event<{ id: number, event: TerminalShellType }>; readonly onProcessOverrideDimensions: Event<{ id: number, event: ITerminalDimensionsOverride | undefined }>; readonly onProcessResolvedShellLaunchConfig: Event<{ id: number, event: IShellLaunchConfig }>; readonly onProcessReplay: Event<{ id: number, event: IPtyHostProcessReplayEvent }>; @@ -296,6 +304,7 @@ export interface ITerminalChildProcess { onProcessTitleChanged: Event; onProcessOverrideDimensions?: Event; onProcessResolvedShellLaunchConfig?: Event; + onProcessShellTypeChanged: Event; /** * Starts the process. diff --git a/src/vs/platform/terminal/electron-browser/localPtyService.ts b/src/vs/platform/terminal/electron-browser/localPtyService.ts index 8f711e52d54..7d5e9bf9a3f 100644 --- a/src/vs/platform/terminal/electron-browser/localPtyService.ts +++ b/src/vs/platform/terminal/electron-browser/localPtyService.ts @@ -5,7 +5,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; -import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, TerminalIpcChannels, IHeartbeatService, HeartbeatConstants } from 'vs/platform/terminal/common/terminal'; +import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, TerminalIpcChannels, IHeartbeatService, HeartbeatConstants, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; import { FileAccess } from 'vs/base/common/network'; import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; @@ -56,6 +56,8 @@ export class LocalPtyService extends Disposable implements IPtyService { readonly onProcessReplay = this._onProcessReplay.event; private readonly _onProcessTitleChanged = this._register(new Emitter<{ id: number, event: string }>()); readonly onProcessTitleChanged = this._onProcessTitleChanged.event; + private readonly _onProcessShellTypeChanged = this._register(new Emitter<{ id: number, event: TerminalShellType }>()); + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter<{ id: number, event: ITerminalDimensionsOverride | undefined }>()); readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event; private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter<{ id: number, event: IShellLaunchConfig }>()); @@ -116,6 +118,7 @@ export class LocalPtyService extends Disposable implements IPtyService { this._register(proxy.onProcessExit(e => this._onProcessExit.fire(e))); this._register(proxy.onProcessReady(e => this._onProcessReady.fire(e))); this._register(proxy.onProcessTitleChanged(e => this._onProcessTitleChanged.fire(e))); + this._register(proxy.onProcessShellTypeChanged(e => this._onProcessShellTypeChanged.fire(e))); this._register(proxy.onProcessOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e))); this._register(proxy.onProcessResolvedShellLaunchConfig(e => this._onProcessResolvedShellLaunchConfig.fire(e))); this._register(proxy.onProcessReplay(e => this._onProcessReplay.fire(e))); diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 4d631e3bd74..e9259bf9971 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -5,7 +5,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment } from 'vs/base/common/platform'; -import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, LocalReconnectConstants, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById } from 'vs/platform/terminal/common/terminal'; +import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, LocalReconnectConstants, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { AutoOpenBarrier, Queue, RunOnceScheduler } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder'; @@ -34,6 +34,8 @@ export class PtyService extends Disposable implements IPtyService { readonly onProcessReady = this._onProcessReady.event; private readonly _onProcessTitleChanged = this._register(new Emitter<{ id: number, event: string }>()); readonly onProcessTitleChanged = this._onProcessTitleChanged.event; + private readonly _onProcessShellTypeChanged = this._register(new Emitter<{ id: number, event: TerminalShellType }>()); + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter<{ id: number, event: ITerminalDimensionsOverride | undefined }>()); readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event; private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter<{ id: number, event: IShellLaunchConfig }>()); @@ -90,6 +92,7 @@ export class PtyService extends Disposable implements IPtyService { persistentProcess.onProcessReplay(event => this._onProcessReplay.fire({ id, event })); persistentProcess.onProcessReady(event => this._onProcessReady.fire({ id, event })); persistentProcess.onProcessTitleChanged(event => this._onProcessTitleChanged.fire({ id, event })); + persistentProcess.onProcessShellTypeChanged(event => this._onProcessShellTypeChanged.fire({ id, event })); this._ptys.set(id, persistentProcess); return id; } @@ -219,6 +222,8 @@ export class PersistentTerminalProcess extends Disposable { readonly onProcessReady = this._onProcessReady.event; private readonly _onProcessTitleChanged = this._register(new Emitter()); readonly onProcessTitleChanged = this._onProcessTitleChanged.event; + private readonly _onProcessShellTypeChanged = this._register(new Emitter()); + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter()); readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event; private readonly _onProcessData = this._register(new Emitter()); @@ -269,7 +274,7 @@ export class PersistentTerminalProcess extends Disposable { this._onProcessReady.fire(e); })); this._register(this._terminalProcess.onProcessTitleChanged(e => this._onProcessTitleChanged.fire(e))); - + this._register(this._terminalProcess.onProcessShellTypeChanged(e => this._onProcessShellTypeChanged.fire(e))); // Buffer data events to reduce the amount of messages going to the renderer // this._register(this._bufferer.startBuffering(this._persistentProcessId, this._terminalProcess.onProcessData)); this._register(this._terminalProcess.onProcessData(e => this._recorder.recordData(e))); @@ -301,6 +306,7 @@ export class PersistentTerminalProcess extends Disposable { } else { this._onProcessReady.fire({ pid: this._pid, cwd: this._cwd }); this._onProcessTitleChanged.fire(this._terminalProcess.currentTitle); + this._onProcessShellTypeChanged.fire(this._terminalProcess.shellType); this.triggerReplay(); } return undefined; diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index aa66c8724f1..984a9561c83 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -10,12 +10,13 @@ import * as fs from 'fs'; import * as os from 'os'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IShellLaunchConfig, ITerminalLaunchError, FlowControlConstants, ITerminalChildProcess, ITerminalDimensionsOverride } from 'vs/platform/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalLaunchError, FlowControlConstants, ITerminalChildProcess, ITerminalDimensionsOverride, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { exec } from 'child_process'; import { ILogService } from 'vs/platform/log/common/log'; import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; +import { WindowsShellHelper } from 'vs/platform/terminal/node/windowsShellHelper'; // Writing large amounts of data can be corrupted for some reason, after looking into this is // appears to be a race condition around writing to the FD which may be based on how powerful the @@ -54,6 +55,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess private _currentTitle: string = ''; private _processStartupComplete: Promise | undefined; private _isDisposed: boolean = false; + private _windowsShellHelper: WindowsShellHelper | undefined; private _titleInterval: NodeJS.Timer | null = null; private _writeQueue: string[] = []; private _writeTimeout: NodeJS.Timeout | undefined; @@ -63,9 +65,10 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess private _isPtyPaused: boolean = false; private _unacknowledgedCharCount: number = 0; - public get exitMessage(): string | undefined { return this._exitMessage; } - public get currentTitle(): string { return this._currentTitle; } + + public get currentTitle(): string { return this._windowsShellHelper?.shellTitle || this._currentTitle; } + public get shellType(): TerminalShellType { return this._windowsShellHelper ? this._windowsShellHelper.shellType : undefined; } private readonly _onProcessData = this._register(new Emitter()); public get onProcessData(): Event { return this._onProcessData.event; } @@ -75,6 +78,8 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); public get onProcessTitleChanged(): Event { return this._onProcessTitleChanged.event; } + private readonly _onProcessShellTypeChanged = this._register(new Emitter()); + public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; constructor( private readonly _shellLaunchConfig: IShellLaunchConfig, @@ -111,15 +116,23 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess conptyInheritCursor: useConpty && !!_shellLaunchConfig.initialText }; // Delay resizes to avoid conpty not respecting very early resize calls - if (platform.isWindows && useConpty && cols === 0 && rows === 0 && this._shellLaunchConfig.executable?.endsWith('Git\\bin\\bash.exe')) { - this._delayedResizer = new DelayedResizer(); - this._register(this._delayedResizer.onTrigger(dimensions => { - this._delayedResizer?.dispose(); - this._delayedResizer = undefined; - if (dimensions.cols && dimensions.rows) { - this.resize(dimensions.cols, dimensions.rows); - } - })); + if (platform.isWindows) { + if (useConpty && cols === 0 && rows === 0 && this._shellLaunchConfig.executable?.endsWith('Git\\bin\\bash.exe')) { + this._delayedResizer = new DelayedResizer(); + this._register(this._delayedResizer.onTrigger(dimensions => { + this._delayedResizer?.dispose(); + this._delayedResizer = undefined; + if (dimensions.cols && dimensions.rows) { + this.resize(dimensions.cols, dimensions.rows); + } + })); + } + // WindowsShellHelper is used to fetch the process title and shell type + this.onProcessReady(e => { + this._windowsShellHelper = this._register(new WindowsShellHelper(e.pid)); + this._register(this._windowsShellHelper.onShellTypeChanged(e => this._onProcessShellTypeChanged.fire(e))); + this._register(this._windowsShellHelper.onShellNameChanged(e => this._onProcessTitleChanged.fire(e))); + }); } } onProcessOverrideDimensions?: Event | undefined; @@ -196,12 +209,14 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess ptyProcess.pause(); } + // Refire the data event this._onProcessData.fire(data); if (this._closeTimeout) { clearTimeout(this._closeTimeout); this._queueProcessExit(); } + this._windowsShellHelper?.checkShell(); }); ptyProcess.onExit(e => { this._exitCode = e.exitCode; @@ -217,10 +232,6 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess clearInterval(this._titleInterval); } this._titleInterval = null; - this._onProcessData.dispose(); - this._onProcessExit.dispose(); - this._onProcessReady.dispose(); - this._onProcessTitleChanged.dispose(); super.dispose(); } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/windowsShellHelper.ts b/src/vs/platform/terminal/node/windowsShellHelper.ts similarity index 56% rename from src/vs/workbench/contrib/terminal/electron-browser/windowsShellHelper.ts rename to src/vs/platform/terminal/node/windowsShellHelper.ts index b510486baaf..829afecba27 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/windowsShellHelper.ts +++ b/src/vs/platform/terminal/node/windowsShellHelper.ts @@ -5,12 +5,19 @@ import * as platform from 'vs/base/common/platform'; import { Emitter, Event } from 'vs/base/common/event'; -import { IWindowsShellHelper } from 'vs/workbench/contrib/terminal/common/terminal'; -import type { Terminal as XTermTerminal } from 'xterm'; import type * as WindowsProcessTreeType from 'windows-process-tree'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { TerminalShellType, WindowsShellType } from 'vs/platform/terminal/common/terminal'; +import { debounce } from 'vs/base/common/decorators'; import { timeout } from 'vs/base/common/async'; +export interface IWindowsShellHelper extends IDisposable { + readonly onShellNameChanged: Event; + readonly onShellTypeChanged: Event; + getShellType(title: string): TerminalShellType; + getShellName(): Promise; +} + const SHELL_EXECUTABLES = [ 'cmd.exe', 'powershell.exe', @@ -28,17 +35,19 @@ const SHELL_EXECUTABLES = [ let windowsProcessTree: typeof WindowsProcessTreeType; export class WindowsShellHelper extends Disposable implements IWindowsShellHelper { - private _onCheckShell: Emitter | undefined> = this._register(new Emitter | undefined>()); private _isDisposed: boolean; private _currentRequest: Promise | undefined; - private _newLineFeed: boolean = false; - - private readonly _onShellNameChange = new Emitter(); - public get onShellNameChange(): Event { return this._onShellNameChange.event; } + private _shellType: TerminalShellType | undefined; + public get shellType(): TerminalShellType | undefined { return this._shellType; } + private _shellTitle: string = ''; + public get shellTitle(): string { return this._shellTitle; } + private readonly _onShellNameChanged = new Emitter(); + public get onShellNameChanged(): Event { return this._onShellNameChanged.event; } + private readonly _onShellTypeChanged = new Emitter(); + public get onShellTypeChanged(): Event { return this._onShellTypeChanged.event; } public constructor( - private _rootProcessId: number, - private _xterm: XTermTerminal + private _rootProcessId: number ) { super(); @@ -55,35 +64,25 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe if (this._isDisposed) { return; } - - // The debounce is necessary to prevent multiple processes from spawning when - // the enter key or output is spammed - Event.debounce(this._onCheckShell.event, (l, e) => e, 150, true)(async () => { - await timeout(50); - this.checkShell(); - }); - - // We want to fire a new check for the shell on a linefeed, but only - // when parsing has finished which is indicated by the cursormove event. - // If this is done on every linefeed, parsing ends up taking - // significantly longer due to resetting timers. Note that this is - // private API. - this._xterm.onLineFeed(() => this._newLineFeed = true); - this._xterm.onCursorMove(() => { - if (this._newLineFeed) { - this._onCheckShell.fire(undefined); - this._newLineFeed = false; - } - }); - - // Fire a new check for the shell when any key is pressed. - this._xterm.onKey(() => this._onCheckShell.fire(undefined)); + this.checkShell(); } - private checkShell(): void { + @debounce(500) + async checkShell(): Promise { if (platform.isWindows) { - // TODO: Only fire when it's different - this.getShellName().then(title => this._onShellNameChange.fire(title)); + // Wait to give the shell some time to actually launch a process, this + // could lead to a race condition but it would be recovered from when + // data stops and should cover the majority of cases + await timeout(300); + this.getShellName().then(title => { + const type = this.getShellType(title); + if (type !== this._shellType) { + this._onShellTypeChanged.fire(type); + this._onShellNameChanged.fire(title); + this._shellType = type; + this._shellTitle = title; + } + }); } } @@ -141,4 +140,27 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe }); return this._currentRequest; } + + public getShellType(executable: string): TerminalShellType { + switch (executable.toLowerCase()) { + case 'cmd.exe': + return WindowsShellType.CommandPrompt; + case 'powershell.exe': + case 'pwsh.exe': + return WindowsShellType.PowerShell; + case 'bash.exe': + case 'git-cmd.exe': + return WindowsShellType.GitBash; + case 'wsl.exe': + case 'ubuntu.exe': + case 'ubuntu1804.exe': + case 'kali.exe': + case 'debian.exe': + case 'opensuse-42.exe': + case 'sles-12.exe': + return WindowsShellType.Wsl; + default: + return undefined; + } + } } diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 714077d7113..75a2229767a 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -19,7 +19,7 @@ import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/ter import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { generateUuid } from 'vs/base/common/uuid'; import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal'; +import { ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable { @@ -198,6 +198,9 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess { public readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; private readonly _onProcessOverrideDimensions = new Emitter(); public get onProcessOverrideDimensions(): Event { return this._onProcessOverrideDimensions.event; } + private readonly _onProcessShellTypeChanged = new Emitter(); + public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; + constructor(private readonly _pty: vscode.Pseudoterminal) { } diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts index 8bc7d3dd0a9..c9ca7e28d74 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts @@ -16,7 +16,7 @@ import { IRemoteTerminalService, ITerminalInstanceService } from 'vs/workbench/c import { IRemoteTerminalProcessExecCommandEvent, IShellLaunchConfigDto, RemoteTerminalChannelClient, REMOTE_TERMINAL_CHANNEL_NAME } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { IRemoteTerminalAttachTarget, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal'; export class RemoteTerminalService extends Disposable implements IRemoteTerminalService { public _serviceBrand: undefined; @@ -101,6 +101,8 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP public readonly onProcessOverrideDimensions: Event = this._onProcessOverrideDimensions.event; private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter()); public get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessResolvedShellLaunchConfig.event; } + private readonly _onProcessShellTypeChanged = this._register(new Emitter()); + public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private _startBarrier: Barrier; private _persistentProcessId: number; diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 0fb957f34ff..05379896410 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -26,7 +26,7 @@ import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminal import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { TerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IRemoteTerminalService, ITerminalService, WindowsShellType } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IRemoteTerminalService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess'; @@ -36,6 +36,7 @@ import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/co import { terminalViewIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons'; import { RemoteTerminalService } from 'vs/workbench/contrib/terminal/browser/remoteTerminalService'; import { isIPad } from 'vs/base/browser/browser'; +import { WindowsShellType } from 'vs/platform/terminal/common/terminal'; // Register services registerSingleton(ITerminalService, TerminalService, true); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 35716729d92..d6d386a16c2 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -9,8 +9,8 @@ import { IProcessEnvironment, Platform } from 'vs/base/common/platform'; 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, ITerminalChildProcess, ITerminalDimensions, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ITerminalTabLayoutInfoById } from 'vs/platform/terminal/common/terminal'; -import { IAvailableShellsRequest, ICommandTracker, IDefaultShellAndArgsRequest, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, IWindowsShellHelper, LinuxDistro, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ITerminalTabLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IAvailableShellsRequest, ICommandTracker, IDefaultShellAndArgsRequest, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, LinuxDistro, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; @@ -35,7 +35,6 @@ export interface ITerminalInstanceService { getXtermSearchConstructor(): Promise; getXtermUnicode11Constructor(): Promise; getXtermWebglConstructor(): Promise; - createWindowsShellHelper(shellProcessId: number, xterm: XTermTerminal): IWindowsShellHelper; getDefaultShellAndArgs(useAutomationShell: boolean, platformOverride?: Platform): Promise<{ shell: string, args: string[] | string | undefined }>; getMainProcessParentEnv(): Promise; } @@ -226,14 +225,6 @@ export interface ISearchOptions { incremental?: boolean; } -export enum WindowsShellType { - CommandPrompt = 'cmd', - PowerShell = 'pwsh', - Wsl = 'wsl', - GitBash = 'gitbash' -} -export type TerminalShellType = WindowsShellType | undefined; - export interface ITerminalBeforeHandleLinkEvent { terminal?: ITerminalInstance; /** The text of the link */ @@ -536,11 +527,6 @@ export interface ITerminalInstance { */ setTitle(title: string, eventSource: TitleEventSource): void; - /** - * Sets the shell type of the terminal instance. - */ - setShellType(shellType: TerminalShellType): void; - waitForTitle(): Promise; setDimensions(dimensions: ITerminalDimensions): void; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 0a3d6b8c503..c75356f716b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -25,12 +25,12 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, TERMINAL_CREATION_COMMANDS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, SUGGESTED_RENDERER_TYPE } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, TERMINAL_CREATION_COMMANDS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, SUGGESTED_RENDERER_TYPE } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; -import { ITerminalInstanceService, ITerminalInstance, TerminalShellType, WindowsShellType, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalInstanceService, ITerminalInstance, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager'; import type { Terminal as XTermTerminal, IBuffer, ITerminalAddon } from 'xterm'; import type { SearchAddon, ISearchOptions } from 'xterm-addon-search'; @@ -47,7 +47,7 @@ import { TypeAheadAddon } from 'vs/workbench/contrib/terminal/browser/terminalTy import { BrowserFeatures } from 'vs/base/browser/canIUse'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; // How long in milliseconds should an average frame take to render for a notification to appear // which suggests the fallback DOM-based renderer @@ -99,7 +99,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _cols: number = 0; private _rows: number = 0; private _dimensionsOverride: ITerminalDimensionsOverride | undefined; - private _windowsShellHelper: IWindowsShellHelper | undefined; private _xtermReadyPromise: Promise; private _titleReadyPromise: Promise; private _titleReadyComplete: ((title: string) => any) | undefined; @@ -648,7 +647,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._terminalFocusContextKey.reset(); this._refreshSelectionContextKey(); })); - this._widgetManager.attachToElement(xterm.element); this._processManager.onProcessReady(() => this._linkManager?.setWidgetManager(this._widgetManager)); @@ -773,8 +771,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { public dispose(immediate?: boolean): void { this._logService.trace(`terminalInstance#dispose (instanceId: ${this.instanceId})`); - dispose(this._windowsShellHelper); - this._windowsShellHelper = undefined; dispose(this._linkManager); this._linkManager = undefined; dispose(this._commandTrackerAddon); @@ -969,25 +965,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._messageTitleDisposable = this._processManager.onProcessTitle(title => this.setTitle(title ? title : '', TitleEventSource.Process)); } } - - if (platform.isWindows) { - this._processManager.ptyProcessReady.then(() => { - if (this._processManager.remoteAuthority) { - return; - } - this._xtermReadyPromise.then(xterm => { - if (!this._isDisposed && this._processManager && this._processManager.shellProcessId) { - this._windowsShellHelper = this._terminalInstanceService.createWindowsShellHelper(this._processManager.shellProcessId, xterm); - this._windowsShellHelper.onShellNameChange(title => { - this.setShellType(this.getShellType(title)); - if (this.isTitleSetByProcess && !this._configHelper.config.experimentalUseTitleEvent) { - this.setTitle(title, TitleEventSource.Process); - } - }); - } - }); - }); - } + this._processManager.onProcessShellTypeChanged(type => { + this.setShellType(type); + }); } private _createProcess(): void { @@ -998,29 +978,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { }); } - private getShellType(executable: string): TerminalShellType { - switch (executable.toLowerCase()) { - case 'cmd.exe': - return WindowsShellType.CommandPrompt; - case 'powershell.exe': - case 'pwsh.exe': - return WindowsShellType.PowerShell; - case 'bash.exe': - case 'git-cmd.exe': - return WindowsShellType.GitBash; - case 'wsl.exe': - case 'ubuntu.exe': - case 'ubuntu1804.exe': - case 'kali.exe': - case 'debian.exe': - case 'opensuse-42.exe': - case 'sles-12.exe': - return WindowsShellType.Wsl; - default: - return undefined; - } - } - private _onProcessData(ev: IProcessDataEvent): void { if (ev.sync) { this._xtermCore?.writeSync(ev.data); @@ -1541,8 +1498,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // automatically updates the terminal name dispose(this._messageTitleDisposable); this._messageTitleDisposable = undefined; - dispose(this._windowsShellHelper); - this._windowsShellHelper = undefined; break; } const didTitleChange = title !== this._title; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts index b329d5a2533..09a56a029be 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { IWindowsShellHelper, IDefaultShellAndArgsRequest } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IDefaultShellAndArgsRequest } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; @@ -59,10 +59,6 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst return WebglAddon; } - public createWindowsShellHelper(): IWindowsShellHelper { - throw new Error('Not implemented'); - } - public createTerminalProcess(): Promise { throw new Error('Not implemented'); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index e96ac8ccbe5..9744d4ff0f5 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts @@ -5,7 +5,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; @@ -42,6 +42,8 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal public readonly onRequestCwd: Event = this._onRequestCwd.event; private readonly _onRequestLatency = this._register(new Emitter()); public readonly onRequestLatency: Event = this._onRequestLatency.event; + private readonly _onProcessShellTypeChanged = this._register(new Emitter()); + public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private _pendingInitialCwdRequests: ((value: string | PromiseLike) => void)[] = []; private _pendingCwdRequests: ((value: string | PromiseLike) => void)[] = []; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 3693928c51a..9377db248a4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -27,7 +27,7 @@ import { EnvironmentVariableInfoChangesActive, EnvironmentVariableInfoStale } fr import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { URI } from 'vs/base/common/uri'; import { IEnvironmentVariableInfo, IEnvironmentVariableService, IMergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, FlowControlConstants, ILocalTerminalService } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, FlowControlConstants, TerminalShellType, ILocalTerminalService } from 'vs/platform/terminal/common/terminal'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -84,6 +84,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce public get onProcessData(): Event { return this._onProcessData.event; } private readonly _onProcessTitle = this._register(new Emitter()); public get onProcessTitle(): Event { return this._onProcessTitle.event; } + private readonly _onProcessShellTypeChanged = this._register(new Emitter()); + public get onProcessShellTypeChanged(): Event { return this._onProcessShellTypeChanged.event; } private readonly _onProcessExit = this._register(new Emitter()); public get onProcessExit(): Event { return this._onProcessExit.event; } private readonly _onProcessOverrideDimensions = this._register(new Emitter()); @@ -240,6 +242,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce }); this._process.onProcessTitleChanged(title => this._onProcessTitle.fire(title)); + this._process.onProcessShellTypeChanged(type => this._onProcessShellTypeChanged.fire(type)); this._process.onProcessExit(exitCode => this._onExit(exitCode)); if (this._process.onProcessOverrideDimensions) { this._process.onProcessOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e)); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 0539b9de447..5b072dbf47c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -17,9 +17,9 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; import { IPickOptions, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { ILocalTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById } from 'vs/platform/terminal/common/terminal'; +import { ILocalTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType, WindowsShellType } from 'vs/platform/terminal/common/terminal'; import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; -import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalTab, TerminalConnectionState, TerminalShellType, WindowsShellType } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalTab, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 1cb1e0da83f..dff256e9500 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -9,7 +9,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { OperatingSystem } from 'vs/base/common/platform'; import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; export const TERMINAL_VIEW_ID = 'terminal'; @@ -231,12 +231,6 @@ export interface IDefaultShellAndArgsRequest { callback: (shell: string, args: string[] | string | undefined) => void; } -export interface IWindowsShellHelper extends IDisposable { - readonly onShellNameChange: Event; - - getShellName(): Promise; -} - export interface ITerminalProcessManager extends IDisposable { readonly processState: ProcessState; readonly ptyProcessReady: Promise; @@ -258,6 +252,7 @@ export interface ITerminalProcessManager extends IDisposable { readonly onBeforeProcessData: Event; readonly onProcessData: Event; readonly onProcessTitle: Event; + readonly onProcessShellTypeChanged: Event; readonly onProcessExit: Event; readonly onProcessOverrideDimensions: Event; readonly onProcessResolvedShellLaunchConfig: Event; @@ -347,12 +342,6 @@ export enum TitleEventSource { Sequence } -export interface IWindowsShellHelper extends IDisposable { - readonly onShellNameChange: Event; - - getShellName(): Promise; -} - export const enum TERMINAL_COMMAND_ID { FIND_NEXT = 'workbench.action.terminal.findNext', FIND_PREVIOUS = 'workbench.action.terminal.findPrevious', diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts index 99d1e066423..32673f92f70 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -2,7 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - +import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY } from 'vs/workbench/contrib/terminal/common/terminal'; import { Disposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment, platform, Platform } from 'vs/base/common/platform'; import { getSystemShell } from 'vs/base/node/shell'; @@ -10,10 +11,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ILogService } from 'vs/platform/log/common/log'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, IWindowsShellHelper } from 'vs/workbench/contrib/terminal/common/terminal'; -import { createVariableResolver, getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; -import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/electron-browser/windowsShellHelper'; import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; @@ -21,6 +18,7 @@ import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; +import { createVariableResolver, getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; let Terminal: typeof XTermTerminal; let SearchAddon: typeof XTermSearchAddon; @@ -69,10 +67,6 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst return WebglAddon; } - public createWindowsShellHelper(shellProcessId: number, xterm: XTermTerminal): IWindowsShellHelper { - return new WindowsShellHelper(shellProcessId, xterm); - } - private _isWorkspaceShellAllowed(): boolean { return this._storageService.getBoolean(IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, StorageScope.WORKSPACE, false); } diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts index 31dbc96bb37..0bd0e04d4e4 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; /** @@ -30,6 +30,8 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { public readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event; private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter()); public readonly onProcessResolvedShellLaunchConfig = this._onProcessResolvedShellLaunchConfig.event; + private readonly _onProcessShellTypeChanged = this._register(new Emitter()); + public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; constructor( readonly id: number, @@ -95,6 +97,9 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { handleTitleChanged(e: string) { this._onProcessTitleChanged.fire(e); } + handleShellTypeChanged(e: TerminalShellType) { + this._onProcessShellTypeChanged.fire(e); + } handleOverrideDimensions(e: ITerminalDimensionsOverride | undefined) { this._onProcessOverrideDimensions.fire(e); } diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index cb96d1a57b9..28a8f78cc1b 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -1477,7 +1477,6 @@ export class TestTerminalInstanceService implements ITerminalInstanceService { createWindowsShellHelper(shellProcessId: number, xterm: any): any { throw new Error('Method not implemented.'); } } - export class TestLocalTerminalService implements ILocalTerminalService { declare readonly _serviceBrand: undefined; @@ -1507,7 +1506,7 @@ class TestTerminalChildProcess implements ITerminalChildProcess { onProcessExit = Event.None; onProcessReady = Event.None; onProcessTitleChanged = Event.None; - + onProcessShellTypeChanged = Event.None; async start(): Promise { return undefined; } shutdown(immediate: boolean): void { } input(data: string): void { }