mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 16:50:30 -04:00
Merge from vscode 10492ba146318412cbee8b76a8c630f226914734
This commit is contained in:
@@ -161,7 +161,18 @@
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .title > .title-actions .switch-terminal {
|
||||
.monaco-workbench .part.sidebar > .title > .title-actions .switch-terminal,
|
||||
.monaco-pane-view .pane > .pane-header .monaco-action-bar .switch-terminal {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.part.panel > .title > .title-actions .switch-terminal > .monaco-select-box {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.sidebar > .title > .title-actions .switch-terminal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 11px;
|
||||
@@ -171,11 +182,11 @@
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.monaco-workbench.mac .part > .title > .title-actions .switch-terminal {
|
||||
.monaco-workbench.mac .part.sidebar > .title > .title-actions .switch-terminal {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .title > .title-actions .switch-terminal > .monaco-select-box {
|
||||
.monaco-workbench .part.sidebar > .title > .title-actions .switch-terminal > .monaco-select-box {
|
||||
border: none !important;
|
||||
display: block !important;
|
||||
background-color: unset !important;
|
||||
@@ -185,7 +196,7 @@
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .title > .title-actions .switch-terminal > .monaco-select-box {
|
||||
.monaco-workbench .part.sidebar > .title > .title-actions .switch-terminal > .monaco-select-box {
|
||||
padding: 0 22px 0 6px;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,16 +12,16 @@ import 'vs/css!./media/xterm';
|
||||
import * as nls from 'vs/nls';
|
||||
import { SyncActionDescriptor, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingWeight, KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as panel from 'vs/workbench/browser/panel';
|
||||
import { getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
|
||||
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
|
||||
import { Extensions as ViewContainerExtensions, IViewContainersRegistry, ViewContainerLocation, IViewsRegistry } from 'vs/workbench/common/views';
|
||||
import { ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, DeleteToLineStartTerminalAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, FindNext, FindPrevious, FocusActiveTerminalAction, FocusNextPaneTerminalAction, FocusNextTerminalAction, FocusPreviousPaneTerminalAction, FocusPreviousTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, KillTerminalAction, MoveToLineEndTerminalAction, MoveToLineStartTerminalAction, QuickAccessTerminalAction, RenameTerminalAction, ResizePaneDownTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, RunActiveFileInTerminalAction, RunSelectedTextInTerminalAction, ScrollDownPageTerminalAction, ScrollDownTerminalAction, ScrollToBottomTerminalAction, ScrollToNextCommandAction, ScrollToPreviousCommandAction, ScrollToTopTerminalAction, ScrollUpPageTerminalAction, ScrollUpTerminalAction, SelectAllTerminalAction, SelectDefaultShellWindowsTerminalAction, SelectToNextCommandAction, SelectToNextLineAction, SelectToPreviousCommandAction, SelectToPreviousLineAction, SplitInActiveWorkspaceTerminalAction, SplitTerminalAction, TerminalPasteAction, ToggleCaseSensitiveCommand, ToggleEscapeSequenceLoggingAction, ToggleRegexCommand, ToggleTerminalAction, ToggleWholeWordCommand, NavigationModeFocusPreviousTerminalAction, NavigationModeFocusNextTerminalAction, NavigationModeExitTerminalAction, ManageWorkspaceShellPermissionsTerminalCommand, CreateNewWithCwdTerminalAction, RenameWithArgTerminalAction, SendSequenceTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
|
||||
import { ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, FindNext, FindPrevious, FocusActiveTerminalAction, FocusNextPaneTerminalAction, FocusNextTerminalAction, FocusPreviousPaneTerminalAction, FocusPreviousTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, KillTerminalAction, QuickAccessTerminalAction, RenameTerminalAction, ResizePaneDownTerminalAction, ResizePaneLeftTerminalAction, ResizePaneRightTerminalAction, ResizePaneUpTerminalAction, RunActiveFileInTerminalAction, RunSelectedTextInTerminalAction, ScrollDownPageTerminalAction, ScrollDownTerminalAction, ScrollToBottomTerminalAction, ScrollToNextCommandAction, ScrollToPreviousCommandAction, ScrollToTopTerminalAction, ScrollUpPageTerminalAction, ScrollUpTerminalAction, SelectAllTerminalAction, SelectDefaultShellWindowsTerminalAction, SelectToNextCommandAction, SelectToNextLineAction, SelectToPreviousCommandAction, SelectToPreviousLineAction, SplitInActiveWorkspaceTerminalAction, SplitTerminalAction, TerminalPasteAction, ToggleCaseSensitiveCommand, ToggleEscapeSequenceLoggingAction, ToggleRegexCommand, ToggleTerminalAction, ToggleWholeWordCommand, NavigationModeFocusPreviousTerminalAction, NavigationModeFocusNextTerminalAction, NavigationModeExitTerminalAction, ManageWorkspaceShellPermissionsTerminalCommand, CreateNewWithCwdTerminalAction, RenameWithArgTerminalAction, SendSequenceTerminalAction, terminalSendSequenceCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions';
|
||||
import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView';
|
||||
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_VIEW_ID, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, TERMINAL_COMMAND_ID } 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_SHELL_TYPE_KEY, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_VIEW_ID, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
|
||||
import { setupTerminalCommands } from 'vs/workbench/contrib/terminal/browser/terminalCommands';
|
||||
import { setupTerminalMenu } from 'vs/workbench/contrib/terminal/common/terminalMenu';
|
||||
@@ -32,7 +32,7 @@ import { TerminalService } from 'vs/workbench/contrib/terminal/browser/terminalS
|
||||
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';
|
||||
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalService, WindowsShellType } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
@@ -333,6 +333,11 @@ configurationRegistry.registerConfiguration({
|
||||
type: 'boolean',
|
||||
default: true
|
||||
},
|
||||
'terminal.integrated.wordSeparators': {
|
||||
description: nls.localize('terminal.integrated.wordSeparators', "A string containing all characters to be considered word separators by the double click to select word feature."),
|
||||
type: 'string',
|
||||
default: ' ()[]{}\',"`'
|
||||
},
|
||||
'terminal.integrated.experimentalUseTitleEvent': {
|
||||
description: nls.localize('terminal.integrated.experimentalUseTitleEvent', "An experimental setting that will use the terminal title event for the dropdown title. This setting will only apply to new terminals."),
|
||||
type: 'boolean',
|
||||
@@ -447,26 +452,6 @@ actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(HideTerminalF
|
||||
primary: KeyCode.Escape,
|
||||
secondary: [KeyMod.Shift | KeyCode.Escape]
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE)), 'Terminal: Hide Find Widget', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(DeleteWordLeftTerminalAction, DeleteWordLeftTerminalAction.ID, DeleteWordLeftTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Backspace,
|
||||
mac: { primary: KeyMod.Alt | KeyCode.Backspace }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Left', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(DeleteWordRightTerminalAction, DeleteWordRightTerminalAction.ID, DeleteWordRightTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Delete,
|
||||
mac: { primary: KeyMod.Alt | KeyCode.Delete }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Right', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(DeleteToLineStartTerminalAction, DeleteToLineStartTerminalAction.ID, DeleteToLineStartTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete To Line Start', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(MoveToLineStartTerminalAction, MoveToLineStartTerminalAction.ID, MoveToLineStartTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.LeftArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line Start', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(MoveToLineEndTerminalAction, MoveToLineEndTerminalAction.ID, MoveToLineEndTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.RightArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Move To Line End', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_5,
|
||||
mac: {
|
||||
@@ -576,14 +561,60 @@ if (BrowserFeatures.clipboard.writeText) {
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C }
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Copy Selection', category);
|
||||
}
|
||||
|
||||
function registerSendSequenceKeybinding(text: string, rule: { when?: ContextKeyExpression } & IKeybindings): void {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: SendSequenceTerminalAction.ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: rule.when || KEYBINDING_CONTEXT_TERMINAL_FOCUS,
|
||||
primary: rule.primary,
|
||||
mac: rule.mac,
|
||||
linux: rule.linux,
|
||||
win: rule.win,
|
||||
handler: terminalSendSequenceCommand,
|
||||
args: { text }
|
||||
});
|
||||
}
|
||||
|
||||
if (BrowserFeatures.clipboard.readText) {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_V,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_V] },
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_V }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category);
|
||||
// An extra Windows-only ctrl+v keybinding is used for pwsh that sends ctrl+v directly to the
|
||||
// shell, this gets handled by PSReadLine which properly handles multi-line pastes
|
||||
if (platform.isWindows) {
|
||||
registerSendSequenceKeybinding(String.fromCharCode('V'.charCodeAt(0) - 64), { // ctrl+v
|
||||
when: ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, ContextKeyExpr.equals(KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY, WindowsShellType.PowerShell)),
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_V
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Delete word left: ctrl+w
|
||||
registerSendSequenceKeybinding(String.fromCharCode('W'.charCodeAt(0) - 64), {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Backspace,
|
||||
mac: { primary: KeyMod.Alt | KeyCode.Backspace }
|
||||
});
|
||||
// Delete word right: alt+d
|
||||
registerSendSequenceKeybinding('\x1bd', {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Delete,
|
||||
mac: { primary: KeyMod.Alt | KeyCode.Delete }
|
||||
});
|
||||
// Delete to line start: ctrl+u
|
||||
registerSendSequenceKeybinding('\u0015', {
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace }
|
||||
});
|
||||
// Move to line start: ctrl+A
|
||||
registerSendSequenceKeybinding(String.fromCharCode('A'.charCodeAt(0) - 64), {
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.LeftArrow }
|
||||
});
|
||||
// Move to line end: ctrl+E
|
||||
registerSendSequenceKeybinding(String.fromCharCode('E'.charCodeAt(0) - 64), {
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.RightArrow }
|
||||
});
|
||||
|
||||
registerAction2(class extends SendSequenceTerminalAction {
|
||||
constructor() {
|
||||
super({
|
||||
|
||||
@@ -139,7 +139,7 @@ export interface ITerminalService {
|
||||
*/
|
||||
addLinkHandler(key: string, callback: TerminalLinkHandlerCallback): IDisposable;
|
||||
|
||||
selectDefaultWindowsShell(): Promise<void>;
|
||||
selectDefaultShell(): Promise<void>;
|
||||
|
||||
setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void;
|
||||
manageWorkspaceShellPermissions(): void;
|
||||
@@ -180,10 +180,10 @@ export interface ISearchOptions {
|
||||
}
|
||||
|
||||
export enum WindowsShellType {
|
||||
CommandPrompt,
|
||||
PowerShell,
|
||||
Wsl,
|
||||
GitBash
|
||||
CommandPrompt = 'cmd',
|
||||
PowerShell = 'pwsh',
|
||||
Wsl = 'wsl',
|
||||
GitBash = 'gitbash'
|
||||
}
|
||||
export type TerminalShellType = WindowsShellType | undefined;
|
||||
|
||||
|
||||
@@ -165,115 +165,31 @@ export class SelectAllTerminalAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseSendTextTerminalAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private _text: string,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(event?: any): Promise<any> {
|
||||
const terminalInstance = this._terminalService.getActiveInstance();
|
||||
if (terminalInstance) {
|
||||
terminalInstance.sendText(this._text, false);
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeleteWordLeftTerminalAction extends BaseSendTextTerminalAction {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.DELETE_WORD_LEFT;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.deleteWordLeft', "Delete Word Left");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ITerminalService terminalService: ITerminalService
|
||||
) {
|
||||
// Send ctrl+W
|
||||
super(id, label, String.fromCharCode('W'.charCodeAt(0) - 64), terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeleteWordRightTerminalAction extends BaseSendTextTerminalAction {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.DELETE_WORD_RIGHT;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.deleteWordRight', "Delete Word Right");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ITerminalService terminalService: ITerminalService
|
||||
) {
|
||||
// Send alt+d
|
||||
super(id, label, '\x1bd', terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeleteToLineStartTerminalAction extends BaseSendTextTerminalAction {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.DELETE_TO_LINE_START;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.deleteToLineStart', "Delete To Line Start");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ITerminalService terminalService: ITerminalService
|
||||
) {
|
||||
// Send ctrl+u
|
||||
super(id, label, '\u0015', terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveToLineStartTerminalAction extends BaseSendTextTerminalAction {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.MOVE_TO_LINE_START;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.moveToLineStart', "Move To Line Start");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ITerminalService terminalService: ITerminalService
|
||||
) {
|
||||
// Send ctrl+A
|
||||
super(id, label, String.fromCharCode('A'.charCodeAt(0) - 64), terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveToLineEndTerminalAction extends BaseSendTextTerminalAction {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.MOVE_TO_LINE_END;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.moveToLineEnd', "Move To Line End");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ITerminalService terminalService: ITerminalService
|
||||
) {
|
||||
// Send ctrl+E
|
||||
super(id, label, String.fromCharCode('E'.charCodeAt(0) - 64), terminalService);
|
||||
}
|
||||
}
|
||||
|
||||
export class SendSequenceTerminalAction extends Action2 {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.SEND_SEQUENCE;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.sendSequence', "Send Custom Sequence To Terminal");
|
||||
|
||||
public run(accessor: ServicesAccessor, args: any): void {
|
||||
const terminalInstance = accessor.get(ITerminalService).getActiveInstance();
|
||||
if (!terminalInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
const configurationResolverService = accessor.get(IConfigurationResolverService);
|
||||
const workspaceContextService = accessor.get(IWorkspaceContextService);
|
||||
const historyService = accessor.get(IHistoryService);
|
||||
const activeWorkspaceRootUri = historyService.getLastActiveWorkspaceRoot(Schemas.file);
|
||||
const lastActiveWorkspaceRoot = activeWorkspaceRootUri ? withNullAsUndefined(workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri)) : undefined;
|
||||
const resolvedText = configurationResolverService.resolve(lastActiveWorkspaceRoot, args.text);
|
||||
terminalInstance.sendText(resolvedText, false);
|
||||
terminalSendSequenceCommand(accessor, args);
|
||||
}
|
||||
}
|
||||
|
||||
export const terminalSendSequenceCommand = (accessor: ServicesAccessor, args: any) => {
|
||||
const terminalInstance = accessor.get(ITerminalService).getActiveInstance();
|
||||
if (!terminalInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
const configurationResolverService = accessor.get(IConfigurationResolverService);
|
||||
const workspaceContextService = accessor.get(IWorkspaceContextService);
|
||||
const historyService = accessor.get(IHistoryService);
|
||||
const activeWorkspaceRootUri = historyService.getLastActiveWorkspaceRoot(Schemas.file);
|
||||
const lastActiveWorkspaceRoot = activeWorkspaceRootUri ? withNullAsUndefined(workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri)) : undefined;
|
||||
const resolvedText = configurationResolverService.resolve(lastActiveWorkspaceRoot, args.text);
|
||||
terminalInstance.sendText(resolvedText, false);
|
||||
};
|
||||
|
||||
export class CreateNewWithCwdTerminalAction extends Action2 {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.NEW_WITH_CWD;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.newWithCwd', "Create New Integrated Terminal Starting in a Custom Working Directory");
|
||||
@@ -609,7 +525,7 @@ export class SelectDefaultShellWindowsTerminalAction extends Action {
|
||||
}
|
||||
|
||||
public run(event?: any): Promise<any> {
|
||||
return this._terminalService.selectDefaultWindowsShell();
|
||||
return this._terminalService.selectDefaultShell();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,6 +595,7 @@ export class RunActiveFileInTerminalAction extends Action {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
// TODO: Convert this to ctrl+c, ctrl+v for pwsh?
|
||||
const path = await this.terminalService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title, instance.shellType);
|
||||
instance.sendText(path, true);
|
||||
return this.terminalService.showPanel();
|
||||
@@ -707,7 +624,7 @@ export class SwitchTerminalAction extends Action {
|
||||
}
|
||||
if (item === SelectDefaultShellWindowsTerminalAction.LABEL) {
|
||||
this.terminalService.refreshActiveTab();
|
||||
return this.terminalService.selectDefaultWindowsShell();
|
||||
return this.terminalService.selectDefaultShell();
|
||||
}
|
||||
const selectedTabIndex = parseInt(item.split(':')[0], 10) - 1;
|
||||
this.terminalService.setActiveTabByIndex(selectedTabIndex);
|
||||
@@ -725,7 +642,7 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem {
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IContextViewService contextViewService: IContextViewService
|
||||
) {
|
||||
super(null, action, terminalService.getTabLabels().map(label => <ISelectOptionItem>{ text: label }), terminalService.activeTabIndex, contextViewService, { ariaLabel: nls.localize('terminals', 'Open Terminals.') });
|
||||
super(null, action, getTerminalSelectOpenItems(terminalService), terminalService.activeTabIndex, contextViewService, { ariaLabel: nls.localize('terminals', 'Open Terminals.') });
|
||||
|
||||
this._register(terminalService.onInstancesChanged(this._updateItems, this));
|
||||
this._register(terminalService.onActiveTabChanged(this._updateItems, this));
|
||||
@@ -738,18 +655,22 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem {
|
||||
super.render(container);
|
||||
addClass(container, 'switch-terminal');
|
||||
this._register(attachStylerCallback(this.themeService, { selectBorder }, colors => {
|
||||
container.style.border = colors.selectBorder ? `1px solid ${colors.selectBorder}` : '';
|
||||
container.style.borderColor = colors.selectBorder ? `${colors.selectBorder}` : '';
|
||||
}));
|
||||
}
|
||||
|
||||
private _updateItems(): void {
|
||||
const items = this.terminalService.getTabLabels().map(label => <ISelectOptionItem>{ text: label });
|
||||
items.push({ text: SwitchTerminalActionViewItem.SEPARATOR, isDisabled: true });
|
||||
items.push({ text: SelectDefaultShellWindowsTerminalAction.LABEL });
|
||||
this.setOptions(items, this.terminalService.activeTabIndex);
|
||||
this.setOptions(getTerminalSelectOpenItems(this.terminalService), this.terminalService.activeTabIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function getTerminalSelectOpenItems(terminalService: ITerminalService): ISelectOptionItem[] {
|
||||
const items = terminalService.getTabLabels().map(label => <ISelectOptionItem>{ text: label });
|
||||
items.push({ text: SwitchTerminalActionViewItem.SEPARATOR, isDisabled: true });
|
||||
items.push({ text: SelectDefaultShellWindowsTerminalAction.LABEL });
|
||||
return items;
|
||||
}
|
||||
|
||||
export class ScrollDownTerminalAction extends Action {
|
||||
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.SCROLL_DOWN_LINE;
|
||||
@@ -957,6 +878,7 @@ export class ClearTerminalAction extends Action {
|
||||
const terminalInstance = this.terminalService.getActiveInstance();
|
||||
if (terminalInstance) {
|
||||
terminalInstance.clear();
|
||||
terminalInstance.focus();
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -124,9 +124,23 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
|
||||
fontSize,
|
||||
letterSpacing,
|
||||
lineHeight,
|
||||
charWidth: rect && rect.width ? rect.width : 0,
|
||||
charHeight: rect && rect.height ? Math.ceil(rect.height) : 0
|
||||
charWidth: 0,
|
||||
charHeight: 0
|
||||
};
|
||||
|
||||
if (rect && rect.width && rect.height) {
|
||||
this._lastFontMeasurement.charHeight = Math.ceil(rect.height);
|
||||
// Char width is calculated differently for DOM and the other renderer types. Refer to
|
||||
// how each renderer updates their dimensions in xterm.js
|
||||
if (this.config.rendererType === 'dom') {
|
||||
this._lastFontMeasurement.charWidth = rect.width;
|
||||
} else {
|
||||
const scaledCharWidth = rect.width * window.devicePixelRatio;
|
||||
const scaledCellWidth = scaledCharWidth + Math.round(letterSpacing);
|
||||
this._lastFontMeasurement.charWidth = Math.round(scaledCellWidth / window.devicePixelRatio);
|
||||
}
|
||||
}
|
||||
|
||||
return this._lastFontMeasurement;
|
||||
}
|
||||
|
||||
@@ -167,14 +181,14 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
|
||||
|
||||
// Get the character dimensions from xterm if it's available
|
||||
if (xtermCore) {
|
||||
if (xtermCore._charSizeService && xtermCore._charSizeService.width && xtermCore._charSizeService.height) {
|
||||
if (xtermCore._renderService && xtermCore._renderService.dimensions?.actualCellWidth && xtermCore._renderService.dimensions?.actualCellHeight) {
|
||||
return {
|
||||
fontFamily,
|
||||
fontSize,
|
||||
letterSpacing,
|
||||
lineHeight,
|
||||
charHeight: xtermCore._charSizeService.height,
|
||||
charWidth: xtermCore._charSizeService.width
|
||||
charHeight: xtermCore._renderService.dimensions.actualCellHeight / lineHeight,
|
||||
charWidth: xtermCore._renderService.dimensions.actualCellWidth
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +277,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
public constructor(
|
||||
private readonly _terminalFocusContextKey: IContextKey<boolean>,
|
||||
private readonly _terminalShellTypeContextKey: IContextKey<string>,
|
||||
private readonly _configHelper: TerminalConfigHelper,
|
||||
private _container: HTMLElement | undefined,
|
||||
private _shellLaunchConfig: IShellLaunchConfig,
|
||||
@@ -488,7 +489,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
fastScrollSensitivity: editorOptions.fastScrollSensitivity,
|
||||
scrollSensitivity: editorOptions.mouseWheelScrollSensitivity,
|
||||
rendererType: config.rendererType === 'auto' || config.rendererType === 'experimentalWebgl' ? 'canvas' : config.rendererType,
|
||||
wordSeparator: ' ()[]{}\',"`'
|
||||
wordSeparator: config.wordSeparators
|
||||
});
|
||||
this._xterm = xterm;
|
||||
this._xtermCore = (xterm as any)._core as XTermCore;
|
||||
@@ -671,13 +672,18 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
while (!dom.hasClass(currentElement, 'part')) {
|
||||
currentElement = currentElement.parentElement!;
|
||||
}
|
||||
const hidePanelElement = <HTMLElement>currentElement.querySelector('.hide-panel-action');
|
||||
hidePanelElement.focus();
|
||||
const hidePanelElement = currentElement.querySelector<HTMLElement>('.hide-panel-action');
|
||||
hidePanelElement?.focus();
|
||||
}));
|
||||
xtermHelper.insertBefore(focusTrap, xterm.textarea);
|
||||
|
||||
this._register(dom.addDisposableListener(xterm.textarea, 'focus', () => {
|
||||
this._terminalFocusContextKey.set(true);
|
||||
if (this.shellType) {
|
||||
this._terminalShellTypeContextKey.set(this.shellType.toString());
|
||||
} else {
|
||||
this._terminalShellTypeContextKey.reset();
|
||||
}
|
||||
this._onFocused.fire(this);
|
||||
}));
|
||||
this._register(dom.addDisposableListener(xterm.textarea, 'blur', () => {
|
||||
@@ -686,6 +692,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}));
|
||||
this._register(dom.addDisposableListener(xterm.element, 'focus', () => {
|
||||
this._terminalFocusContextKey.set(true);
|
||||
if (this.shellType) {
|
||||
this._terminalShellTypeContextKey.set(this.shellType.toString());
|
||||
} else {
|
||||
this._terminalShellTypeContextKey.reset();
|
||||
}
|
||||
}));
|
||||
this._register(dom.addDisposableListener(xterm.element, 'blur', () => {
|
||||
this._terminalFocusContextKey.reset();
|
||||
@@ -1248,6 +1259,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._safeSetOption('macOptionIsMeta', config.macOptionIsMeta);
|
||||
this._safeSetOption('macOptionClickForcesSelection', config.macOptionClickForcesSelection);
|
||||
this._safeSetOption('rightClickSelectsWord', config.rightClickBehavior === 'selectWord');
|
||||
this._safeSetOption('wordSeparator', config.wordSeparators);
|
||||
if (config.rendererType !== 'experimentalWebgl') {
|
||||
// Never set webgl as it's an addon not a rendererType
|
||||
this._safeSetOption('rendererType', config.rendererType === 'auto' ? 'canvas' : config.rendererType);
|
||||
|
||||
@@ -24,6 +24,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { IEnvironmentVariableService, IMergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService';
|
||||
|
||||
/** The amount of time to consider terminal errors to be related to the launch */
|
||||
const LAUNCHING_DURATION = 500;
|
||||
@@ -90,6 +91,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
@IProductService private readonly _productService: IProductService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
|
||||
@IRemotePathService private readonly _remotePathService: IRemotePathService,
|
||||
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService
|
||||
) {
|
||||
super();
|
||||
@@ -133,23 +135,22 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
const hasRemoteAuthority = !!this.remoteAuthority;
|
||||
let launchRemotely = hasRemoteAuthority || forceExtHostProcess;
|
||||
|
||||
this.userHome = this._environmentService.userHome;
|
||||
const userHomeUri = await this._remotePathService.userHome;
|
||||
this.os = platform.OS;
|
||||
if (launchRemotely) {
|
||||
this.userHome = userHomeUri.path;
|
||||
if (hasRemoteAuthority) {
|
||||
this._remoteAgentService.getEnvironment().then(env => {
|
||||
if (!env) {
|
||||
return;
|
||||
}
|
||||
this.userHome = env.userHome.path;
|
||||
this.os = env.os;
|
||||
});
|
||||
const remoteEnv = await this._remoteAgentService.getEnvironment();
|
||||
if (remoteEnv) {
|
||||
this.os = remoteEnv.os;
|
||||
}
|
||||
}
|
||||
|
||||
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot();
|
||||
this._process = this._instantiationService.createInstance(TerminalProcessExtHostProxy, this._terminalId, shellLaunchConfig, activeWorkspaceRootUri, cols, rows, this._configHelper);
|
||||
} else {
|
||||
this._process = await this._launchProcess(shellLaunchConfig, cols, rows, isScreenReaderModeEnabled);
|
||||
this.userHome = userHomeUri.fsPath;
|
||||
this._process = await this._launchProcess(shellLaunchConfig, cols, rows, this.userHome, isScreenReaderModeEnabled);
|
||||
}
|
||||
}
|
||||
this.processState = ProcessState.LAUNCHING;
|
||||
@@ -194,6 +195,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
shellLaunchConfig: IShellLaunchConfig,
|
||||
cols: number,
|
||||
rows: number,
|
||||
userHome: string,
|
||||
isScreenReaderModeEnabled: boolean
|
||||
): Promise<ITerminalChildProcess> {
|
||||
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
|
||||
@@ -220,7 +222,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
|
||||
const initialCwd = terminalEnvironment.getCwd(
|
||||
shellLaunchConfig,
|
||||
this._environmentService.userHome,
|
||||
userHome,
|
||||
lastActiveWorkspace,
|
||||
this._configurationResolverService,
|
||||
activeWorkspaceRootUri,
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { TERMINAL_VIEW_ID, IShellLaunchConfig, ITerminalConfigHelper, ITerminalNativeService, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, IAvailableShellsRequest, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, ITerminalProcessExtHostProxy, IShellDefinition, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TERMINAL_VIEW_ID, IShellLaunchConfig, ITerminalConfigHelper, ITerminalNativeService, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, IAvailableShellsRequest, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, ITerminalProcessExtHostProxy, IShellDefinition, LinuxDistro, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView';
|
||||
@@ -26,10 +25,12 @@ import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { isWindows, isMacintosh, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { IOpenFileRequest } from 'vs/platform/windows/common/windows';
|
||||
// TODO@daniel code layering
|
||||
// eslint-disable-next-line code-layering, code-import-patterns
|
||||
import { INativeOpenFileRequest } from 'vs/platform/windows/node/window';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { IViewsService, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
interface IExtHostReadyEntry {
|
||||
@@ -40,12 +41,13 @@ interface IExtHostReadyEntry {
|
||||
export class TerminalService implements ITerminalService {
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
protected _isShuttingDown: boolean;
|
||||
protected _terminalFocusContextKey: IContextKey<boolean>;
|
||||
protected _findWidgetVisible: IContextKey<boolean>;
|
||||
protected _terminalTabs: ITerminalTab[] = [];
|
||||
protected _backgroundedTerminalInstances: ITerminalInstance[] = [];
|
||||
protected get _terminalInstances(): ITerminalInstance[] {
|
||||
private _isShuttingDown: boolean;
|
||||
private _terminalFocusContextKey: IContextKey<boolean>;
|
||||
private _terminalShellTypeContextKey: IContextKey<string>;
|
||||
private _findWidgetVisible: IContextKey<boolean>;
|
||||
private _terminalTabs: ITerminalTab[] = [];
|
||||
private _backgroundedTerminalInstances: ITerminalInstance[] = [];
|
||||
private get _terminalInstances(): ITerminalInstance[] {
|
||||
return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), <ITerminalInstance[]>[]);
|
||||
}
|
||||
private _findState: FindReplaceState;
|
||||
@@ -62,38 +64,37 @@ export class TerminalService implements ITerminalService {
|
||||
|
||||
public get configHelper(): ITerminalConfigHelper { return this._configHelper; }
|
||||
|
||||
protected readonly _onActiveTabChanged = new Emitter<void>();
|
||||
private readonly _onActiveTabChanged = new Emitter<void>();
|
||||
public get onActiveTabChanged(): Event<void> { return this._onActiveTabChanged.event; }
|
||||
protected readonly _onInstanceCreated = new Emitter<ITerminalInstance>();
|
||||
private readonly _onInstanceCreated = new Emitter<ITerminalInstance>();
|
||||
public get onInstanceCreated(): Event<ITerminalInstance> { return this._onInstanceCreated.event; }
|
||||
protected readonly _onInstanceDisposed = new Emitter<ITerminalInstance>();
|
||||
private readonly _onInstanceDisposed = new Emitter<ITerminalInstance>();
|
||||
public get onInstanceDisposed(): Event<ITerminalInstance> { return this._onInstanceDisposed.event; }
|
||||
protected readonly _onInstanceProcessIdReady = new Emitter<ITerminalInstance>();
|
||||
private readonly _onInstanceProcessIdReady = new Emitter<ITerminalInstance>();
|
||||
public get onInstanceProcessIdReady(): Event<ITerminalInstance> { return this._onInstanceProcessIdReady.event; }
|
||||
protected readonly _onInstanceRequestSpawnExtHostProcess = new Emitter<ISpawnExtHostProcessRequest>();
|
||||
private readonly _onInstanceRequestSpawnExtHostProcess = new Emitter<ISpawnExtHostProcessRequest>();
|
||||
public get onInstanceRequestSpawnExtHostProcess(): Event<ISpawnExtHostProcessRequest> { return this._onInstanceRequestSpawnExtHostProcess.event; }
|
||||
protected readonly _onInstanceRequestStartExtensionTerminal = new Emitter<IStartExtensionTerminalRequest>();
|
||||
private readonly _onInstanceRequestStartExtensionTerminal = new Emitter<IStartExtensionTerminalRequest>();
|
||||
public get onInstanceRequestStartExtensionTerminal(): Event<IStartExtensionTerminalRequest> { return this._onInstanceRequestStartExtensionTerminal.event; }
|
||||
protected readonly _onInstanceDimensionsChanged = new Emitter<ITerminalInstance>();
|
||||
private readonly _onInstanceDimensionsChanged = new Emitter<ITerminalInstance>();
|
||||
public get onInstanceDimensionsChanged(): Event<ITerminalInstance> { return this._onInstanceDimensionsChanged.event; }
|
||||
protected readonly _onInstanceMaximumDimensionsChanged = new Emitter<ITerminalInstance>();
|
||||
private readonly _onInstanceMaximumDimensionsChanged = new Emitter<ITerminalInstance>();
|
||||
public get onInstanceMaximumDimensionsChanged(): Event<ITerminalInstance> { return this._onInstanceMaximumDimensionsChanged.event; }
|
||||
protected readonly _onInstancesChanged = new Emitter<void>();
|
||||
private readonly _onInstancesChanged = new Emitter<void>();
|
||||
public get onInstancesChanged(): Event<void> { return this._onInstancesChanged.event; }
|
||||
protected readonly _onInstanceTitleChanged = new Emitter<ITerminalInstance>();
|
||||
private readonly _onInstanceTitleChanged = new Emitter<ITerminalInstance>();
|
||||
public get onInstanceTitleChanged(): Event<ITerminalInstance> { return this._onInstanceTitleChanged.event; }
|
||||
protected readonly _onActiveInstanceChanged = new Emitter<ITerminalInstance | undefined>();
|
||||
private readonly _onActiveInstanceChanged = new Emitter<ITerminalInstance | undefined>();
|
||||
public get onActiveInstanceChanged(): Event<ITerminalInstance | undefined> { return this._onActiveInstanceChanged.event; }
|
||||
protected readonly _onTabDisposed = new Emitter<ITerminalTab>();
|
||||
private readonly _onTabDisposed = new Emitter<ITerminalTab>();
|
||||
public get onTabDisposed(): Event<ITerminalTab> { return this._onTabDisposed.event; }
|
||||
protected readonly _onRequestAvailableShells = new Emitter<IAvailableShellsRequest>();
|
||||
private readonly _onRequestAvailableShells = new Emitter<IAvailableShellsRequest>();
|
||||
public get onRequestAvailableShells(): Event<IAvailableShellsRequest> { return this._onRequestAvailableShells.event; }
|
||||
|
||||
private readonly _terminalNativeService: ITerminalNativeService | undefined;
|
||||
|
||||
constructor(
|
||||
@IContextKeyService private _contextKeyService: IContextKeyService,
|
||||
@IPanelService private _panelService: IPanelService,
|
||||
@IWorkbenchLayoutService private _layoutService: IWorkbenchLayoutService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@IDialogService private _dialogService: IDialogService,
|
||||
@@ -103,6 +104,7 @@ export class TerminalService implements ITerminalService {
|
||||
@IQuickInputService private _quickInputService: IQuickInputService,
|
||||
@IConfigurationService private _configurationService: IConfigurationService,
|
||||
@IViewsService private _viewsService: IViewsService,
|
||||
@IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService,
|
||||
@optional(ITerminalNativeService) terminalNativeService: ITerminalNativeService
|
||||
) {
|
||||
// @optional could give undefined and properly typing it breaks service registration
|
||||
@@ -118,6 +120,7 @@ export class TerminalService implements ITerminalService {
|
||||
this._terminalNativeService.onOsResume(() => this._onOsResume());
|
||||
}
|
||||
this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService);
|
||||
this._terminalShellTypeContextKey = KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE.bindTo(this._contextKeyService);
|
||||
this._findWidgetVisible = KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE.bindTo(this._contextKeyService);
|
||||
this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper, this._terminalNativeService?.linuxDistro || LinuxDistro.Unknown);
|
||||
this.onTabDisposed(tab => this._removeTab(tab));
|
||||
@@ -207,7 +210,7 @@ export class TerminalService implements ITerminalService {
|
||||
this.terminalInstances.forEach(instance => instance.dispose(true));
|
||||
}
|
||||
|
||||
private async _onOpenFileRequest(request: IOpenFileRequest): Promise<void> {
|
||||
private async _onOpenFileRequest(request: INativeOpenFileRequest): Promise<void> {
|
||||
// if the request to open files is coming in from the integrated terminal (identified though
|
||||
// the termProgram variable) and we are instructed to wait for editors close, wait for the
|
||||
// marker file to get deleted and then focus back to the integrated terminal.
|
||||
@@ -582,8 +585,8 @@ export class TerminalService implements ITerminalService {
|
||||
});
|
||||
}
|
||||
|
||||
public async selectDefaultWindowsShell(): Promise<void> {
|
||||
const shells = await this._detectWindowsShells();
|
||||
public async selectDefaultShell(): Promise<void> {
|
||||
const shells = await this._detectShells();
|
||||
const options: IPickOptions<IQuickPickItem> = {
|
||||
placeHolder: nls.localize('terminal.integrated.chooseWindowsShell', "Select your preferred terminal shell, you can change this later in your settings")
|
||||
};
|
||||
@@ -605,13 +608,13 @@ export class TerminalService implements ITerminalService {
|
||||
await this._configurationService.updateValue(`terminal.integrated.shell.${platformKey}`, shell, ConfigurationTarget.USER);
|
||||
}
|
||||
|
||||
private _detectWindowsShells(): Promise<IShellDefinition[]> {
|
||||
private _detectShells(): Promise<IShellDefinition[]> {
|
||||
return new Promise(r => this._onRequestAvailableShells.fire({ callback: r }));
|
||||
}
|
||||
|
||||
|
||||
public createInstance(container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance {
|
||||
const instance = this._instantiationService.createInstance(TerminalInstance, this._terminalFocusContextKey, this._configHelper, container, shellLaunchConfig);
|
||||
const instance = this._instantiationService.createInstance(TerminalInstance, this._terminalFocusContextKey, this._terminalShellTypeContextKey, this._configHelper, container, shellLaunchConfig);
|
||||
this._onInstanceCreated.fire(instance);
|
||||
return instance;
|
||||
}
|
||||
@@ -623,11 +626,7 @@ export class TerminalService implements ITerminalService {
|
||||
this._initInstanceListeners(instance);
|
||||
return instance;
|
||||
}
|
||||
const terminalTab = this._instantiationService.createInstance(TerminalTab,
|
||||
this._terminalFocusContextKey,
|
||||
this.configHelper,
|
||||
this._terminalContainer,
|
||||
shell);
|
||||
const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalContainer, shell);
|
||||
this._terminalTabs.push(terminalTab);
|
||||
const instance = terminalTab.terminalInstances[0];
|
||||
terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed));
|
||||
@@ -644,11 +643,7 @@ export class TerminalService implements ITerminalService {
|
||||
protected _showBackgroundTerminal(instance: ITerminalInstance): void {
|
||||
this._backgroundedTerminalInstances.splice(this._backgroundedTerminalInstances.indexOf(instance), 1);
|
||||
instance.shellLaunchConfig.hideFromUser = false;
|
||||
const terminalTab = this._instantiationService.createInstance(TerminalTab,
|
||||
this._terminalFocusContextKey,
|
||||
this.configHelper,
|
||||
this._terminalContainer,
|
||||
instance);
|
||||
const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalContainer, instance);
|
||||
this._terminalTabs.push(terminalTab);
|
||||
terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed));
|
||||
terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged));
|
||||
@@ -698,9 +693,13 @@ export class TerminalService implements ITerminalService {
|
||||
}
|
||||
|
||||
public hidePanel(): void {
|
||||
const panel = this._panelService.getActivePanel();
|
||||
if (panel && panel.getId() === TERMINAL_VIEW_ID) {
|
||||
this._layoutService.setPanelHidden(true);
|
||||
// Hide the panel if the terminal is in the panel and it has no sibling views
|
||||
const location = this._viewDescriptorService.getViewLocation(TERMINAL_VIEW_ID);
|
||||
if (location === ViewContainerLocation.Panel) {
|
||||
const panel = this._viewDescriptorService.getViewContainer(TERMINAL_VIEW_ID);
|
||||
if (panel && this._viewDescriptorService.getViewDescriptors(panel).activeViewDescriptors.length === 1) {
|
||||
this._layoutService.setPanelHidden(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IShellLaunchConfig, ITerminalConfigHelper, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IShellLaunchConfig, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { SplitView, Orientation, IView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
|
||||
@@ -228,8 +227,6 @@ export class TerminalTab extends Disposable implements ITerminalTab {
|
||||
public readonly onInstancesChanged: Event<void> = this._onInstancesChanged.event;
|
||||
|
||||
constructor(
|
||||
terminalFocusContextKey: IContextKey<boolean>,
|
||||
configHelper: ITerminalConfigHelper,
|
||||
private _container: HTMLElement | undefined,
|
||||
shellLaunchConfigOrInstance: IShellLaunchConfig | ITerminalInstance,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
|
||||
@@ -232,6 +232,13 @@ export class TerminalViewPane extends ViewPane {
|
||||
if (!terminal) {
|
||||
return;
|
||||
}
|
||||
|
||||
// copyPaste: Shift+right click should open context menu
|
||||
if (rightClickBehavior === 'copyPaste' && event.shiftKey) {
|
||||
this._openContextMenu(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rightClickBehavior === 'copyPaste' && terminal.hasSelection()) {
|
||||
await terminal.copySelection();
|
||||
terminal.clearSelection();
|
||||
@@ -253,13 +260,7 @@ export class TerminalViewPane extends ViewPane {
|
||||
}));
|
||||
this._register(dom.addDisposableListener(parentDomElement, 'contextmenu', (event: MouseEvent) => {
|
||||
if (!this._cancelContextMenu) {
|
||||
const standardEvent = new StandardMouseEvent(event);
|
||||
const anchor: { x: number, y: number } = { x: standardEvent.posx, y: standardEvent.posy };
|
||||
this._contextMenuService.showContextMenu({
|
||||
getAnchor: () => anchor,
|
||||
getActions: () => this._getContextMenuActions(),
|
||||
getActionsContext: () => this._parentDomElement
|
||||
});
|
||||
this._openContextMenu(event);
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
@@ -306,6 +307,16 @@ export class TerminalViewPane extends ViewPane {
|
||||
}));
|
||||
}
|
||||
|
||||
private _openContextMenu(event: MouseEvent): void {
|
||||
const standardEvent = new StandardMouseEvent(event);
|
||||
const anchor: { x: number, y: number } = { x: standardEvent.posx, y: standardEvent.posy };
|
||||
this._contextMenuService.showContextMenu({
|
||||
getAnchor: () => anchor,
|
||||
getActions: () => this._getContextMenuActions(),
|
||||
getActionsContext: () => this._parentDomElement
|
||||
});
|
||||
}
|
||||
|
||||
private _updateTheme(theme?: IColorTheme): void {
|
||||
if (!theme) {
|
||||
theme = this.themeService.getColorTheme();
|
||||
|
||||
@@ -17,6 +17,10 @@ export interface XTermCore {
|
||||
};
|
||||
|
||||
_renderService: {
|
||||
dimensions: {
|
||||
actualCellWidth: number;
|
||||
actualCellHeight: number;
|
||||
},
|
||||
_renderer: {
|
||||
_renderLayers: any[];
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IEnvironmentVariableCollection, EnvironmentVariableMutatorType, IMergedEnvironmentVariableCollection, IMergedEnvironmentVariableCollectionDiff, IExtensionOwnedEnvironmentVariableMutator } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { IProcessEnvironment, isWindows } from 'vs/base/common/platform';
|
||||
|
||||
export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVariableCollection {
|
||||
readonly map: Map<string, IExtensionOwnedEnvironmentVariableMutator[]> = new Map();
|
||||
@@ -42,17 +42,23 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa
|
||||
}
|
||||
|
||||
applyToProcessEnvironment(env: IProcessEnvironment): void {
|
||||
let lowerToActualVariableNames: { [lowerKey: string]: string | undefined } | undefined;
|
||||
if (isWindows) {
|
||||
lowerToActualVariableNames = {};
|
||||
Object.keys(env).forEach(e => lowerToActualVariableNames![e.toLowerCase()] = e);
|
||||
}
|
||||
this.map.forEach((mutators, variable) => {
|
||||
const actualVariable = isWindows ? lowerToActualVariableNames![variable.toLowerCase()] || variable : variable;
|
||||
mutators.forEach(mutator => {
|
||||
switch (mutator.type) {
|
||||
case EnvironmentVariableMutatorType.Append:
|
||||
env[variable] = (env[variable] || '') + mutator.value;
|
||||
env[actualVariable] = (env[actualVariable] || '') + mutator.value;
|
||||
break;
|
||||
case EnvironmentVariableMutatorType.Prepend:
|
||||
env[variable] = mutator.value + (env[variable] || '');
|
||||
env[actualVariable] = mutator.value + (env[actualVariable] || '');
|
||||
break;
|
||||
case EnvironmentVariableMutatorType.Replace:
|
||||
env[variable] = mutator.value;
|
||||
env[actualVariable] = mutator.value;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,10 +16,17 @@ export const TERMINAL_VIEW_ID = 'workbench.panel.terminal';
|
||||
|
||||
/** A context key that is set when there is at least one opened integrated terminal. */
|
||||
export const KEYBINDING_CONTEXT_TERMINAL_IS_OPEN = new RawContextKey<boolean>('terminalIsOpen', false);
|
||||
|
||||
/** A context key that is set when the integrated terminal has focus. */
|
||||
export const KEYBINDING_CONTEXT_TERMINAL_FOCUS = new RawContextKey<boolean>('terminalFocus', false);
|
||||
|
||||
export const KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY = 'terminalShellType';
|
||||
/** A context key that is set to the detected shell for the most recently active terminal, this is set to the last known value when no terminals exist. */
|
||||
export const KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE = new RawContextKey<string>(KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY, undefined);
|
||||
|
||||
/** A context key that is set when the integrated terminal does not have focus. */
|
||||
export const KEYBINDING_CONTEXT_TERMINAL_NOT_FOCUSED = 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);
|
||||
|
||||
@@ -120,6 +127,7 @@ export interface ITerminalConfiguration {
|
||||
showExitAlert: boolean;
|
||||
splitCwd: 'workspaceRoot' | 'initial' | 'inherited';
|
||||
windowsEnableConpty: boolean;
|
||||
wordSeparators: string;
|
||||
experimentalUseTitleEvent: boolean;
|
||||
enableFileLinks: boolean;
|
||||
unicodeVersion: '6' | '11';
|
||||
|
||||
@@ -109,8 +109,8 @@ async function detectAvailableWindowsShells(): Promise<IShellDefinition[]> {
|
||||
|
||||
const expectedLocations: { [key: string]: string[] } = {
|
||||
'Command Prompt': [`${system32Path}\\cmd.exe`],
|
||||
PowerShell: [`${system32Path}\\WindowsPowerShell\\v1.0\\powershell.exe`],
|
||||
'PowerShell Core': [await getShellPathFromRegistry('pwsh')],
|
||||
'Windows PowerShell': [`${system32Path}\\WindowsPowerShell\\v1.0\\powershell.exe`],
|
||||
'PowerShell': [await getShellPathFromRegistry('pwsh')],
|
||||
'WSL Bash': [`${system32Path}\\${useWSLexe ? 'wsl.exe' : 'bash.exe'}`],
|
||||
'Git Bash': [
|
||||
`${process.env['ProgramW6432']}\\Git\\bin\\bash.exe`,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { deepStrictEqual, strictEqual } from 'assert';
|
||||
import { EnvironmentVariableMutatorType } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { IProcessEnvironment, isWindows } from 'vs/base/common/platform';
|
||||
import { MergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableCollection';
|
||||
import { deserializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
|
||||
|
||||
@@ -119,6 +119,40 @@ suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => {
|
||||
C: 'c'
|
||||
});
|
||||
});
|
||||
|
||||
test('should apply to variable case insensitively on Windows only', () => {
|
||||
const merged = new MergedEnvironmentVariableCollection(new Map([
|
||||
['ext', {
|
||||
map: deserializeEnvironmentVariableCollection([
|
||||
['a', { value: 'a', type: EnvironmentVariableMutatorType.Replace }],
|
||||
['b', { value: 'b', type: EnvironmentVariableMutatorType.Append }],
|
||||
['c', { value: 'c', type: EnvironmentVariableMutatorType.Prepend }]
|
||||
])
|
||||
}]
|
||||
]));
|
||||
const env: IProcessEnvironment = {
|
||||
A: 'A',
|
||||
B: 'B',
|
||||
C: 'C'
|
||||
};
|
||||
merged.applyToProcessEnvironment(env);
|
||||
if (isWindows) {
|
||||
deepStrictEqual(env, {
|
||||
A: 'a',
|
||||
B: 'Bb',
|
||||
C: 'cC'
|
||||
});
|
||||
} else {
|
||||
deepStrictEqual(env, {
|
||||
a: 'a',
|
||||
A: 'A',
|
||||
b: 'b',
|
||||
B: 'B',
|
||||
c: 'c',
|
||||
C: 'C'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
suite('diff', () => {
|
||||
|
||||
Reference in New Issue
Block a user