mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 01:00:29 -04:00
Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c (#8525)
* Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c * remove files we don't want * fix hygiene * update distro * update distro * fix hygiene * fix strict nulls * distro * distro * fix tests * fix tests * add another edit * fix viewlet icon * fix azure dialog * fix some padding * fix more padding issues
This commit is contained in:
@@ -64,7 +64,15 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon {
|
||||
}
|
||||
|
||||
let markerIndex;
|
||||
if (this._currentMarker === Boundary.Bottom) {
|
||||
const currentLineY = Math.min(this._getLine(this._terminal, this._currentMarker), this._terminal.buffer.baseY);
|
||||
const viewportY = this._terminal.buffer.viewportY;
|
||||
if (!retainSelection && currentLineY !== viewportY) {
|
||||
// The user has scrolled, find the line based on the current scroll position. This only
|
||||
// works when not retaining selection
|
||||
const markersBelowViewport = this._terminal.markers.filter(e => e.line >= viewportY).length;
|
||||
// -1 will scroll to the top
|
||||
markerIndex = this._terminal.markers.length - markersBelowViewport - 1;
|
||||
} else if (this._currentMarker === Boundary.Bottom) {
|
||||
markerIndex = this._terminal.markers.length - 1;
|
||||
} else if (this._currentMarker === Boundary.Top) {
|
||||
markerIndex = -1;
|
||||
@@ -95,7 +103,15 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon {
|
||||
}
|
||||
|
||||
let markerIndex;
|
||||
if (this._currentMarker === Boundary.Bottom) {
|
||||
const currentLineY = Math.min(this._getLine(this._terminal, this._currentMarker), this._terminal.buffer.baseY);
|
||||
const viewportY = this._terminal.buffer.viewportY;
|
||||
if (!retainSelection && currentLineY !== viewportY) {
|
||||
// The user has scrolled, find the line based on the current scroll position. This only
|
||||
// works when not retaining selection
|
||||
const markersAboveViewport = this._terminal.markers.filter(e => e.line <= viewportY).length;
|
||||
// markers.length will scroll to the bottom
|
||||
markerIndex = markersAboveViewport;
|
||||
} else if (this._currentMarker === Boundary.Bottom) {
|
||||
markerIndex = this._terminal.markers.length;
|
||||
} else if (this._currentMarker === Boundary.Top) {
|
||||
markerIndex = 0;
|
||||
|
||||
@@ -38,4 +38,4 @@
|
||||
|
||||
.monaco-workbench .panel.integrated-terminal .xterm .xterm-viewport::-webkit-scrollbar-thumb:window-inactive {
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
flex-direction: column;
|
||||
background-color: transparent!important;
|
||||
user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -104,6 +105,7 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.monaco-workbench .panel.integrated-terminal .monaco-split-view2.vertical .split-view-view:not(:last-child) .xterm {
|
||||
/* When vertical and NOT the bottom terminal, align to the top instead to prevent the output jumping around erratically */
|
||||
@@ -149,6 +151,11 @@
|
||||
cursor: -webkit-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAL0lEQVQoz2NgCD3x//9/BhBYBWdhgFVAiVW4JBFKGIa4AqD0//9D3pt4I4tAdAMAHTQ/j5Zom30AAAAASUVORK5CYII=') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAz0lEQVRIx2NgYGBY/R8I/vx5eelX3n82IJ9FxGf6tksvf/8FiTMQAcAGQMDvSwu09abffY8QYSAScNk45G198eX//yev73/4///701eh//kZSARckrNBRvz//+8+6ZohwCzjGNjdgQxkAg7B9WADeBjIBqtJCbhRA0YNoIkBSNmaPEMoNmA0FkYNoFKhapJ6FGyAH3nauaSmPfwI0v/3OukVi0CIZ+F25KrtYcx/CTIy0e+rC7R1Z4KMICVTQQ14feVXIbR695u14+Ir4gwAAD49E54wc1kWAAAAAElFTkSuQmCC') 2x) 5 8, text;
|
||||
}
|
||||
|
||||
/* Override default xterm style to make !important so it takes precedence over custom mac cursor */
|
||||
.xterm.xterm-cursor-pointer {
|
||||
cursor: pointer!important;
|
||||
}
|
||||
|
||||
.monaco-workbench .quick-open-terminal-configure {
|
||||
background-image: url('configure-light.svg');
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
font-feature-settings: "liga" 0;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ 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 { ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, DeleteToLineStartTerminalAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, 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, ManageWorkspaceShellPermissionsTerminalCommand, CreateNewWithCwdTerminalCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions';
|
||||
import { ClearSelectionTerminalAction, ClearTerminalAction, CopyTerminalSelectionAction, CreateNewInActiveWorkspaceTerminalAction, CreateNewTerminalAction, DeleteToLineStartTerminalAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, 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, ManageWorkspaceShellPermissionsTerminalCommand, CreateNewWithCwdTerminalCommand, RenameWithArgTerminalCommand } 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, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
@@ -35,6 +35,7 @@ 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 { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
registerSingleton(ITerminalService, TerminalService, true);
|
||||
|
||||
@@ -47,7 +48,7 @@ const quickOpenRegistry = (Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Q
|
||||
const inTerminalsPicker = 'inTerminalPicker';
|
||||
|
||||
quickOpenRegistry.registerQuickOpenHandler(
|
||||
new QuickOpenHandlerDescriptor(
|
||||
QuickOpenHandlerDescriptor.create(
|
||||
TerminalPickerHandler,
|
||||
TerminalPickerHandler.ID,
|
||||
TERMINAL_PICKER_PREFIX,
|
||||
@@ -168,6 +169,11 @@ configurationRegistry.registerConfiguration({
|
||||
type: 'number',
|
||||
default: DEFAULT_LINE_HEIGHT
|
||||
},
|
||||
'terminal.integrated.minimumContrastRatio': {
|
||||
description: nls.localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: The default, do nothing.\n- 4.5: Minimum for WCAG AA compliance.\n- 7: Minimum for WCAG AAA compliance.\n- 21: White on black or black on white."),
|
||||
type: 'number',
|
||||
default: 1
|
||||
},
|
||||
'terminal.integrated.fontWeight': {
|
||||
type: 'string',
|
||||
enum: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
||||
@@ -208,11 +214,12 @@ configurationRegistry.registerConfiguration({
|
||||
},
|
||||
'terminal.integrated.rendererType': {
|
||||
type: 'string',
|
||||
enum: ['auto', 'canvas', 'dom'],
|
||||
enum: ['auto', 'canvas', 'dom', 'experimentalWebgl'],
|
||||
enumDescriptions: [
|
||||
nls.localize('terminal.integrated.rendererType.auto', "Let Azure Data Studio guess which renderer to use."),// {{SQL CARBON EDIT}} Change product name to ADS
|
||||
nls.localize('terminal.integrated.rendererType.canvas', "Use the standard GPU/canvas-based renderer"),
|
||||
nls.localize('terminal.integrated.rendererType.dom', "Use the fallback DOM-based renderer.")
|
||||
nls.localize('terminal.integrated.rendererType.auto', "Let Azure Data Studio which renderer to use."), // {{SQL CARBON EDIT}} Change product name to ADS
|
||||
nls.localize('terminal.integrated.rendererType.canvas', "Use the standard GPU/canvas-based renderer."),
|
||||
nls.localize('terminal.integrated.rendererType.dom', "Use the fallback DOM-based renderer."),
|
||||
nls.localize('terminal.integrated.rendererType.experimentalWebgl', "Use the experimental webgl-based renderer. Note that this has some [known issues](https://github.com/xtermjs/xterm.js/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Faddon%2Fwebgl) and this will only be enabled for new terminals (not hot swappable like the other renderers).")
|
||||
],
|
||||
default: 'auto',
|
||||
description: nls.localize('terminal.integrated.rendererType', "Controls how the terminal is rendered.")
|
||||
@@ -326,11 +333,11 @@ configurationRegistry.registerConfiguration({
|
||||
});
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenTermAction, QuickOpenTermAction.ID, QuickOpenTermAction.LABEL), 'Terminal: Switch Active Terminal', nls.localize('terminal', "Terminal"));
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenTermAction, QuickOpenTermAction.ID, QuickOpenTermAction.LABEL), 'Terminal: Switch Active Terminal', nls.localize('terminal', "Terminal"));
|
||||
const actionBarRegistry = Registry.as<IActionBarRegistry>(ActionBarExtensions.Actionbar);
|
||||
actionBarRegistry.registerActionBarContributor(Scope.VIEWER, QuickOpenActionTermContributor);
|
||||
|
||||
(<panel.PanelRegistry>Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor(
|
||||
(<panel.PanelRegistry>Registry.as(panel.Extensions.Panels)).registerPanel(panel.PanelDescriptor.create(
|
||||
TerminalPanel,
|
||||
TERMINAL_PANEL_ID,
|
||||
nls.localize('terminal', "Terminal"),
|
||||
@@ -343,28 +350,20 @@ Registry.as<panel.PanelRegistry>(panel.Extensions.Panels).setDefaultPanelId(TERM
|
||||
// On mac cmd+` is reserved to cycle between windows, that's why the keybindings use WinCtrl
|
||||
const category = TERMINAL_ACTION_CATEGORY;
|
||||
const actionRegistry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.LABEL), 'Terminal: Kill the Active Terminal Instance', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, CopyTerminalSelectionAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_C,
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C }
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Copy Selection', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(KillTerminalAction, KillTerminalAction.ID, KillTerminalAction.LABEL), 'Terminal: Kill the Active Terminal Instance', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_BACKTICK }
|
||||
}), 'Terminal: Create New Integrated Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearSelectionTerminalAction, ClearSelectionTerminalAction.ID, ClearSelectionTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ClearSelectionTerminalAction, ClearSelectionTerminalAction.ID, ClearSelectionTerminalAction.LABEL, {
|
||||
primary: KeyCode.Escape,
|
||||
linux: { primary: KeyCode.Escape }
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE)), 'Terminal: Clear Selection', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewInActiveWorkspaceTerminalAction, CreateNewInActiveWorkspaceTerminalAction.ID, CreateNewInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (In Active Workspace)', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousTerminalAction, FocusPreviousTerminalAction.ID, FocusPreviousTerminalAction.LABEL), 'Terminal: Focus Previous Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_V,
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_V }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(CreateNewInActiveWorkspaceTerminalAction, CreateNewInActiveWorkspaceTerminalAction.ID, CreateNewInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (In Active Workspace)', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusActiveTerminalAction, FocusActiveTerminalAction.ID, FocusActiveTerminalAction.LABEL), 'Terminal: Focus Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusNextTerminalAction, FocusNextTerminalAction.ID, FocusNextTerminalAction.LABEL), 'Terminal: Focus Next Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusPreviousTerminalAction, FocusPreviousTerminalAction.ID, FocusPreviousTerminalAction.LABEL), 'Terminal: Focus Previous Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL, {
|
||||
// Don't use ctrl+a by default as that would override the common go to start
|
||||
// of prompt shell binding
|
||||
primary: 0,
|
||||
@@ -373,82 +372,82 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectAllTermina
|
||||
// makes it easier for users to see how it works though.
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_A }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select All', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunSelectedTextInTerminalAction, RunSelectedTextInTerminalAction.ID, RunSelectedTextInTerminalAction.LABEL), 'Terminal: Run Selected Text In Active Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunActiveFileInTerminalAction, RunActiveFileInTerminalAction.ID, RunActiveFileInTerminalAction.LABEL), 'Terminal: Run Active File In Active Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(RunSelectedTextInTerminalAction, RunSelectedTextInTerminalAction.ID, RunSelectedTextInTerminalAction.LABEL), 'Terminal: Run Selected Text In Active Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(RunActiveFileInTerminalAction, RunActiveFileInTerminalAction.ID, RunActiveFileInTerminalAction.LABEL), 'Terminal: Run Active File In Active Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyCode.US_BACKTICK }
|
||||
}), 'View: Toggle Integrated Terminal', nls.localize('viewCategory', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownTerminalAction, ScrollDownTerminalAction.ID, ScrollDownTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollDownTerminalAction, ScrollDownTerminalAction.ID, ScrollDownTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageDown,
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Line)', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollDownPageTerminalAction, ScrollDownPageTerminalAction.ID, ScrollDownPageTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollDownPageTerminalAction, ScrollDownPageTerminalAction.ID, ScrollDownPageTerminalAction.LABEL, {
|
||||
primary: KeyMod.Shift | KeyCode.PageDown,
|
||||
mac: { primary: KeyCode.PageDown }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Down (Page)', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToBottomTerminalAction, ScrollToBottomTerminalAction.ID, ScrollToBottomTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollToBottomTerminalAction, ScrollToBottomTerminalAction.ID, ScrollToBottomTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.End,
|
||||
linux: { primary: KeyMod.Shift | KeyCode.End }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Bottom', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpTerminalAction, ScrollUpTerminalAction.ID, ScrollUpTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollUpTerminalAction, ScrollUpTerminalAction.ID, ScrollUpTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.PageUp,
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow },
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Line)', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollUpPageTerminalAction, ScrollUpPageTerminalAction.ID, ScrollUpPageTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollUpPageTerminalAction, ScrollUpPageTerminalAction.ID, ScrollUpPageTerminalAction.LABEL, {
|
||||
primary: KeyMod.Shift | KeyCode.PageUp,
|
||||
mac: { primary: KeyCode.PageUp }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll Up (Page)', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToTopTerminalAction, ScrollToTopTerminalAction.ID, ScrollToTopTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollToTopTerminalAction, ScrollToTopTerminalAction.ID, ScrollToTopTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Home,
|
||||
linux: { primary: KeyMod.Shift | KeyCode.Home }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Scroll to Top', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClearTerminalAction, ClearTerminalAction.ID, ClearTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ClearTerminalAction, ClearTerminalAction.ID, ClearTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_K }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KeybindingWeight.WorkbenchContrib + 1), 'Terminal: Clear', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectDefaultShellWindowsTerminalAction, SelectDefaultShellWindowsTerminalAction.ID, SelectDefaultShellWindowsTerminalAction.LABEL), 'Terminal: Select Default Shell', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ManageWorkspaceShellPermissionsTerminalCommand, ManageWorkspaceShellPermissionsTerminalCommand.ID, ManageWorkspaceShellPermissionsTerminalCommand.LABEL), 'Terminal: Manage Workspace Shell Permissions', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectDefaultShellWindowsTerminalAction, SelectDefaultShellWindowsTerminalAction.ID, SelectDefaultShellWindowsTerminalAction.LABEL), 'Terminal: Select Default Shell', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ManageWorkspaceShellPermissionsTerminalCommand, ManageWorkspaceShellPermissionsTerminalCommand.ID, ManageWorkspaceShellPermissionsTerminalCommand.LABEL), 'Terminal: Manage Workspace Shell Permissions', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_F
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_F
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, {
|
||||
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(new SyncActionDescriptor(DeleteWordLeftTerminalAction, DeleteWordLeftTerminalAction.ID, DeleteWordLeftTerminalAction.LABEL, {
|
||||
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(new SyncActionDescriptor(DeleteWordRightTerminalAction, DeleteWordRightTerminalAction.ID, DeleteWordRightTerminalAction.LABEL, {
|
||||
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(new SyncActionDescriptor(DeleteToLineStartTerminalAction, DeleteToLineStartTerminalAction.ID, DeleteToLineStartTerminalAction.LABEL, {
|
||||
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(new SyncActionDescriptor(MoveToLineStartTerminalAction, MoveToLineStartTerminalAction.ID, MoveToLineStartTerminalAction.LABEL, {
|
||||
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(new SyncActionDescriptor(MoveToLineEndTerminalAction, MoveToLineEndTerminalAction.ID, MoveToLineEndTerminalAction.LABEL, {
|
||||
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(new SyncActionDescriptor(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_5,
|
||||
mac: {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH,
|
||||
secondary: [KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_5]
|
||||
}
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Split Terminal', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SplitInActiveWorkspaceTerminalAction, SplitInActiveWorkspaceTerminalAction.ID, SplitInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Split Terminal (In Active Workspace)', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousPaneTerminalAction, FocusPreviousPaneTerminalAction.ID, FocusPreviousPaneTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SplitInActiveWorkspaceTerminalAction, SplitInActiveWorkspaceTerminalAction.ID, SplitInActiveWorkspaceTerminalAction.LABEL), 'Terminal: Split Terminal (In Active Workspace)', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusPreviousPaneTerminalAction, FocusPreviousPaneTerminalAction.ID, FocusPreviousPaneTerminalAction.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.LeftArrow,
|
||||
secondary: [KeyMod.Alt | KeyCode.UpArrow],
|
||||
mac: {
|
||||
@@ -456,7 +455,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousPan
|
||||
secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.UpArrow]
|
||||
}
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Previous Pane', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextPaneTerminalAction, FocusNextPaneTerminalAction.ID, FocusNextPaneTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusNextPaneTerminalAction, FocusNextPaneTerminalAction.ID, FocusNextPaneTerminalAction.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.RightArrow,
|
||||
secondary: [KeyMod.Alt | KeyCode.DownArrow],
|
||||
mac: {
|
||||
@@ -464,101 +463,116 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextPaneTer
|
||||
secondary: [KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.DownArrow]
|
||||
}
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Next Pane', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneLeftTerminalAction, ResizePaneLeftTerminalAction.ID, ResizePaneLeftTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ResizePaneLeftTerminalAction, ResizePaneLeftTerminalAction.ID, ResizePaneLeftTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow },
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Left', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneRightTerminalAction, ResizePaneRightTerminalAction.ID, ResizePaneRightTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ResizePaneRightTerminalAction, ResizePaneRightTerminalAction.ID, ResizePaneRightTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow },
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Right', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneUpTerminalAction, ResizePaneUpTerminalAction.ID, ResizePaneUpTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ResizePaneUpTerminalAction, ResizePaneUpTerminalAction.ID, ResizePaneUpTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.UpArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Up', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ResizePaneDownTerminalAction, ResizePaneDownTerminalAction.ID, ResizePaneDownTerminalAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ResizePaneDownTerminalAction, ResizePaneDownTerminalAction.ID, ResizePaneDownTerminalAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.DownArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Resize Pane Down', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToPreviousCommandAction, ScrollToPreviousCommandAction.ID, ScrollToPreviousCommandAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollToPreviousCommandAction, ScrollToPreviousCommandAction.ID, ScrollToPreviousCommandAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow }
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate())), 'Terminal: Scroll To Previous Command', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ScrollToNextCommandAction, ScrollToNextCommandAction.ID, ScrollToNextCommandAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ScrollToNextCommandAction, ScrollToNextCommandAction.ID, ScrollToNextCommandAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow }
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate())), 'Terminal: Scroll To Next Command', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToPreviousCommandAction, SelectToPreviousCommandAction.ID, SelectToPreviousCommandAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToPreviousCommandAction, SelectToPreviousCommandAction.ID, SelectToPreviousCommandAction.LABEL, {
|
||||
primary: 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Select To Previous Command', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectToNextCommandAction, SelectToNextCommandAction.ID, SelectToNextCommandAction.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToNextCommandAction, SelectToNextCommandAction.ID, SelectToNextCommandAction.LABEL, {
|
||||
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, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(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, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(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, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(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, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(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, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(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);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToPreviousLineAction, SelectToPreviousLineAction.ID, SelectToPreviousLineAction.LABEL), 'Terminal: Select To Previous Line', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToNextLineAction, SelectToNextLineAction.ID, SelectToNextLineAction.LABEL), 'Terminal: Select To Next Line', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleEscapeSequenceLoggingAction, ToggleEscapeSequenceLoggingAction.ID, ToggleEscapeSequenceLoggingAction.LABEL), 'Terminal: Toggle Escape Sequence Logging', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_R,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using regex');
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleRegexCommand, ToggleRegexCommand.ID_TERMINAL_FOCUS, ToggleRegexCommand.LABEL, {
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using regex', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_R,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using regex', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_W,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using whole word');
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWholeWordCommand, ToggleWholeWordCommand.ID_TERMINAL_FOCUS, ToggleWholeWordCommand.LABEL, {
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using whole word', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_W,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using whole word', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_C,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using case sensitive');
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID_TERMINAL_FOCUS, ToggleCaseSensitiveCommand.LABEL, {
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using case sensitive', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_C,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using case sensitive', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindNext, FindNext.ID_TERMINAL_FOCUS, FindNext.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FindNext, FindNext.ID, FindNext.LABEL, {
|
||||
primary: KeyCode.F3,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Find next', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindNext, FindNext.ID, FindNext.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FindNext, FindNext.ID, FindNext.LABEL, {
|
||||
primary: KeyCode.F3,
|
||||
secondary: [KeyMod.Shift | KeyCode.Enter],
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3, KeyMod.Shift | KeyCode.Enter] }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find next');
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, FindPrevious.ID_TERMINAL_FOCUS, FindPrevious.LABEL, {
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find next', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FindPrevious, FindPrevious.ID, FindPrevious.LABEL, {
|
||||
primary: KeyMod.Shift | KeyCode.F3,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] },
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Find previous', category);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, FindPrevious.ID, FindPrevious.LABEL, {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FindPrevious, FindPrevious.ID, FindPrevious.LABEL, {
|
||||
primary: KeyMod.Shift | KeyCode.F3,
|
||||
secondary: [KeyCode.Enter],
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3, KeyCode.Enter] },
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find previous');
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Find previous', category);
|
||||
|
||||
// Commands might be affected by Web restrictons
|
||||
if (BrowserFeatures.clipboard.writeText) {
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, CopyTerminalSelectionAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_C,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_C, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C] },
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C }
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Copy Selection', category);
|
||||
}
|
||||
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);
|
||||
}
|
||||
(new SendSequenceTerminalCommand({
|
||||
id: SendSequenceTerminalCommand.ID,
|
||||
precondition: undefined,
|
||||
@@ -576,6 +590,7 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, Fi
|
||||
}]
|
||||
}
|
||||
})).register();
|
||||
|
||||
(new CreateNewWithCwdTerminalCommand({
|
||||
id: CreateNewWithCwdTerminalCommand.ID,
|
||||
precondition: undefined,
|
||||
@@ -597,6 +612,28 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FindPrevious, Fi
|
||||
}
|
||||
})).register();
|
||||
|
||||
(new RenameWithArgTerminalCommand({
|
||||
id: RenameWithArgTerminalCommand.ID,
|
||||
precondition: undefined,
|
||||
description: {
|
||||
description: RenameWithArgTerminalCommand.LABEL,
|
||||
args: [{
|
||||
name: 'args',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
description: RenameWithArgTerminalCommand.NAME_ARG_LABEL,
|
||||
type: 'string',
|
||||
minLength: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
})).register();
|
||||
|
||||
setupTerminalCommands();
|
||||
setupTerminalMenu();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
||||
import { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig, IDefaultShellAndArgsRequest, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, IAvailableShellsRequest, ITerminalProcessExtHostProxy, ICommandTracker, INavigationMode, TitleEventSource, ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IProcessEnvironment, Platform } from 'vs/base/common/platform';
|
||||
@@ -31,6 +32,7 @@ export interface ITerminalInstanceService {
|
||||
getXtermConstructor(): Promise<typeof XTermTerminal>;
|
||||
getXtermWebLinksConstructor(): Promise<typeof XTermWebLinksAddon>;
|
||||
getXtermSearchConstructor(): Promise<typeof XTermSearchAddon>;
|
||||
getXtermWebglConstructor(): Promise<typeof XTermWebglAddon>;
|
||||
createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper;
|
||||
createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess;
|
||||
|
||||
@@ -141,7 +143,7 @@ export interface ITerminalService {
|
||||
* @param path The path to be escaped and formatted.
|
||||
* @returns An escaped version of the path to be execuded in the terminal.
|
||||
*/
|
||||
preparePathForTerminalAsync(path: string, executable: string | undefined, title: string): Promise<string>;
|
||||
preparePathForTerminalAsync(path: string, executable: string | undefined, title: string, shellType: TerminalShellType): Promise<string>;
|
||||
|
||||
extHostReady(remoteAuthority: string): void;
|
||||
requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
|
||||
@@ -167,6 +169,14 @@ export interface ISearchOptions {
|
||||
incremental?: boolean;
|
||||
}
|
||||
|
||||
export enum WindowsShellType {
|
||||
CommandPrompt,
|
||||
PowerShell,
|
||||
Wsl,
|
||||
GitBash
|
||||
}
|
||||
export type TerminalShellType = WindowsShellType | undefined;
|
||||
|
||||
export interface ITerminalInstance {
|
||||
/**
|
||||
* The ID of the terminal instance, this is an arbitrary number only used to identify the
|
||||
@@ -228,6 +238,8 @@ export interface ITerminalInstance {
|
||||
*/
|
||||
onExit: Event<number | undefined>;
|
||||
|
||||
readonly exitCode: number | undefined;
|
||||
|
||||
processReady: Promise<void>;
|
||||
|
||||
/**
|
||||
@@ -236,6 +248,11 @@ export interface ITerminalInstance {
|
||||
*/
|
||||
readonly title: string;
|
||||
|
||||
/**
|
||||
* The shell type of the terminal.
|
||||
*/
|
||||
readonly shellType: TerminalShellType;
|
||||
|
||||
/**
|
||||
* The focus state of the terminal before exiting.
|
||||
*/
|
||||
@@ -431,6 +448,11 @@ export interface ITerminalInstance {
|
||||
*/
|
||||
setTitle(title: string, eventSource: TitleEventSource): void;
|
||||
|
||||
/**
|
||||
* Sets the shell type of the terminal instance.
|
||||
*/
|
||||
setShellType(shellType: TerminalShellType): void;
|
||||
|
||||
waitForTitle(): Promise<string>;
|
||||
|
||||
setDimensions(dimensions: ITerminalDimensions): void;
|
||||
|
||||
@@ -305,17 +305,7 @@ export class CreateNewWithCwdTerminalCommand extends Command {
|
||||
|
||||
public runCommand(accessor: ServicesAccessor, args: { cwd: string } | undefined): Promise<void> {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
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;
|
||||
|
||||
let cwd: string | undefined;
|
||||
if (args && args.cwd) {
|
||||
cwd = configurationResolverService.resolve(lastActiveWorkspaceRoot, args.cwd);
|
||||
}
|
||||
const instance = terminalService.createTerminal({ cwd });
|
||||
const instance = terminalService.createTerminal({ cwd: args?.cwd });
|
||||
if (!instance) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
@@ -722,7 +712,7 @@ export class RunActiveFileInTerminalAction extends Action {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return this.terminalService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title).then(path => {
|
||||
return this.terminalService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title, instance.shellType).then(path => {
|
||||
instance.sendText(path, true);
|
||||
return this.terminalService.showPanel();
|
||||
});
|
||||
@@ -1065,6 +1055,31 @@ export class RenameTerminalAction extends Action {
|
||||
});
|
||||
}
|
||||
}
|
||||
export class RenameWithArgTerminalCommand extends Command {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.RENAME_WITH_ARG;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.renameWithArg', "Rename the Currently Active Terminal");
|
||||
public static readonly NAME_ARG_LABEL = nls.localize('workbench.action.terminal.renameWithArg.name', "The new name for the terminal");
|
||||
|
||||
public runCommand(
|
||||
accessor: ServicesAccessor,
|
||||
args?: { name?: string }
|
||||
): void {
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
const terminalInstance = accessor.get(ITerminalService).getActiveInstance();
|
||||
|
||||
if (!terminalInstance) {
|
||||
notificationService.warn(nls.localize('workbench.action.terminal.renameWithArg.noTerminal', "No active terminal to rename"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args || !args.name) {
|
||||
notificationService.warn(nls.localize('workbench.action.terminal.renameWithArg.noName', "No name argument provided"));
|
||||
return;
|
||||
}
|
||||
|
||||
terminalInstance.setTitle(args.name, TitleEventSource.Api);
|
||||
}
|
||||
}
|
||||
|
||||
export class FocusTerminalFindWidgetAction extends Action {
|
||||
|
||||
@@ -1328,7 +1343,6 @@ abstract class ToggleFindOptionCommand extends Action {
|
||||
|
||||
export class ToggleRegexCommand extends ToggleFindOptionCommand {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX;
|
||||
public static readonly ID_TERMINAL_FOCUS = TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX_TERMINAL_FOCUS;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.toggleFindRegex', "Toggle find using regex");
|
||||
|
||||
protected runInner(state: FindReplaceState): void {
|
||||
@@ -1338,7 +1352,6 @@ export class ToggleRegexCommand extends ToggleFindOptionCommand {
|
||||
|
||||
export class ToggleWholeWordCommand extends ToggleFindOptionCommand {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD;
|
||||
public static readonly ID_TERMINAL_FOCUS = TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD_TERMINAL_FOCUS;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.toggleFindWholeWord', "Toggle find using whole word");
|
||||
|
||||
protected runInner(state: FindReplaceState): void {
|
||||
@@ -1348,7 +1361,6 @@ export class ToggleWholeWordCommand extends ToggleFindOptionCommand {
|
||||
|
||||
export class ToggleCaseSensitiveCommand extends ToggleFindOptionCommand {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE;
|
||||
public static readonly ID_TERMINAL_FOCUS = TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE_TERMINAL_FOCUS;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle find using case sensitive");
|
||||
|
||||
protected runInner(state: FindReplaceState): void {
|
||||
@@ -1358,7 +1370,6 @@ export class ToggleCaseSensitiveCommand extends ToggleFindOptionCommand {
|
||||
|
||||
export class FindNext extends Action {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.FIND_NEXT;
|
||||
public static readonly ID_TERMINAL_FOCUS = TERMINAL_COMMAND_ID.FIND_NEXT_TERMINAL_FOCUS;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.findNext', "Find next");
|
||||
|
||||
constructor(
|
||||
@@ -1376,7 +1387,6 @@ export class FindNext extends Action {
|
||||
|
||||
export class FindPrevious extends Action {
|
||||
public static readonly ID = TERMINAL_COMMAND_ID.FIND_PREVIOUS;
|
||||
public static readonly ID_TERMINAL_FOCUS = TERMINAL_COMMAND_ID.FIND_PREVIOUS_TERMINAL_FOCUS;
|
||||
public static readonly LABEL = nls.localize('workbench.action.terminal.findPrevious', "Find previous");
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -31,7 +31,7 @@ import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/term
|
||||
import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { ITerminalInstanceService, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalInstanceService, ITerminalInstance, TerminalShellType } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager';
|
||||
import { Terminal as XTermTerminal, IBuffer, ITerminalAddon } from 'xterm';
|
||||
import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
|
||||
@@ -54,11 +54,11 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
|
||||
TERMINAL_COMMAND_ID.DELETE_WORD_RIGHT,
|
||||
TERMINAL_COMMAND_ID.FIND_WIDGET_FOCUS,
|
||||
TERMINAL_COMMAND_ID.FIND_WIDGET_HIDE,
|
||||
TERMINAL_COMMAND_ID.FIND_NEXT_TERMINAL_FOCUS,
|
||||
TERMINAL_COMMAND_ID.FIND_PREVIOUS_TERMINAL_FOCUS,
|
||||
TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX_TERMINAL_FOCUS,
|
||||
TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD_TERMINAL_FOCUS,
|
||||
TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE_TERMINAL_FOCUS,
|
||||
TERMINAL_COMMAND_ID.FIND_NEXT,
|
||||
TERMINAL_COMMAND_ID.FIND_PREVIOUS,
|
||||
TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX,
|
||||
TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD,
|
||||
TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE,
|
||||
TERMINAL_COMMAND_ID.FOCUS_NEXT_PANE,
|
||||
TERMINAL_COMMAND_ID.FOCUS_NEXT,
|
||||
TERMINAL_COMMAND_ID.FOCUS_PREVIOUS_PANE,
|
||||
@@ -181,7 +181,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
private _hadFocusOnExit: boolean;
|
||||
private _isVisible: boolean;
|
||||
private _isDisposed: boolean;
|
||||
private _exitCode: number | undefined;
|
||||
private _skipTerminalCommands: string[];
|
||||
private _shellType: TerminalShellType;
|
||||
private _title: string = '';
|
||||
private _wrapperElement: (HTMLElement & { xterm?: XTermTerminal }) | undefined;
|
||||
private _xterm: XTermTerminal | undefined;
|
||||
@@ -226,10 +228,12 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// TODO: How does this work with detached processes?
|
||||
// TODO: Should this be an event as it can fire twice?
|
||||
public get processReady(): Promise<void> { return this._processManager.ptyProcessReady; }
|
||||
public get exitCode(): number | undefined { return this._exitCode; }
|
||||
public get title(): string { return this._title; }
|
||||
public get hadFocusOnExit(): boolean { return this._hadFocusOnExit; }
|
||||
public get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable; }
|
||||
public get shellLaunchConfig(): IShellLaunchConfig { return this._shellLaunchConfig; }
|
||||
public get shellType(): TerminalShellType { return this._shellType; }
|
||||
public get commandTracker(): CommandTrackerAddon | undefined { return this._commandTrackerAddon; }
|
||||
public get navigationMode(): INavigationMode | undefined { return this._navigationModeAddon; }
|
||||
|
||||
@@ -305,7 +309,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
});
|
||||
|
||||
this.addDisposable(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('terminal.integrated')) {
|
||||
if (e.affectsConfiguration('terminal.integrated') || e.affectsConfiguration('editor.fastScrollSensitivity') || e.affectsConfiguration('editor.mouseWheelScrollSensitivity')) {
|
||||
this.updateConfig();
|
||||
// HACK: Trigger another async layout to ensure xterm's CharMeasure is ready to use,
|
||||
// this hack can be removed when https://github.com/xtermjs/xterm.js/issues/702 is
|
||||
@@ -365,12 +369,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// when window.devicePixelRatio changes.
|
||||
const scaledWidthAvailable = dimension.width * window.devicePixelRatio;
|
||||
|
||||
let scaledCharWidth: number;
|
||||
if (this._configHelper.config.rendererType === 'dom') {
|
||||
scaledCharWidth = font.charWidth * window.devicePixelRatio;
|
||||
} else {
|
||||
scaledCharWidth = Math.floor(font.charWidth * window.devicePixelRatio) + font.letterSpacing;
|
||||
}
|
||||
const scaledCharWidth = font.charWidth * window.devicePixelRatio + font.letterSpacing;
|
||||
const newCols = Math.max(Math.floor(scaledWidthAvailable / scaledCharWidth), 1);
|
||||
|
||||
const scaledHeightAvailable = dimension.height * window.devicePixelRatio;
|
||||
@@ -421,7 +420,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
const bottom = parseInt(wrapperElementStyle.bottom!.split('px')[0], 10);
|
||||
|
||||
const innerWidth = width - marginLeft - marginRight;
|
||||
const innerHeight = height - bottom;
|
||||
const innerHeight = height - bottom - 1;
|
||||
|
||||
TerminalInstance._lastKnownCanvasDimensions = new dom.Dimension(innerWidth, innerHeight);
|
||||
return TerminalInstance._lastKnownCanvasDimensions;
|
||||
@@ -448,7 +447,8 @@ 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 editorOptions = this._configurationService.getValue<IEditorOptions>('editor');
|
||||
|
||||
const xterm = new Terminal({
|
||||
scrollback: config.scrollback,
|
||||
theme: this._getXtermTheme(),
|
||||
@@ -459,14 +459,16 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
fontSize: font.fontSize,
|
||||
letterSpacing: font.letterSpacing,
|
||||
lineHeight: font.lineHeight,
|
||||
minimumContrastRatio: config.minimumContrastRatio,
|
||||
bellStyle: config.enableBell ? 'sound' : 'none',
|
||||
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
|
||||
fastScrollSensitivity: editorOptions.fastScrollSensitivity,
|
||||
scrollSensitivity: editorOptions.mouseWheelScrollSensitivity,
|
||||
rendererType: config.rendererType === 'auto' || config.rendererType === 'experimentalWebgl' ? 'canvas' : config.rendererType,
|
||||
wordSeparator: ' ()[]{}\',:;"`'
|
||||
});
|
||||
this._xterm = xterm;
|
||||
this._xtermCore = (xterm as any)._core as XTermCore;
|
||||
@@ -484,7 +486,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
this._processManager.onProcessData(data => this._onProcessData(data));
|
||||
this._xterm.onData(data => this._processManager.write(data));
|
||||
// TODO: How does the cwd work on detached processes?
|
||||
this.processReady.then(async () => {
|
||||
if (this._linkHandler) {
|
||||
this._linkHandler.processCwd = await this._processManager.getInitialCwd();
|
||||
@@ -524,9 +525,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
throw new Error('The terminal instance has not been attached to a container yet');
|
||||
}
|
||||
|
||||
if (this._wrapperElement.parentNode) {
|
||||
this._wrapperElement.parentNode.removeChild(this._wrapperElement);
|
||||
}
|
||||
this._wrapperElement.parentNode?.removeChild(this._wrapperElement);
|
||||
this._container = container;
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
}
|
||||
@@ -544,9 +543,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
|
||||
// The container changed, reattach
|
||||
if (this._container) {
|
||||
this._container.removeChild(this._wrapperElement);
|
||||
}
|
||||
this._container?.removeChild(this._wrapperElement);
|
||||
this._container = container;
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
}
|
||||
@@ -568,6 +565,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._wrapperElement.appendChild(this._xtermElement);
|
||||
this._container.appendChild(this._wrapperElement);
|
||||
xterm.open(this._xtermElement);
|
||||
if (this._configHelper.config.rendererType === 'experimentalWebgl') {
|
||||
this._terminalInstanceService.getXtermWebglConstructor().then(Addon => {
|
||||
xterm.loadAddon(new Addon());
|
||||
});
|
||||
}
|
||||
|
||||
if (!xterm.element || !xterm.textarea) {
|
||||
throw new Error('xterm elements not set after open');
|
||||
@@ -584,7 +586,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// within commandsToSkipShell
|
||||
const standardKeyboardEvent = new StandardKeyboardEvent(event);
|
||||
const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target);
|
||||
const allowChords = resolveResult && resolveResult.enterChord && this._configHelper.config.allowChords;
|
||||
// Respect chords if the allowChords setting is set and it's not Escape. Escape is
|
||||
// handled specially for Zen Mode's Escape, Escape chord, plus it's important in
|
||||
// terminals generally
|
||||
const allowChords = resolveResult && resolveResult.enterChord && this._configHelper.config.allowChords && event.key !== 'Escape';
|
||||
if (allowChords || resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
@@ -594,6 +599,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
if (TabFocus.getTabFocusMode() && event.keyCode === 9) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always have alt+F4 skip the terminal on Windows and allow it to be handled by the
|
||||
// system
|
||||
if (platform.isWindows && event.altKey && event.key === 'F4' && !event.ctrlKey) {
|
||||
@@ -652,11 +658,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
const widgetManager = new TerminalWidgetManager(this._wrapperElement);
|
||||
this._widgetManager = widgetManager;
|
||||
this._processManager.onProcessReady(() => {
|
||||
if (this._linkHandler) {
|
||||
this._linkHandler.setWidgetManager(widgetManager);
|
||||
}
|
||||
});
|
||||
this._processManager.onProcessReady(() => this._linkHandler?.setWidgetManager(widgetManager));
|
||||
|
||||
const computedStyle = window.getComputedStyle(this._container);
|
||||
const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10);
|
||||
@@ -751,19 +753,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
|
||||
public clearSelection(): void {
|
||||
if (!this._xterm) {
|
||||
return;
|
||||
}
|
||||
this._xterm.clearSelection();
|
||||
this._xterm?.clearSelection();
|
||||
}
|
||||
|
||||
public selectAll(): void {
|
||||
if (!this._xterm) {
|
||||
return;
|
||||
}
|
||||
// Focus here to ensure the terminal context key is set
|
||||
this._xterm.focus();
|
||||
this._xterm.selectAll();
|
||||
this._xterm?.focus();
|
||||
this._xterm?.selectAll();
|
||||
}
|
||||
|
||||
public findNext(term: string, searchOptions: ISearchOptions): boolean {
|
||||
@@ -924,45 +920,31 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
|
||||
public scrollDownLine(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.scrollLines(1);
|
||||
}
|
||||
this._xterm?.scrollLines(1);
|
||||
}
|
||||
|
||||
public scrollDownPage(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.scrollPages(1);
|
||||
}
|
||||
this._xterm?.scrollPages(1);
|
||||
}
|
||||
|
||||
public scrollToBottom(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.scrollToBottom();
|
||||
}
|
||||
this._xterm?.scrollToBottom();
|
||||
}
|
||||
|
||||
public scrollUpLine(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.scrollLines(-1);
|
||||
}
|
||||
this._xterm?.scrollLines(-1);
|
||||
}
|
||||
|
||||
public scrollUpPage(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.scrollPages(-1);
|
||||
}
|
||||
this._xterm?.scrollPages(-1);
|
||||
}
|
||||
|
||||
public scrollToTop(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.scrollToTop();
|
||||
}
|
||||
this._xterm?.scrollToTop();
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
if (this._xterm) {
|
||||
this._xterm.clear();
|
||||
}
|
||||
this._xterm?.clear();
|
||||
}
|
||||
|
||||
private _refreshSelectionContextKey() {
|
||||
@@ -1019,12 +1001,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
}
|
||||
|
||||
private _onProcessData(data: string): void {
|
||||
if (this._widgetManager) {
|
||||
this._widgetManager.closeMessage();
|
||||
}
|
||||
if (this._xterm) {
|
||||
this._xterm.write(data);
|
||||
}
|
||||
this._widgetManager?.closeMessage();
|
||||
this._xterm?.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1041,6 +1019,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
this._logService.debug(`Terminal process exit (id: ${this.id}) with code ${exitCode}`);
|
||||
|
||||
this._exitCode = exitCode;
|
||||
this._isExiting = true;
|
||||
let exitCodeMessage: string | undefined;
|
||||
|
||||
@@ -1130,10 +1109,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
public reuseTerminal(shell: IShellLaunchConfig): void {
|
||||
// Unsubscribe any key listener we may have.
|
||||
if (this._pressAnyKeyToCloseListener) {
|
||||
this._pressAnyKeyToCloseListener.dispose();
|
||||
this._pressAnyKeyToCloseListener = undefined;
|
||||
}
|
||||
this._pressAnyKeyToCloseListener?.dispose();
|
||||
this._pressAnyKeyToCloseListener = undefined;
|
||||
|
||||
// Kill and clear up the process, making the process manager ready for a new process
|
||||
this._processManager.dispose();
|
||||
@@ -1243,11 +1220,18 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._setCommandsToSkipShell(config.commandsToSkipShell);
|
||||
this._setEnableBell(config.enableBell);
|
||||
this._safeSetOption('scrollback', config.scrollback);
|
||||
this._safeSetOption('minimumContrastRatio', config.minimumContrastRatio);
|
||||
this._safeSetOption('macOptionIsMeta', config.macOptionIsMeta);
|
||||
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);
|
||||
if (config.rendererType !== 'experimentalWebgl') {
|
||||
// Never set webgl as it's an addon not a rendererType
|
||||
this._safeSetOption('rendererType', config.rendererType === 'auto' ? 'canvas' : config.rendererType);
|
||||
}
|
||||
|
||||
const editorOptions = this._configurationService.getValue<IEditorOptions>('editor');
|
||||
this._safeSetOption('fastScrollSensitivity', editorOptions.fastScrollSensitivity);
|
||||
this._safeSetOption('scrollSensitivity', editorOptions.mouseWheelScrollSensitivity);
|
||||
}
|
||||
|
||||
public updateAccessibilitySupport(): void {
|
||||
@@ -1256,10 +1240,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._navigationModeAddon = new NavigationModeAddon(this._terminalA11yTreeFocusContextKey);
|
||||
this._xterm!.loadAddon(this._navigationModeAddon);
|
||||
} else {
|
||||
if (this._navigationModeAddon) {
|
||||
this._navigationModeAddon.dispose();
|
||||
this._navigationModeAddon = undefined;
|
||||
}
|
||||
this._navigationModeAddon?.dispose();
|
||||
this._navigationModeAddon = undefined;
|
||||
}
|
||||
this._xterm!.setOption('screenReaderMode', isEnabled);
|
||||
}
|
||||
@@ -1375,6 +1357,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._processManager.ptyProcessReady.then(() => this._processManager.setDimensions(cols, rows));
|
||||
}
|
||||
|
||||
public setShellType(shellType: TerminalShellType) {
|
||||
this._shellType = shellType;
|
||||
}
|
||||
|
||||
public setTitle(title: string | undefined, eventSource: TitleEventSource): void {
|
||||
if (!title) {
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { IWindowsShellHelper, ITerminalChildProcess, IDefaultShellAndArgsRequest
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
||||
import { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
@@ -15,6 +16,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
let Terminal: typeof XTermTerminal;
|
||||
let WebLinksAddon: typeof XTermWebLinksAddon;
|
||||
let SearchAddon: typeof XTermSearchAddon;
|
||||
let WebglAddon: typeof XTermWebglAddon;
|
||||
|
||||
export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
public _serviceBrand: undefined;
|
||||
@@ -43,6 +45,13 @@ export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
return SearchAddon;
|
||||
}
|
||||
|
||||
public async getXtermWebglConstructor(): Promise<typeof XTermWebglAddon> {
|
||||
if (!WebglAddon) {
|
||||
WebglAddon = (await import('xterm-addon-webgl')).WebglAddon;
|
||||
}
|
||||
return WebglAddon;
|
||||
}
|
||||
|
||||
public createWindowsShellHelper(): IWindowsShellHelper {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/terminalWidgetManager';
|
||||
import { TerminalWidgetManager, WidgetVerticalAlignment } from 'vs/workbench/contrib/terminal/browser/terminalWidgetManager';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ITerminalProcessManager, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ITextEditorSelection } from 'vs/platform/editor/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { Terminal, ILinkMatcherOptions } from 'xterm';
|
||||
import { Terminal, ILinkMatcherOptions, IViewportRange } from 'xterm';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { posix, win32 } from 'vs/base/common/path';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
@@ -71,7 +71,7 @@ export class TerminalLinkHandler {
|
||||
private _processCwd: string | undefined;
|
||||
private _gitDiffPreImagePattern: RegExp;
|
||||
private _gitDiffPostImagePattern: RegExp;
|
||||
private readonly _tooltipCallback: (event: MouseEvent, uri: string) => boolean | void;
|
||||
private readonly _tooltipCallback: (event: MouseEvent, uri: string, location: IViewportRange) => boolean | void;
|
||||
private readonly _leaveCallback: () => void;
|
||||
|
||||
constructor(
|
||||
@@ -89,15 +89,42 @@ export class TerminalLinkHandler {
|
||||
// Matches '+++ b/src/file1', capturing 'src/file1' in group 1
|
||||
this._gitDiffPostImagePattern = /^\+\+\+ b\/(\S*)/;
|
||||
|
||||
this._tooltipCallback = (e: MouseEvent) => {
|
||||
this._tooltipCallback = (e: MouseEvent, uri: string, location: IViewportRange) => {
|
||||
if (!this._widgetManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the row bottom up
|
||||
let offsetRow = this._xterm.rows - location.start.y;
|
||||
let verticalAlignment = WidgetVerticalAlignment.Bottom;
|
||||
|
||||
// Show the tooltip on the top of the next row to avoid obscuring the first row
|
||||
if (location.start.y <= 0) {
|
||||
offsetRow = this._xterm.rows - 1;
|
||||
verticalAlignment = WidgetVerticalAlignment.Top;
|
||||
// The start of the wrapped line is above the viewport, move to start of the line
|
||||
if (location.start.y < 0) {
|
||||
location.start.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._configHelper.config.rendererType === 'dom') {
|
||||
const target = (e.target as HTMLElement);
|
||||
this._widgetManager.showMessage(target.offsetLeft, target.offsetTop, this._getLinkHoverString());
|
||||
const font = this._configHelper.getFont();
|
||||
const charWidth = font.charWidth;
|
||||
const charHeight = font.charHeight;
|
||||
|
||||
const leftPosition = location.start.x * (charWidth! + (font.letterSpacing / window.devicePixelRatio));
|
||||
const bottomPosition = offsetRow * (Math.ceil(charHeight! * window.devicePixelRatio) * font.lineHeight) / window.devicePixelRatio;
|
||||
|
||||
this._widgetManager.showMessage(leftPosition, bottomPosition, this._getLinkHoverString(), verticalAlignment);
|
||||
} else {
|
||||
this._widgetManager.showMessage(e.offsetX, e.offsetY, this._getLinkHoverString());
|
||||
const target = (e.target as HTMLElement);
|
||||
const colWidth = target.offsetWidth / this._xterm.cols;
|
||||
const rowHeight = target.offsetHeight / this._xterm.rows;
|
||||
|
||||
const leftPosition = location.start.x * colWidth;
|
||||
const bottomPosition = offsetRow * rowHeight;
|
||||
this._widgetManager.showMessage(leftPosition, bottomPosition, this._getLinkHoverString(), verticalAlignment);
|
||||
}
|
||||
};
|
||||
this._leaveCallback = () => {
|
||||
@@ -239,8 +266,7 @@ export class TerminalLinkHandler {
|
||||
}
|
||||
|
||||
private _handleHypertextLink(url: string): void {
|
||||
const uri = URI.parse(url);
|
||||
this._openerService.open(uri, { allowTunneling: !!(this._processManager && this._processManager.remoteAuthority) });
|
||||
this._openerService.open(url, { allowTunneling: !!(this._processManager && this._processManager.remoteAuthority) });
|
||||
}
|
||||
|
||||
private _isLinkActivationModifierDown(event: MouseEvent): boolean {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TERMINAL_PANEL_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IThemeService, ITheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
||||
import { TerminalFindWidget } from 'vs/workbench/contrib/terminal/browser/terminalFindWidget';
|
||||
import { editorHoverBackground, editorHoverBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { editorHoverBackground, editorHoverBorder, editorHoverForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { KillTerminalAction, SwitchTerminalAction, SwitchTerminalActionViewItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction, SelectAllTerminalAction, CreateNewTerminalAction, SplitTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
|
||||
import { Panel } from 'vs/workbench/browser/panel';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
@@ -26,6 +26,7 @@ import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notif
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
const FIND_FOCUS_CLASS = 'find-focused';
|
||||
|
||||
@@ -141,13 +142,22 @@ export class TerminalPanel extends Panel {
|
||||
private _getContextMenuActions(): IAction[] {
|
||||
if (!this._contextMenuActions || !this._copyContextMenuAction) {
|
||||
this._copyContextMenuAction = this._instantiationService.createInstance(CopyTerminalSelectionAction, CopyTerminalSelectionAction.ID, CopyTerminalSelectionAction.SHORT_LABEL);
|
||||
|
||||
const clipboardActions = [];
|
||||
if (BrowserFeatures.clipboard.writeText) {
|
||||
clipboardActions.push(this._copyContextMenuAction);
|
||||
}
|
||||
if (BrowserFeatures.clipboard.readText) {
|
||||
clipboardActions.push(this._instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.SHORT_LABEL));
|
||||
}
|
||||
|
||||
clipboardActions.push(this._instantiationService.createInstance(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL));
|
||||
|
||||
this._contextMenuActions = [
|
||||
this._instantiationService.createInstance(CreateNewTerminalAction, CreateNewTerminalAction.ID, CreateNewTerminalAction.SHORT_LABEL),
|
||||
this._instantiationService.createInstance(SplitTerminalAction, SplitTerminalAction.ID, SplitTerminalAction.SHORT_LABEL),
|
||||
new Separator(),
|
||||
this._copyContextMenuAction,
|
||||
this._instantiationService.createInstance(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.SHORT_LABEL),
|
||||
this._instantiationService.createInstance(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL),
|
||||
...clipboardActions,
|
||||
new Separator(),
|
||||
this._instantiationService.createInstance(ClearTerminalAction, ClearTerminalAction.ID, ClearTerminalAction.LABEL),
|
||||
new Separator(),
|
||||
@@ -252,9 +262,9 @@ export class TerminalPanel extends Panel {
|
||||
getActions: () => this._getContextMenuActions(),
|
||||
getActionsContext: () => this._parentDomElement
|
||||
});
|
||||
} else {
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
this._cancelContextMenu = false;
|
||||
}));
|
||||
this._register(dom.addDisposableListener(document, 'keydown', (event: KeyboardEvent) => {
|
||||
@@ -291,7 +301,7 @@ export class TerminalPanel extends Panel {
|
||||
|
||||
const terminal = this._terminalService.getActiveInstance();
|
||||
if (terminal) {
|
||||
return this._terminalService.preparePathForTerminalAsync(path, terminal.shellLaunchConfig.executable, terminal.title).then(preparedPath => {
|
||||
return this._terminalService.preparePathForTerminalAsync(path, terminal.shellLaunchConfig.executable, terminal.title, terminal.shellType).then(preparedPath => {
|
||||
terminal.sendText(preparedPath, false);
|
||||
});
|
||||
}
|
||||
@@ -337,7 +347,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
if (hoverBorder) {
|
||||
collector.addRule(`.monaco-workbench .panel.integrated-terminal .terminal-message-widget { border: 1px solid ${hoverBorder}; }`);
|
||||
}
|
||||
const hoverForeground = theme.getColor(editorForeground);
|
||||
const hoverForeground = theme.getColor(editorHoverForeground);
|
||||
if (hoverForeground) {
|
||||
collector.addRule(`.monaco-workbench .panel.integrated-terminal .terminal-message-widget { color: ${hoverForeground}; }`);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
|
||||
|
||||
private readonly _onProcessData = this._register(new Emitter<string>());
|
||||
public readonly onProcessData: Event<string> = this._onProcessData.event;
|
||||
private readonly _onProcessExit = this._register(new Emitter<number>());
|
||||
public readonly onProcessExit: Event<number> = this._onProcessExit.event;
|
||||
private readonly _onProcessExit = this._register(new Emitter<number | undefined>());
|
||||
public readonly onProcessExit: Event<number | undefined> = this._onProcessExit.event;
|
||||
private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>());
|
||||
public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; }
|
||||
private readonly _onProcessTitleChanged = this._register(new Emitter<string>());
|
||||
@@ -87,7 +87,7 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
|
||||
this._onProcessReady.fire({ pid, cwd });
|
||||
}
|
||||
|
||||
public emitExit(exitCode: number): void {
|
||||
public emitExit(exitCode: number | undefined): void {
|
||||
this._onProcessExit.fire(exitCode);
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
public get onProcessData(): Event<string> { return this._onProcessData.event; }
|
||||
private readonly _onProcessTitle = this._register(new Emitter<string>());
|
||||
public get onProcessTitle(): Event<string> { return this._onProcessTitle.event; }
|
||||
private readonly _onProcessExit = this._register(new Emitter<number>());
|
||||
public get onProcessExit(): Event<number> { return this._onProcessExit.event; }
|
||||
private readonly _onProcessExit = this._register(new Emitter<number | undefined>());
|
||||
public get onProcessExit(): Event<number | undefined> { return this._onProcessExit.event; }
|
||||
private readonly _onProcessOverrideDimensions = this._register(new Emitter<ITerminalDimensions | undefined>());
|
||||
public get onProcessOverrideDimensions(): Event<ITerminalDimensions | undefined> { return this._onProcessOverrideDimensions.event; }
|
||||
private readonly _onProcessOverrideShellLaunchConfig = this._register(new Emitter<IShellLaunchConfig>());
|
||||
@@ -285,7 +285,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
return Promise.resolve(this._latency);
|
||||
}
|
||||
|
||||
private _onExit(exitCode: number): void {
|
||||
private _onExit(exitCode: number | undefined): void {
|
||||
this._process = null;
|
||||
|
||||
// If the process is marked as launching then mark the process as killed
|
||||
|
||||
@@ -88,7 +88,7 @@ export class TerminalPickerHandler extends QuickOpenHandler {
|
||||
const normalizedSearchValueLowercase = stripWildcards(searchValue).toLowerCase();
|
||||
|
||||
const terminalEntries: QuickOpenEntry[] = this.getTerminals();
|
||||
terminalEntries.push(new CreateTerminal(nls.localize("workbench.action.terminal.newplus", "$(plus) Create New Integrated Terminal"), this.commandService));
|
||||
terminalEntries.push(new CreateTerminal('$(plus) ' + nls.localize("workbench.action.terminal.newplus", "Create New Integrated Terminal"), this.commandService));
|
||||
|
||||
const entries = terminalEntries.filter(e => {
|
||||
if (!searchValue) {
|
||||
@@ -113,7 +113,7 @@ export class TerminalPickerHandler extends QuickOpenHandler {
|
||||
}
|
||||
|
||||
private getTerminals(): TerminalEntry[] {
|
||||
return this.terminalService.terminalTabs.reduce((terminals, tab, tabIndex) => {
|
||||
return this.terminalService.terminalTabs.reduce((terminals: TerminalEntry[], tab, tabIndex) => {
|
||||
const terminalsInTab = tab.terminalInstances.map((terminal, terminalIndex) => {
|
||||
const label = `${tabIndex + 1}.${terminalIndex + 1}: ${terminal.title}`;
|
||||
return new TerminalEntry(terminal, label, this.terminalService);
|
||||
|
||||
@@ -16,7 +16,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
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 { ITerminalService, ITerminalInstance, ITerminalTab } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalService, ITerminalInstance, ITerminalTab, TerminalShellType, WindowsShellType } 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';
|
||||
@@ -504,7 +504,7 @@ export class TerminalService implements ITerminalService {
|
||||
});
|
||||
}
|
||||
|
||||
public preparePathForTerminalAsync(originalPath: string, executable: string, title: string): Promise<string> {
|
||||
public preparePathForTerminalAsync(originalPath: string, executable: string, title: string, shellType: TerminalShellType): Promise<string> {
|
||||
return new Promise<string>(c => {
|
||||
if (!executable) {
|
||||
c(originalPath);
|
||||
@@ -527,18 +527,41 @@ export class TerminalService implements ITerminalService {
|
||||
if (isWindows) {
|
||||
// 17063 is the build number where wsl path was introduced.
|
||||
// Update Windows uriPath to be executed in WSL.
|
||||
const lowerExecutable = executable.toLowerCase();
|
||||
if (this._terminalNativeService.getWindowsBuildNumber() >= 17063 &&
|
||||
(lowerExecutable.indexOf('wsl') !== -1 || (lowerExecutable.indexOf('bash.exe') !== -1 && lowerExecutable.toLowerCase().indexOf('git') === -1))) {
|
||||
c(this._terminalNativeService.getWslPath(originalPath));
|
||||
return;
|
||||
} else if (hasSpace) {
|
||||
c('"' + originalPath + '"');
|
||||
if (shellType !== undefined) {
|
||||
if (shellType === WindowsShellType.GitBash) {
|
||||
c(originalPath.replace(/\\/g, '/'));
|
||||
return;
|
||||
}
|
||||
else if (shellType === WindowsShellType.Wsl) {
|
||||
if (this._terminalNativeService.getWindowsBuildNumber() >= 17063) {
|
||||
c(this._terminalNativeService.getWslPath(originalPath));
|
||||
} else {
|
||||
c(originalPath.replace(/\\/g, '/'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasSpace) {
|
||||
c('"' + originalPath + '"');
|
||||
} else {
|
||||
c(originalPath);
|
||||
}
|
||||
} else {
|
||||
c(originalPath);
|
||||
const lowerExecutable = executable.toLowerCase();
|
||||
if (this._terminalNativeService.getWindowsBuildNumber() >= 17063 &&
|
||||
(lowerExecutable.indexOf('wsl') !== -1 || (lowerExecutable.indexOf('bash.exe') !== -1 && lowerExecutable.toLowerCase().indexOf('git') === -1))) {
|
||||
c(this._terminalNativeService.getWslPath(originalPath));
|
||||
return;
|
||||
} else if (hasSpace) {
|
||||
c('"' + originalPath + '"');
|
||||
} else {
|
||||
c(originalPath);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
c(escapeNonWindowsPath(originalPath));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
|
||||
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
export enum WidgetVerticalAlignment {
|
||||
Bottom,
|
||||
Top
|
||||
}
|
||||
|
||||
const WIDGET_HEIGHT = 29;
|
||||
|
||||
export class TerminalWidgetManager implements IDisposable {
|
||||
@@ -43,13 +48,13 @@ export class TerminalWidgetManager implements IDisposable {
|
||||
mutationObserver.observe(this._xtermViewport, { attributes: true, attributeFilter: ['style'] });
|
||||
}
|
||||
|
||||
public showMessage(left: number, top: number, text: string): void {
|
||||
public showMessage(left: number, y: number, text: string, verticalAlignment: WidgetVerticalAlignment = WidgetVerticalAlignment.Bottom): void {
|
||||
if (!this._container) {
|
||||
return;
|
||||
}
|
||||
dispose(this._messageWidget);
|
||||
this._messageListeners.clear();
|
||||
this._messageWidget = new MessageWidget(this._container, left, top, text);
|
||||
this._messageWidget = new MessageWidget(this._container, left, y, text, verticalAlignment);
|
||||
}
|
||||
|
||||
public closeMessage(): void {
|
||||
@@ -71,9 +76,10 @@ class MessageWidget {
|
||||
private _domNode: HTMLDivElement;
|
||||
|
||||
public get left(): number { return this._left; }
|
||||
public get top(): number { return this._top; }
|
||||
public get y(): number { return this._y; }
|
||||
public get text(): string { return this._text; }
|
||||
public get domNode(): HTMLElement { return this._domNode; }
|
||||
public get verticalAlignment(): WidgetVerticalAlignment { return this._verticalAlignment; }
|
||||
|
||||
public static fadeOut(messageWidget: MessageWidget): IDisposable {
|
||||
let handle: any;
|
||||
@@ -91,13 +97,22 @@ class MessageWidget {
|
||||
constructor(
|
||||
private _container: HTMLElement,
|
||||
private _left: number,
|
||||
private _top: number,
|
||||
private _text: string
|
||||
private _y: number,
|
||||
private _text: string,
|
||||
private _verticalAlignment: WidgetVerticalAlignment
|
||||
) {
|
||||
this._domNode = document.createElement('div');
|
||||
this._domNode.style.position = 'absolute';
|
||||
this._domNode.style.left = `${_left}px`;
|
||||
this._domNode.style.bottom = `${_container.offsetHeight - Math.max(_top, WIDGET_HEIGHT)}px`;
|
||||
|
||||
if (this.verticalAlignment === WidgetVerticalAlignment.Top) {
|
||||
// Y position is to the top of the widget
|
||||
this._domNode.style.bottom = `${Math.max(_y, WIDGET_HEIGHT) - WIDGET_HEIGHT}px`;
|
||||
} else {
|
||||
// Y position is to the bottom of the widget
|
||||
this._domNode.style.bottom = `${Math.min(_y, _container.offsetHeight - WIDGET_HEIGHT)}px`;
|
||||
}
|
||||
|
||||
this._domNode.classList.add('terminal-message-widget', 'fadeIn');
|
||||
this._domNode.textContent = _text;
|
||||
this._container.appendChild(this._domNode);
|
||||
|
||||
@@ -87,7 +87,7 @@ export interface ITerminalConfiguration {
|
||||
};
|
||||
macOptionIsMeta: boolean;
|
||||
macOptionClickForcesSelection: boolean;
|
||||
rendererType: 'auto' | 'canvas' | 'dom';
|
||||
rendererType: 'auto' | 'canvas' | 'dom' | 'experimentalWebgl';
|
||||
rightClickBehavior: 'default' | 'copyPaste' | 'paste' | 'selectWord';
|
||||
cursorBlinking: boolean;
|
||||
cursorStyle: string;
|
||||
@@ -95,6 +95,7 @@ export interface ITerminalConfiguration {
|
||||
fontFamily: string;
|
||||
fontWeight: FontWeight;
|
||||
fontWeightBold: FontWeight;
|
||||
minimumContrastRatio: number;
|
||||
// fontLigatures: boolean;
|
||||
fontSize: number;
|
||||
letterSpacing: number;
|
||||
@@ -113,7 +114,6 @@ export interface ITerminalConfiguration {
|
||||
windows: { [key: string]: string };
|
||||
};
|
||||
showExitAlert: boolean;
|
||||
experimentalBufferImpl: 'JsArray' | 'TypedArray';
|
||||
splitCwd: 'workspaceRoot' | 'initial' | 'inherited';
|
||||
windowsEnableConpty: boolean;
|
||||
experimentalRefreshOnResume: boolean;
|
||||
@@ -286,7 +286,7 @@ export interface ITerminalProcessManager extends IDisposable {
|
||||
readonly onBeforeProcessData: Event<IBeforeProcessDataEvent>;
|
||||
readonly onProcessData: Event<string>;
|
||||
readonly onProcessTitle: Event<string>;
|
||||
readonly onProcessExit: Event<number>;
|
||||
readonly onProcessExit: Event<number | undefined>;
|
||||
readonly onProcessOverrideDimensions: Event<ITerminalDimensions | undefined>;
|
||||
readonly onProcessResolvedShellLaunchConfig: Event<IShellLaunchConfig>;
|
||||
|
||||
@@ -325,7 +325,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable {
|
||||
emitData(data: string): void;
|
||||
emitTitle(title: string): void;
|
||||
emitReady(pid: number, cwd: string): void;
|
||||
emitExit(exitCode: number): void;
|
||||
emitExit(exitCode: number | undefined): void;
|
||||
emitOverrideDimensions(dimensions: ITerminalDimensions | undefined): void;
|
||||
emitResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void;
|
||||
emitInitialCwd(initialCwd: string): void;
|
||||
@@ -389,7 +389,7 @@ export interface IWindowsShellHelper extends IDisposable {
|
||||
*/
|
||||
export interface ITerminalChildProcess {
|
||||
onProcessData: Event<string>;
|
||||
onProcessExit: Event<number>;
|
||||
onProcessExit: Event<number | undefined>;
|
||||
onProcessReady: Event<{ pid: number, cwd: string }>;
|
||||
onProcessTitleChanged: Event<string>;
|
||||
onProcessOverrideDimensions?: Event<ITerminalDimensions | undefined>;
|
||||
@@ -412,9 +412,7 @@ export interface ITerminalChildProcess {
|
||||
|
||||
export const enum TERMINAL_COMMAND_ID {
|
||||
FIND_NEXT = 'workbench.action.terminal.findNext',
|
||||
FIND_NEXT_TERMINAL_FOCUS = 'workbench.action.terminal.findNextTerminalFocus',
|
||||
FIND_PREVIOUS = 'workbench.action.terminal.findPrevious',
|
||||
FIND_PREVIOUS_TERMINAL_FOCUS = 'workbench.action.terminal.findPreviousTerminalFocus',
|
||||
TOGGLE = 'workbench.action.terminal.toggleTerminal',
|
||||
KILL = 'workbench.action.terminal.kill',
|
||||
QUICK_KILL = 'workbench.action.terminal.quickKill',
|
||||
@@ -455,6 +453,7 @@ export const enum TERMINAL_COMMAND_ID {
|
||||
CLEAR_SELECTION = 'workbench.action.terminal.clearSelection',
|
||||
MANAGE_WORKSPACE_SHELL_PERMISSIONS = 'workbench.action.terminal.manageWorkspaceShellPermissions',
|
||||
RENAME = 'workbench.action.terminal.rename',
|
||||
RENAME_WITH_ARG = 'workbench.action.terminal.renameWithArg',
|
||||
FIND_WIDGET_FOCUS = 'workbench.action.terminal.focusFindWidget',
|
||||
FIND_WIDGET_HIDE = 'workbench.action.terminal.hideFindWidget',
|
||||
QUICK_OPEN_TERM = 'workbench.action.quickOpenTerm',
|
||||
@@ -469,9 +468,6 @@ export const enum TERMINAL_COMMAND_ID {
|
||||
TOGGLE_FIND_REGEX = 'workbench.action.terminal.toggleFindRegex',
|
||||
TOGGLE_FIND_WHOLE_WORD = 'workbench.action.terminal.toggleFindWholeWord',
|
||||
TOGGLE_FIND_CASE_SENSITIVE = 'workbench.action.terminal.toggleFindCaseSensitive',
|
||||
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'
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
interface TerminalDataBuffer extends IDisposable {
|
||||
data: string[];
|
||||
timeoutId: any;
|
||||
}
|
||||
|
||||
export class TerminalDataBufferer implements IDisposable {
|
||||
private readonly _terminalBufferMap = new Map<number, TerminalDataBuffer>();
|
||||
|
||||
dispose() {
|
||||
for (const buffer of this._terminalBufferMap.values()) {
|
||||
buffer.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
startBuffering(id: number, event: Event<string>, callback: (id: number, data: string) => void, throttleBy: number = 5): IDisposable {
|
||||
let disposable: IDisposable;
|
||||
disposable = event((e: string) => {
|
||||
let buffer = this._terminalBufferMap.get(id);
|
||||
if (buffer) {
|
||||
buffer.data.push(e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
this._terminalBufferMap.delete(id);
|
||||
callback(id, buffer!.data.join(''));
|
||||
}, throttleBy);
|
||||
buffer = {
|
||||
data: [e],
|
||||
timeoutId: timeoutId,
|
||||
dispose: () => {
|
||||
clearTimeout(timeoutId);
|
||||
this._terminalBufferMap.delete(id);
|
||||
disposable.dispose();
|
||||
}
|
||||
};
|
||||
this._terminalBufferMap.set(id, buffer);
|
||||
});
|
||||
return disposable;
|
||||
}
|
||||
|
||||
stopBuffering(id: number) {
|
||||
const buffer = this._terminalBufferMap.get(id);
|
||||
if (buffer) {
|
||||
buffer.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,23 +184,16 @@ export function getCwd(
|
||||
logService?: ILogService
|
||||
): string {
|
||||
if (shell.cwd) {
|
||||
return (typeof shell.cwd === 'object') ? shell.cwd.fsPath : shell.cwd;
|
||||
const unresolved = (typeof shell.cwd === 'object') ? shell.cwd.fsPath : shell.cwd;
|
||||
const resolved = _resolveCwd(unresolved, lastActiveWorkspace, configurationResolverService);
|
||||
return resolved || unresolved;
|
||||
}
|
||||
|
||||
let cwd: string | undefined;
|
||||
|
||||
if (!shell.ignoreConfigurationCwd && customCwd) {
|
||||
if (configurationResolverService) {
|
||||
try {
|
||||
customCwd = configurationResolverService.resolve(lastActiveWorkspace, customCwd);
|
||||
} catch (e) {
|
||||
// There was an issue resolving a variable, log the error in the console and
|
||||
// fallback to the default.
|
||||
if (logService) {
|
||||
logService.error('Could not resolve terminal.integrated.cwd', e);
|
||||
}
|
||||
customCwd = undefined;
|
||||
}
|
||||
customCwd = _resolveCwd(customCwd, lastActiveWorkspace, configurationResolverService, logService);
|
||||
}
|
||||
if (customCwd) {
|
||||
if (path.isAbsolute(customCwd)) {
|
||||
@@ -219,6 +212,18 @@ export function getCwd(
|
||||
return _sanitizeCwd(cwd);
|
||||
}
|
||||
|
||||
function _resolveCwd(cwd: string, lastActiveWorkspace: IWorkspaceFolder | undefined, configurationResolverService: IConfigurationResolverService | undefined, logService?: ILogService): string | undefined {
|
||||
if (configurationResolverService) {
|
||||
try {
|
||||
return configurationResolverService.resolve(lastActiveWorkspace, cwd);
|
||||
} catch (e) {
|
||||
logService?.error('Could not resolve terminal cwd', e);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
function _sanitizeCwd(cwd: string): string {
|
||||
// Make the drive letter uppercase on Windows (see #9448)
|
||||
if (platform.platform === platform.Platform.Windows && cwd && cwd[1] === ':') {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
||||
import { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
|
||||
@@ -25,6 +26,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
let Terminal: typeof XTermTerminal;
|
||||
let WebLinksAddon: typeof XTermWebLinksAddon;
|
||||
let SearchAddon: typeof XTermSearchAddon;
|
||||
let WebglAddon: typeof XTermWebglAddon;
|
||||
|
||||
export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
public _serviceBrand: undefined;
|
||||
@@ -61,6 +63,13 @@ export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
return SearchAddon;
|
||||
}
|
||||
|
||||
public async getXtermWebglConstructor(): Promise<typeof XTermWebglAddon> {
|
||||
if (!WebglAddon) {
|
||||
WebglAddon = (await import('xterm-addon-webgl')).WebglAddon;
|
||||
}
|
||||
return WebglAddon;
|
||||
}
|
||||
|
||||
public createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper {
|
||||
return new WindowsShellHelper(shellProcessId, instance, xterm);
|
||||
}
|
||||
|
||||
@@ -69,9 +69,10 @@ export class TerminalNativeService implements ITerminalNativeService {
|
||||
throw new Error('wslpath does not exist on Windows build < 17063');
|
||||
}
|
||||
return new Promise<string>(c => {
|
||||
execFile('bash.exe', ['-c', 'echo $(wslpath ' + escapeNonWindowsPath(path) + ')'], {}, (error, stdout, stderr) => {
|
||||
const proc = execFile('bash.exe', ['-c', `wslpath ${escapeNonWindowsPath(path)}`], {}, (error, stdout, stderr) => {
|
||||
c(escapeNonWindowsPath(stdout.trim()));
|
||||
});
|
||||
proc.stdin!.end();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal
|
||||
|
||||
export function registerRemoteContributions() {
|
||||
const actionRegistry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(CreateNewLocalTerminalAction, CreateNewLocalTerminalAction.ID, CreateNewLocalTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (Local)', TERMINAL_ACTION_CATEGORY);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(CreateNewLocalTerminalAction, CreateNewLocalTerminalAction.ID, CreateNewLocalTerminalAction.LABEL), 'Terminal: Create New Integrated Terminal (Local)', TERMINAL_ACTION_CATEGORY);
|
||||
}
|
||||
|
||||
export class CreateNewLocalTerminalAction extends Action {
|
||||
|
||||
@@ -9,11 +9,12 @@ import { IWindowsShellHelper, TitleEventSource } from 'vs/workbench/contrib/term
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import * as WindowsProcessTreeType from 'windows-process-tree';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalInstance, TerminalShellType, WindowsShellType } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
|
||||
const SHELL_EXECUTABLES = [
|
||||
'cmd.exe',
|
||||
'powershell.exe',
|
||||
'pwsh.exe',
|
||||
'bash.exe',
|
||||
'wsl.exe',
|
||||
'ubuntu.exe',
|
||||
@@ -81,6 +82,7 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe
|
||||
if (platform.isWindows && this._terminalInstance.isTitleSetByProcess) {
|
||||
this.getShellName().then(title => {
|
||||
if (!this._isDisposed) {
|
||||
this._terminalInstance.setShellType(this.getShellType(title));
|
||||
this._terminalInstance.setTitle(title, TitleEventSource.Process);
|
||||
}
|
||||
});
|
||||
@@ -138,4 +140,26 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe
|
||||
});
|
||||
return this._currentRequest;
|
||||
}
|
||||
|
||||
public getShellType(executable: string): TerminalShellType {
|
||||
switch (executable.toLowerCase()) {
|
||||
case 'cmd.exe':
|
||||
return WindowsShellType.CommandPrompt;
|
||||
case 'powershell.exe':
|
||||
case 'pwsh.exe':
|
||||
return WindowsShellType.PowerShell;
|
||||
case 'bash.exe':
|
||||
return WindowsShellType.GitBash;
|
||||
case 'wsl.exe':
|
||||
case 'ubuntu.exe':
|
||||
case 'ubuntu1804.exe':
|
||||
case 'kali.exe':
|
||||
case 'debian.exe':
|
||||
case 'opensuse-42.exe':
|
||||
case 'sles-12.exe':
|
||||
return WindowsShellType.Wsl;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
|
||||
env,
|
||||
cols,
|
||||
rows,
|
||||
experimentalUseConpty: useConpty,
|
||||
useConpty,
|
||||
// This option will force conpty to not redraw the whole viewport on launch
|
||||
conptyInheritCursor: useConpty && !!shellLaunchConfig.initialText
|
||||
};
|
||||
@@ -74,18 +74,21 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
|
||||
if (!stat.isDirectory()) {
|
||||
return Promise.reject(SHELL_CWD_INVALID_EXIT_CODE);
|
||||
}
|
||||
return undefined;
|
||||
}, async err => {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
// So we can include in the error message the specified CWD
|
||||
shellLaunchConfig.cwd = cwd;
|
||||
return Promise.reject(SHELL_CWD_INVALID_EXIT_CODE);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const executableVerification = stat(shellLaunchConfig.executable!).then(async stat => {
|
||||
if (!stat.isFile() && !stat.isSymbolicLink()) {
|
||||
return Promise.reject(stat.isDirectory() ? SHELL_PATH_DIRECTORY_EXIT_CODE : SHELL_PATH_INVALID_EXIT_CODE);
|
||||
}
|
||||
return undefined;
|
||||
}, async (err) => {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
let cwd = shellLaunchConfig.cwd instanceof URI ? shellLaunchConfig.cwd.path : shellLaunchConfig.cwd!;
|
||||
@@ -96,6 +99,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
|
||||
return Promise.reject(SHELL_PATH_INVALID_EXIT_CODE);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
|
||||
Promise.all([cwdVerification, executableVerification]).then(() => {
|
||||
@@ -260,7 +264,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
|
||||
return;
|
||||
}
|
||||
this._logService.trace('IPty#pid');
|
||||
exec('lsof -p ' + this._ptyProcess.pid + ' | grep cwd', (error, stdout, stderr) => {
|
||||
exec('lsof -OPl -p ' + this._ptyProcess.pid + ' | grep cwd', (error, stdout, stderr) => {
|
||||
if (stdout !== '') {
|
||||
resolve(stdout.substring(stdout.indexOf('/'), stdout.length - 1));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
|
||||
|
||||
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
suite('Workbench - TerminalDataBufferer', () => {
|
||||
let bufferer: TerminalDataBufferer;
|
||||
|
||||
setup(async () => {
|
||||
bufferer = new TerminalDataBufferer();
|
||||
});
|
||||
|
||||
test('start', async () => {
|
||||
let terminalOnData = new Emitter<string>();
|
||||
let counter = 0;
|
||||
let data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(1, terminalOnData.event, (id, e) => {
|
||||
counter++;
|
||||
data = e;
|
||||
}, 0);
|
||||
|
||||
terminalOnData.fire('1');
|
||||
terminalOnData.fire('2');
|
||||
terminalOnData.fire('3');
|
||||
|
||||
await wait(0);
|
||||
|
||||
terminalOnData.fire('4');
|
||||
|
||||
assert.equal(counter, 1);
|
||||
assert.equal(data, '123');
|
||||
|
||||
await wait(0);
|
||||
|
||||
assert.equal(counter, 2);
|
||||
assert.equal(data, '4');
|
||||
});
|
||||
|
||||
test('start 2', async () => {
|
||||
let terminal1OnData = new Emitter<string>();
|
||||
let terminal1Counter = 0;
|
||||
let terminal1Data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(1, terminal1OnData.event, (id, e) => {
|
||||
terminal1Counter++;
|
||||
terminal1Data = e;
|
||||
}, 0);
|
||||
|
||||
let terminal2OnData = new Emitter<string>();
|
||||
let terminal2Counter = 0;
|
||||
let terminal2Data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(2, terminal2OnData.event, (id, e) => {
|
||||
terminal2Counter++;
|
||||
terminal2Data = e;
|
||||
}, 0);
|
||||
|
||||
terminal1OnData.fire('1');
|
||||
terminal2OnData.fire('4');
|
||||
terminal1OnData.fire('2');
|
||||
terminal2OnData.fire('5');
|
||||
terminal1OnData.fire('3');
|
||||
terminal2OnData.fire('6');
|
||||
terminal2OnData.fire('7');
|
||||
|
||||
assert.equal(terminal1Counter, 0);
|
||||
assert.equal(terminal1Data, undefined);
|
||||
assert.equal(terminal2Counter, 0);
|
||||
assert.equal(terminal2Data, undefined);
|
||||
|
||||
await wait(0);
|
||||
|
||||
assert.equal(terminal1Counter, 1);
|
||||
assert.equal(terminal1Data, '123');
|
||||
assert.equal(terminal2Counter, 1);
|
||||
assert.equal(terminal2Data, '4567');
|
||||
});
|
||||
|
||||
test('stop', async () => {
|
||||
let terminalOnData = new Emitter<string>();
|
||||
let counter = 0;
|
||||
let data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(1, terminalOnData.event, (id, e) => {
|
||||
counter++;
|
||||
data = e;
|
||||
}, 0);
|
||||
|
||||
terminalOnData.fire('1');
|
||||
terminalOnData.fire('2');
|
||||
terminalOnData.fire('3');
|
||||
|
||||
bufferer.stopBuffering(1);
|
||||
|
||||
await wait(0);
|
||||
|
||||
assert.equal(counter, 0);
|
||||
assert.equal(data, undefined);
|
||||
});
|
||||
|
||||
test('start 2 stop 1', async () => {
|
||||
let terminal1OnData = new Emitter<string>();
|
||||
let terminal1Counter = 0;
|
||||
let terminal1Data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(1, terminal1OnData.event, (id, e) => {
|
||||
terminal1Counter++;
|
||||
terminal1Data = e;
|
||||
}, 0);
|
||||
|
||||
let terminal2OnData = new Emitter<string>();
|
||||
let terminal2Counter = 0;
|
||||
let terminal2Data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(2, terminal2OnData.event, (id, e) => {
|
||||
terminal2Counter++;
|
||||
terminal2Data = e;
|
||||
}, 0);
|
||||
|
||||
|
||||
terminal1OnData.fire('1');
|
||||
terminal2OnData.fire('4');
|
||||
terminal1OnData.fire('2');
|
||||
terminal2OnData.fire('5');
|
||||
terminal1OnData.fire('3');
|
||||
terminal2OnData.fire('6');
|
||||
terminal2OnData.fire('7');
|
||||
|
||||
assert.equal(terminal1Counter, 0);
|
||||
assert.equal(terminal1Data, undefined);
|
||||
assert.equal(terminal2Counter, 0);
|
||||
assert.equal(terminal2Data, undefined);
|
||||
|
||||
bufferer.stopBuffering(1);
|
||||
await wait(0);
|
||||
|
||||
assert.equal(terminal1Counter, 0);
|
||||
assert.equal(terminal1Data, undefined);
|
||||
assert.equal(terminal2Counter, 1);
|
||||
assert.equal(terminal2Data, '4567');
|
||||
});
|
||||
|
||||
test('dispose', async () => {
|
||||
let terminal1OnData = new Emitter<string>();
|
||||
let terminal1Counter = 0;
|
||||
let terminal1Data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(1, terminal1OnData.event, (id, e) => {
|
||||
terminal1Counter++;
|
||||
terminal1Data = e;
|
||||
}, 0);
|
||||
|
||||
let terminal2OnData = new Emitter<string>();
|
||||
let terminal2Counter = 0;
|
||||
let terminal2Data: string | undefined;
|
||||
|
||||
bufferer.startBuffering(2, terminal2OnData.event, (id, e) => {
|
||||
terminal2Counter++;
|
||||
terminal2Data = e;
|
||||
}, 0);
|
||||
|
||||
|
||||
terminal1OnData.fire('1');
|
||||
terminal2OnData.fire('4');
|
||||
terminal1OnData.fire('2');
|
||||
terminal2OnData.fire('5');
|
||||
terminal1OnData.fire('3');
|
||||
terminal2OnData.fire('6');
|
||||
terminal2OnData.fire('7');
|
||||
|
||||
assert.equal(terminal1Counter, 0);
|
||||
assert.equal(terminal1Data, undefined);
|
||||
assert.equal(terminal2Counter, 0);
|
||||
assert.equal(terminal2Data, undefined);
|
||||
|
||||
bufferer.dispose();
|
||||
await wait(0);
|
||||
|
||||
assert.equal(terminal1Counter, 0);
|
||||
assert.equal(terminal1Data, undefined);
|
||||
assert.equal(terminal2Counter, 0);
|
||||
assert.equal(terminal2Data, undefined);
|
||||
});
|
||||
});
|
||||
@@ -19,7 +19,10 @@ function getMockTheme(type: ThemeType): ITheme {
|
||||
label: '',
|
||||
type: type,
|
||||
getColor: (colorId: ColorIdentifier): Color | undefined => themingRegistry.resolveDefaultColor(colorId, theme),
|
||||
defines: () => true
|
||||
defines: () => true,
|
||||
getTokenStyleMetadata: () => undefined,
|
||||
tokenColorMap: []
|
||||
|
||||
};
|
||||
return theme;
|
||||
}
|
||||
@@ -99,4 +102,4 @@ suite('Workbench - TerminalColorRegistry', () => {
|
||||
'#e5e5e5'
|
||||
], 'The dark terminal colors should be used when a dark theme is active');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,6 +46,9 @@ class MockTerminalInstanceService implements ITerminalInstanceService {
|
||||
getXtermSearchConstructor(): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getXtermWebglConstructor(): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
createWindowsShellHelper(): any {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user