Skip to content

Commit

Permalink
Ensure shell integration is enables for custom keys
Browse files Browse the repository at this point in the history
Fixes #45705
  • Loading branch information
Tyriar committed Jul 10, 2022
1 parent 5bb939a commit be10e63
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 13 deletions.
15 changes: 14 additions & 1 deletion src/vs/platform/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,19 @@ export type ITerminalProfileObject = ITerminalExecutable | ITerminalProfileSourc
export type ITerminalProfileType = ITerminalProfile | IExtensionTerminalProfile;

export interface IShellIntegration {
capabilities: ITerminalCapabilityStore;
readonly capabilities: ITerminalCapabilityStore;
readonly status: ShellIntegrationStatus;

readonly onDidChangeStatus: Event<ShellIntegrationStatus>;

deserialize(serialized: ISerializedCommandDetectionCapability): void;
}

export const enum ShellIntegrationStatus {
/** No shell integration sequences have been encountered. */
Off,
/** Final term shell integration sequences have been encountered. */
FinalTerm,
/** VS Code shell integration sequences have been encountered. Supercedes FinalTerm. */
VSCode
}
22 changes: 21 additions & 1 deletion src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IShellIntegration } from 'vs/platform/terminal/common/terminal';
import { IShellIntegration, ShellIntegrationStatus } from 'vs/platform/terminal/common/terminal';
import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
Expand All @@ -16,6 +16,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import type { ITerminalAddon, Terminal } from 'xterm-headless';
import { ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/terminalProcess';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Emitter } from 'vs/base/common/event';

/**
* Shell integration is a feature that enhances the terminal's understanding of what's happening
Expand Down Expand Up @@ -137,6 +138,12 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
private _hasUpdatedTelemetry: boolean = false;
private _activationTimeout: any;
private _commonProtocolDisposables: IDisposable[] = [];
private _status: ShellIntegrationStatus = ShellIntegrationStatus.Off;

get status(): ShellIntegrationStatus { return this._status; }

private readonly _onDidChangeStatus = new Emitter<ShellIntegrationStatus>();
readonly onDidChangeStatus = this._onDidChangeStatus.event;

constructor(
private readonly _disableTelemetry: boolean | undefined,
Expand Down Expand Up @@ -167,6 +174,15 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
}

private _handleFinalTermSequence(data: string): boolean {
const didHandle = this._doHandleFinalTermSequence(data);
if (this._status === ShellIntegrationStatus.Off) {
this._status = ShellIntegrationStatus.FinalTerm;
this._onDidChangeStatus.fire(this._status);
}
return didHandle;
}

private _doHandleFinalTermSequence(data: string): boolean {
if (!this._terminal) {
return false;
}
Expand Down Expand Up @@ -204,6 +220,10 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
this._hasUpdatedTelemetry = true;
this._clearActivationTimeout();
}
if (this._status !== ShellIntegrationStatus.VSCode) {
this._status = ShellIntegrationStatus.VSCode;
this._onDidChangeStatus.fire(this._status);
}
return didHandle;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,21 +181,21 @@ if (isWindows) {
// Map certain keybindings in pwsh to unused keys which get handled by PSReadLine handlers in the
// shell integration script. This allows keystrokes that cannot be sent via VT sequences to work.
// See https://github.com/microsoft/terminal/issues/879#issuecomment-497775007
registerSendSequenceKeybinding('\x1b[24~a', { // F12,a -> ctrl+space
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
registerSendSequenceKeybinding('\x1b[24~a', { // F12,a -> ctrl+space (MenuComplete)
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
primary: KeyMod.CtrlCmd | KeyCode.Space,
mac: { primary: KeyMod.WinCtrl | KeyCode.Space }
});
registerSendSequenceKeybinding('\x1b[24~b', { // F12,b -> alt+space
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
registerSendSequenceKeybinding('\x1b[24~b', { // F12,b -> alt+space (SetMark)
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
primary: KeyMod.Alt | KeyCode.Space
});
registerSendSequenceKeybinding('\x1b[24~c', { // F12,c -> shift+enter
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
registerSendSequenceKeybinding('\x1b[24~c', { // F12,c -> shift+enter (AddLine)
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
primary: KeyMod.Shift | KeyCode.Enter
});
registerSendSequenceKeybinding('\x1b[24~d', { // F12,d -> shift+end - \x1b[1;2F is supposed to work but it doesn't
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell)),
registerSendSequenceKeybinding('\x1b[24~d', { // F12,d -> shift+end (SelectLine) - HACK: \x1b[1;2F is supposed to work but it doesn't
when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()),
mac: { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.RightArrow }
});

Expand Down
28 changes: 25 additions & 3 deletions src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
import { TerminalCapabilityStoreMultiplexer } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
import { IProcessDataEvent, IProcessPropertyMap, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, PosixShellType, ProcessPropertyType, TerminalIcon, TerminalLocation, TerminalSettingId, TerminalShellType, TitleEventSource, WindowsShellType } from 'vs/platform/terminal/common/terminal';
import { IProcessDataEvent, IProcessPropertyMap, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, PosixShellType, ProcessPropertyType, ShellIntegrationStatus, TerminalIcon, TerminalLocation, TerminalSettingId, TerminalShellType, TitleEventSource, WindowsShellType } from 'vs/platform/terminal/common/terminal';
import { escapeNonWindowsPath, collapseTildePath } from 'vs/platform/terminal/common/terminalEnvironment';
import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry';
import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
Expand Down Expand Up @@ -356,6 +356,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
private readonly _terminalShellTypeContextKey: IContextKey<string>,
private readonly _terminalAltBufferActiveContextKey: IContextKey<boolean>,
private readonly _terminalInRunCommandPicker: IContextKey<boolean>,
private readonly _terminalShellIntegrationEnabledContextKey: IContextKey<boolean>,
private readonly _configHelper: TerminalConfigHelper,
private _shellLaunchConfig: IShellLaunchConfig,
resource: URI | undefined,
Expand Down Expand Up @@ -1083,6 +1084,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
const screenElement = xterm.attachToElement(xtermElement);

xterm.onDidChangeFindResults((results) => this._onDidChangeFindResults.fire(results));
xterm.shellIntegration.onDidChangeStatus(() => {
if (this.hasFocus) {
this._setShellIntegrationContextKey();
} else {
this._terminalShellIntegrationEnabledContextKey.reset();
}
});

if (!xterm.raw.element || !xterm.raw.textarea) {
throw new Error('xterm elements not set after open');
Expand Down Expand Up @@ -1216,16 +1224,25 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
private _setFocus(focused?: boolean): void {
if (focused) {
this._terminalFocusContextKey.set(true);
this._setShellIntegrationContextKey();
this._onDidFocus.fire(this);
} else {
this._terminalFocusContextKey.reset();
this.resetFocusContextKey();
this._onDidBlur.fire(this);
this._refreshSelectionContextKey();
}
}

private _setShellIntegrationContextKey(): void {
console.log('set', this.xterm?.shellIntegration.status === ShellIntegrationStatus.VSCode);
if (this.xterm) {
this._terminalShellIntegrationEnabledContextKey.set(this.xterm.shellIntegration.status === ShellIntegrationStatus.VSCode);
}
}

resetFocusContextKey(): void {
this._terminalFocusContextKey.reset();
this._terminalShellIntegrationEnabledContextKey.reset();
}

private _initDragAndDrop(container: HTMLElement) {
Expand Down Expand Up @@ -1301,6 +1318,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}
const terminalFocused = !isFocused && (document.activeElement === this.xterm.raw.textarea || document.activeElement === this.xterm.raw.element);
this._terminalFocusContextKey.set(terminalFocused);
if (terminalFocused) {
this._setShellIntegrationContextKey();
} else {
this._terminalShellIntegrationEnabledContextKey.reset();
}
}

private _refreshAltBufferContextKey() {
Expand Down Expand Up @@ -1381,7 +1403,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
// as 'blur' event in xterm.raw.textarea is not triggered on xterm.dispose()
// See https://github.com/microsoft/vscode/issues/138358
if (isFirefox) {
this._terminalFocusContextKey.reset();
this.resetFocusContextKey();
this._terminalHasTextContextKey.reset();
this._onDidBlur.fire(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
private _terminalShellTypeContextKey: IContextKey<string>;
private _terminalAltBufferActiveContextKey: IContextKey<boolean>;
private _terminalInRunCommandPicker: IContextKey<boolean>;
private _terminalShellIntegrationEnabled: IContextKey<boolean>;
private _configHelper: TerminalConfigHelper;

private readonly _onDidCreateInstance = new Emitter<ITerminalInstance>();
Expand All @@ -39,6 +40,7 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
this._terminalShellTypeContextKey = TerminalContextKeys.shellType.bindTo(this._contextKeyService);
this._terminalAltBufferActiveContextKey = TerminalContextKeys.altBufferActive.bindTo(this._contextKeyService);
this._terminalInRunCommandPicker = TerminalContextKeys.inTerminalRunCommandPicker.bindTo(this._contextKeyService);
this._terminalShellIntegrationEnabled = TerminalContextKeys.terminalShellIntegrationEnabled.bindTo(this._contextKeyService);
this._configHelper = _instantiationService.createInstance(TerminalConfigHelper);
}

Expand All @@ -52,6 +54,7 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
this._terminalShellTypeContextKey,
this._terminalAltBufferActiveContextKey,
this._terminalInRunCommandPicker,
this._terminalShellIntegrationEnabled,
this._configHelper,
shellLaunchConfig,
resource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const enum TerminalContextKeyStrings {
SplitTerminal = 'terminalSplitTerminal',
ShellType = 'terminalShellType',
InTerminalRunCommandPicker = 'inTerminalRunCommandPicker',
TerminalShellIntegrationEnabled = 'terminalShellIntegrationEnabled'
}

export namespace TerminalContextKeys {
Expand Down Expand Up @@ -123,4 +124,7 @@ export namespace TerminalContextKeys {

/** Whether the terminal run command picker is currently open. */
export const inTerminalRunCommandPicker = new RawContextKey<boolean>(TerminalContextKeyStrings.InTerminalRunCommandPicker, false, localize('inTerminalRunCommandPickerContextKey', "Whether the terminal run command picker is currently open."));

/** Whether shell integration is enabled in the active terminal. This only considers full VS Code shell integration. */
export const terminalShellIntegrationEnabled = new RawContextKey<boolean>(TerminalContextKeyStrings.TerminalShellIntegrationEnabled, false, localize('terminalShellIntegrationEnabled', "Whether shell integration is enabled in the active terminal"));
}

0 comments on commit be10e63

Please sign in to comment.