diff --git a/lib/components/term.js b/lib/components/term.js index 73474455..9a69151d 100644 --- a/lib/components/term.js +++ b/lib/components/term.js @@ -145,6 +145,10 @@ export default class Term extends Component { this.term.onVTKeystroke('\x05'); } + selectAll () { + this.term.selectAll(); + } + getTermDocument () { return this.term.document_; } diff --git a/lib/containers/hyperterm.js b/lib/containers/hyperterm.js index bd5f298a..98a6b720 100644 --- a/lib/containers/hyperterm.js +++ b/lib/containers/hyperterm.js @@ -62,6 +62,7 @@ class HyperTerm extends Component { keys.bind('command+backspace', bound('deleteLine')); keys.bind('command+left', bound('moveToStart')); keys.bind('command+right', bound('moveToEnd')); + keys.bind('command+a', bound('selectAll')); this.keys = keys; } diff --git a/lib/hterm.js b/lib/hterm.js index 9b25d5e7..ee61af3a 100644 --- a/lib/hterm.js +++ b/lib/hterm.js @@ -1,17 +1,20 @@ import { hterm, lib } from 'hterm-umdjs'; +const selection = require('./utils/selection'); hterm.defaultStorage = new lib.Storage.Memory(); -// clear selection range of current selected term view -// Fix event when terminal text is selected and keyboard action is invoked -hterm.Terminal.prototype.clearSelection = function () { - this.document_.getSelection().removeAllRanges(); +// Provide selectAll to terminal viewport +hterm.Terminal.prototype.selectAll = function () { + // We need to clear dom range to reset anchorNode + selection.clear(this); + selection.all(this); }; // override double click behavior to copy const oldMouse = hterm.Terminal.prototype.onMouse_; hterm.Terminal.prototype.onMouse_ = function (e) { if ('dblclick' === e.type) { + selection.extend(this); console.log('[hyperterm+hterm] ignore double click'); return; } @@ -94,7 +97,7 @@ hterm.Keyboard.prototype.onKeyDown_ = function (e) { } else { // Test for valid keys in order to clear the terminal selection if ((!e.ctrlKey || e.code !== 'ControlLeft') && !e.shiftKey && e.code !== 'CapsLock') { - this.terminal.clearSelection(); + selection.clear(this.terminal); } } return oldKeyDown.call(this, e); @@ -105,7 +108,7 @@ hterm.Keyboard.prototype.onKeyPress_ = function (e) { if (e.metaKey) { return; } else { - this.terminal.clearSelection(); + selection.clear(this.terminal); } return oldKeyPress.call(this, e); }; diff --git a/lib/utils/selection.js b/lib/utils/selection.js new file mode 100644 index 00000000..b6bfaad3 --- /dev/null +++ b/lib/utils/selection.js @@ -0,0 +1,44 @@ +// clear selection range of current selected term view +// Fix event when terminal text is selected and keyboard action is invoked +exports.clear = function (terminal) { + terminal.document_.getSelection().removeAllRanges(); +}; + +// Use selection extend upon dblclick +exports.extend = function (terminal) { + terminal.screen_.expandSelection(terminal.document_.getSelection()); +}; + +// Fix a bug in ScrollPort selectAll behavior +// Select all rows in the viewport +exports.all = function (terminal) { + let scrollPort = terminal.scrollPort_; + let firstRow, lastRowIndex, lastRow; + + if (scrollPort.topFold_.nextSibling.rowIndex !== 0) { + while (scrollPort.topFold_.previousSibling) { + scrollPort.rowNodes_.removeChild(scrollPort.topFold_.previousSibling); + } + + firstRow = scrollPort.fetchRowNode_(0); + scrollPort.rowNodes_.insertBefore(firstRow, scrollPort.topFold_); + scrollPort.syncRowNodesDimensions_(); + } else { + firstRow = scrollPort.topFold_.nextSibling; + } + + lastRowIndex = scrollPort.rowProvider_.getRowCount() - 1; + + if (scrollPort.bottomFold_.previousSibling.rowIndex !== lastRowIndex) { + while (scrollPort.bottomFold_.nextSibling) { + scrollPort.rowNodes_.removeChild(scrollPort.bottomFold_.nextSibling); + } + + lastRow = scrollPort.fetchRowNode_(lastRowIndex); + scrollPort.rowNodes_.appendChild(lastRow); + } else { + lastRow = scrollPort.bottomFold_.previousSibling.rowIndex; + } + + scrollPort.selection.sync(); +};