Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3 (#6516)

* Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3

* fix tests
This commit is contained in:
Anthony Dresser
2019-07-28 15:15:24 -07:00
committed by GitHub
parent aacf1e7f1c
commit 1d56a17f32
292 changed files with 19784 additions and 1873 deletions

View File

@@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { Terminal, ITerminalAddon } from 'xterm';
import { addDisposableListener } from 'vs/base/browser/dom';
import { INavigationMode } from 'vs/workbench/contrib/terminal/common/terminal';
export class NavigationModeAddon implements INavigationMode, ITerminalAddon {
private _terminal: Terminal;
constructor(
private _navigationModeContextKey: IContextKey<boolean>
) { }
activate(terminal: Terminal): void {
this._terminal = terminal;
}
dispose() { }
exitNavigationMode(): void {
this._terminal.scrollToBottom();
this._terminal.focus();
}
focusPreviousLine(): void {
// Focus previous row if a row is already focused
if (document.activeElement && document.activeElement.parentElement && document.activeElement.parentElement.classList.contains('xterm-accessibility-tree')) {
const element = <HTMLElement | null>document.activeElement.previousElementSibling;
if (element) {
element.focus();
const disposable = addDisposableListener(element, 'blur', () => {
this._navigationModeContextKey.set(false);
disposable.dispose();
});
this._navigationModeContextKey.set(true);
}
return;
}
// Ensure a11y tree exists
const treeContainer = this._terminal.element.querySelector('.xterm-accessibility-tree');
if (!treeContainer) {
return;
}
// Target is row before the cursor
const targetRow = Math.max(this._terminal.buffer.cursorY - 1, 0);
// Check bounds
if (treeContainer.childElementCount < targetRow) {
return;
}
// Focus
const element = <HTMLElement>treeContainer.childNodes.item(targetRow);
element.focus();
const disposable = addDisposableListener(element, 'blur', () => {
this._navigationModeContextKey.set(false);
disposable.dispose();
});
this._navigationModeContextKey.set(true);
}
focusNextLine(): void {
// Focus previous row if a row is already focused
if (document.activeElement && document.activeElement.parentElement && document.activeElement.parentElement.classList.contains('xterm-accessibility-tree')) {
const element = <HTMLElement | null>document.activeElement.nextElementSibling;
if (element) {
element.focus();
const disposable = addDisposableListener(element, 'blur', () => {
this._navigationModeContextKey.set(false);
disposable.dispose();
});
this._navigationModeContextKey.set(true);
}
return;
}
// Ensure a11y tree exists
const treeContainer = this._terminal.element.querySelector('.xterm-accessibility-tree');
if (!treeContainer) {
return;
}
// Target is cursor row
const targetRow = this._terminal.buffer.cursorY;
// Check bounds
if (treeContainer.childElementCount < targetRow) {
return;
}
// Focus row before cursor
const element = <HTMLElement>treeContainer.childNodes.item(targetRow);
element.focus();
const disposable = addDisposableListener(element, 'blur', () => {
this._navigationModeContextKey.set(false);
disposable.dispose();
});
this._navigationModeContextKey.set(true);
}
}

View File

@@ -20,10 +20,10 @@ import * as panel from 'vs/workbench/browser/panel';
import { getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
import { Extensions as QuickOpenExtensions, IQuickOpenRegistry, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
import { AllowWorkspaceShellTerminalCommand, ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, DeleteToLineStartTerminalAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, DisallowWorkspaceShellTerminalCommand, FindNext, FindPrevious, FocusActiveTerminalAction, FocusNextPaneTerminalAction, FocusNextTerminalAction, FocusPreviousPaneTerminalAction, FocusPreviousTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, KillTerminalAction, MoveToLineEndTerminalAction, MoveToLineStartTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, RenameTerminalAction, ResizePaneDownTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, RunActiveFileInTerminalAction, RunSelectedTextInTerminalAction, ScrollDownPageTerminalAction, ScrollDownTerminalAction, ScrollToBottomTerminalAction, ScrollToNextCommandAction, ScrollToPreviousCommandAction, ScrollToTopTerminalAction, ScrollUpPageTerminalAction, ScrollUpTerminalAction, SelectAllTerminalAction, SelectDefaultShellWindowsTerminalAction, SelectToNextCommandAction, SelectToNextLineAction, SelectToPreviousCommandAction, SelectToPreviousLineAction, SendSequenceTerminalCommand, SplitInActiveWorkspaceTerminalAction, SplitTerminalAction, TerminalPasteAction, TERMINAL_PICKER_PREFIX, ToggleCaseSensitiveCommand, ToggleEscapeSequenceLoggingAction, ToggleRegexCommand, ToggleTerminalAction, ToggleWholeWordCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { AllowWorkspaceShellTerminalCommand, ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, DeleteToLineStartTerminalAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, DisallowWorkspaceShellTerminalCommand, FindNext, FindPrevious, FocusActiveTerminalAction, FocusNextPaneTerminalAction, FocusNextTerminalAction, FocusPreviousPaneTerminalAction, FocusPreviousTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, KillTerminalAction, MoveToLineEndTerminalAction, MoveToLineStartTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, RenameTerminalAction, ResizePaneDownTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, RunActiveFileInTerminalAction, RunSelectedTextInTerminalAction, ScrollDownPageTerminalAction, ScrollDownTerminalAction, ScrollToBottomTerminalAction, ScrollToNextCommandAction, ScrollToPreviousCommandAction, ScrollToTopTerminalAction, ScrollUpPageTerminalAction, ScrollUpTerminalAction, SelectAllTerminalAction, SelectDefaultShellWindowsTerminalAction, SelectToNextCommandAction, SelectToNextLineAction, SelectToPreviousCommandAction, SelectToPreviousLineAction, SendSequenceTerminalCommand, SplitInActiveWorkspaceTerminalAction, SplitTerminalAction, TerminalPasteAction, TERMINAL_PICKER_PREFIX, ToggleCaseSensitiveCommand, ToggleEscapeSequenceLoggingAction, ToggleRegexCommand, ToggleTerminalAction, ToggleWholeWordCommand, NavigationModeFocusPreviousTerminalAction, NavigationModeFocusNextTerminalAction, NavigationModeExitTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel';
import { TerminalPickerHandler } from 'vs/workbench/contrib/terminal/browser/terminalQuickOpen';
import { KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, ITerminalService, TERMINAL_ACTION_CATEGORY } from 'vs/workbench/contrib/terminal/common/terminal';
import { KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, ITerminalService, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS } from 'vs/workbench/contrib/terminal/common/terminal';
import { registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands';
import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu';
@@ -33,6 +33,7 @@ import { DEFAULT_COMMANDS_TO_SKIP_SHELL } from 'vs/workbench/contrib/terminal/br
import { TerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { registerShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalShellConfig';
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
registerSingleton(ITerminalService, TerminalService, true);
@@ -459,6 +460,21 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextComm
primary: 0,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow }
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Next Command', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigationModeExitTerminalAction, NavigationModeExitTerminalAction.ID, NavigationModeExitTerminalAction.LABEL, {
primary: KeyCode.Escape
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Exit Navigation Mode', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigationModeFocusPreviousTerminalAction, NavigationModeFocusPreviousTerminalAction.ID, NavigationModeFocusPreviousTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.UpArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Previous Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigationModeFocusPreviousTerminalAction, NavigationModeFocusPreviousTerminalAction.ID, NavigationModeFocusPreviousTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.UpArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Previous Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigationModeFocusNextTerminalAction, NavigationModeFocusNextTerminalAction.ID, NavigationModeFocusNextTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.DownArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Next Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigationModeFocusNextTerminalAction, NavigationModeFocusNextTerminalAction.ID, NavigationModeFocusNextTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.DownArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Next Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousLineAction, SelectToPreviousLineAction.ID, SelectToPreviousLineAction.LABEL), 'Terminal: Select To Previous Line', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextLineAction, SelectToNextLineAction.ID, SelectToNextLineAction.LABEL), 'Terminal: Select To Next Line', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEscapeSequenceLoggingAction, ToggleEscapeSequenceLoggingAction.ID, ToggleEscapeSequenceLoggingAction.LABEL), 'Terminal: Toggle Escape Sequence Logging', category);

View File

@@ -607,12 +607,11 @@ export class TerminalPasteAction extends Action {
super(id, label);
}
public run(event?: any): Promise<any> {
public async run(event?: any): Promise<any> {
const instance = this.terminalService.getActiveOrCreateInstance();
if (instance) {
instance.paste();
await instance.paste();
}
return Promise.resolve(undefined);
}
}
@@ -749,6 +748,7 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem {
this._register(terminalService.onInstancesChanged(this._updateItems, this));
this._register(terminalService.onActiveTabChanged(this._updateItems, this));
this._register(terminalService.onInstanceTitleChanged(this._updateItems, this));
this._register(terminalService.onTabDisposed(this._updateItems, this));
this._register(attachSelectBoxStyler(this.selectBox, themeService));
}
@@ -886,6 +886,71 @@ export class ScrollToTopTerminalAction extends Action {
}
}
export class NavigationModeExitTerminalAction extends Action {
public static readonly ID = TERMINAL_COMMAND_ID.NAVIGATION_MODE_EXIT;
public static readonly LABEL = nls.localize('workbench.action.terminal.navigationModeExit', "Exit Navigation Mode");
constructor(
id: string, label: string,
@ITerminalService private readonly terminalService: ITerminalService
) {
super(id, label);
}
public run(event?: any): Promise<any> {
const terminalInstance = this.terminalService.getActiveInstance();
if (terminalInstance && terminalInstance.navigationMode) {
terminalInstance.navigationMode.exitNavigationMode();
}
return Promise.resolve(undefined);
}
}
export class NavigationModeFocusPreviousTerminalAction extends Action {
public static readonly ID = TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_PREVIOUS;
public static readonly LABEL = nls.localize('workbench.action.terminal.navigationModeFocusPrevious', "Focus Previous Line (Navigation Mode)");
constructor(
id: string, label: string,
@ITerminalService private readonly terminalService: ITerminalService
) {
super(id, label);
}
public run(event?: any): Promise<any> {
const terminalInstance = this.terminalService.getActiveInstance();
if (terminalInstance && terminalInstance.navigationMode) {
terminalInstance.navigationMode.focusPreviousLine();
}
return Promise.resolve(undefined);
}
}
export class NavigationModeFocusNextTerminalAction extends Action {
public static readonly ID = TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_NEXT;
public static readonly LABEL = nls.localize('workbench.action.terminal.navigationModeFocusNext', "Focus Next Line (Navigation Mode)");
constructor(
id: string, label: string,
@ITerminalService private readonly terminalService: ITerminalService
) {
super(id, label);
}
public run(event?: any): Promise<any> {
const terminalInstance = this.terminalService.getActiveInstance();
if (terminalInstance && terminalInstance.navigationMode) {
terminalInstance.navigationMode.focusNextLine();
}
return Promise.resolve(undefined);
}
}
export class ClearTerminalAction extends Action {
public static readonly ID = TERMINAL_COMMAND_ID.CLEAR;

View File

@@ -19,7 +19,7 @@ export class TerminalFindWidget extends SimpleFindWidget {
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@ITerminalService private readonly _terminalService: ITerminalService
) {
super(_contextViewService, _contextKeyService, findState, true);
super(_contextViewService, _contextKeyService, findState, true, true);
this._register(findState.onFindReplaceStateChange(() => {
this.show();
}));
@@ -50,7 +50,7 @@ export class TerminalFindWidget extends SimpleFindWidget {
// Ignore input changes for now
const instance = this._terminalService.getActiveInstance();
if (instance !== null) {
return instance.findNext(this.inputValue, { regex: this._getRegexValue(), wholeWord: this._getWholeWordValue(), caseSensitive: this._getCaseSensitiveValue(), incremental: true });
return instance.findPrevious(this.inputValue, { regex: this._getRegexValue(), wholeWord: this._getWholeWordValue(), caseSensitive: this._getCaseSensitiveValue(), incremental: true });
}
return false;
}
@@ -78,4 +78,4 @@ export class TerminalFindWidget extends SimpleFindWidget {
protected onFindInputFocusTrackerBlur() {
this._findInputFocused.reset();
}
}
}

View File

@@ -25,7 +25,7 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { PANEL_BACKGROUND } from 'vs/workbench/common/theme';
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/terminalWidgetManager';
import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID, IWindowsShellHelper, SHELL_PATH_INVALID_EXIT_CODE, SHELL_PATH_DIRECTORY_EXIT_CODE, SHELL_CWD_INVALID_EXIT_CODE } from 'vs/workbench/contrib/terminal/common/terminal';
import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID, IWindowsShellHelper, SHELL_PATH_INVALID_EXIT_CODE, SHELL_PATH_DIRECTORY_EXIT_CODE, SHELL_CWD_INVALID_EXIT_CODE, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode } from 'vs/workbench/contrib/terminal/common/terminal';
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
@@ -35,8 +35,9 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager';
import { Terminal as XTermTerminal, IBuffer } from 'xterm';
import { Terminal as XTermTerminal, IBuffer, ITerminalAddon } from 'xterm';
import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/addons/navigationModeAddon';
// How long in milliseconds should an average frame take to render for a notification to appear
// which suggests the fallback DOM-based renderer
@@ -91,6 +92,9 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
TERMINAL_COMMAND_ID.SPLIT_IN_ACTIVE_WORKSPACE,
TERMINAL_COMMAND_ID.SPLIT,
TERMINAL_COMMAND_ID.TOGGLE,
TERMINAL_COMMAND_ID.NAVIGATION_MODE_EXIT,
TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_NEXT,
TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_PREVIOUS,
'editor.action.toggleTabFocusMode',
'workbench.action.quickOpen',
'workbench.action.quickOpenPreviousEditor',
@@ -183,6 +187,7 @@ export class TerminalInstance implements ITerminalInstance {
private _xtermSearch: SearchAddon | undefined;
private _xtermElement: HTMLDivElement;
private _terminalHasTextContextKey: IContextKey<boolean>;
private _terminalA11yTreeFocusContextKey: IContextKey<boolean>;
private _cols: number;
private _rows: number;
private _dimensionsOverride: ITerminalDimensions | undefined;
@@ -197,6 +202,7 @@ export class TerminalInstance implements ITerminalInstance {
private _widgetManager: TerminalWidgetManager;
private _linkHandler: TerminalLinkHandler;
private _commandTracker: TerminalCommandTracker;
private _navigationModeAddon: INavigationMode & ITerminalAddon | undefined;
public disableLayout: boolean;
public get id(): number { return this._id; }
@@ -224,6 +230,7 @@ export class TerminalInstance implements ITerminalInstance {
public get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable; }
public get shellLaunchConfig(): IShellLaunchConfig { return this._shellLaunchConfig; }
public get commandTracker(): TerminalCommandTracker { return this._commandTracker; }
public get navigationMode(): INavigationMode | undefined { return this._navigationModeAddon; }
private readonly _onExit = new Emitter<number>();
public get onExit(): Event<number> { return this._onExit.event; }
@@ -280,6 +287,7 @@ export class TerminalInstance implements ITerminalInstance {
});
this._terminalHasTextContextKey = KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED.bindTo(this._contextKeyService);
this._terminalA11yTreeFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS.bindTo(this._contextKeyService);
this.disableLayout = false;
this._logService.trace(`terminalInstance#ctor (id: ${this.id})`, this._shellLaunchConfig);
@@ -462,13 +470,13 @@ export class TerminalInstance implements ITerminalInstance {
letterSpacing: font.letterSpacing,
lineHeight: font.lineHeight,
bellStyle: config.enableBell ? 'sound' : 'none',
screenReaderMode: this._isScreenReaderOptimized(),
macOptionIsMeta: config.macOptionIsMeta,
macOptionClickForcesSelection: config.macOptionClickForcesSelection,
rightClickSelectsWord: config.rightClickBehavior === 'selectWord',
// TODO: Guess whether to use canvas or dom better
rendererType: config.rendererType === 'auto' ? 'canvas' : config.rendererType
});
this.updateAccessibilitySupport();
this._terminalInstanceService.getXtermSearchConstructor().then(Addon => {
this._xtermSearch = new Addon();
this._xterm.loadAddon(this._xtermSearch);
@@ -861,9 +869,9 @@ export class TerminalInstance implements ITerminalInstance {
return this._xtermReadyPromise.then(() => this.focus(force));
}
public paste(): void {
public async paste(): Promise<void> {
this.focus();
document.execCommand('paste');
this._xterm._core._coreService.triggerDataEvent(await this._clipboardService.readText(), true);
}
public write(text: string): void {
@@ -958,7 +966,6 @@ export class TerminalInstance implements ITerminalInstance {
private _refreshSelectionContextKey() {
const activePanel = this._panelService.getActivePanel();
const isActive = !!activePanel && activePanel.getId() === TERMINAL_PANEL_ID;
this._terminalHasTextContextKey.set(isActive && this.hasSelection());
}
@@ -968,6 +975,7 @@ export class TerminalInstance implements ITerminalInstance {
this._processManager.onProcessExit(exitCode => this._onProcessExit(exitCode));
this._processManager.onProcessData(data => this._onData.fire(data));
this._processManager.onProcessOverrideDimensions(e => this.setDimensions(e));
this._processManager.onProcessResolvedShellLaunchConfig(e => this._setResolvedShellLaunchConfig(e));
if (this._shellLaunchConfig.name) {
this.setTitle(this._shellLaunchConfig.name, false);
@@ -1223,7 +1231,17 @@ export class TerminalInstance implements ITerminalInstance {
}
public updateAccessibilitySupport(): void {
this._xterm.setOption('screenReaderMode', this._isScreenReaderOptimized());
const isEnabled = this._isScreenReaderOptimized();
if (isEnabled) {
this._navigationModeAddon = new NavigationModeAddon(this._terminalA11yTreeFocusContextKey);
this._xterm.loadAddon(this._navigationModeAddon);
} else {
if (this._navigationModeAddon) {
this._navigationModeAddon.dispose();
this._navigationModeAddon = undefined;
}
}
this._xterm.setOption('screenReaderMode', isEnabled);
}
private _setCursorBlink(blink: boolean): void {
@@ -1379,6 +1397,13 @@ export class TerminalInstance implements ITerminalInstance {
this._resize();
}
private _setResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void {
this._shellLaunchConfig.args = shellLaunchConfig.args;
this._shellLaunchConfig.cwd = shellLaunchConfig.cwd;
this._shellLaunchConfig.executable = shellLaunchConfig.executable;
this._shellLaunchConfig.env = shellLaunchConfig.env;
}
private _getXtermTheme(theme?: ITheme): any {
if (!theme) {
theme = this._themeService.getTheme();
@@ -1420,8 +1445,7 @@ export class TerminalInstance implements ITerminalInstance {
}
public toggleEscapeSequenceLogging(): void {
this._xterm._core.debug = !this._xterm._core.debug;
this._xterm.setOption('debug', this._xterm._core.debug);
this._xterm.setOption('logLevel', 'debug');
}
public getInitialCwd(): Promise<string> {

View File

@@ -31,7 +31,7 @@ const LATENCY_MEASURING_INTERVAL = 1000;
enum ProcessType {
Process,
VirtualProcess
ExtensionTerminal
}
/**
@@ -70,6 +70,8 @@ export class TerminalProcessManager implements ITerminalProcessManager {
public get onProcessExit(): Event<number> { return this._onProcessExit.event; }
private readonly _onProcessOverrideDimensions = new Emitter<ITerminalDimensions | undefined>();
public get onProcessOverrideDimensions(): Event<ITerminalDimensions | undefined> { return this._onProcessOverrideDimensions.event; }
private readonly _onProcessOverrideShellLaunchConfig = new Emitter<IShellLaunchConfig>();
public get onProcessResolvedShellLaunchConfig(): Event<IShellLaunchConfig> { return this._onProcessOverrideShellLaunchConfig.event; }
constructor(
private readonly _terminalId: number,
@@ -111,8 +113,8 @@ export class TerminalProcessManager implements ITerminalProcessManager {
rows: number,
isScreenReaderModeEnabled: boolean
): Promise<void> {
if (shellLaunchConfig.isVirtualProcess) {
this._processType = ProcessType.VirtualProcess;
if (shellLaunchConfig.isExtensionTerminal) {
this._processType = ProcessType.ExtensionTerminal;
this._process = this._instantiationService.createInstance(TerminalProcessExtHostProxy, this._terminalId, shellLaunchConfig, undefined, cols, rows, this._configHelper);
} else {
const forceExtHostProcess = (this._configHelper.config as any).extHostProcess;
@@ -170,6 +172,9 @@ export class TerminalProcessManager implements ITerminalProcessManager {
if (this._process.onProcessOverrideDimensions) {
this._process.onProcessOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e));
}
if (this._process.onProcessResolvedShellLaunchConfig) {
this._process.onProcessResolvedShellLaunchConfig(e => this._onProcessOverrideShellLaunchConfig.fire(e));
}
setTimeout(() => {
if (this.processState === ProcessState.LAUNCHING) {
@@ -234,7 +239,7 @@ export class TerminalProcessManager implements ITerminalProcessManager {
}
public write(data: string): void {
if (this.shellProcessId || this._processType === ProcessType.VirtualProcess) {
if (this.shellProcessId || this._processType === ProcessType.ExtensionTerminal) {
if (this._process) {
// Send data if the pty is ready
this._process.input(data);
@@ -287,4 +292,4 @@ export class TerminalProcessManager implements ITerminalProcessManager {
this._onProcessExit.fire(exitCode);
}
}
}

View File

@@ -49,7 +49,7 @@ export class TerminalService extends CommonTerminalService implements ITerminalS
this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper, this.terminalNativeService.linuxDistro);
}
public createInstance(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance {
public createInstance(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance {
const instance = this._instantiationService.createInstance(TerminalInstance, terminalFocusContextKey, configHelper, container, shellLaunchConfig);
this._onInstanceCreated.fire(instance);
return instance;
@@ -60,8 +60,7 @@ export class TerminalService extends CommonTerminalService implements ITerminalS
const instance = this.createInstance(this._terminalFocusContextKey,
this.configHelper,
undefined,
shell,
true);
shell);
this._backgroundedTerminalInstances.push(instance);
this._initInstanceListeners(instance);
return instance;

View File

@@ -246,8 +246,7 @@ export class TerminalTab extends Disposable implements ITerminalTab {
terminalFocusContextKey,
configHelper,
undefined,
shellLaunchConfigOrInstance,
true);
shellLaunchConfigOrInstance);
}
this._terminalInstances.push(instance);
this._initInstanceListeners(instance);
@@ -389,8 +388,7 @@ export class TerminalTab extends Disposable implements ITerminalTab {
terminalFocusContextKey,
configHelper,
undefined,
shellLaunchConfig,
true);
shellLaunchConfig);
this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance);
this._initInstanceListeners(instance);
this._setActiveInstance(instance);

View File

@@ -21,6 +21,8 @@ export const KEYBINDING_CONTEXT_TERMINAL_IS_OPEN = new RawContextKey<boolean>('t
export const KEYBINDING_CONTEXT_TERMINAL_FOCUS = new RawContextKey<boolean>('terminalFocus', false);
/** A context key that is set when the integrated terminal does not have focus. */
export const KEYBINDING_CONTEXT_TERMINAL_NOT_FOCUSED: ContextKeyExpr = KEYBINDING_CONTEXT_TERMINAL_FOCUS.toNegated();
/** A context key that is set when the user is navigating the accessibility tree */
export const KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS = new RawContextKey<boolean>('terminalA11yTreeFocus', false);
/** A keybinding context key that is set when the integrated terminal has text selected. */
export const KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED = new RawContextKey<boolean>('terminalTextSelected', false);
@@ -186,14 +188,14 @@ export interface IShellLaunchConfig {
initialText?: string;
/**
* @deprecated use `isVirtualProcess`
* @deprecated use `isExtensionTerminal`
*/
isRendererOnly?: boolean;
/**
* When true an extension is acting as the terminal's process.
* Whether an extension is controlling the terminal via a `vscode.Pseudoterminal`.
*/
isVirtualProcess?: boolean;
isExtensionTerminal?: boolean;
/**
* Whether the terminal process environment should be exactly as provided in
@@ -229,8 +231,8 @@ export interface ITerminalService {
onInstanceProcessIdReady: Event<ITerminalInstance>;
onInstanceDimensionsChanged: Event<ITerminalInstance>;
onInstanceMaximumDimensionsChanged: Event<ITerminalInstance>;
onInstanceRequestExtHostProcess: Event<ITerminalProcessExtHostRequest>;
onInstanceRequestVirtualProcess: Event<ITerminalVirtualProcessRequest>;
onInstanceRequestSpawnExtHostProcess: Event<ISpawnExtHostProcessRequest>;
onInstanceRequestStartExtensionTerminal: Event<IStartExtensionTerminalRequest>;
onInstancesChanged: Event<void>;
onInstanceTitleChanged: Event<ITerminalInstance>;
onActiveInstanceChanged: Event<ITerminalInstance | undefined>;
@@ -251,7 +253,7 @@ export interface ITerminalService {
/**
* Creates a raw terminal instance, this should not be used outside of the terminal part.
*/
createInstance(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance;
createInstance(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance;
getInstanceFromId(terminalId: number): ITerminalInstance | undefined;
getInstanceFromIndex(terminalIndex: number): ITerminalInstance;
getTabLabels(): string[];
@@ -297,8 +299,8 @@ export interface ITerminalService {
preparePathForTerminalAsync(path: string, executable: string | undefined, title: string): Promise<string>;
extHostReady(remoteAuthority: string): void;
requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
requestVirtualProcess(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): void;
requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): void;
}
/**
@@ -483,6 +485,8 @@ export interface ITerminalInstance {
*/
readonly commandTracker: ITerminalCommandTracker;
readonly navigationMode: INavigationMode | undefined;
/**
* Dispose the terminal instance, removing it from the panel/service and freeing up resources.
*
@@ -584,7 +588,7 @@ export interface ITerminalInstance {
/**
* Focuses and pastes the contents of the clipboard into the terminal instance.
*/
paste(): void;
paste(): Promise<void>;
/**
* Send text to the terminal instance. The text is written to the stdin of the underlying pty
@@ -629,17 +633,6 @@ export interface ITerminalInstance {
*/
attachToElement(container: HTMLElement): void;
/**
* Updates the configuration of the terminal instance.
*/
updateConfig(): void;
/**
* Updates the accessibility support state of the terminal instance.
* @param isEnabled Whether it's enabled.
*/
updateAccessibilitySupport(isEnabled: boolean): void;
/**
* Configure the dimensions of the terminal instance.
*
@@ -687,6 +680,12 @@ export interface ITerminalCommandTracker {
selectToNextLine(): void;
}
export interface INavigationMode {
exitNavigationMode(): void;
focusPreviousLine(): void;
focusNextLine(): void;
}
export interface IBeforeProcessDataEvent {
/**
* The data of the event, this can be modified by the event listener to change what gets sent
@@ -709,6 +708,7 @@ export interface ITerminalProcessManager extends IDisposable {
readonly onProcessTitle: Event<string>;
readonly onProcessExit: Event<number>;
readonly onProcessOverrideDimensions: Event<ITerminalDimensions | undefined>;
readonly onProcessResolvedShellLaunchConfig: Event<IShellLaunchConfig>;
dispose(immediate?: boolean): void;
createProcess(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number, isScreenReaderModeEnabled: boolean): Promise<void>;
@@ -747,6 +747,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable {
emitReady(pid: number, cwd: string): void;
emitExit(exitCode: number): void;
emitOverrideDimensions(dimensions: ITerminalDimensions | undefined): void;
emitResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void;
emitInitialCwd(initialCwd: string): void;
emitCwd(cwd: string): void;
emitLatency(latency: number): void;
@@ -759,7 +760,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable {
onRequestLatency: Event<void>;
}
export interface ITerminalProcessExtHostRequest {
export interface ISpawnExtHostProcessRequest {
proxy: ITerminalProcessExtHostProxy;
shellLaunchConfig: IShellLaunchConfig;
activeWorkspaceRootUri: URI;
@@ -768,7 +769,7 @@ export interface ITerminalProcessExtHostRequest {
isWorkspaceShellAllowed: boolean;
}
export interface ITerminalVirtualProcessRequest {
export interface IStartExtensionTerminalRequest {
proxy: ITerminalProcessExtHostProxy;
cols: number;
rows: number;
@@ -802,6 +803,7 @@ export interface ITerminalChildProcess {
onProcessReady: Event<{ pid: number, cwd: string }>;
onProcessTitleChanged: Event<string>;
onProcessOverrideDimensions?: Event<ITerminalDimensions | undefined>;
onProcessResolvedShellLaunchConfig?: Event<IShellLaunchConfig>;
/**
* Shutdown the terminal process.

View File

@@ -68,6 +68,9 @@ export const enum TERMINAL_COMMAND_ID {
TOGGLE_FIND_REGEX_TERMINAL_FOCUS = 'workbench.action.terminal.toggleFindRegexTerminalFocus',
TOGGLE_FIND_WHOLE_WORD_TERMINAL_FOCUS = 'workbench.action.terminal.toggleFindWholeWordTerminalFocus',
TOGGLE_FIND_CASE_SENSITIVE_TERMINAL_FOCUS = 'workbench.action.terminal.toggleFindCaseSensitiveTerminalFocus',
NAVIGATION_MODE_EXIT = 'workbench.action.terminal.navigationModeExit',
NAVIGATION_MODE_FOCUS_NEXT = 'workbench.action.terminal.navigationModeFocusNext',
NAVIGATION_MODE_FOCUS_PREVIOUS = 'workbench.action.terminal.navigationModeFocusPrevious'
}
export function setupTerminalCommands(): void {

View File

@@ -106,6 +106,7 @@ function _getLangEnvVariable(locale?: string) {
ko: 'KR',
pl: 'PL',
ru: 'RU',
sk: 'SK',
zh: 'CN'
};
if (parts[0] in languageVariants) {

View File

@@ -24,6 +24,8 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
public readonly onProcessTitleChanged: Event<string> = this._onProcessTitleChanged.event;
private readonly _onProcessOverrideDimensions = new Emitter<ITerminalDimensions | undefined>();
public get onProcessOverrideDimensions(): Event<ITerminalDimensions | undefined> { return this._onProcessOverrideDimensions.event; }
private readonly _onProcessResolvedShellLaunchConfig = new Emitter<IShellLaunchConfig>();
public get onProcessResolvedShellLaunchConfig(): Event<IShellLaunchConfig> { return this._onProcessResolvedShellLaunchConfig.event; }
private readonly _onInput = this._register(new Emitter<string>());
public readonly onInput: Event<string> = this._onInput.event;
@@ -56,14 +58,14 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
// Request a process if needed, if this is a virtual process this step can be skipped as
// there is no real "process" and we know it's ready on the ext host already.
if (shellLaunchConfig.isVirtualProcess) {
this._terminalService.requestVirtualProcess(this, cols, rows);
if (shellLaunchConfig.isExtensionTerminal) {
this._terminalService.requestStartExtensionTerminal(this, cols, rows);
} else {
remoteAgentService.getEnvironment().then(env => {
if (!env) {
throw new Error('Could not fetch environment');
}
this._terminalService.requestExtHostProcess(this, shellLaunchConfig, activeWorkspaceRootUri, cols, rows, configHelper.checkWorkspaceShellPermissions(env.os));
this._terminalService.requestSpawnExtHostProcess(this, shellLaunchConfig, activeWorkspaceRootUri, cols, rows, configHelper.checkWorkspaceShellPermissions(env.os));
});
if (!hasReceivedResponse) {
setTimeout(() => this._onProcessTitleChanged.fire(nls.localize('terminal.integrated.starting', "Starting...")), 0);
@@ -93,6 +95,10 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
this._onProcessOverrideDimensions.fire(dimensions);
}
public emitResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void {
this._onProcessResolvedShellLaunchConfig.fire(shellLaunchConfig);
}
public emitInitialCwd(initialCwd: string): void {
while (this._pendingInitialCwdRequests.length > 0) {
this._pendingInitialCwdRequests.pop()!(initialCwd);
@@ -143,4 +149,4 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
this._pendingLatencyRequests.push(resolve);
});
}
}
}

View File

@@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TERMINAL_PANEL_ID, ITerminalTab, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, ITerminalNativeService, IShellDefinition, IAvailableShellsRequest, ITerminalVirtualProcessRequest } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TERMINAL_PANEL_ID, ITerminalTab, ITerminalProcessExtHostProxy, ISpawnExtHostProcessRequest, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, ITerminalNativeService, IShellDefinition, IAvailableShellsRequest, IStartExtensionTerminalRequest } from 'vs/workbench/contrib/terminal/common/terminal';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { URI } from 'vs/base/common/uri';
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
@@ -20,11 +20,15 @@ import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/termi
import { isWindows, isMacintosh, OperatingSystem } from 'vs/base/common/platform';
import { basename } from 'vs/base/common/path';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { timeout } from 'vs/base/common/async';
import { IOpenFileRequest } from 'vs/platform/windows/common/windows';
import { IPickOptions, IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
interface IExtHostReadyEntry {
promise: Promise<void>;
resolve: () => void;
}
export abstract class TerminalService implements ITerminalService {
public _serviceBrand: any;
@@ -38,7 +42,7 @@ export abstract class TerminalService implements ITerminalService {
return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), <ITerminalInstance[]>[]);
}
private _findState: FindReplaceState;
private _extHostsReady: { [authority: string]: boolean } = {};
private _extHostsReady: { [authority: string]: IExtHostReadyEntry | undefined } = {};
private _activeTabIndex: number;
public get activeTabIndex(): number { return this._activeTabIndex; }
@@ -53,10 +57,10 @@ export abstract class TerminalService implements ITerminalService {
public get onInstanceDisposed(): Event<ITerminalInstance> { return this._onInstanceDisposed.event; }
protected readonly _onInstanceProcessIdReady = new Emitter<ITerminalInstance>();
public get onInstanceProcessIdReady(): Event<ITerminalInstance> { return this._onInstanceProcessIdReady.event; }
protected readonly _onInstanceRequestExtHostProcess = new Emitter<ITerminalProcessExtHostRequest>();
public get onInstanceRequestExtHostProcess(): Event<ITerminalProcessExtHostRequest> { return this._onInstanceRequestExtHostProcess.event; }
protected readonly _onInstanceRequestVirtualProcess = new Emitter<ITerminalVirtualProcessRequest>();
public get onInstanceRequestVirtualProcess(): Event<ITerminalVirtualProcessRequest> { return this._onInstanceRequestVirtualProcess.event; }
protected readonly _onInstanceRequestSpawnExtHostProcess = new Emitter<ISpawnExtHostProcessRequest>();
public get onInstanceRequestSpawnExtHostProcess(): Event<ISpawnExtHostProcessRequest> { return this._onInstanceRequestSpawnExtHostProcess.event; }
protected readonly _onInstanceRequestStartExtensionTerminal = new Emitter<IStartExtensionTerminalRequest>();
public get onInstanceRequestStartExtensionTerminal(): Event<IStartExtensionTerminalRequest> { return this._onInstanceRequestStartExtensionTerminal.event; }
protected readonly _onInstanceDimensionsChanged = new Emitter<ITerminalInstance>();
public get onInstanceDimensionsChanged(): Event<ITerminalInstance> { return this._onInstanceDimensionsChanged.event; }
protected readonly _onInstanceMaximumDimensionsChanged = new Emitter<ITerminalInstance>();
@@ -119,7 +123,7 @@ export abstract class TerminalService implements ITerminalService {
protected abstract _showBackgroundTerminal(instance: ITerminalInstance): void;
public abstract createTerminal(shell?: IShellLaunchConfig, wasNewTerminalAction?: boolean): ITerminalInstance;
public abstract createInstance(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig, doCreateProcess: boolean): ITerminalInstance;
public abstract createInstance(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, container: HTMLElement, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance;
public abstract setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void;
public createTerminalRenderer(name: string): ITerminalInstance {
@@ -131,26 +135,39 @@ export abstract class TerminalService implements ITerminalService {
return activeInstance ? activeInstance : this.createTerminal(undefined, wasNewTerminalAction);
}
public requestExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void {
public requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void {
this._extensionService.whenInstalledExtensionsRegistered().then(async () => {
// Wait for the remoteAuthority to be ready (and listening for events) before proceeding
// Wait for the remoteAuthority to be ready (and listening for events) before firing
// the event to spawn the ext host process
const conn = this._remoteAgentService.getConnection();
const remoteAuthority = conn ? conn.remoteAuthority : 'null';
let retries = 0;
while (!this._extHostsReady[remoteAuthority] && ++retries < 50) {
await timeout(100);
}
this._onInstanceRequestExtHostProcess.fire({ proxy, shellLaunchConfig, activeWorkspaceRootUri, cols, rows, isWorkspaceShellAllowed });
await this._whenExtHostReady(remoteAuthority);
this._onInstanceRequestSpawnExtHostProcess.fire({ proxy, shellLaunchConfig, activeWorkspaceRootUri, cols, rows, isWorkspaceShellAllowed });
});
}
public requestVirtualProcess(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): void {
// Don't need to wait on extensions here as this can only be triggered by an extension
this._onInstanceRequestVirtualProcess.fire({ proxy, cols, rows });
public requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): void {
this._onInstanceRequestStartExtensionTerminal.fire({ proxy, cols, rows });
}
public extHostReady(remoteAuthority: string): void {
this._extHostsReady[remoteAuthority] = true;
public async extHostReady(remoteAuthority: string): Promise<void> {
this._createExtHostReadyEntry(remoteAuthority);
this._extHostsReady[remoteAuthority]!.resolve();
}
private async _whenExtHostReady(remoteAuthority: string): Promise<void> {
this._createExtHostReadyEntry(remoteAuthority);
return this._extHostsReady[remoteAuthority]!.promise;
}
private _createExtHostReadyEntry(remoteAuthority: string): void {
if (this._extHostsReady[remoteAuthority]) {
return;
}
let resolve!: () => void;
const promise = new Promise<void>(r => resolve = r);
this._extHostsReady[remoteAuthority] = { promise, resolve };
}
private _onBeforeShutdown(): boolean | Promise<boolean> {