diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index e65421ea803..b9dd2aac82f 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -178,13 +178,18 @@ export enum TerminalIpcChannels { export const IPtyService = createDecorator('ptyService'); export const enum TerminalPropertyType { - cwd, - initialCwd + Cwd, + InitialCwd } -export interface TerminalProperty { - type: TerminalPropertyType, - value: any +export interface ITerminalProperty { + type: T, + value: ITerminalPropertyMap[T] +} + +export interface ITerminalPropertyMap { + [TerminalPropertyType.Cwd]: string, + [TerminalPropertyType.InitialCwd]: string, } export interface IPtyService { @@ -207,7 +212,7 @@ export interface IPtyService { readonly onProcessOrphanQuestion: Event<{ id: number }>; readonly onDidRequestDetach: Event<{ requestId: number, workspaceId: string, instanceId: number }>; readonly onProcessDidChangeHasChildProcesses: Event<{ id: number, event: boolean }>; - readonly onDidChangeProperty: Event<{ id: number, event: TerminalProperty }> + readonly onDidChangeProperty: Event<{ id: number, property: ITerminalProperty }> restartPtyHost?(): Promise; shutdownAll?(): Promise; @@ -483,7 +488,7 @@ export interface ITerminalChildProcess { onProcessOverrideDimensions?: Event; onProcessResolvedShellLaunchConfig?: Event; onDidChangeHasChildProcesses?: Event; - onDidChangeProperty: Event; + onDidChangeProperty: Event>; /** * Starts the process. diff --git a/src/vs/platform/terminal/node/ptyHostService.ts b/src/vs/platform/terminal/node/ptyHostService.ts index d2fff7c7abf..031aa6ec49a 100644 --- a/src/vs/platform/terminal/node/ptyHostService.ts +++ b/src/vs/platform/terminal/node/ptyHostService.ts @@ -15,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { LogLevelChannelClient } from 'vs/platform/log/common/logIpc'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RequestStore } from 'vs/platform/terminal/common/requestStore'; -import { HeartbeatConstants, IHeartbeatService, IProcessDataEvent, IPtyService, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, TerminalIcon, TerminalIpcChannels, TerminalProperty, TerminalShellType, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { HeartbeatConstants, IHeartbeatService, IProcessDataEvent, IPtyService, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, TerminalIcon, TerminalIpcChannels, ITerminalProperty, TerminalShellType, TitleEventSource } from 'vs/platform/terminal/common/terminal'; import { registerTerminalPlatformConfiguration } from 'vs/platform/terminal/common/terminalPlatformConfiguration'; import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; import { detectAvailableProfiles } from 'vs/platform/terminal/node/terminalProfiles'; @@ -83,7 +83,7 @@ export class PtyHostService extends Disposable implements IPtyService { readonly onDidRequestDetach = this._onDidRequestDetach.event; private readonly _onProcessDidChangeHasChildProcesses = this._register(new Emitter<{ id: number, event: boolean }>()); readonly onProcessDidChangeHasChildProcesses = this._onProcessDidChangeHasChildProcesses.event; - private readonly _onDidChangeProperty = this._register(new Emitter<{ id: number, event: TerminalProperty }>()); + private readonly _onDidChangeProperty = this._register(new Emitter<{ id: number, property: ITerminalProperty }>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; constructor( diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index b9d7f1bbff9..b3f342396bd 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { getSystemShell } from 'vs/base/node/shell'; import { ILogService } from 'vs/platform/log/common/log'; import { RequestStore } from 'vs/platform/terminal/common/requestStore'; -import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, TerminalProperty, TerminalShellType, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, ITerminalProperty, TerminalShellType, TitleEventSource } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; import { Terminal as XtermTerminal } from 'xterm-headless'; @@ -60,7 +60,7 @@ export class PtyService extends Disposable implements IPtyService { readonly onDidRequestDetach = this._onDidRequestDetach.event; private readonly _onProcessDidChangeHasChildProcesses = this._register(new Emitter<{ id: number, event: boolean }>()); readonly onProcessDidChangeHasChildProcesses = this._onProcessDidChangeHasChildProcesses.event; - private readonly _onDidChangeProperty = this._register(new Emitter<{ id: number, event: TerminalProperty }>()); + private readonly _onDidChangeProperty = this._register(new Emitter<{ id: number, property: ITerminalProperty }>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; constructor( @@ -140,7 +140,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.onDidChangeProperty(event => this._onDidChangeProperty.fire({ id, event })); + persistentProcess.onDidChangeProperty(property => this._onDidChangeProperty.fire({ id, property })); persistentProcess.onProcessShellTypeChanged(event => this._onProcessShellTypeChanged.fire({ id, event })); persistentProcess.onProcessOrphanQuestion(() => this._onProcessOrphanQuestion.fire({ id })); this._ptys.set(id, persistentProcess); @@ -342,7 +342,7 @@ export class PersistentTerminalProcess extends Disposable { readonly onProcessData = this._onProcessData.event; private readonly _onProcessOrphanQuestion = this._register(new Emitter()); readonly onProcessOrphanQuestion = this._onProcessOrphanQuestion.event; - private readonly _onDidChangeProperty = this._register(new Emitter()); + private readonly _onDidChangeProperty = this._register(new Emitter>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; private _inReplay = false; diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 374eb2f9297..77eded2457c 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -15,7 +15,7 @@ import { URI } from 'vs/base/common/uri'; import { Promises } from 'vs/base/node/pfs'; import { localize } from 'vs/nls'; import { ILogService } from 'vs/platform/log/common/log'; -import { FlowControlConstants, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalProperty, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { FlowControlConstants, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProperty, TerminalPropertyType, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { ChildProcessMonitor } from 'vs/platform/terminal/node/childProcessMonitor'; import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; import { WindowsShellHelper } from 'vs/platform/terminal/node/windowsShellHelper'; @@ -77,6 +77,8 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess readonly id = 0; readonly shouldPersist = false; + currentCwd: string | undefined = undefined; + private static _lastKillOrStart = 0; private _exitCode: number | undefined; @@ -114,7 +116,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private readonly _onDidChangeHasChildProcesses = this._register(new Emitter()); readonly onDidChangeHasChildProcesses = this._onDidChangeHasChildProcesses.event; - private readonly _onDidChangeProperty = this._register(new Emitter()); + private readonly _onDidChangeProperty = this._register(new Emitter>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; onProcessOverrideDimensions?: Event | undefined; @@ -143,6 +145,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess name = 'xterm-256color'; } this._initialCwd = cwd; + this.currentCwd = cwd; const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309; this._ptyOptions = { name, @@ -203,6 +206,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess return { message: localize('launchFail.cwdDoesNotExist', "Starting directory (cwd) \"{0}\" does not exist", this._initialCwd.toString()) }; } } + this._onDidChangeProperty.fire({ type: TerminalPropertyType.InitialCwd, value: this._initialCwd }); return undefined; } @@ -494,7 +498,12 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess this._logService.trace('IPty#pid'); exec('lsof -OPln -p ' + this._ptyProcess.pid + ' | grep cwd', (error, stdout, stderr) => { if (!error && stdout !== '') { - resolve(stdout.substring(stdout.indexOf('/'), stdout.length - 1)); + const newCwd = stdout.substring(stdout.indexOf('/'), stdout.length - 1); + if (this.currentCwd !== newCwd) { + this.currentCwd = newCwd; + this._onDidChangeProperty.fire({ type: TerminalPropertyType.Cwd, value: this.currentCwd }); + resolve(newCwd); + } } else { this._logService.error('lsof did not run successfully, it may not be on the $PATH?', error, stdout, stderr); resolve(this._initialCwd); @@ -510,7 +519,12 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } this._logService.trace('IPty#pid'); try { - return await Promises.readlink(`/proc/${this._ptyProcess.pid}/cwd`); + const newCwd = await Promises.readlink(`/proc/${this._ptyProcess.pid}/cwd`); + if (newCwd !== this.currentCwd) { + this.currentCwd = newCwd; + this._onDidChangeProperty.fire({ type: TerminalPropertyType.Cwd, value: this.currentCwd }); + } + return this.currentCwd; } catch (error) { return this._initialCwd; } diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index ad119a9ec32..643c3bbeef5 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -18,7 +18,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 { ICreateContributedTerminalProfileOptions, IProcessReadyEvent, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, TerminalIcon, TerminalLocation, TerminalProperty, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { ICreateContributedTerminalProfileOptions, IProcessReadyEvent, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, TerminalIcon, TerminalLocation, ITerminalProperty, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { withNullAsUndefined } from 'vs/base/common/types'; @@ -250,7 +250,7 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess { public get onProcessOverrideDimensions(): Event { return this._onProcessOverrideDimensions.event; } private readonly _onProcessShellTypeChanged = new Emitter(); public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; - private readonly _onDidChangeProperty = new Emitter(); + private readonly _onDidChangeProperty = new Emitter>(); public readonly onDidChangeProperty = this._onDidChangeProperty.event; diff --git a/src/vs/workbench/contrib/terminal/browser/remotePty.ts b/src/vs/workbench/contrib/terminal/browser/remotePty.ts index e9321672369..10527388f13 100644 --- a/src/vs/workbench/contrib/terminal/browser/remotePty.ts +++ b/src/vs/workbench/contrib/terminal/browser/remotePty.ts @@ -8,14 +8,16 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; -import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalProperty, TerminalPropertyType, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProperty, TerminalPropertyType, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; import { RemoteTerminalChannelClient } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; export class RemotePty extends Disposable implements ITerminalChildProcess { - initialCwd: string | undefined = undefined; - cwd: string | undefined = undefined; + private _properties: { + cwd: string; + initialCwd: string + }; private readonly _onProcessData = this._register(new Emitter()); readonly onProcessData = this._onProcessData.event; private readonly _onProcessExit = this._register(new Emitter()); @@ -32,7 +34,7 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { readonly onProcessResolvedShellLaunchConfig = this._onProcessResolvedShellLaunchConfig.event; private readonly _onDidChangeHasChildProcesses = this._register(new Emitter()); readonly onDidChangeHasChildProcesses = this._onDidChangeHasChildProcesses.event; - private readonly _onDidChangeProperty = this._register(new Emitter()); + private readonly _onDidChangeProperty = this._register(new Emitter>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; private _startBarrier: Barrier; @@ -49,6 +51,10 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { private readonly _logService: ILogService ) { super(); + this._properties = { + cwd: '', + initialCwd: '' + }; this._startBarrier = new Barrier(); } @@ -120,21 +126,11 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { } async getInitialCwd(): Promise { - if (!this.initialCwd) { - await this._startBarrier.wait(); - this.initialCwd = await this._remoteTerminalChannel.getInitialCwd(this._id); - } - return this.initialCwd; + return this._properties.initialCwd; } async getCwd(): Promise { - await this._startBarrier.wait(); - const cwd = await this._remoteTerminalChannel.getCwd(this._id); - if (this.cwd !== cwd) { - this.cwd = cwd; - this.handleDidChangeProperty({ type: TerminalPropertyType.cwd, value: this.cwd }); - } - return this.cwd; + return this._properties.cwd || this._properties.initialCwd; } handleData(e: string | IProcessDataEvent) { @@ -168,7 +164,12 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { handleDidChangeHasChildProcesses(e: boolean) { this._onDidChangeHasChildProcesses.fire(e); } - handleDidChangeProperty(e: TerminalProperty) { + handleDidChangeProperty(e: ITerminalProperty) { + if (e.type === TerminalPropertyType.Cwd) { + this._properties.cwd = e.value; + } else if (e.type === TerminalPropertyType.InitialCwd) { + this._properties.initialCwd = e.value; + } this._onDidChangeProperty.fire(e); } diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts index 4cac0e267a3..b4cf20f62d5 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts @@ -79,7 +79,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal channel.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion()); channel.onDidRequestDetach(e => this._onDidRequestDetach.fire(e)); channel.onProcessDidChangeHasChildProcesses(e => this._ptys.get(e.id)?.handleDidChangeHasChildProcesses(e.event)); - channel.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.event)); + channel.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.property)); const allowedCommands = ['_remoteCLI.openExternal', '_remoteCLI.windowOpen', '_remoteCLI.getSystemStatus', '_remoteCLI.manageExtensions']; channel.onExecuteCommand(async e => { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 5911e452c69..50f7a83fdab 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1160,7 +1160,7 @@ 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 this._processManager.onDidChangeProperty(e => { - if (e.type === TerminalPropertyType.cwd || e.type === TerminalPropertyType.initialCwd) { + if (e.type === TerminalPropertyType.Cwd || e.type === TerminalPropertyType.InitialCwd) { this._cwd = e.value; this.setTitle(this.title, TitleEventSource.Api); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index 3423d0e3baa..60d311dc9a8 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 { IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalProperty, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProperty, 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'; @@ -46,7 +46,7 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal readonly onRequestLatency: Event = this._onRequestLatency.event; private readonly _onProcessShellTypeChanged = this._register(new Emitter()); readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; - private readonly _onDidChangeProperty = this._register(new Emitter()); + private readonly _onDidChangeProperty = this._register(new Emitter>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index f9449eeadd8..8cf4904ed96 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -22,7 +22,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { EnvironmentVariableInfoChangesActive, EnvironmentVariableInfoStale } from 'vs/workbench/contrib/terminal/browser/environmentVariableInfo'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { IEnvironmentVariableInfo, IEnvironmentVariableService, IMergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, FlowControlConstants, TerminalShellType, ITerminalDimensions, TerminalSettingId, IProcessReadyEvent, TerminalProperty } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, FlowControlConstants, TerminalShellType, ITerminalDimensions, TerminalSettingId, IProcessReadyEvent, ITerminalProperty } from 'vs/platform/terminal/common/terminal'; import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder'; import { localize } from 'vs/nls'; import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/terminalStrings'; @@ -96,7 +96,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce readonly onProcessData = this._onProcessData.event; private readonly _onProcessTitle = this._register(new Emitter()); readonly onProcessTitle = this._onProcessTitle.event; - private readonly _onDidChangeProperty = this._register(new Emitter()); + private readonly _onDidChangeProperty = this._register(new Emitter>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; private readonly _onProcessShellTypeChanged = this._register(new Emitter()); readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index ecfc0bed541..8eabe98f78f 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -18,7 +18,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { Schemas } from 'vs/base/common/network'; import { ILabelService } from 'vs/platform/label/common/label'; import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { IProcessDataEvent, IRequestResolveVariablesEvent, IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalProperty, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IRequestResolveVariablesEvent, IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, ITerminalProperty, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; @@ -124,8 +124,8 @@ export class RemoteTerminalChannelClient { get onDidRequestDetach(): Event<{ requestId: number, workspaceId: string, instanceId: number }> { return this._channel.listen<{ requestId: number, workspaceId: string, instanceId: number }>('$onDidRequestDetach'); } - get onDidChangeProperty(): Event<{ id: number, event: TerminalProperty }> { - return this._channel.listen<{ id: number, event: TerminalProperty }>('$onDidChangeProperty'); + get onDidChangeProperty(): Event<{ id: number, property: ITerminalProperty }> { + return this._channel.listen<{ id: number, property: ITerminalProperty }>('$onDidChangeProperty'); } constructor( diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 6b4dc599f7e..5e5851cb4fc 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -8,7 +8,7 @@ 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, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalLocationString, TerminalProperty, TerminalShellType, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalLocationString, ITerminalProperty, TerminalShellType, TitleEventSource } 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'; @@ -291,13 +291,13 @@ export interface ITerminalProcessManager extends IDisposable { readonly onBeforeProcessData: Event; readonly onProcessData: Event; readonly onProcessTitle: Event; - readonly onDidChangeProperty: Event; readonly onProcessShellTypeChanged: Event; readonly onProcessExit: Event; readonly onProcessOverrideDimensions: Event; readonly onProcessResolvedShellLaunchConfig: Event; readonly onProcessDidChangeHasChildProcesses: Event; readonly onEnvironmentVariableInfoChanged: Event; + readonly onDidChangeProperty: Event>; dispose(immediate?: boolean): void; detachFromProcess(): Promise; diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts index 7a6323c4473..15cf60ab532 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, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalProperty, TerminalPropertyType, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProperty, TerminalPropertyType, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; /** @@ -15,8 +15,10 @@ import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminal */ export class LocalPty extends Disposable implements ITerminalChildProcess { private _inReplay = false; - initialCwd: string | undefined = undefined; - cwd: string | undefined = undefined; + private _properties: { + cwd: string; + initialCwd: string + }; private readonly _onProcessData = this._register(new Emitter()); readonly onProcessData = this._onProcessData.event; private readonly _onProcessReplay = this._register(new Emitter()); @@ -35,7 +37,7 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private readonly _onDidChangeHasChildProcesses = this._register(new Emitter()); readonly onDidChangeHasChildProcesses = this._onDidChangeHasChildProcesses.event; - private readonly _onDidChangeProperty = this._register(new Emitter()); + private readonly _onDidChangeProperty = this._register(new Emitter>()); readonly onDidChangeProperty = this._onDidChangeProperty.event; constructor( @@ -44,6 +46,10 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { @ILocalPtyService private readonly _localPtyService: ILocalPtyService ) { super(); + this._properties = { + cwd: '', + initialCwd: '' + }; } start(): Promise { @@ -74,18 +80,10 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { this._localPtyService.resize(this.id, cols, rows); } async getInitialCwd(): Promise { - if (!this.initialCwd) { - this.initialCwd = await this._localPtyService.getInitialCwd(this.id); - } - return this.initialCwd; + return this._properties.initialCwd; } async getCwd(): Promise { - const cwd = await this._localPtyService.getCwd(this.id); - if (this.cwd !== cwd) { - this.cwd = cwd; - this.handleDidChangeProperty({ type: TerminalPropertyType.cwd, value: this.cwd }); - } - return this.cwd; + return this._properties.cwd || this._properties.initialCwd; } getLatency(): Promise { // TODO: The idea here was to add the result plus the time it took to get the latency @@ -125,7 +123,12 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { handleDidChangeHasChildProcesses(e: boolean) { this._onDidChangeHasChildProcesses.fire(e); } - handleDidChangeProperty(e: TerminalProperty) { + handleDidChangeProperty(e: ITerminalProperty) { + if (e.type === TerminalPropertyType.Cwd) { + this._properties.cwd = e.value; + } else if (e.type === TerminalPropertyType.InitialCwd) { + this._properties.initialCwd = e.value; + } this._onDidChangeProperty.fire(e); } diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts index 58c6b829b03..7333a8e4523 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts @@ -66,7 +66,7 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe this._localPtyService.onProcessOverrideDimensions(e => this._ptys.get(e.id)?.handleOverrideDimensions(e.event)); this._localPtyService.onProcessResolvedShellLaunchConfig(e => this._ptys.get(e.id)?.handleResolvedShellLaunchConfig(e.event)); this._localPtyService.onProcessDidChangeHasChildProcesses(e => this._ptys.get(e.id)?.handleDidChangeHasChildProcesses(e.event)); - this._localPtyService.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.event)); + this._localPtyService.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.property)); this._localPtyService.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event)); this._localPtyService.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion()); this._localPtyService.onDidRequestDetach(e => this._onDidRequestDetach.fire(e));