Skip to content

Commit

Permalink
Merge pull request #28388 from Microsoft/tyriar/9958
Browse files Browse the repository at this point in the history
Integrate xterm.js's new terminal selection feature
  • Loading branch information
Tyriar authored Jun 9, 2017
2 parents 8702fba + dea0e91 commit 7688ec0
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 43 deletions.
6 changes: 3 additions & 3 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"vscode-ripgrep": "0.0.12",
"vscode-textmate": "^3.1.5",
"winreg": "1.2.0",
"xterm": "Tyriar/xterm.js#vscode-release/1.13",
"xterm": "Tyriar/xterm.js#vscode-release/1.14",
"yauzl": "2.3.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/platform/theme/common/colorRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export const focusBorder = registerColor('focusBorder', { dark: Color.fromHex('#
export const contrastBorder = registerColor('contrastBorder', { light: null, dark: null, hc: '#6FC3DF' }, nls.localize('contrastBorder', "An extra border around elements to separate them from others for greater contrast."));
export const activeContrastBorder = registerColor('contrastActiveBorder', { light: null, dark: null, hc: focusBorder }, nls.localize('activeContrastBorder', "An extra border around active elements to separate them from others for greater contrast."));

export const selectionBackground = registerColor('selection.background', { light: null, dark: null, hc: null }, nls.localize('selectionBackground', "The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor and the terminal."));
export const selectionBackground = registerColor('selection.background', { light: null, dark: null, hc: null }, nls.localize('selectionBackground', "The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor."));

// ------ text colors

Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/parts/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ export interface ITerminalInstance {
*/
clearSelection(): void;

/**
* Select all text in the terminal.
*/
selectAll(): void;

/**
* Focuses the terminal instance.
*
Expand Down
34 changes: 17 additions & 17 deletions src/vs/workbench/parts/terminal/electron-browser/media/xterm.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
.monaco-workbench .panel.integrated-terminal .xterm {
position: relative;
height: 100%;
user-select: none;
}

.monaco-workbench .panel.integrated-terminal .xterm:focus {
Expand Down Expand Up @@ -126,6 +127,22 @@
left: -9999em;
}

.monaco-workbench .panel.integrated-terminal .xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default;
}

.monaco-workbench .panel.integrated-terminal .xterm .xterm-selection {
position: absolute;
left: 0;
bottom: 0;
}

.monaco-workbench .panel.integrated-terminal .xterm .xterm-selection div {
position: absolute;
opacity: 0.5;
}

.monaco-workbench .panel.integrated-terminal .xterm .xterm-bold {
font-weight: bold;
}
Expand Down Expand Up @@ -157,23 +174,6 @@
display: block;
}

/* Base selection colors */

.monaco-workbench .panel.integrated-terminal .xterm ::selection {
color: #FFF;
background-color: rgba(51, 51, 51, 0.996);
}

.vs-dark .monaco-workbench .panel.integrated-terminal .xterm ::selection {
color: #1e1e1e;
background-color: rgba(204, 204, 204, 0.996);
}

.hc-black .monaco-workbench .panel.integrated-terminal .xterm ::selection {
color: #000;
background-color: rgba(255, 255, 255, 0.996);
}

/* Terminal colors 16-255 */

.monaco-workbench .panel.integrated-terminal .xterm .xterm-color-16 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFA
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, FocusTerminalAtIndexAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, FocusTerminalAtIndexAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, SelectAllTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
import { Registry } from 'vs/platform/platform';
import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
Expand Down Expand Up @@ -185,7 +185,8 @@ configurationRegistry.registerConfiguration({
OpenPreviousRecentlyUsedEditorInGroupAction.ID,
FocusFirstGroupAction.ID,
FocusSecondGroupAction.ID,
FocusThirdGroupAction.ID
FocusThirdGroupAction.ID,
SelectAllTerminalAction.ID
].sort()
}
}
Expand All @@ -209,9 +210,7 @@ let actionRegistry = <IWorkbenchActionRegistry>Registry.as(ActionExtensions.Work
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 },
// Don't apply to Mac since cmd+c works
mac: { primary: null }
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, {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_BACKTICK,
Expand All @@ -229,6 +228,15 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminalPasteAct
// Don't apply to Mac since cmd+v works
mac: { primary: null }
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(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: null,
// Technically this doesn't need to be here as it will fall back to this
// behavior anyway when handed to xterm.js, having this handled by VS Code
// 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, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ export class CopyTerminalSelectionAction extends Action {
}
}

export class SelectAllTerminalAction extends Action {

public static ID = 'workbench.action.terminal.selectAll';
public static LABEL = nls.localize('workbench.action.terminal.selectAll', "Select All");

constructor(
id: string, label: string,
@ITerminalService private terminalService: ITerminalService
) {
super(id, label);
}

public run(event?: any): TPromise<any> {
let terminalInstance = this.terminalService.getActiveInstance();
if (terminalInstance) {
terminalInstance.selectAll();
}
return TPromise.as(void 0);
}
}

