Merge pull request #17496 from hun1ahpu/i14202

Right click to copy selection and paste on Windows
This commit is contained in:
Daniel Imms
2016-12-21 15:20:06 -08:00
committed by GitHub
6 changed files with 57 additions and 20 deletions
@@ -19,6 +19,8 @@ export const TERMINAL_DEFAULT_SHELL_LINUX = !platform.isWindows ? (process.env.S
export const TERMINAL_DEFAULT_SHELL_OSX = !platform.isWindows ? (process.env.SHELL || 'sh') : 'sh';
export const TERMINAL_DEFAULT_SHELL_WINDOWS = processes.getWindowsShell();
export const TERMINAL_DEFAULT_RIGHT_CLICK_COPY_PASTE = platform.isWindows;
/** A context key that is set when the integrated terminal has focus. */
export const KEYBINDING_CONTEXT_TERMINAL_FOCUS = new RawContextKey<boolean>('terminalFocus', undefined);
/** A context key that is set when the integrated terminal does not have focus. */
@@ -44,6 +46,7 @@ export interface ITerminalConfiguration {
osx: string[],
windows: string[]
},
rightClickCopyPaste: boolean,
cursorBlinking: boolean,
fontFamily: string,
fontLigatures: boolean,
@@ -62,6 +65,7 @@ export interface ITerminalConfigHelper {
getFont(): ITerminalFont;
getFontLigaturesEnabled(): boolean;
getCursorBlink(): boolean;
getRightClickCopyPaste(): boolean;
getCommandsToSkipShell(): string[];
getScrollback(): number;
getCwd(): string;
@@ -146,11 +150,21 @@ export interface ITerminalInstance {
*/
dispose(): void;
/**
* Check if anything is selected in terminal.
*/
hasSelection(): boolean;
/**
* Copies the terminal selection to the clipboard.
*/
copySelection(): void;
/**
* Clear current selection.
*/
clearSelection(): void;
/**
* Focuses the terminal instance.
*
@@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform';
import nls = require('vs/nls');
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { GlobalQuickOpenAction } from 'vs/workbench/browser/parts/quickopen/quickopen.contribution';
import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFAULT_SHELL_WINDOWS } from 'vs/workbench/parts/terminal/common/terminal';
import { ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_SHELL_LINUX, TERMINAL_DEFAULT_SHELL_OSX, TERMINAL_DEFAULT_SHELL_WINDOWS, TERMINAL_DEFAULT_RIGHT_CLICK_COPY_PASTE } from 'vs/workbench/parts/terminal/common/terminal';
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';
@@ -73,6 +73,11 @@ configurationRegistry.registerConfiguration({
},
'default': []
},
'terminal.integrated.rightClickCopyPaste': {
'description': nls.localize('terminal.integrated.rightClickCopyPaste', "When set, this will prevent the context menu from appearing when right clicking within the terminal, instead it will copy when there is a selection and paste when there is no selection."),
'type': 'boolean',
'default': TERMINAL_DEFAULT_RIGHT_CLICK_COPY_PASTE
},
'terminal.integrated.fontFamily': {
'description': nls.localize('terminal.integrated.fontFamily', "Controls the font family of the terminal, this defaults to editor.fontFamily's value."),
'type': 'string'
@@ -57,7 +57,7 @@ export class KillTerminalAction extends Action {
/**
* Copies the terminal selection. Note that since the command palette takes focus from the terminal,
* this can only be triggered via a keybinding.
* this cannot be triggered through the command palette.
*/
export class CopyTerminalSelectionAction extends Action {
@@ -138,6 +138,11 @@ export class TerminalConfigHelper implements ITerminalConfigHelper {
return terminalConfig.cursorBlinking;
}
public getRightClickCopyPaste(): boolean {
let config = this._configurationService.getConfiguration<ITerminalConfiguration>();
return config.terminal.integrated.rightClickCopyPaste;
}
public getShell(): IShell {
let config = this._configurationService.getConfiguration<ITerminalConfiguration>();
let shell: IShell = {
@@ -195,6 +195,10 @@ export class TerminalInstance implements ITerminalInstance {
this.updateConfig();
}
public hasSelection(): boolean {
return !document.getSelection().isCollapsed;
}
public copySelection(): void {
if (document.activeElement.classList.contains('xterm')) {
document.execCommand('copy');
@@ -203,6 +207,10 @@ export class TerminalInstance implements ITerminalInstance {
}
}
public clearSelection(): void {
document.getSelection().empty();
}
public dispose(): void {
this._isExiting = true;
@@ -149,25 +149,30 @@ export class TerminalPanel extends Panel {
// occurs on the selection itself.
this._terminalService.getActiveInstance().focus();
} else if (event.which === 3) {
// Trigger the context menu on right click
let anchor: HTMLElement | { x: number, y: number } = this._parentDomElement;
if (event instanceof MouseEvent) {
const standardEvent = new StandardMouseEvent(event);
anchor = { x: standardEvent.posx, y: standardEvent.posy };
}
this._contextMenuService.showContextMenu({
getAnchor: () => anchor,
getActions: () => TPromise.as(this._getContextMenuActions()),
getActionsContext: () => this._parentDomElement,
getKeyBinding: (action) => {
const opts = this._keybindingService.lookupKeybindings(action.id);
if (opts.length > 0) {
return opts[0]; // only take the first one
}
return null;
if (this._terminalService.configHelper.getRightClickCopyPaste()) {
let terminal = this._terminalService.getActiveInstance();
if (terminal.hasSelection()) {
terminal.copySelection();
terminal.clearSelection();
} else {
terminal.paste();
}
});
} else {
const standardEvent = new StandardMouseEvent(event);
let anchor: { x: number, y: number } = { x: standardEvent.posx, y: standardEvent.posy };
this._contextMenuService.showContextMenu({
getAnchor: () => anchor,
getActions: () => TPromise.as(this._getContextMenuActions()),
getActionsContext: () => this._parentDomElement,
getKeyBinding: (action) => {
const opts = this._keybindingService.lookupKeybindings(action.id);
if (opts.length > 0) {
return opts[0]; // only take the first one
}
return null;
}
});
}
}
}));
this._register(DOM.addDisposableListener(this._parentDomElement, 'click', (event) => {