diff --git a/docs/source/user/terminal.rst b/docs/source/user/terminal.rst index 98ce39893ec8..47335e9ebba8 100644 --- a/docs/source/user/terminal.rst +++ b/docs/source/user/terminal.rst @@ -47,20 +47,19 @@ re-open it using the Running tab in the left sidebar: Copy/Paste ~~~~~~~~~~~~ -For both Windows and Mac users, press ``shift`` + ``right-click`` to get to the right-click menu from inside Jupyterlab terminal. Or by using shortcut keys as follows: +For macOS users, ``Cmd+C`` and ``Cmd+V`` work as usual. -* **For Mac users:** - - **Copy** : ``Cmd`` + ``c`` - - **Paste**: ``Cmd`` + ``v`` - - -* **For Windows users (Power shell):** - - **Copy** : ``Ctrl`` + ``Insert`` - - **Paste** : ``Shift`` + ``Insert`` +For Windows users using ``PowerShell``, ``Ctrl+Insert`` and ``Shift+Insert`` work as usual. +To use the native browser Copy/Paste menu, hold ``Shift`` and right click to bring up the +context menu (note: this may not work in all browsers). +For non-macOS users, JupyterLab will interpret ``Ctrl+C`` as a copy if there is text selected. +In addition, ``Ctrl+V`` will be interpreted as a paste command unless the ``pasteWithCtrlV`` +setting is disabled. One may want to disable ``pasteWithCtrlV`` if the shortcut is needed +for something else such as the vi editor. +For anyone using a \*nix shell, the default ``Ctrl+Shift+C`` conflicts with the default +shortcut for toggling the command palette (``apputils:activate-command-palette``). +If desired, that shortcut can be changed by editing the keyboard shortcuts in setttings. +Using ``Ctrl+Shift+V`` for paste works as usual. diff --git a/packages/terminal-extension/schema/plugin.json b/packages/terminal-extension/schema/plugin.json index 730c9db7be2e..bac2ba28b1fa 100644 --- a/packages/terminal-extension/schema/plugin.json +++ b/packages/terminal-extension/schema/plugin.json @@ -21,6 +21,9 @@ }, "scrollback": { "type": "number" + }, + "pasteWithCtrlV": { + "type": "boolean" } }, "properties": { @@ -59,6 +62,12 @@ "description": "Whether to shut down or not the session when closing the terminal.", "type": "boolean", "default": false + }, + "pasteWithCtrlV": { + "title": "Paste with Ctrl+V", + "description": "Whether to enable pasting with Ctrl+V. This can be disabled to use Ctrl+V in the vi editor, for instance. This setting has no effect on macOS, where Cmd+V is available", + "type": "boolean", + "default": true } }, "additionalProperties": false, diff --git a/packages/terminal/package.json b/packages/terminal/package.json index f5ce712cb6b5..6d5f8cc0bbd6 100644 --- a/packages/terminal/package.json +++ b/packages/terminal/package.json @@ -34,6 +34,7 @@ "@jupyterlab/apputils": "^1.0.0-alpha.6", "@jupyterlab/services": "^4.0.0-alpha.6", "@phosphor/coreutils": "^1.3.0", + "@phosphor/domutils": "^1.1.2", "@phosphor/messaging": "^1.2.2", "@phosphor/widgets": "^1.6.0", "xterm": "~3.10.1" diff --git a/packages/terminal/src/tokens.ts b/packages/terminal/src/tokens.ts index cb0017ce1567..2349d344cd68 100644 --- a/packages/terminal/src/tokens.ts +++ b/packages/terminal/src/tokens.ts @@ -96,11 +96,18 @@ export namespace ITerminal { initialCommand: string; /** - * Wether to enable screen reader support. + * Whether to enable screen reader support. * * Set to false if you run into performance problems from DOM overhead */ screenReaderMode: boolean; + + /** + * Whether to enable using Ctrl+V to paste. + * + * This setting has no effect on macOS, where Cmd+V is available. + */ + pasteWithCtrlV: boolean; } /** @@ -115,7 +122,8 @@ export namespace ITerminal { shutdownOnClose: false, cursorBlink: true, initialCommand: '', - screenReaderMode: true + screenReaderMode: true, + pasteWithCtrlV: true }; /** diff --git a/packages/terminal/src/widget.ts b/packages/terminal/src/widget.ts index 4970c2981ef9..f6a897385d3f 100644 --- a/packages/terminal/src/widget.ts +++ b/packages/terminal/src/widget.ts @@ -3,6 +3,8 @@ import { TerminalSession } from '@jupyterlab/services'; +import { Platform } from '@phosphor/domutils'; + import { Message, MessageLoop } from '@phosphor/messaging'; import { Widget } from '@phosphor/widgets'; @@ -237,7 +239,8 @@ export class Terminal extends Widget implements ITerminal.ITerminal { * Initialize the terminal object. */ private _initializeTerm(): void { - this._term.on('data', (data: string) => { + const term = this._term; + term.on('data', (data: string) => { if (this.isDisposed) { return; } @@ -247,9 +250,30 @@ export class Terminal extends Widget implements ITerminal.ITerminal { }); }); - this._term.on('title', (title: string) => { + term.on('title', (title: string) => { this.title.label = title; }); + + // Do not add any Ctrl+C/Ctrl+V handling on macOS, + // where Cmd+C/Cmd+V works as intended. + if (Platform.IS_MAC) { + return; + } + + term.attachCustomKeyEventHandler(event => { + if (event.ctrlKey && event.key === 'c' && term.hasSelection()) { + // Return so that the usual OS copy happens + // instead of interrupt signal. + return false; + } + + if (event.ctrlKey && event.key === 'v' && this._options.pasteWithCtrlV) { + // Return so that the usual paste happens. + return false; + } + + return true; + }); } /** @@ -303,7 +327,7 @@ export class Terminal extends Widget implements ITerminal.ITerminal { } } - private _term: Xterm; + private readonly _term: Xterm; private _needsResize = true; private _termOpened = false; private _offsetWidth = -1;