export class CreateNewTerminalAction extends Action {

public static ID = 'workbench.action.terminal.new';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import { TerminalLinkHandler } from 'vs/workbench/parts/terminal/electron-browse
import { TerminalWidgetManager } from 'vs/workbench/parts/terminal/browser/terminalWidgetManager';
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { scrollbarSliderBackground, scrollbarSliderHoverBackground, scrollbarSliderActiveBackground } from 'vs/platform/theme/common/colorRegistry';
import { TPromise } from "vs/base/common/winjs.base";
import { TPromise } from 'vs/base/common/winjs.base';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';

/** The amount of time to consider terminal errors to be related to the launch */
const LAUNCHING_DURATION = 500;
Expand Down Expand Up @@ -99,7 +100,8 @@ export class TerminalInstance implements ITerminalInstance {
@IPanelService private _panelService: IPanelService,
@IWorkspaceContextService private _contextService: IWorkspaceContextService,
@IWorkbenchEditorService private _editorService: IWorkbenchEditorService,
@IInstantiationService private _instantiationService: IInstantiationService
@IInstantiationService private _instantiationService: IInstantiationService,
@IClipboardService private _clipboardService: IClipboardService
) {
this._instanceDisposables = [];
this._processDisposables = [];
Expand Down Expand Up @@ -323,19 +325,23 @@ export class TerminalInstance implements ITerminalInstance {
}

public hasSelection(): boolean {
return !document.getSelection().isCollapsed;
return this._xterm.hasSelection();
}

public copySelection(): void {
if (document.activeElement.classList.contains('xterm')) {
document.execCommand('copy');
if (this.hasSelection()) {
this._clipboardService.writeText(this._xterm.getSelection());
} else {
this._messageService.show(Severity.Warning, nls.localize('terminal.integrated.copySelection.noSelection', 'Cannot copy terminal selection when terminal does not have focus'));
this._messageService.show(Severity.Warning, nls.localize('terminal.integrated.copySelection.noSelection', 'The terminal has no selection to copy'));
}
}

public clearSelection(): void {
window.getSelection().empty();
this._xterm.clearSelection();
}

public selectAll(): void {
this._xterm.selectAll();
}

public dispose(): void {
Expand Down Expand Up @@ -439,8 +445,8 @@ export class TerminalInstance implements ITerminalInstance {

private _refreshSelectionContextKey() {
const activePanel = this._panelService.getActivePanel();
const isFocused = activePanel && activePanel.getId() === TERMINAL_PANEL_ID;
this._terminalHasTextContextKey.set(isFocused && !window.getSelection().isCollapsed);
const isActive = activePanel && activePanel.getId() === TERMINAL_PANEL_ID;
this._terminalHasTextContextKey.set(isActive && this.hasSelection());
}

private _sanitizeInput(data: any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ITerminalService, ITerminalFont, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_FOREGROUND_COLOR } from './terminalColorRegistry';
import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
import { ColorIdentifier, selectionBackground } from 'vs/platform/theme/common/colorRegistry';
import { KillTerminalAction, CreateNewTerminalAction, SwitchTerminalInstanceAction, SwitchTerminalInstanceActionItem, CopyTerminalSelectionAction, TerminalPasteAction, ClearTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
import { Panel } from 'vs/workbench/browser/panel';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
Expand Down Expand Up @@ -243,13 +243,8 @@ export class TerminalPanel extends Panel {
ansiColorIdentifiers.forEach((colorId: ColorIdentifier, index: number) => {
if (colorId) { // should not happen, all indices should have a color defined.
let color = theme.getColor(colorId);
let rgba = color.transparent(0.996);
css += `.monaco-workbench .panel.integrated-terminal .xterm .xterm-color-${index} { color: ${color}; }` +
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-color-${index}::selection,` +
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-color-${index} *::selection { background-color: ${rgba}; }` +
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-bg-color-${index} { background-color: ${color}; }` +
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-bg-color-${index}::selection,` +
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-bg-color-${index} *::selection { color: ${color}; }`;
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-bg-color-${index} { background-color: ${color}; }`;
}
});
const bgColor = theme.getColor(TERMINAL_BACKGROUND_COLOR);
Expand All @@ -267,6 +262,12 @@ export class TerminalPanel extends Panel {
`.monaco-workbench .panel.integrated-terminal .xterm.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,` +
`.monaco-workbench .panel.integrated-terminal .xterm.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before { background-color: ${fgColor}; }`;
}
// Use selection.background as the terminal selection, this is temporary
// until proper color inverting is implemented to ensure contrast.
const selectionColor = theme.getColor(selectionBackground);
if (selectionColor) {
css += `.monaco-workbench .panel.integrated-terminal .xterm .xterm-selection div { background-color: ${selectionColor}; }`;
}

this._themeStyleElement.innerHTML = css;
}
Expand Down

0 comments on commit 7688ec0

Please sign in to comment.