mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
Merge pull request #144925 from microsoft/tyriar/142669
Run shell integration on pty host and restore on reconnect
This commit is contained in:
commit
473ca6818d
|
@ -4,8 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability';
|
||||
import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability';
|
||||
import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
|
||||
/**
|
||||
* Primarily driven by the shell integration feature, a terminal capability is the mechanism for
|
||||
|
@ -69,12 +68,20 @@ export interface ITerminalCapabilityStore {
|
|||
* implementations.
|
||||
*/
|
||||
export interface ITerminalCapabilityImplMap {
|
||||
[TerminalCapability.CwdDetection]: InstanceType<typeof CwdDetectionCapability>;
|
||||
[TerminalCapability.CwdDetection]: ICwdDetectionCapability;
|
||||
[TerminalCapability.CommandDetection]: ICommandDetectionCapability;
|
||||
[TerminalCapability.NaiveCwdDetection]: InstanceType<typeof NaiveCwdDetectionCapability>;
|
||||
[TerminalCapability.NaiveCwdDetection]: INaiveCwdDetectionCapability;
|
||||
[TerminalCapability.PartialCommandDetection]: IPartialCommandDetectionCapability;
|
||||
}
|
||||
|
||||
export interface ICwdDetectionCapability {
|
||||
readonly type: TerminalCapability.CwdDetection;
|
||||
readonly onDidChangeCwd: Event<string>;
|
||||
readonly cwds: string[];
|
||||
getCwd(): string;
|
||||
updateCwd(cwd: string): void;
|
||||
}
|
||||
|
||||
export interface ICommandDetectionCapability {
|
||||
readonly type: TerminalCapability.CommandDetection;
|
||||
readonly commands: readonly ITerminalCommand[];
|
||||
|
@ -97,6 +104,14 @@ export interface ICommandDetectionCapability {
|
|||
* Set the command line explicitly.
|
||||
*/
|
||||
setCommandLine(commandLine: string): void;
|
||||
serializeCommands(): ISerializedCommand[];
|
||||
restoreCommands(serialized: ISerializedCommand[]): void;
|
||||
}
|
||||
|
||||
export interface INaiveCwdDetectionCapability {
|
||||
readonly type: TerminalCapability.NaiveCwdDetection;
|
||||
readonly onDidChangeCwd: Event<string>;
|
||||
getCwd(): Promise<string>;
|
||||
}
|
||||
|
||||
export interface IPartialCommandDetectionCapability {
|
||||
|
@ -112,6 +127,7 @@ export interface ITerminalCommand {
|
|||
exitCode?: number;
|
||||
marker?: IXtermMarker;
|
||||
endMarker?: IXtermMarker;
|
||||
executedMarker?: IXtermMarker;
|
||||
getOutput(): string | undefined;
|
||||
hasOutput: boolean;
|
||||
}
|
|
@ -6,8 +6,11 @@
|
|||
import { timeout } from 'vs/base/common/async';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { IBuffer, IDisposable, IMarker, Terminal } from 'xterm';
|
||||
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
// Importing types is safe in any layer
|
||||
// eslint-disable-next-line code-import-patterns
|
||||
import type { IBuffer, IDisposable, IMarker, Terminal } from 'xterm-headless';
|
||||
|
||||
export interface ICurrentPartialCommand {
|
||||
previousCommandMarker?: IMarker;
|
||||
|
@ -140,7 +143,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
|
|||
}
|
||||
|
||||
// Sanity check optional props
|
||||
if (!this._currentCommand.commandStartMarker || !this._currentCommand.commandExecutedMarker || !this._currentCommand.commandStartX) {
|
||||
if (!this._currentCommand.commandStartMarker || !this._currentCommand.commandExecutedMarker || this._currentCommand.commandStartX === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -197,17 +200,19 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
|
|||
|
||||
if (command !== undefined && !command.startsWith('\\')) {
|
||||
const buffer = this._terminal.buffer.active;
|
||||
const clonedPartialCommand = { ...this._currentCommand };
|
||||
const timestamp = Date.now();
|
||||
const newCommand = {
|
||||
const executedMarker = this._currentCommand.commandExecutedMarker;
|
||||
const endMarker = this._currentCommand.commandFinishedMarker;
|
||||
const newCommand: ITerminalCommand = {
|
||||
command,
|
||||
marker: this._currentCommand.commandStartMarker,
|
||||
endMarker: this._currentCommand.commandFinishedMarker,
|
||||
endMarker,
|
||||
executedMarker,
|
||||
timestamp,
|
||||
cwd: this._cwd,
|
||||
exitCode: this._exitCode,
|
||||
hasOutput: !!(this._currentCommand.commandExecutedMarker && this._currentCommand.commandFinishedMarker && this._currentCommand.commandExecutedMarker?.line < this._currentCommand.commandFinishedMarker!.line),
|
||||
getOutput: () => getOutputForCommand(clonedPartialCommand, buffer)
|
||||
hasOutput: !!(executedMarker && endMarker && executedMarker?.line < endMarker!.line),
|
||||
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer)
|
||||
};
|
||||
this._commands.push(newCommand);
|
||||
this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand);
|
||||
|
@ -221,11 +226,78 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
|
|||
this._logService.debug('CommandDetectionCapability#setCommandLine', commandLine);
|
||||
this._currentCommand.command = commandLine;
|
||||
}
|
||||
|
||||
serializeCommands(): ISerializedCommand[] {
|
||||
const serialized: ISerializedCommand[] = this.commands.map(e => {
|
||||
return {
|
||||
startLine: e.marker?.line,
|
||||
startX: undefined,
|
||||
endLine: e.endMarker?.line,
|
||||
executedLine: e.executedMarker?.line,
|
||||
command: e.command,
|
||||
cwd: e.cwd,
|
||||
exitCode: e.exitCode,
|
||||
timestamp: e.timestamp
|
||||
};
|
||||
});
|
||||
if (this._currentCommand.commandStartMarker) {
|
||||
serialized.push({
|
||||
startLine: this._currentCommand.commandStartMarker.line,
|
||||
startX: this._currentCommand.commandStartX,
|
||||
endLine: undefined,
|
||||
executedLine: undefined,
|
||||
command: '',
|
||||
cwd: this._cwd,
|
||||
exitCode: undefined,
|
||||
timestamp: 0,
|
||||
});
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
restoreCommands(serialized: ISerializedCommand[]): void {
|
||||
const buffer = this._terminal.buffer.normal;
|
||||
for (const e of serialized) {
|
||||
const marker = e.startLine !== undefined ? this._terminal.registerMarker(e.startLine - (buffer.baseY + buffer.cursorY)) : undefined;
|
||||
// Check for invalid command
|
||||
if (!marker) {
|
||||
continue;
|
||||
}
|
||||
// Partial command
|
||||
if (!e.endLine) {
|
||||
this._currentCommand.commandStartMarker = marker;
|
||||
this._currentCommand.commandStartX = e.startX;
|
||||
this._cwd = e.cwd;
|
||||
this._onCommandStarted.fire({ marker } as ITerminalCommand);
|
||||
continue;
|
||||
}
|
||||
// Full command
|
||||
const endMarker = e.endLine !== undefined ? this._terminal.registerMarker(e.endLine - (buffer.baseY + buffer.cursorY)) : undefined;
|
||||
const executedMarker = e.executedLine !== undefined ? this._terminal.registerMarker(e.executedLine - (buffer.baseY + buffer.cursorY)) : undefined;
|
||||
const newCommand = {
|
||||
command: e.command,
|
||||
marker,
|
||||
endMarker,
|
||||
executedMarker,
|
||||
timestamp: e.timestamp,
|
||||
cwd: e.cwd,
|
||||
exitCode: e.exitCode,
|
||||
hasOutput: !!(executedMarker && endMarker && executedMarker.line < endMarker.line),
|
||||
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer)
|
||||
};
|
||||
this._commands.push(newCommand);
|
||||
this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand);
|
||||
this._onCommandFinished.fire(newCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getOutputForCommand(command: ICurrentPartialCommand, buffer: IBuffer): string | undefined {
|
||||
const startLine = command.commandExecutedMarker!.line;
|
||||
const endLine = command.commandFinishedMarker!.line;
|
||||
function getOutputForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer): string | undefined {
|
||||
if (!executedMarker || !endMarker) {
|
||||
return undefined;
|
||||
}
|
||||
const startLine = executedMarker.line;
|
||||
const endLine = endMarker.line;
|
||||
|
||||
if (startLine === endLine) {
|
||||
return undefined;
|
|
@ -4,9 +4,9 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ICwdDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
export class CwdDetectionCapability {
|
||||
export class CwdDetectionCapability implements ICwdDetectionCapability {
|
||||
readonly type = TerminalCapability.CwdDetection;
|
||||
private _cwd = '';
|
||||
private _cwds = new Map</*cwd*/string, /*frequency*/number>();
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ITerminalChildProcess } from 'vs/platform/terminal/common/terminal';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapability, INaiveCwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
export class NaiveCwdDetectionCapability {
|
||||
export class NaiveCwdDetectionCapability implements INaiveCwdDetectionCapability {
|
||||
constructor(private readonly _process: ITerminalChildProcess) { }
|
||||
readonly type = TerminalCapability.NaiveCwdDetection;
|
||||
private _cwd = '';
|
|
@ -4,8 +4,10 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IPartialCommandDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { IMarker, Terminal } from 'xterm';
|
||||
import { IPartialCommandDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
// Importing types is safe in any layer
|
||||
// eslint-disable-next-line code-import-patterns
|
||||
import { IMarker, Terminal } from 'xterm-headless';
|
||||
|
||||
const enum Constants {
|
||||
/**
|
||||
|
@ -31,11 +33,11 @@ export class PartialCommandDetectionCapability implements IPartialCommandDetecti
|
|||
constructor(
|
||||
private readonly _terminal: Terminal,
|
||||
) {
|
||||
this._terminal.onKey(e => this._onKey(e.key));
|
||||
this._terminal.onData(e => this._onData(e));
|
||||
}
|
||||
|
||||
private _onKey(key: string): void {
|
||||
if (key === '\x0d') {
|
||||
private _onData(data: string): void {
|
||||
if (data === '\x0d') {
|
||||
this._onEnter();
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
export class TerminalCapabilityStore extends Disposable implements ITerminalCapabilityStore {
|
||||
private _map: Map<TerminalCapability, { type: TerminalCapability }> = new Map();
|
|
@ -7,7 +7,8 @@ import { Event } from 'vs/base/common/event';
|
|||
import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISerializedCommand, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export const enum TerminalSettingPrefix {
|
||||
|
@ -597,6 +598,7 @@ export interface ITerminalChildProcess {
|
|||
onProcessReady: Event<IProcessReadyEvent>;
|
||||
onDidChangeProperty: Event<IProcessProperty<any>>;
|
||||
onProcessExit: Event<number | undefined>;
|
||||
onRestoreCommands?: Event<ISerializedCommand[]>;
|
||||
|
||||
/**
|
||||
* Starts the process.
|
||||
|
@ -768,3 +770,8 @@ export interface IExtensionTerminalProfile extends ITerminalProfileContribution
|
|||
|
||||
export type ITerminalProfileObject = ITerminalExecutable | ITerminalProfileSource | IExtensionTerminalProfile | null;
|
||||
export type ITerminalProfileType = ITerminalProfile | IExtensionTerminalProfile;
|
||||
|
||||
export interface IShellIntegration {
|
||||
capabilities: ITerminalCapabilityStore;
|
||||
restoreCommands(serialized: ISerializedCommand[]): void;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,22 @@ export interface IProcessDetails {
|
|||
|
||||
export type ITerminalTabLayoutInfoDto = IRawTerminalTabLayoutInfo<IProcessDetails>;
|
||||
|
||||
export interface ReplayEntry { cols: number; rows: number; data: string }
|
||||
export interface ReplayEntry {
|
||||
cols: number;
|
||||
rows: number;
|
||||
data: string;
|
||||
}
|
||||
export interface ISerializedCommand {
|
||||
command: string;
|
||||
cwd: string | undefined;
|
||||
startLine: number | undefined;
|
||||
startX: number | undefined;
|
||||
endLine: number | undefined;
|
||||
executedLine: number | undefined;
|
||||
exitCode: number | undefined;
|
||||
timestamp: number;
|
||||
}
|
||||
export interface IPtyHostProcessReplayEvent {
|
||||
events: ReplayEntry[];
|
||||
commands: ISerializedCommand[];
|
||||
}
|
||||
|
|
|
@ -84,7 +84,9 @@ export class TerminalRecorder {
|
|||
}
|
||||
});
|
||||
return {
|
||||
events: this._entries.map(entry => ({ cols: entry.cols, rows: entry.rows, data: entry.data[0] ?? '' }))
|
||||
events: this._entries.map(entry => ({ cols: entry.cols, rows: entry.rows, data: entry.data[0] ?? '' })),
|
||||
// No command restoration is needed when relaunching terminals
|
||||
commands: []
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,18 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITerminalAddon, Terminal } from 'xterm';
|
||||
import { IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IShellIntegration } from 'vs/platform/terminal/common/terminal';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability';
|
||||
import { ICommandDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
|
||||
import { CwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/cwdDetectionCapability';
|
||||
import { ICommandDetectionCapability, ICwdDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/partialCommandDetectionCapability';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
// Importing types is safe in any layer
|
||||
// eslint-disable-next-line code-import-patterns
|
||||
import type { ITerminalAddon, Terminal } from 'xterm-headless';
|
||||
import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
|
||||
/**
|
||||
* Shell integration is a feature that enhances the terminal's understanding of what's happening
|
||||
|
@ -112,7 +115,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
|
|||
readonly capabilities = new TerminalCapabilityStore();
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
@ILogService private readonly _logService: ILogService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -188,7 +191,22 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
|
|||
return false;
|
||||
}
|
||||
|
||||
protected _createOrGetCwdDetection(): CwdDetectionCapability {
|
||||
serializeCommands(): ISerializedCommand[] {
|
||||
if (!this._terminal || !this.capabilities.has(TerminalCapability.CommandDetection)) {
|
||||
return [];
|
||||
}
|
||||
const result = this._createOrGetCommandDetection(this._terminal).serializeCommands();
|
||||
return result;
|
||||
}
|
||||
|
||||
restoreCommands(serialized: ISerializedCommand[]): void {
|
||||
if (!this._terminal) {
|
||||
throw new Error('Cannot restore commands before addon is activated');
|
||||
}
|
||||
this._createOrGetCommandDetection(this._terminal).restoreCommands(serialized);
|
||||
}
|
||||
|
||||
protected _createOrGetCwdDetection(): ICwdDetectionCapability {
|
||||
let cwdDetection = this.capabilities.get(TerminalCapability.CwdDetection);
|
||||
if (!cwdDetection) {
|
||||
cwdDetection = new CwdDetectionCapability();
|
||||
|
@ -200,7 +218,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
|
|||
protected _createOrGetCommandDetection(terminal: Terminal): ICommandDetectionCapability {
|
||||
let commandDetection = this.capabilities.get(TerminalCapability.CommandDetection);
|
||||
if (!commandDetection) {
|
||||
commandDetection = this._instantiationService.createInstance(CommandDetectionCapability, terminal);
|
||||
commandDetection = new CommandDetectionCapability(terminal, this._logService);
|
||||
this.capabilities.add(TerminalCapability.CommandDetection, commandDetection);
|
||||
}
|
||||
return commandDetection;
|
|
@ -25,6 +25,7 @@ import { localize } from 'vs/nls';
|
|||
import { ignoreProcessNames } from 'vs/platform/terminal/node/childProcessMonitor';
|
||||
import { TerminalAutoResponder } from 'vs/platform/terminal/common/terminalAutoResponder';
|
||||
import { ErrorNoTelemetry } from 'vs/base/common/errors';
|
||||
import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon';
|
||||
|
||||
type WorkspaceId = string;
|
||||
|
||||
|
@ -500,7 +501,8 @@ export class PersistentTerminalProcess extends Disposable {
|
|||
rows,
|
||||
reconnectConstants.scrollback,
|
||||
unicodeVersion,
|
||||
reviveBuffer
|
||||
reviveBuffer,
|
||||
this._logService
|
||||
);
|
||||
this._fixedDimensions = fixedDimensions;
|
||||
this._orphanQuestionBarrier = null;
|
||||
|
@ -723,35 +725,25 @@ export class PersistentTerminalProcess extends Disposable {
|
|||
}
|
||||
|
||||
class XtermSerializer implements ITerminalSerializer {
|
||||
private _xterm: XtermTerminal;
|
||||
private readonly _xterm: XtermTerminal;
|
||||
private readonly _shellIntegrationAddon: ShellIntegrationAddon;
|
||||
private _unicodeAddon?: XtermUnicode11Addon;
|
||||
private _shellIntegrationEnabled: boolean = false;
|
||||
|
||||
constructor(
|
||||
cols: number,
|
||||
rows: number,
|
||||
scrollback: number,
|
||||
unicodeVersion: '6' | '11',
|
||||
reviveBuffer: string | undefined
|
||||
reviveBuffer: string | undefined,
|
||||
logService: ILogService
|
||||
) {
|
||||
this._xterm = new XtermTerminal({ cols, rows, scrollback });
|
||||
if (reviveBuffer) {
|
||||
this._xterm.writeln(reviveBuffer);
|
||||
if (this._shellIntegrationEnabled) {
|
||||
this._xterm.write('\x1b033]133;E\x1b007');
|
||||
}
|
||||
}
|
||||
this._xterm.parser.registerOscHandler(133, (data => this._handleShellIntegration(data)));
|
||||
this.setUnicodeVersion(unicodeVersion);
|
||||
}
|
||||
|
||||
private _handleShellIntegration(data: string): boolean {
|
||||
const [command,] = data.split(';');
|
||||
if (command === 'E') {
|
||||
this._shellIntegrationEnabled = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
this._shellIntegrationAddon = new ShellIntegrationAddon(logService);
|
||||
this._xterm.loadAddon(this._shellIntegrationAddon);
|
||||
}
|
||||
|
||||
handleData(data: string): void {
|
||||
|
@ -778,7 +770,8 @@ class XtermSerializer implements ITerminalSerializer {
|
|||
rows: this._xterm.getOption('rows'),
|
||||
data: serialized
|
||||
}
|
||||
]
|
||||
],
|
||||
commands: this._shellIntegrationAddon.serializeCommands()
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import type { IViewportRange, IBufferRange, IBufferLine, IBuffer, IBufferCellPos
|
|||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { IPath, posix, win32 } from 'vs/base/common/path';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
/**
|
||||
* Converts a possibly wrapped link's range (comprised of string indices) into a buffer range that plays nicely with xterm.js
|
||||
|
|
|
@ -29,7 +29,7 @@ import { ITerminalExternalLinkProvider, TerminalLinkQuickPickEvent } from 'vs/wo
|
|||
import { ILinkHoverTargetOptions, TerminalHover } from 'vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget';
|
||||
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager';
|
||||
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IHoverAction } from 'vs/workbench/services/hover/browser/hover';
|
||||
import type { ILink, ILinkProvider, IViewportRange, Terminal } from 'xterm';
|
||||
|
|
|
@ -17,7 +17,7 @@ import { ITerminalLinkOpener, ITerminalSimpleLink } from 'vs/workbench/contrib/t
|
|||
import { osPathModule, updateLinkWithRelativeCwd } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers';
|
||||
import { ILineColumnInfo } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
|
||||
import { getLocalLinkRegex, lineAndColumnClause, lineAndColumnClauseGroupCount, unixLineAndColumnMatchIndex, winLineAndColumnMatchIndex } from 'vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
|
|
|
@ -9,7 +9,7 @@ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'
|
|||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { ITerminalLinkDetector, ITerminalSimpleLink, ResolvedLink, TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links';
|
||||
import { convertLinkRangeToBuffer, getXtermLineContent, osPathModule, updateLinkWithRelativeCwd } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { IBufferLine, Terminal } from 'xterm';
|
||||
|
||||
const enum Constants {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
|||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IProcessDataEvent, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap, ProcessPropertyType, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal';
|
||||
import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { IPtyHostProcessReplayEvent, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { RemoteTerminalChannelClient } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
|
||||
|
@ -22,6 +22,8 @@ export class RemotePty extends Disposable implements ITerminalChildProcess {
|
|||
readonly onDidChangeProperty = this._onDidChangeProperty.event;
|
||||
private readonly _onProcessExit = this._register(new Emitter<number | undefined>());
|
||||
readonly onProcessExit = this._onProcessExit.event;
|
||||
private readonly _onRestoreCommands = this._register(new Emitter<ISerializedCommand[]>());
|
||||
readonly onRestoreCommands = this._onRestoreCommands.event;
|
||||
|
||||
private _startBarrier: Barrier;
|
||||
|
||||
|
@ -178,6 +180,10 @@ export class RemotePty extends Disposable implements ITerminalChildProcess {
|
|||
this._inReplay = false;
|
||||
}
|
||||
|
||||
if (e.commands.length > 0) {
|
||||
this._onRestoreCommands.fire(e.commands);
|
||||
}
|
||||
|
||||
// remove size override
|
||||
this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: undefined });
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalEnvironment, ITerminalProcessOptions, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ProcessPropertyType, TerminalIcon, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal';
|
||||
import { IProcessDetails } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { IProcessDetails, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { BaseTerminalBackend } from 'vs/workbench/contrib/terminal/browser/baseTerminalBackend';
|
||||
|
@ -52,6 +52,8 @@ class RemoteTerminalBackend extends BaseTerminalBackend implements ITerminalBack
|
|||
|
||||
private readonly _onDidRequestDetach = this._register(new Emitter<{ requestId: number; workspaceId: string; instanceId: number }>());
|
||||
readonly onDidRequestDetach = this._onDidRequestDetach.event;
|
||||
private readonly _onRestoreCommands = this._register(new Emitter<{ id: number; commands: ISerializedCommand[] }>());
|
||||
readonly onRestoreCommands = this._onRestoreCommands.event;
|
||||
|
||||
constructor(
|
||||
readonly remoteAuthority: string | undefined,
|
||||
|
@ -70,7 +72,12 @@ class RemoteTerminalBackend extends BaseTerminalBackend implements ITerminalBack
|
|||
super(_remoteTerminalChannel, logService, notificationService, _historyService, configurationResolverService, workspaceContextService);
|
||||
|
||||
this._remoteTerminalChannel.onProcessData(e => this._ptys.get(e.id)?.handleData(e.event));
|
||||
this._remoteTerminalChannel.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event));
|
||||
this._remoteTerminalChannel.onProcessReplay(e => {
|
||||
this._ptys.get(e.id)?.handleReplay(e.event);
|
||||
if (e.event.commands.length > 0) {
|
||||
this._onRestoreCommands.fire({ id: e.id, commands: e.event.commands });
|
||||
}
|
||||
});
|
||||
this._remoteTerminalChannel.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion());
|
||||
this._remoteTerminalChannel.onDidRequestDetach(e => this._onDidRequestDetach.fire(e));
|
||||
this._remoteTerminalChannel.onProcessReady(e => this._ptys.get(e.id)?.handleReady(e.event));
|
||||
|
|
|
@ -8,14 +8,14 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
|||
import { URI } from 'vs/base/common/uri';
|
||||
import { FindReplaceState } from 'vs/editor/contrib/find/browser/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 { INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs, IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource, TerminalShellType, IExtensionTerminalProfile, TerminalLocation, ProcessPropertyType, IProcessPropertyMap, IShellIntegration } from 'vs/platform/terminal/common/terminal';
|
||||
import { INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs } 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';
|
||||
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';
|
||||
import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
|
||||
|
|
|
@ -66,8 +66,8 @@ import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/wid
|
|||
import { LineDataEventAddon } from 'vs/workbench/contrib/terminal/browser/xterm/lineDataEventAddon';
|
||||
import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/xterm/navigationModeAddon';
|
||||
import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal';
|
||||
import { ITerminalCommand, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStoreMultiplexer } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStoreMultiplexer } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { getCommandHistory, getDirectoryHistory } from 'vs/workbench/contrib/terminal/common/history';
|
||||
import { DEFAULT_COMMANDS_TO_SKIP_SHELL, INavigationMode, ITerminalBackend, ITerminalProcessManager, ITerminalProfileResolverService, ProcessState, ShellIntegrationExitCode, TerminalCommandId, TERMINAL_CREATION_COMMANDS, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
|
@ -708,6 +708,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
|||
this._areLinksReady = true;
|
||||
this._onLinksReady.fire(this);
|
||||
});
|
||||
this._processManager.onRestoreCommands(e => this.xterm?.shellIntegration.restoreCommands(e));
|
||||
|
||||
this._loadTypeAheadAddon(xterm);
|
||||
|
||||
|
|
|
@ -28,10 +28,11 @@ import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/t
|
|||
import { IProcessEnvironment, isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
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';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { NaiveCwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/naiveCwdDetectionCapability';
|
||||
import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
|
||||
/** The amount of time to consider terminal errors to be related to the launch */
|
||||
const LAUNCHING_DURATION = 500;
|
||||
|
@ -105,6 +106,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
|||
readonly onEnvironmentVariableInfoChanged = this._onEnvironmentVariableInfoChange.event;
|
||||
private readonly _onProcessExit = this._register(new Emitter<number | undefined>());
|
||||
readonly onProcessExit = this._onProcessExit.event;
|
||||
private readonly _onRestoreCommands = this._register(new Emitter<ISerializedCommand[]>());
|
||||
readonly onRestoreCommands = this._onRestoreCommands.event;
|
||||
|
||||
get persistentProcessId(): number | undefined { return this._process?.id; }
|
||||
get shouldPersist(): boolean { return this._process ? this._process.shouldPersist : false; }
|
||||
|
@ -334,6 +337,11 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
|||
this._onDidChangeProperty.fire({ type, value });
|
||||
})
|
||||
];
|
||||
if (newProcess.onRestoreCommands) {
|
||||
this._processListeners.push(newProcess.onRestoreCommands(e => {
|
||||
this._onRestoreCommands.fire(e);
|
||||
}));
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.processState === ProcessState.Launching) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { localize } from 'vs/nls';
|
||||
import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
function getCapabilityName(capability: TerminalCapability): string | undefined {
|
||||
switch (capability) {
|
||||
|
|
|
@ -13,6 +13,7 @@ export interface IXtermCore {
|
|||
viewport?: {
|
||||
_innerRefresh(): void;
|
||||
};
|
||||
_onData: IEventEmitter<string>;
|
||||
_onKey: IEventEmitter<{ key: string }>;
|
||||
|
||||
_charSizeService: {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ICommandTracker } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ICommandDetectionCapability, IPartialCommandDetectionCapability, ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ICommandDetectionCapability, IPartialCommandDetectionCapability, ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import type { Terminal, IMarker, ITerminalAddon } from 'xterm';
|
||||
|
||||
enum Boundary {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/terminal'
|
|||
import { IDecoration, ITerminalAddon, Terminal } from 'xterm';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { IColorTheme, ICssStyleCollector, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
|
||||
|
@ -131,6 +131,12 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {
|
|||
if (!capability) {
|
||||
return;
|
||||
}
|
||||
if (capability.commands.length > 0) {
|
||||
const lastCommand = capability.commands[capability.commands.length - 1];
|
||||
if (lastCommand.marker && !lastCommand.endMarker) {
|
||||
this.registerCommandDecoration(lastCommand, true);
|
||||
}
|
||||
}
|
||||
this._commandStartedListener = capability.onCommandStarted(command => this.registerCommandDecoration(command, true));
|
||||
}
|
||||
|
||||
|
@ -143,6 +149,9 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {
|
|||
if (!capability) {
|
||||
return;
|
||||
}
|
||||
for (const command of capability.commands) {
|
||||
this.registerCommandDecoration(command);
|
||||
}
|
||||
this._commandFinishedListener = capability.onCommandFinished(command => {
|
||||
if (command.command.trim().toLowerCase() === 'clear' || command.command.trim().toLowerCase() === 'cls') {
|
||||
this.clearDecorations();
|
||||
|
@ -174,12 +183,13 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {
|
|||
this._placeholderDecoration = decoration;
|
||||
this._placeholderDecoration.onDispose(() => this._placeholderDecoration = undefined);
|
||||
} else {
|
||||
this._decorations.set(decoration.marker.id,
|
||||
{
|
||||
if (!this._decorations.has(decoration.marker.id)) {
|
||||
this._decorations.set(decoration.marker.id, {
|
||||
decoration,
|
||||
disposables: command.exitCode === undefined ? [] : [this._createContextMenu(element, command), ...this._createHover(element, command)],
|
||||
exitCode: command.exitCode
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!element.classList.contains(DecorationSelector.Codicon) || command.marker?.line === 0) {
|
||||
// first render or buffer was cleared
|
||||
|
|
|
@ -13,8 +13,8 @@ import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configur
|
|||
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { TerminalLocation, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
import { IShellIntegration, ITerminalFont, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IShellIntegration, TerminalLocation, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
import { ITerminalFont, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { isSafari } from 'vs/base/browser/browser';
|
||||
import { ICommandTracker, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
@ -29,10 +29,10 @@ import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
|||
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { TERMINAL_FOREGROUND_COLOR, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, ansiColorIdentifiers, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon';
|
||||
import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon';
|
||||
import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
// How long in milliseconds should an average frame take to render for a notification to appear
|
||||
|
|
|
@ -12,9 +12,9 @@ import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChi
|
|||
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 { IProcessDetails, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ITerminalCapabilityStore, IXtermMarker } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityStore, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
export const TERMINAL_VIEW_ID = 'terminal';
|
||||
|
||||
|
@ -328,10 +328,6 @@ export interface IRemoteTerminalAttachTarget {
|
|||
fixedDimensions: IFixedTerminalDimensions | undefined;
|
||||
}
|
||||
|
||||
export interface IShellIntegration {
|
||||
capabilities: ITerminalCapabilityStore;
|
||||
}
|
||||
|
||||
export interface ITerminalCommand {
|
||||
command: string;
|
||||
timestamp: number;
|
||||
|
@ -386,6 +382,7 @@ export interface ITerminalProcessManager extends IDisposable {
|
|||
readonly onEnvironmentVariableInfoChanged: Event<IEnvironmentVariableInfo>;
|
||||
readonly onDidChangeProperty: Event<IProcessProperty<any>>;
|
||||
readonly onProcessExit: Event<number | undefined>;
|
||||
readonly onRestoreCommands: Event<ISerializedCommand[]>;
|
||||
|
||||
dispose(immediate?: boolean): void;
|
||||
detachFromProcess(): Promise<void>;
|
||||
|
|
|
@ -7,7 +7,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, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap, ProcessPropertyType, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal';
|
||||
import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { IPtyHostProcessReplayEvent, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
/**
|
||||
|
@ -36,6 +36,8 @@ export class LocalPty extends Disposable implements ITerminalChildProcess {
|
|||
readonly onDidChangeProperty = this._onDidChangeProperty.event;
|
||||
private readonly _onProcessExit = this._register(new Emitter<number | undefined>());
|
||||
readonly onProcessExit = this._onProcessExit.event;
|
||||
private readonly _onRestoreCommands = this._register(new Emitter<ISerializedCommand[]>());
|
||||
readonly onRestoreCommands = this._onRestoreCommands.event;
|
||||
|
||||
constructor(
|
||||
readonly id: number,
|
||||
|
@ -139,6 +141,10 @@ export class LocalPty extends Disposable implements ITerminalChildProcess {
|
|||
this._inReplay = false;
|
||||
}
|
||||
|
||||
if (e.commands.length > 0) {
|
||||
this._onRestoreCommands.fire(e.commands);
|
||||
}
|
||||
|
||||
// remove size override
|
||||
this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: undefined });
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
import { deepStrictEqual, ok } from 'assert';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { Terminal } from 'xterm';
|
||||
import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability';
|
||||
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
async function writeP(terminal: Terminal, data: string): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { deepStrictEqual } from 'assert';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability';
|
||||
import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/partialCommandDetectionCapability';
|
||||
import { IMarker, Terminal } from 'xterm';
|
||||
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
|
||||
|
||||
|
@ -43,11 +43,11 @@ suite('PartialCommandDetectionCapability', () => {
|
|||
|
||||
test('should not add commands when the cursor position is too close to the left side', async () => {
|
||||
assertCommands([]);
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
xterm._core._onData.fire('\x0d');
|
||||
await writeP(xterm, '\r\n');
|
||||
assertCommands([]);
|
||||
await writeP(xterm, 'a');
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
xterm._core._onData.fire('\x0d');
|
||||
await writeP(xterm, '\r\n');
|
||||
assertCommands([]);
|
||||
});
|
||||
|
@ -55,11 +55,11 @@ suite('PartialCommandDetectionCapability', () => {
|
|||
test('should add commands when the cursor position is not too close to the left side', async () => {
|
||||
assertCommands([]);
|
||||
await writeP(xterm, 'ab');
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
xterm._core._onData.fire('\x0d');
|
||||
await writeP(xterm, '\r\n\r\n');
|
||||
assertCommands([0]);
|
||||
await writeP(xterm, 'cd');
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
xterm._core._onData.fire('\x0d');
|
||||
await writeP(xterm, '\r\n');
|
||||
assertCommands([0, 2]);
|
||||
});
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { deepStrictEqual } from 'assert';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore, TerminalCapabilityStoreMultiplexer } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore, TerminalCapabilityStoreMultiplexer } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
|
||||
suite('TerminalCapabilityStore', () => {
|
||||
let store: TerminalCapabilityStore;
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
|||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IDetectedLinks, TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
|
||||
import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { ITerminalConfiguration, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TestViewDescriptorService } from 'vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test';
|
||||
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
|
|
|
@ -14,11 +14,11 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
|
|||
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability';
|
||||
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
|
||||
import { TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links';
|
||||
import { TerminalLocalFileLinkOpener, TerminalLocalFolderInWorkspaceLinkOpener, TerminalSearchLinkOpener } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners';
|
||||
import { TerminalCapability, ITerminalCommand, IXtermMarker } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapability, ITerminalCommand, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
|
|||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ITerminalSimpleLink, TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links';
|
||||
import { TerminalLocalLinkDetector } from 'vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { assertLinkHelper, resolveLinkForTest } from 'vs/workbench/contrib/terminal/test/browser/links/linkTestUtils';
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ import { CommandTrackerAddon } from 'vs/workbench/contrib/terminal/browser/xterm
|
|||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/partialCommandDetectionCapability';
|
||||
import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
|
||||
interface TestTerminal extends Terminal {
|
||||
_core: IXtermCore;
|
||||
|
@ -62,13 +62,13 @@ suite('Workbench - TerminalCommandTracker', function () {
|
|||
test('should track commands when the prompt is of sufficient size', async () => {
|
||||
assert.strictEqual(xterm.markers.length, 0);
|
||||
await writeP(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
xterm._core._onData.fire('\x0d');
|
||||
assert.strictEqual(xterm.markers.length, 1);
|
||||
});
|
||||
test('should not track commands when the prompt is too small', async () => {
|
||||
assert.strictEqual(xterm.markers.length, 0);
|
||||
await writeP(xterm, '\x1b[2G'); // Move cursor to column 2
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
xterm._core._onData.fire('\x0d');
|
||||
assert.strictEqual(xterm.markers.length, 0);
|
||||
});
|
||||
});
|
||||
|
@ -85,7 +85,7 @@ suite('Workbench - TerminalCommandTracker', function () {
|
|||
});
|
||||
test('should scroll to the next and previous commands', async () => {
|
||||
await writeP(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line #10
|
||||
xterm._core._onData.fire('\x0d'); // Mark line #10
|
||||
assert.strictEqual(xterm.markers[0].line, 9);
|
||||
|
||||
await writeP(xterm, `\r\n`.repeat(20));
|
||||
|
@ -114,13 +114,13 @@ suite('Workbench - TerminalCommandTracker', function () {
|
|||
'\n\r1' +
|
||||
'\x1b[3G' // Move cursor to column 3
|
||||
);
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
xterm._core._onData.fire('\x0d'); // Mark line
|
||||
assert.strictEqual(xterm.markers[0].line, 10);
|
||||
await writeP(xterm,
|
||||
'\n\r2' +
|
||||
'\x1b[3G' // Move cursor to column 3
|
||||
);
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
xterm._core._onData.fire('\x0d'); // Mark line
|
||||
assert.strictEqual(xterm.markers[1].line, 11);
|
||||
await writeP(xterm, '\n\r3');
|
||||
|
||||
|
@ -143,13 +143,13 @@ suite('Workbench - TerminalCommandTracker', function () {
|
|||
'\n\r1' +
|
||||
'\x1b[3G' // Move cursor to column 3
|
||||
);
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
xterm._core._onData.fire('\x0d'); // Mark line
|
||||
assert.strictEqual(xterm.markers[0].line, 10);
|
||||
await writeP(xterm,
|
||||
'\n\r2' +
|
||||
'\x1b[3G' // Move cursor to column 3
|
||||
);
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
xterm._core._onData.fire('\x0d'); // Mark line
|
||||
assert.strictEqual(xterm.markers[1].line, 11);
|
||||
await writeP(xterm, '\n\r3');
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/termina
|
|||
import { ProcessState } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
function createInstance(partial?: Partial<ITerminalInstance>): Pick<ITerminalInstance, 'shellLaunchConfig' | 'userHome' | 'cwd' | 'initialCwd' | 'processName' | 'sequence' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'> {
|
||||
|
|
|
@ -8,12 +8,12 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IDecoration, IDecorationOptions, Terminal } from 'xterm';
|
||||
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability';
|
||||
import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import { Terminal } from 'xterm';
|
|||
import { strictEqual } from 'assert';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import * as sinon from 'sinon';
|
||||
import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
|
||||
import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon';
|
||||
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
|||
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { isSafari } from 'vs/base/browser/browser';
|
||||
import { TerminalLocation } from 'vs/platform/terminal/common/terminal';
|
||||
import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
|
||||
|
||||
|
|
Loading…
Reference in a new issue