2016-07-08 10:48:24 -08:00
|
|
|
|
import { hterm, lib } from 'hterm-umdjs';
|
2016-08-17 17:45:18 -08:00
|
|
|
|
const selection = require('./utils/selection');
|
2016-07-08 10:48:24 -08:00
|
|
|
|
|
|
|
|
|
|
hterm.defaultStorage = new lib.Storage.Memory();
|
|
|
|
|
|
|
2016-08-18 19:09:40 -08:00
|
|
|
|
// 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);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2016-07-08 10:48:24 -08:00
|
|
|
|
// override double click behavior to copy
|
|
|
|
|
|
const oldMouse = hterm.Terminal.prototype.onMouse_;
|
|
|
|
|
|
hterm.Terminal.prototype.onMouse_ = function (e) {
|
|
|
|
|
|
if ('dblclick' === e.type) {
|
2016-08-18 19:09:40 -08:00
|
|
|
|
selection.extend(this);
|
2016-07-08 10:48:24 -08:00
|
|
|
|
console.log('[hyperterm+hterm] ignore double click');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
return oldMouse.call(this, e);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// there's no option to turn off the size overlay
|
|
|
|
|
|
hterm.Terminal.prototype.overlaySize = function () {};
|
|
|
|
|
|
|
|
|
|
|
|
// fixing a bug in hterm where a double click triggers
|
|
|
|
|
|
// a non-collapsed selection whose text is '', and results
|
|
|
|
|
|
// in an infinite copy loop
|
|
|
|
|
|
hterm.Terminal.prototype.copySelectionToClipboard = function () {
|
|
|
|
|
|
var text = this.getSelectionText();
|
|
|
|
|
|
if (text != null && text !== '') {
|
|
|
|
|
|
this.copyStringToClipboard(text);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// passthrough all the commands that are meant to control
|
|
|
|
|
|
// hyperterm and not the terminal itself
|
|
|
|
|
|
const oldKeyDown = hterm.Keyboard.prototype.onKeyDown_;
|
|
|
|
|
|
hterm.Keyboard.prototype.onKeyDown_ = function (e) {
|
2016-08-01 16:08:51 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Add fixes for U.S. International PC Keyboard layout
|
|
|
|
|
|
* These keys are sent through as 'Dead' keys, as they're used as modifiers.
|
|
|
|
|
|
* Ignore that and insert the correct character.
|
|
|
|
|
|
*/
|
2016-08-10 09:37:35 -08:00
|
|
|
|
if (e.key === 'Dead') {
|
|
|
|
|
|
if (e.code === 'Quote' && e.shiftKey === false) {
|
|
|
|
|
|
this.terminal.onVTKeystroke("'");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (e.code === 'Quote' && e.shiftKey === true) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('"');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((e.code === 'IntlBackslash' || e.code === 'Backquote') && e.shiftKey === true) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('~');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// This key is also a tilde on all tested keyboards
|
|
|
|
|
|
if (e.code === 'KeyN' && e.altKey === true) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('~');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((e.code === 'IntlBackslash' || e.code === 'Backquote') && e.shiftKey === false) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('`');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (e.code === 'Digit6') {
|
|
|
|
|
|
this.terminal.onVTKeystroke('^');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// German keyboard layout
|
|
|
|
|
|
if (e.code === 'Equal' && e.shiftKey === false) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('´');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (e.code === 'Equal' && e.shiftKey === true) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('`');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Italian keyboard layout
|
|
|
|
|
|
if (e.code === 'Digit9' && e.altKey === true) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('`');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (e.code === 'Digit8' && e.altKey === true) {
|
|
|
|
|
|
this.terminal.onVTKeystroke('´');
|
|
|
|
|
|
// To fix issue with changing the terminal prompt
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2016-08-22 09:43:56 -08:00
|
|
|
|
// French keyboard layout
|
|
|
|
|
|
if (e.code === 'BracketLeft') {
|
|
|
|
|
|
this.terminal.onVTKeystroke('^');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (e.code === 'Backslash') {
|
|
|
|
|
|
this.terminal.onVTKeystroke('`');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2016-08-10 09:37:35 -08:00
|
|
|
|
console.warn('Uncaught dead key on international keyboard', e);
|
2016-08-01 16:08:51 -08:00
|
|
|
|
}
|
2016-08-10 09:37:35 -08:00
|
|
|
|
|
2016-09-14 21:36:16 -08:00
|
|
|
|
if (e.metaKey || e.altKey || (e.ctrlKey && e.code === 'Tab')) {
|
2016-07-08 10:48:24 -08:00
|
|
|
|
return;
|
2016-08-13 13:03:44 -08:00
|
|
|
|
} else {
|
|
|
|
|
|
// Test for valid keys in order to clear the terminal selection
|
|
|
|
|
|
if ((!e.ctrlKey || e.code !== 'ControlLeft') && !e.shiftKey && e.code !== 'CapsLock') {
|
2016-08-17 17:45:18 -08:00
|
|
|
|
selection.clear(this.terminal);
|
2016-08-13 13:03:44 -08:00
|
|
|
|
}
|
2016-07-08 10:48:24 -08:00
|
|
|
|
}
|
|
|
|
|
|
return oldKeyDown.call(this, e);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const oldKeyPress = hterm.Keyboard.prototype.onKeyPress_;
|
|
|
|
|
|
hterm.Keyboard.prototype.onKeyPress_ = function (e) {
|
|
|
|
|
|
if (e.metaKey) {
|
|
|
|
|
|
return;
|
2016-08-13 13:03:44 -08:00
|
|
|
|
} else {
|
2016-08-17 17:45:18 -08:00
|
|
|
|
selection.clear(this.terminal);
|
2016-07-08 10:48:24 -08:00
|
|
|
|
}
|
|
|
|
|
|
return oldKeyPress.call(this, e);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2016-07-13 12:44:24 -08:00
|
|
|
|
// we re-implement `wipeContents` to preserve the line
|
|
|
|
|
|
// and cursor position that the client is in.
|
|
|
|
|
|
// otherwise the user ends up with a completely clear
|
|
|
|
|
|
// screen which is really strange
|
|
|
|
|
|
hterm.Terminal.prototype.clearPreserveCursorRow = function () {
|
|
|
|
|
|
this.scrollbackRows_.length = 0;
|
|
|
|
|
|
this.scrollPort_.resetCache();
|
|
|
|
|
|
|
|
|
|
|
|
[this.primaryScreen_, this.alternateScreen_].forEach((screen) => {
|
|
|
|
|
|
const bottom = screen.getHeight();
|
|
|
|
|
|
if (bottom > 0) {
|
|
|
|
|
|
this.renumberRows_(0, bottom);
|
|
|
|
|
|
|
|
|
|
|
|
const x = screen.cursorPosition.column;
|
|
|
|
|
|
const y = screen.cursorPosition.row;
|
|
|
|
|
|
|
|
|
|
|
|
if (x === 0) {
|
|
|
|
|
|
// Empty screen, nothing to do.
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// here we move the row that the user was focused on
|
|
|
|
|
|
// to the top of the screen
|
|
|
|
|
|
this.moveRows_(y, 1, 0);
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 1; i < bottom; i++) {
|
|
|
|
|
|
screen.setCursorPosition(i, 0);
|
|
|
|
|
|
screen.clearCursorRow();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// we restore the cursor position
|
|
|
|
|
|
screen.setCursorPosition(0, x);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.syncCursorPosition_();
|
|
|
|
|
|
this.scrollPort_.invalidate();
|
|
|
|
|
|
|
|
|
|
|
|
// this will avoid a bug where the `wipeContents`
|
2016-07-17 13:05:37 -08:00
|
|
|
|
// hterm API doesn't send the scroll to the top
|
2016-07-13 12:44:24 -08:00
|
|
|
|
this.scrollPort_.redraw_();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2016-07-19 09:46:26 -08:00
|
|
|
|
// fixes a bug in hterm, where the shorthand hex
|
|
|
|
|
|
// is not properly converted to rgb
|
2016-07-20 14:21:29 -08:00
|
|
|
|
lib.colors.hexToRGB = function (arg) {
|
2016-07-19 09:46:26 -08:00
|
|
|
|
var hex16 = lib.colors.re_.hex16;
|
|
|
|
|
|
var hex24 = lib.colors.re_.hex24;
|
|
|
|
|
|
|
2016-07-20 14:21:29 -08:00
|
|
|
|
function convert (hex) {
|
|
|
|
|
|
if (hex.length === 4) {
|
|
|
|
|
|
hex = hex.replace(hex16, function (h, r, g, b) {
|
|
|
|
|
|
return '#' + r + r + g + g + b + b;
|
2016-07-19 09:46:26 -08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
var ary = hex.match(hex24);
|
2016-07-20 14:21:29 -08:00
|
|
|
|
if (!ary) return null;
|
2016-07-19 09:46:26 -08:00
|
|
|
|
|
2016-07-20 14:21:29 -08:00
|
|
|
|
return 'rgb(' +
|
|
|
|
|
|
parseInt(ary[1], 16) + ', ' +
|
|
|
|
|
|
parseInt(ary[2], 16) + ', ' +
|
|
|
|
|
|
parseInt(ary[3], 16) +
|
|
|
|
|
|
')';
|
2016-07-19 09:46:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (arg instanceof Array) {
|
|
|
|
|
|
for (var i = 0; i < arg.length; i++) {
|
|
|
|
|
|
arg[i] = convert(arg[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
arg = convert(arg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return arg;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2016-07-13 12:44:24 -08:00
|
|
|
|
export default hterm;
|
2016-07-08 10:48:24 -08:00
|
|
|
|
export { lib };
|