mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 16:50:30 -04:00
Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)
* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 * fix pipelines * fix strict-null-checks * add missing files
This commit is contained in:
@@ -30,7 +30,7 @@ export class NavigationModeAddon implements INavigationMode, ITerminalAddon {
|
||||
}
|
||||
|
||||
focusPreviousLine(): void {
|
||||
if (!this._terminal) {
|
||||
if (!this._terminal || !this._terminal.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export class NavigationModeAddon implements INavigationMode, ITerminalAddon {
|
||||
}
|
||||
|
||||
focusNextLine(): void {
|
||||
if (!this._terminal) {
|
||||
if (!this._terminal || !this._terminal.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -251,6 +251,11 @@ configurationRegistry.registerConfiguration({
|
||||
},
|
||||
default: []
|
||||
},
|
||||
'terminal.integrated.allowChords': {
|
||||
markdownDescription: nls.localize('terminal.integrated.allowChords', "Whether or not to allow chord keybindings in the terminal. Note that when this is true and the keystroke results in a chord it will bypass `terminal.integrated.commandsToSkipShell`, setting this to false is particularly useful when you want ctrl+k to go to your shell (not VS Code)."),
|
||||
type: 'boolean',
|
||||
default: true
|
||||
},
|
||||
'terminal.integrated.inheritEnv': {
|
||||
markdownDescription: nls.localize('terminal.integrated.inheritEnv', "Whether new shells should inherit their environment from Azure Data Studio. This is not supported on Windows."), // {{SQL CARBON EDIT}} Change product name to ADS
|
||||
type: 'boolean',
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShe
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IProcessEnvironment, Platform } from 'vs/base/common/platform';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -65,7 +64,7 @@ export interface ITerminalTab {
|
||||
setVisible(visible: boolean): void;
|
||||
layout(width: number, height: number): void;
|
||||
addDisposable(disposable: IDisposable): void;
|
||||
split(terminalFocusContextKey: IContextKey<boolean>, configHelper: ITerminalConfigHelper, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance | undefined;
|
||||
split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance;
|
||||
}
|
||||
|
||||
export interface ITerminalService {
|
||||
@@ -227,7 +226,7 @@ export interface ITerminalInstance {
|
||||
* is the processes' exit code, an exit code of null means the process was killed as a result of
|
||||
* the ITerminalInstance being disposed.
|
||||
*/
|
||||
onExit: Event<number>;
|
||||
onExit: Event<number | undefined>;
|
||||
|
||||
processReady: Promise<void>;
|
||||
|
||||
|
||||
@@ -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, 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, TitleEventSource, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IShellLaunchConfig, ITerminalDimensions, 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, TitleEventSource, TERMINAL_COMMAND_ID, LEGACY_CONSOLE_MODE_EXIT_CODE } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
|
||||
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
|
||||
import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler';
|
||||
@@ -38,6 +38,7 @@ import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
|
||||
import { CommandTrackerAddon } from 'vs/workbench/contrib/terminal/browser/addons/commandTrackerAddon';
|
||||
import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/addons/navigationModeAddon';
|
||||
import { XTermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
// How long in milliseconds should an average frame take to render for a notification to appear
|
||||
// which suggests the fallback DOM-based renderer
|
||||
@@ -232,8 +233,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
public get commandTracker(): CommandTrackerAddon | undefined { return this._commandTrackerAddon; }
|
||||
public get navigationMode(): INavigationMode | undefined { return this._navigationModeAddon; }
|
||||
|
||||
private readonly _onExit = new Emitter<number>();
|
||||
public get onExit(): Event<number> { return this._onExit.event; }
|
||||
private readonly _onExit = new Emitter<number | undefined>();
|
||||
public get onExit(): Event<number | undefined> { return this._onExit.event; }
|
||||
private readonly _onDisposed = new Emitter<ITerminalInstance>();
|
||||
public get onDisposed(): Event<ITerminalInstance> { return this._onDisposed.event; }
|
||||
private readonly _onFocused = new Emitter<ITerminalInstance>();
|
||||
@@ -258,7 +259,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
public constructor(
|
||||
private readonly _terminalFocusContextKey: IContextKey<boolean>,
|
||||
private readonly _configHelper: TerminalConfigHelper,
|
||||
private _container: HTMLElement,
|
||||
private _container: HTMLElement | undefined,
|
||||
private _shellLaunchConfig: IShellLaunchConfig,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@@ -408,14 +409,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// The panel is minimized
|
||||
if (!this._isVisible) {
|
||||
return TerminalInstance._lastKnownCanvasDimensions;
|
||||
} else {
|
||||
// Trigger scroll event manually so that the viewport's scroll area is synced. This
|
||||
// needs to happen otherwise its scrollTop value is invalid when the panel is toggled as
|
||||
// it gets removed and then added back to the DOM (resetting scrollTop to 0).
|
||||
// Upstream issue: https://github.com/sourcelair/xterm.js/issues/291
|
||||
if (this._xterm && this._xtermCore) {
|
||||
this._xtermCore._onScroll.fire(this._xterm.buffer.viewportY);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._wrapperElement) {
|
||||
@@ -455,6 +448,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
const Terminal = await this._getXtermConstructor();
|
||||
const font = this._configHelper.getFont(undefined, true);
|
||||
const config = this._configHelper.config;
|
||||
const fastScrollSensitivity = this._configurationService.getValue<IEditorOptions>('editor.fastScrollSensitivity').fastScrollSensitivity;
|
||||
const xterm = new Terminal({
|
||||
scrollback: config.scrollback,
|
||||
theme: this._getXtermTheme(),
|
||||
@@ -469,6 +463,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
macOptionIsMeta: config.macOptionIsMeta,
|
||||
macOptionClickForcesSelection: config.macOptionClickForcesSelection,
|
||||
rightClickSelectsWord: config.rightClickBehavior === 'selectWord',
|
||||
fastScrollModifier: 'alt',
|
||||
fastScrollSensitivity,
|
||||
// TODO: Guess whether to use canvas or dom better
|
||||
rendererType: config.rendererType === 'auto' ? 'canvas' : config.rendererType
|
||||
});
|
||||
@@ -507,7 +503,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, this._processManager, this._configHelper);
|
||||
this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, xterm, this._processManager, this._configHelper);
|
||||
});
|
||||
|
||||
this._commandTrackerAddon = new CommandTrackerAddon();
|
||||
@@ -548,7 +544,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
|
||||
// The container changed, reattach
|
||||
this._container.removeChild(this._wrapperElement);
|
||||
if (this._container) {
|
||||
this._container.removeChild(this._wrapperElement);
|
||||
}
|
||||
this._container = container;
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
}
|
||||
@@ -567,7 +565,14 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// Attach the xterm object to the DOM, exposing it to the smoke tests
|
||||
this._wrapperElement.xterm = this._xterm;
|
||||
|
||||
this._wrapperElement.appendChild(this._xtermElement);
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
xterm.open(this._xtermElement);
|
||||
|
||||
if (!xterm.element || !xterm.textarea) {
|
||||
throw new Error('xterm elements not set after open');
|
||||
}
|
||||
|
||||
xterm.textarea.addEventListener('focus', () => this._onFocus.fire(this));
|
||||
xterm.attachCustomKeyEventHandler((event: KeyboardEvent): boolean => {
|
||||
// Disable all input if the terminal is exiting
|
||||
@@ -579,7 +584,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// within commandsToSkipShell
|
||||
const standardKeyboardEvent = new StandardKeyboardEvent(event);
|
||||
const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target);
|
||||
if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) {
|
||||
const allowChords = resolveResult && resolveResult.enterChord && this._configHelper.config.allowChords;
|
||||
if (allowChords || resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
@@ -644,9 +650,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._refreshSelectionContextKey();
|
||||
}));
|
||||
|
||||
this._wrapperElement.appendChild(this._xtermElement);
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
|
||||
const widgetManager = new TerminalWidgetManager(this._wrapperElement);
|
||||
this._widgetManager = widgetManager;
|
||||
this._processManager.onProcessReady(() => {
|
||||
@@ -801,7 +804,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
if (this._wrapperElement.xterm) {
|
||||
this._wrapperElement.xterm = undefined;
|
||||
}
|
||||
if (this._wrapperElement.parentElement) {
|
||||
if (this._wrapperElement.parentElement && this._container) {
|
||||
this._container.removeChild(this._wrapperElement);
|
||||
}
|
||||
}
|
||||
@@ -900,6 +903,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// necessary if the number of rows in the terminal has decreased while it was in the
|
||||
// background since scrollTop changes take no effect but the terminal's position does
|
||||
// change since the number of visible rows decreases.
|
||||
// This can likely be removed after https://github.com/xtermjs/xterm.js/issues/291 is
|
||||
// fixed upstream.
|
||||
this._xtermCore._onScroll.fire(this._xterm.buffer.viewportY);
|
||||
if (this._container && this._container.parentElement) {
|
||||
// Force a layout when the instance becomes invisible. This is particularly important
|
||||
@@ -1047,6 +1052,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
exitCodeMessage = nls.localize('terminal.integrated.exitedWithInvalidPathDirectory', 'The terminal shell path "{0}" is a directory', this._shellLaunchConfig.executable);
|
||||
} else if (exitCode === SHELL_CWD_INVALID_EXIT_CODE && this._shellLaunchConfig.cwd) {
|
||||
exitCodeMessage = nls.localize('terminal.integrated.exitedWithInvalidCWD', 'The terminal shell CWD "{0}" does not exist', this._shellLaunchConfig.cwd.toString());
|
||||
} else if (exitCode === LEGACY_CONSOLE_MODE_EXIT_CODE) {
|
||||
exitCodeMessage = nls.localize('terminal.integrated.legacyConsoleModeError', 'The terminal failed to launch properly because your system has legacy console mode enabled, uncheck "Use legacy console" cmd.exe\'s properties to fix this.');
|
||||
} else if (this._processManager.processState === ProcessState.KILLED_DURING_LAUNCH) {
|
||||
let args = '';
|
||||
if (typeof this._shellLaunchConfig.args === 'string') {
|
||||
@@ -1105,11 +1112,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
}
|
||||
|
||||
this._onExit.fire(exitCode || 0);
|
||||
this._onExit.fire(exitCode);
|
||||
}
|
||||
|
||||
private _attachPressAnyKeyToCloseListener(xterm: XTermTerminal) {
|
||||
if (!this._pressAnyKeyToCloseListener) {
|
||||
if (xterm.textarea && !this._pressAnyKeyToCloseListener) {
|
||||
this._pressAnyKeyToCloseListener = dom.addDisposableListener(xterm.textarea, 'keypress', (event: KeyboardEvent) => {
|
||||
if (this._pressAnyKeyToCloseListener) {
|
||||
this._pressAnyKeyToCloseListener.dispose();
|
||||
@@ -1240,6 +1247,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._safeSetOption('macOptionClickForcesSelection', config.macOptionClickForcesSelection);
|
||||
this._safeSetOption('rightClickSelectsWord', config.rightClickBehavior === 'selectWord');
|
||||
this._safeSetOption('rendererType', config.rendererType === 'auto' ? 'canvas' : config.rendererType);
|
||||
this._safeSetOption('fastScrollSensitivity', this._configurationService.getValue<IEditorOptions>('editor.fastScrollSensitivity').fastScrollSensitivity);
|
||||
}
|
||||
|
||||
public updateAccessibilitySupport(): void {
|
||||
@@ -1312,7 +1320,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._xterm) {
|
||||
if (this._xterm && this._xterm.element) {
|
||||
this._xterm.element.style.width = terminalWidth + 'px';
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
|
||||
const FIND_FOCUS_CLASS = 'find-focused';
|
||||
|
||||
@@ -70,7 +71,8 @@ export class TerminalPanel extends Panel {
|
||||
|
||||
this._attachEventListeners(this._parentDomElement, this._terminalContainer);
|
||||
|
||||
this._terminalService.setContainers(this.getContainer(), this._terminalContainer);
|
||||
const container = assertIsDefined(this.getContainer());
|
||||
this._terminalService.setContainers(container, this._terminalContainer);
|
||||
|
||||
this._register(this.themeService.onThemeChange(theme => this._updateTheme(theme)));
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
|
||||
@@ -11,13 +11,12 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { TerminalPanel } from 'vs/workbench/contrib/terminal/browser/terminalPanel';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance';
|
||||
import { IBrowserTerminalConfigHelper, ITerminalService, ITerminalInstance, ITerminalTab } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalService, ITerminalInstance, ITerminalTab } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
|
||||
import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput';
|
||||
@@ -29,6 +28,7 @@ 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 { IOpenFileRequest } from 'vs/platform/windows/common/windows';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
|
||||
interface IExtHostReadyEntry {
|
||||
promise: Promise<void>;
|
||||
@@ -54,7 +54,7 @@ export class TerminalService implements ITerminalService {
|
||||
public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; }
|
||||
public get terminalTabs(): ITerminalTab[] { return this._terminalTabs; }
|
||||
|
||||
private _configHelper: IBrowserTerminalConfigHelper;
|
||||
private _configHelper: TerminalConfigHelper;
|
||||
private _terminalContainer: HTMLElement | undefined;
|
||||
|
||||
public get configHelper(): ITerminalConfigHelper { return this._configHelper; }
|
||||
@@ -91,7 +91,6 @@ export class TerminalService implements ITerminalService {
|
||||
@IPanelService private _panelService: IPanelService,
|
||||
@IWorkbenchLayoutService private _layoutService: IWorkbenchLayoutService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@INotificationService private _notificationService: INotificationService,
|
||||
@IDialogService private _dialogService: IDialogService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IExtensionService private _extensionService: IExtensionService,
|
||||
@@ -392,12 +391,7 @@ export class TerminalService implements ITerminalService {
|
||||
return null;
|
||||
}
|
||||
|
||||
const instance = tab.split(this._terminalFocusContextKey, this.configHelper, shellLaunchConfig);
|
||||
if (!instance) {
|
||||
this._showNotEnoughSpaceToast();
|
||||
return null;
|
||||
}
|
||||
|
||||
const instance = tab.split(shellLaunchConfig);
|
||||
this._initInstanceListeners(instance);
|
||||
this._onInstancesChanged.fire();
|
||||
|
||||
@@ -414,13 +408,8 @@ export class TerminalService implements ITerminalService {
|
||||
instance.addDisposable(instance.onFocus(this._onActiveInstanceChanged.fire, this._onActiveInstanceChanged));
|
||||
}
|
||||
|
||||
private _getTabForInstance(instance: ITerminalInstance): ITerminalTab | null {
|
||||
for (const tab of this._terminalTabs) {
|
||||
if (tab.terminalInstances.indexOf(instance) !== -1) {
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
private _getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined {
|
||||
return find(this._terminalTabs, tab => tab.terminalInstances.indexOf(instance) !== -1);
|
||||
}
|
||||
|
||||
public showPanel(focus?: boolean): Promise<void> {
|
||||
@@ -499,10 +488,6 @@ export class TerminalService implements ITerminalService {
|
||||
return !res.confirmed;
|
||||
}
|
||||
|
||||
protected _showNotEnoughSpaceToast(): void {
|
||||
this._notificationService.info(nls.localize('terminal.minWidth', "Not enough space to split terminal."));
|
||||
}
|
||||
|
||||
protected _validateShellPaths(label: string, potentialPaths: string[]): Promise<[string, string] | null> {
|
||||
if (potentialPaths.length === 0) {
|
||||
return Promise.resolve(null);
|
||||
|
||||
@@ -14,7 +14,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { ITerminalInstance, Direction, ITerminalTab, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
|
||||
const SPLIT_PANE_MIN_SIZE = 120;
|
||||
const TERMINAL_MIN_USEFUL_SIZE = 250;
|
||||
|
||||
class SplitPaneContainer extends Disposable {
|
||||
private _height: number;
|
||||
@@ -370,18 +369,11 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
||||
this.terminalInstances.forEach(i => i.setVisible(visible));
|
||||
}
|
||||
|
||||
public split(
|
||||
terminalFocusContextKey: IContextKey<boolean>,
|
||||
configHelper: ITerminalConfigHelper,
|
||||
shellLaunchConfig: IShellLaunchConfig
|
||||
): ITerminalInstance | undefined {
|
||||
public split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance {
|
||||
if (!this._container) {
|
||||
throw new Error('Cannot split terminal that has not been attached');
|
||||
}
|
||||
const newTerminalSize = ((this._panelPosition === Position.BOTTOM ? this._container.clientWidth : this._container.clientHeight) / (this._terminalInstances.length + 1));
|
||||
if (newTerminalSize < TERMINAL_MIN_USEFUL_SIZE) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const instance = this._terminalService.createInstance(undefined, shellLaunchConfig);
|
||||
this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance);
|
||||
this._initInstanceListeners(instance);
|
||||
|
||||
@@ -65,6 +65,7 @@ export const DEFAULT_LINE_HEIGHT = 1;
|
||||
export const SHELL_PATH_INVALID_EXIT_CODE = -1;
|
||||
export const SHELL_PATH_DIRECTORY_EXIT_CODE = -2;
|
||||
export const SHELL_CWD_INVALID_EXIT_CODE = -3;
|
||||
export const LEGACY_CONSOLE_MODE_EXIT_CODE = 3221225786; // microsoft/vscode#73790
|
||||
|
||||
export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
|
||||
|
||||
@@ -101,6 +102,7 @@ export interface ITerminalConfiguration {
|
||||
detectLocale: 'auto' | 'off' | 'on';
|
||||
scrollback: number;
|
||||
commandsToSkipShell: string[];
|
||||
allowChords: boolean;
|
||||
cwd: string;
|
||||
confirmOnExit: boolean;
|
||||
enableBell: boolean;
|
||||
|
||||
@@ -282,7 +282,6 @@ export function getDefaultShell(
|
||||
executable = configurationResolverService.resolve(lastActiveWorkspace, executable);
|
||||
} catch (e) {
|
||||
logService.error(`Could not resolve shell`, e);
|
||||
executable = executable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,14 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
|
||||
cols = Math.max(cols, 1);
|
||||
rows = Math.max(rows, 1);
|
||||
this._logService.trace('IPty#resize', cols, rows);
|
||||
this._ptyProcess.resize(cols, rows);
|
||||
try {
|
||||
this._ptyProcess.resize(cols, rows);
|
||||
} catch (e) {
|
||||
// Swallow error if the pty has already exited
|
||||
if (this._exitCode !== undefined) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,138 @@ function writePromise(term: Terminal, data: string): Promise<void> {
|
||||
const ROWS = 10;
|
||||
const COLS = 10;
|
||||
|
||||
suite('Workbench - TerminalCommandTracker', () => {
|
||||
suite.skip('Workbench - TerminalCommandTracker', () => { // {{SQL CARBON EDIT}} skip suite
|
||||
let xterm: TestTerminal;
|
||||
let commandTracker: CommandTrackerAddon;
|
||||
|
||||
setup(async () => {
|
||||
xterm = (<TestTerminal>new Terminal({
|
||||
cols: COLS,
|
||||
rows: ROWS
|
||||
}));
|
||||
// Fill initial viewport
|
||||
for (let i = 0; i < ROWS - 1; i++) {
|
||||
await writePromise(xterm, `${i}\n`);
|
||||
}
|
||||
commandTracker = new CommandTrackerAddon();
|
||||
xterm.loadAddon(commandTracker);
|
||||
});
|
||||
|
||||
suite('Command tracking', () => {
|
||||
test('should track commands when the prompt is of sufficient size', () => {
|
||||
assert.equal(0, 0);
|
||||
test('should track commands when the prompt is of sufficient size', async () => {
|
||||
assert.equal(xterm.markers.length, 0);
|
||||
await writePromise(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
assert.equal(xterm.markers.length, 1);
|
||||
});
|
||||
test('should not track commands when the prompt is too small', async () => {
|
||||
assert.equal(xterm.markers.length, 0);
|
||||
await writePromise(xterm, '\x1b[2G'); // Move cursor to column 2
|
||||
xterm._core._onKey.fire({ key: '\x0d' });
|
||||
assert.equal(xterm.markers.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Commands', () => {
|
||||
test('should scroll to the next and previous commands', async () => {
|
||||
await writePromise(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line #10
|
||||
assert.equal(xterm.markers[0].line, 9);
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await writePromise(xterm, `\r\n`);
|
||||
}
|
||||
assert.equal(xterm.buffer.baseY, 20);
|
||||
assert.equal(xterm.buffer.viewportY, 20);
|
||||
|
||||
// Scroll to marker
|
||||
commandTracker.scrollToPreviousCommand();
|
||||
assert.equal(xterm.buffer.viewportY, 9);
|
||||
|
||||
// Scroll to top boundary
|
||||
commandTracker.scrollToPreviousCommand();
|
||||
assert.equal(xterm.buffer.viewportY, 0);
|
||||
|
||||
// Scroll to marker
|
||||
commandTracker.scrollToNextCommand();
|
||||
assert.equal(xterm.buffer.viewportY, 9);
|
||||
|
||||
// Scroll to bottom boundary
|
||||
commandTracker.scrollToNextCommand();
|
||||
assert.equal(xterm.buffer.viewportY, 20);
|
||||
});
|
||||
test('should select to the next and previous commands', async () => {
|
||||
(<any>window).matchMedia = () => {
|
||||
return { addListener: () => { } };
|
||||
};
|
||||
const e = document.createElement('div');
|
||||
document.body.appendChild(e);
|
||||
xterm.open(e);
|
||||
|
||||
await writePromise(xterm, '\r0');
|
||||
await writePromise(xterm, '\n\r1');
|
||||
await writePromise(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
assert.equal(xterm.markers[0].line, 10);
|
||||
await writePromise(xterm, '\n\r2');
|
||||
await writePromise(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
assert.equal(xterm.markers[1].line, 11);
|
||||
await writePromise(xterm, '\n\r3');
|
||||
|
||||
assert.equal(xterm.buffer.baseY, 3);
|
||||
assert.equal(xterm.buffer.viewportY, 3);
|
||||
|
||||
assert.equal(xterm.getSelection(), '');
|
||||
commandTracker.selectToPreviousCommand();
|
||||
assert.equal(xterm.getSelection(), '2');
|
||||
commandTracker.selectToPreviousCommand();
|
||||
assert.equal(xterm.getSelection(), isWindows ? '1\r\n2' : '1\n2');
|
||||
commandTracker.selectToNextCommand();
|
||||
assert.equal(xterm.getSelection(), '2');
|
||||
commandTracker.selectToNextCommand();
|
||||
assert.equal(xterm.getSelection(), isWindows ? '\r\n' : '\n');
|
||||
|
||||
document.body.removeChild(e);
|
||||
});
|
||||
test('should select to the next and previous lines & commands', async () => {
|
||||
(<any>window).matchMedia = () => {
|
||||
return { addListener: () => { } };
|
||||
};
|
||||
const e = document.createElement('div');
|
||||
document.body.appendChild(e);
|
||||
xterm.open(e);
|
||||
|
||||
await writePromise(xterm, '\r0');
|
||||
await writePromise(xterm, '\n\r1');
|
||||
await writePromise(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
assert.equal(xterm.markers[0].line, 10);
|
||||
await writePromise(xterm, '\n\r2');
|
||||
await writePromise(xterm, '\x1b[3G'); // Move cursor to column 3
|
||||
xterm._core._onKey.fire({ key: '\x0d' }); // Mark line
|
||||
assert.equal(xterm.markers[1].line, 11);
|
||||
await writePromise(xterm, '\n\r3');
|
||||
|
||||
assert.equal(xterm.buffer.baseY, 3);
|
||||
assert.equal(xterm.buffer.viewportY, 3);
|
||||
|
||||
assert.equal(xterm.getSelection(), '');
|
||||
commandTracker.selectToPreviousLine();
|
||||
assert.equal(xterm.getSelection(), '2');
|
||||
commandTracker.selectToNextLine();
|
||||
commandTracker.selectToNextLine();
|
||||
assert.equal(xterm.getSelection(), '3');
|
||||
commandTracker.selectToPreviousCommand();
|
||||
commandTracker.selectToPreviousCommand();
|
||||
commandTracker.selectToNextLine();
|
||||
assert.equal(xterm.getSelection(), '2');
|
||||
commandTracker.selectToPreviousCommand();
|
||||
assert.equal(xterm.getSelection(), isWindows ? '1\r\n2' : '1\n2');
|
||||
commandTracker.selectToPreviousLine();
|
||||
assert.equal(xterm.getSelection(), isWindows ? '0\r\n1\r\n2' : '0\n1\n2');
|
||||
|
||||
document.body.removeChild(e);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user