mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' of https://github.com/7PH/xterm.js
This commit is contained in:
+3
-3
@@ -170,7 +170,7 @@ function initOptions(term) {
|
||||
fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
||||
fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900']
|
||||
};
|
||||
var options = Object.keys(term.options);
|
||||
var options = Object.keys(term._core.options);
|
||||
var booleanOptions = [];
|
||||
var numberOptions = [];
|
||||
options.filter(o => blacklistedOptions.indexOf(o) === -1).forEach(o => {
|
||||
@@ -241,8 +241,8 @@ function initOptions(term) {
|
||||
function updateTerminalSize() {
|
||||
var cols = parseInt(document.getElementById(`opt-cols`).value, 10);
|
||||
var rows = parseInt(document.getElementById(`opt-rows`).value, 10);
|
||||
var width = (cols * term.renderer.dimensions.actualCellWidth + term.viewport.scrollBarWidth).toString() + 'px';
|
||||
var height = (rows * term.renderer.dimensions.actualCellHeight).toString() + 'px';
|
||||
var width = (cols * term._core.renderer.dimensions.actualCellWidth + term._core.viewport.scrollBarWidth).toString() + 'px';
|
||||
var height = (rows * term._core.renderer.dimensions.actualCellHeight).toString() + 'px';
|
||||
terminalContainer.style.width = width;
|
||||
terminalContainer.style.height = height;
|
||||
term.fit();
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "xterm",
|
||||
"description": "Full xterm terminal, in your browser",
|
||||
"version": "3.4.0",
|
||||
"main": "lib/Terminal.js",
|
||||
"main": "lib/public/Terminal.js",
|
||||
"types": "typings/xterm.d.ts",
|
||||
"repository": "https://github.com/xtermjs/xterm.js",
|
||||
"license": "MIT",
|
||||
|
||||
+4
-3
@@ -4,13 +4,14 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { CharData, IInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer, ICharset } from './Types';
|
||||
import { C0, C1 } from './EscapeSequences';
|
||||
import { CHARSETS, DEFAULT_CHARSET } from './Charsets';
|
||||
import { CharData, IInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer } from './Types';
|
||||
import { C0, C1 } from './common/data/EscapeSequences';
|
||||
import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';
|
||||
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, DEFAULT_ATTR } from './Buffer';
|
||||
import { FLAGS } from './renderer/Types';
|
||||
import { wcwidth } from './CharWidth';
|
||||
import { EscapeSequenceParser } from './EscapeSequenceParser';
|
||||
import { ICharset } from './core/Types';
|
||||
|
||||
/**
|
||||
* Map collect to glevel. Used in `selectCharset`.
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { C0 } from './EscapeSequences';
|
||||
import { C0 } from './common/data/EscapeSequences';
|
||||
import { IInputHandler, IInputHandlingTerminal } from './Types';
|
||||
import { CHARSETS, DEFAULT_CHARSET } from './Charsets';
|
||||
import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';
|
||||
|
||||
const normalStateHandler: {[key: string]: (parser: Parser, handler: IInputHandler) => void} = {};
|
||||
normalStateHandler[C0.BEL] = (parser, handler) => handler.bell();
|
||||
|
||||
+5
-260
@@ -5,7 +5,6 @@
|
||||
|
||||
import { assert, expect } from 'chai';
|
||||
import { Terminal } from './Terminal';
|
||||
import * as attach from './addons/attach/attach';
|
||||
import { MockViewport, MockCompositionHelper, MockRenderer } from './utils/TestUtils.test';
|
||||
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer';
|
||||
|
||||
@@ -13,7 +12,6 @@ const INIT_COLS = 80;
|
||||
const INIT_ROWS = 24;
|
||||
|
||||
class TestTerminal extends Terminal {
|
||||
public evaluateKeyEscapeSequence(ev: any): {cancel: boolean, key: string, scrollLines: number} { return this._evaluateKeyEscapeSequence(<KeyboardEvent>ev); }
|
||||
public keyDown(ev: any): boolean { return this._keyDown(ev); }
|
||||
public keyPress(ev: any): boolean { return this._keyPress(ev); }
|
||||
}
|
||||
@@ -53,13 +51,6 @@ describe('term.js addons', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should apply addons with Terminal.applyAddon', () => {
|
||||
Terminal.applyAddon(attach);
|
||||
// Test that addon was applied successfully, adding attach to Terminal's
|
||||
// prototype.
|
||||
assert.equal(typeof (<any>Terminal).prototype.attach, 'function');
|
||||
});
|
||||
|
||||
describe('getOption', () => {
|
||||
it('should retrieve the option correctly', () => {
|
||||
// In the `options` namespace.
|
||||
@@ -296,22 +287,19 @@ describe('term.js addons', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('keyDown', () => {
|
||||
describe('keyPress', () => {
|
||||
it('should scroll down, when a key is pressed and terminal is scrolled up', () => {
|
||||
// Override _evaluateKeyEscapeSequence to return cancel code
|
||||
(<any>term)._evaluateKeyEscapeSequence = () => {
|
||||
return { key: 'a' };
|
||||
};
|
||||
const event = <KeyboardEvent>{
|
||||
type: 'keydown',
|
||||
keyCode: 0,
|
||||
key: 'a',
|
||||
keyCode: 65,
|
||||
preventDefault: () => {},
|
||||
stopPropagation: () => {}
|
||||
};
|
||||
|
||||
term.buffer.ydisp = 0;
|
||||
term.buffer.ybase = 40;
|
||||
term.keyDown(event);
|
||||
term.keyPress(event);
|
||||
|
||||
// Ensure that now the terminal is scrolled to bottom
|
||||
assert.equal(term.buffer.ydisp, term.buffer.ybase);
|
||||
@@ -330,7 +318,7 @@ describe('term.js addons', () => {
|
||||
assert.equal(term.buffer.ydisp, startYDisp);
|
||||
term.scrollLines(-1);
|
||||
assert.equal(term.buffer.ydisp, startYDisp - 1);
|
||||
term.keyDown(<KeyboardEvent>{ keyCode: 0 });
|
||||
term.keyPress(<KeyboardEvent>{ keyCode: 0 });
|
||||
assert.equal(term.buffer.ydisp, startYDisp - 1);
|
||||
});
|
||||
});
|
||||
@@ -468,249 +456,6 @@ describe('term.js addons', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('evaluateKeyEscapeSequence', () => {
|
||||
it('should return the correct escape sequence for unmodified keys', () => {
|
||||
// Backspace
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 8 }).key, '\x7f'); // ^?
|
||||
// Tab
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 9 }).key, '\t');
|
||||
// Return/enter
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 13 }).key, '\r'); // CR
|
||||
// Escape
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 27 }).key, '\x1b');
|
||||
// Page up, page down
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 33 }).key, '\x1b[5~'); // CSI 5 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 34 }).key, '\x1b[6~'); // CSI 6 ~
|
||||
// End, Home
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 35 }).key, '\x1b[F'); // SS3 F
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 36 }).key, '\x1b[H'); // SS3 H
|
||||
// Left, up, right, down arrows
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 37 }).key, '\x1b[D'); // CSI D
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 38 }).key, '\x1b[A'); // CSI A
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 39 }).key, '\x1b[C'); // CSI C
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 40 }).key, '\x1b[B'); // CSI B
|
||||
// Insert
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 45 }).key, '\x1b[2~'); // CSI 2 ~
|
||||
// Delete
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 46 }).key, '\x1b[3~'); // CSI 3 ~
|
||||
// F1-F12
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 112 }).key, '\x1bOP'); // SS3 P
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 113 }).key, '\x1bOQ'); // SS3 Q
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 114 }).key, '\x1bOR'); // SS3 R
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 115 }).key, '\x1bOS'); // SS3 S
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 116 }).key, '\x1b[15~'); // CSI 1 5 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 117 }).key, '\x1b[17~'); // CSI 1 7 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 118 }).key, '\x1b[18~'); // CSI 1 8 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 119 }).key, '\x1b[19~'); // CSI 1 9 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 120 }).key, '\x1b[20~'); // CSI 2 0 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 121 }).key, '\x1b[21~'); // CSI 2 1 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 122 }).key, '\x1b[23~'); // CSI 2 3 ~
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 123 }).key, '\x1b[24~'); // CSI 2 4 ~
|
||||
});
|
||||
it('should return \\x1b[3;5~ for ctrl+delete', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 46 }).key, '\x1b[3;5~');
|
||||
});
|
||||
it('should return \\x1b[3;2~ for shift+delete', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 46 }).key, '\x1b[3;2~');
|
||||
});
|
||||
it('should return \\x1b[3;3~ for alt+delete', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~');
|
||||
});
|
||||
it('should return \\x1b[5D for ctrl+left', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D
|
||||
});
|
||||
it('should return \\x1b[5C for ctrl+right', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C
|
||||
});
|
||||
it('should return \\x1b[5A for ctrl+up', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A
|
||||
});
|
||||
it('should return \\x1b[5B for ctrl+down', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B
|
||||
});
|
||||
|
||||
describe('On non-macOS platforms', () => {
|
||||
beforeEach(() => {
|
||||
term.browser.isMac = false;
|
||||
});
|
||||
// Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
it('should return \\x1b[5D for alt+left', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D
|
||||
});
|
||||
it('should return \\x1b[5C for alt+right', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C
|
||||
});
|
||||
it('should return \\x1ba for alt+a', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 65 }).key, '\x1ba');
|
||||
});
|
||||
});
|
||||
|
||||
describe('On macOS platforms', () => {
|
||||
beforeEach(() => {
|
||||
term.browser.isMac = true;
|
||||
});
|
||||
it('should return \\x1bb for alt+left', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 37 }).key, '\x1bb'); // CSI 5 D
|
||||
});
|
||||
it('should return \\x1bf for alt+right', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1bf'); // CSI 5 C
|
||||
});
|
||||
it('should return undefined for alt+a', () => {
|
||||
assert.strictEqual(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 65 }).key, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with macOptionIsMeta', () => {
|
||||
beforeEach(() => {
|
||||
term.browser.isMac = true;
|
||||
term.setOption('macOptionIsMeta', true);
|
||||
});
|
||||
it('should return \\x1ba for alt+a', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 65 }).key, '\x1ba');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return \\x1b[5A for alt+up', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A
|
||||
});
|
||||
it('should return \\x1b[5B for alt+down', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B
|
||||
});
|
||||
it('should return the correct escape sequence for modified F1-F12 keys', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 112 }).key, '\x1b[1;2P');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 113 }).key, '\x1b[1;2Q');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 114 }).key, '\x1b[1;2R');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 115 }).key, '\x1b[1;2S');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 116 }).key, '\x1b[15;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 117 }).key, '\x1b[17;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 118 }).key, '\x1b[18;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 119 }).key, '\x1b[19;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 120 }).key, '\x1b[20;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 121 }).key, '\x1b[21;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 122 }).key, '\x1b[23;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 123 }).key, '\x1b[24;2~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 112 }).key, '\x1b[1;3P');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 113 }).key, '\x1b[1;3Q');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 114 }).key, '\x1b[1;3R');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 115 }).key, '\x1b[1;3S');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 116 }).key, '\x1b[15;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 117 }).key, '\x1b[17;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 118 }).key, '\x1b[18;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 119 }).key, '\x1b[19;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 120 }).key, '\x1b[20;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 121 }).key, '\x1b[21;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 122 }).key, '\x1b[23;3~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 123 }).key, '\x1b[24;3~');
|
||||
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 112 }).key, '\x1b[1;5P');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 113 }).key, '\x1b[1;5Q');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 114 }).key, '\x1b[1;5R');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 115 }).key, '\x1b[1;5S');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 116 }).key, '\x1b[15;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 117 }).key, '\x1b[17;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 118 }).key, '\x1b[18;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 119 }).key, '\x1b[19;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 120 }).key, '\x1b[20;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 121 }).key, '\x1b[21;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 122 }).key, '\x1b[23;5~');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 123 }).key, '\x1b[24;5~');
|
||||
});
|
||||
|
||||
// Characters using ctrl+alt sequences
|
||||
it('should return proper sequence for ctrl+alt+a', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, ctrlKey: true, keyCode: 65 }).key, '\x1b\x01');
|
||||
});
|
||||
|
||||
// Characters using alt sequences (numbers)
|
||||
it('should return proper sequences for alt+0', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 48 }).key, '\x1b0');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 48 }).key, '\x1b)');
|
||||
});
|
||||
it('should return proper sequences for alt+1', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 49 }).key, '\x1b1');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 49 }).key, '\x1b!');
|
||||
});
|
||||
it('should return proper sequences for alt+2', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 50 }).key, '\x1b2');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 50 }).key, '\x1b@');
|
||||
});
|
||||
it('should return proper sequences for alt+3', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 51 }).key, '\x1b3');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 51 }).key, '\x1b#');
|
||||
});
|
||||
it('should return proper sequences for alt+4', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 52 }).key, '\x1b4');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 52 }).key, '\x1b$');
|
||||
});
|
||||
it('should return proper sequences for alt+5', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 53 }).key, '\x1b5');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 53 }).key, '\x1b%');
|
||||
});
|
||||
it('should return proper sequences for alt+6', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 54 }).key, '\x1b6');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 54 }).key, '\x1b^');
|
||||
});
|
||||
it('should return proper sequences for alt+7', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 55 }).key, '\x1b7');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 55 }).key, '\x1b&');
|
||||
});
|
||||
it('should return proper sequences for alt+8', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 56 }).key, '\x1b8');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 56 }).key, '\x1b*');
|
||||
});
|
||||
it('should return proper sequences for alt+9', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 57 }).key, '\x1b9');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 57 }).key, '\x1b(');
|
||||
});
|
||||
|
||||
// Characters using alt sequences (special chars)
|
||||
it('should return proper sequences for alt+;', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 186 }).key, '\x1b;');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 186 }).key, '\x1b:');
|
||||
});
|
||||
it('should return proper sequences for alt+=', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 187 }).key, '\x1b=');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 187 }).key, '\x1b+');
|
||||
});
|
||||
it('should return proper sequences for alt+,', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 188 }).key, '\x1b,');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 188 }).key, '\x1b<');
|
||||
});
|
||||
it('should return proper sequences for alt+-', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 189 }).key, '\x1b-');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 189 }).key, '\x1b_');
|
||||
});
|
||||
it('should return proper sequences for alt+.', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 190 }).key, '\x1b.');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 190 }).key, '\x1b>');
|
||||
});
|
||||
it('should return proper sequences for alt+/', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 191 }).key, '\x1b/');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 191 }).key, '\x1b?');
|
||||
});
|
||||
it('should return proper sequences for alt+~', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 192 }).key, '\x1b`');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 192 }).key, '\x1b~');
|
||||
});
|
||||
it('should return proper sequences for alt+[', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 219 }).key, '\x1b[');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 219 }).key, '\x1b{');
|
||||
});
|
||||
it('should return proper sequences for alt+\\', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 220 }).key, '\x1b\\');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 220 }).key, '\x1b|');
|
||||
});
|
||||
it('should return proper sequences for alt+]', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 221 }).key, '\x1b]');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 221 }).key, '\x1b}');
|
||||
});
|
||||
it('should return proper sequences for alt+\'', () => {
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: false, keyCode: 222 }).key, '\x1b\'');
|
||||
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, shiftKey: true, keyCode: 222 }).key, '\x1b"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Third level shift', () => {
|
||||
let evKeyDown: any;
|
||||
let evKeyPress: any;
|
||||
|
||||
+24
-379
@@ -21,7 +21,7 @@
|
||||
* http://linux.die.net/man/7/urxvt
|
||||
*/
|
||||
|
||||
import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharData, LineData } from './Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharData, LineData } from './Types';
|
||||
import { IMouseZoneManager } from './input/Types';
|
||||
import { IRenderer } from './renderer/Types';
|
||||
import { BufferSet } from './BufferSet';
|
||||
@@ -30,7 +30,7 @@ import { CompositionHelper } from './CompositionHelper';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import { Viewport } from './Viewport';
|
||||
import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './handlers/Clipboard';
|
||||
import { C0 } from './EscapeSequences';
|
||||
import { C0 } from './common/data/EscapeSequences';
|
||||
import { InputHandler } from './InputHandler';
|
||||
// import { Parser } from './Parser';
|
||||
import { Renderer } from './renderer/Renderer';
|
||||
@@ -47,37 +47,12 @@ import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager';
|
||||
import { MouseZoneManager } from './input/MouseZoneManager';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { ScreenDprMonitor } from './utils/ScreenDprMonitor';
|
||||
import { ITheme, ILocalizableStrings, IMarker, IDisposable } from 'xterm';
|
||||
import { ITheme, IMarker, IDisposable } from 'xterm';
|
||||
import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';
|
||||
import { DomRenderer } from './renderer/dom/DomRenderer';
|
||||
|
||||
// reg + shift key mappings for digits and special chars
|
||||
const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = {
|
||||
// digits 0-9
|
||||
48: ['0', ')'],
|
||||
49: ['1', '!'],
|
||||
50: ['2', '@'],
|
||||
51: ['3', '#'],
|
||||
52: ['4', '$'],
|
||||
53: ['5', '%'],
|
||||
54: ['6', '^'],
|
||||
55: ['7', '&'],
|
||||
56: ['8', '*'],
|
||||
57: ['9', '('],
|
||||
|
||||
// special chars
|
||||
186: [';', ':'],
|
||||
187: ['=', '+'],
|
||||
188: [',', '<'],
|
||||
189: ['-', '_'],
|
||||
190: ['.', '>'],
|
||||
191: ['/', '?'],
|
||||
192: ['`', '~'],
|
||||
219: ['[', '{'],
|
||||
220: ['\\', '|'],
|
||||
221: [']', '}'],
|
||||
222: ['\'', '"']
|
||||
};
|
||||
import { IKeyboardEvent } from './common/Types';
|
||||
import { evaluateKeyboardEvent } from './core/input/Keyboard';
|
||||
import { KeyboardResultType, ICharset } from './core/Types';
|
||||
|
||||
// Let it work inside Node.js for automated testing purposes.
|
||||
const document = (typeof window !== 'undefined') ? window.document : null;
|
||||
@@ -354,10 +329,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
return this.buffers.active;
|
||||
}
|
||||
|
||||
public static get strings(): ILocalizableStrings {
|
||||
return Strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* back_color_erase feature for xterm.
|
||||
*/
|
||||
@@ -773,14 +744,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the provided addon on the `Terminal` class.
|
||||
* @param addon The addon to apply.
|
||||
*/
|
||||
public static applyAddon(addon: any): void {
|
||||
addon.apply(Terminal);
|
||||
}
|
||||
|
||||
/**
|
||||
* XTerm mouse events
|
||||
* http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
|
||||
@@ -1437,19 +1400,19 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
* - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent
|
||||
* @param {KeyboardEvent} ev The keydown event to be handled.
|
||||
*/
|
||||
protected _keyDown(ev: KeyboardEvent): boolean {
|
||||
if (this._customKeyEventHandler && this._customKeyEventHandler(ev) === false) {
|
||||
protected _keyDown(event: KeyboardEvent): boolean {
|
||||
if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this._compositionHelper.keydown(ev)) {
|
||||
if (!this._compositionHelper.keydown(event)) {
|
||||
if (this.buffer.ybase !== this.buffer.ydisp) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = this._evaluateKeyEscapeSequence(ev);
|
||||
const result = evaluateKeyboardEvent(event, this.applicationCursor, this.browser.isMac, this.options.macOptionIsMeta);
|
||||
|
||||
// if (result.key === C0.DC3) { // XOFF
|
||||
// this._writeStopped = true;
|
||||
@@ -1457,33 +1420,38 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
// this._writeStopped = false;
|
||||
// }
|
||||
|
||||
if (result.scrollLines) {
|
||||
this.scrollLines(result.scrollLines);
|
||||
return this.cancel(ev, true);
|
||||
if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
|
||||
const scrollCount = this.rows - 1;
|
||||
this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
|
||||
return this.cancel(event, true);
|
||||
}
|
||||
|
||||
if (this._isThirdLevelShift(this.browser, ev)) {
|
||||
if (result.type === KeyboardResultType.SELECT_ALL) {
|
||||
this.selectAll();
|
||||
}
|
||||
|
||||
if (this._isThirdLevelShift(this.browser, event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result.cancel) {
|
||||
// The event is canceled at the end already, is this necessary?
|
||||
this.cancel(ev, true);
|
||||
this.cancel(event, true);
|
||||
}
|
||||
|
||||
if (!result.key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.emit('keydown', ev);
|
||||
this.emit('key', result.key, ev);
|
||||
this.emit('keydown', event);
|
||||
this.emit('key', result.key, event);
|
||||
this.showCursor();
|
||||
this.handler(result.key);
|
||||
|
||||
return this.cancel(ev, true);
|
||||
return this.cancel(event, true);
|
||||
}
|
||||
|
||||
private _isThirdLevelShift(browser: IBrowser, ev: KeyboardEvent): boolean {
|
||||
private _isThirdLevelShift(browser: IBrowser, ev: IKeyboardEvent): boolean {
|
||||
const thirdLevelKey =
|
||||
(browser.isMac && !this.options.macOptionIsMeta && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||
|
||||
(browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);
|
||||
@@ -1496,329 +1464,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object that determines how a KeyboardEvent should be handled. The key of the
|
||||
* returned value is the new key code to pass to the PTY.
|
||||
*
|
||||
* Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
* @param ev The keyboard event to be translated to key escape sequence.
|
||||
*/
|
||||
protected _evaluateKeyEscapeSequence(ev: KeyboardEvent): {cancel: boolean, key: string, scrollLines: number} {
|
||||
const result: {cancel: boolean, key: string, scrollLines: number} = {
|
||||
// Whether to cancel event propogation (NOTE: this may not be needed since the event is
|
||||
// canceled at the end of keyDown
|
||||
cancel: false,
|
||||
// The new key even to emit
|
||||
key: undefined,
|
||||
// The number of characters to scroll, if this is defined it will cancel the event
|
||||
scrollLines: undefined
|
||||
};
|
||||
const modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0);
|
||||
switch (ev.keyCode) {
|
||||
case 0:
|
||||
if (ev.key === 'UIKeyInputUpArrow') {
|
||||
if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OA';
|
||||
} else {
|
||||
result.key = C0.ESC + '[A';
|
||||
}
|
||||
}
|
||||
else if (ev.key === 'UIKeyInputLeftArrow') {
|
||||
if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OD';
|
||||
} else {
|
||||
result.key = C0.ESC + '[D';
|
||||
}
|
||||
}
|
||||
else if (ev.key === 'UIKeyInputRightArrow') {
|
||||
if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OC';
|
||||
} else {
|
||||
result.key = C0.ESC + '[C';
|
||||
}
|
||||
}
|
||||
else if (ev.key === 'UIKeyInputDownArrow') {
|
||||
if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OB';
|
||||
} else {
|
||||
result.key = C0.ESC + '[B';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// backspace
|
||||
if (ev.shiftKey) {
|
||||
result.key = C0.BS; // ^H
|
||||
break;
|
||||
} else if (ev.altKey) {
|
||||
result.key = C0.ESC + C0.DEL; // \e ^?
|
||||
break;
|
||||
}
|
||||
result.key = C0.DEL; // ^?
|
||||
break;
|
||||
case 9:
|
||||
// tab
|
||||
if (ev.shiftKey) {
|
||||
result.key = C0.ESC + '[Z';
|
||||
break;
|
||||
}
|
||||
result.key = C0.HT;
|
||||
result.cancel = true;
|
||||
break;
|
||||
case 13:
|
||||
// return/enter
|
||||
result.key = C0.CR;
|
||||
result.cancel = true;
|
||||
break;
|
||||
case 27:
|
||||
// escape
|
||||
result.key = C0.ESC;
|
||||
result.cancel = true;
|
||||
break;
|
||||
case 37:
|
||||
// left-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'D';
|
||||
// HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
// macOS uses different escape sequences than linux
|
||||
if (result.key === C0.ESC + '[1;3D') {
|
||||
result.key = (this.browser.isMac) ? C0.ESC + 'b' : C0.ESC + '[1;5D';
|
||||
}
|
||||
} else if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OD';
|
||||
} else {
|
||||
result.key = C0.ESC + '[D';
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
// right-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'C';
|
||||
// HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
// macOS uses different escape sequences than linux
|
||||
if (result.key === C0.ESC + '[1;3C') {
|
||||
result.key = (this.browser.isMac) ? C0.ESC + 'f' : C0.ESC + '[1;5C';
|
||||
}
|
||||
} else if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OC';
|
||||
} else {
|
||||
result.key = C0.ESC + '[C';
|
||||
}
|
||||
break;
|
||||
case 38:
|
||||
// up-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'A';
|
||||
// HACK: Make Alt + up-arrow behave like Ctrl + up-arrow
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
if (result.key === C0.ESC + '[1;3A') {
|
||||
result.key = C0.ESC + '[1;5A';
|
||||
}
|
||||
} else if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OA';
|
||||
} else {
|
||||
result.key = C0.ESC + '[A';
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
// down-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'B';
|
||||
// HACK: Make Alt + down-arrow behave like Ctrl + down-arrow
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
if (result.key === C0.ESC + '[1;3B') {
|
||||
result.key = C0.ESC + '[1;5B';
|
||||
}
|
||||
} else if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OB';
|
||||
} else {
|
||||
result.key = C0.ESC + '[B';
|
||||
}
|
||||
break;
|
||||
case 45:
|
||||
// insert
|
||||
if (!ev.shiftKey && !ev.ctrlKey) {
|
||||
// <Ctrl> or <Shift> + <Insert> are used to
|
||||
// copy-paste on some systems.
|
||||
result.key = C0.ESC + '[2~';
|
||||
}
|
||||
break;
|
||||
case 46:
|
||||
// delete
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[3;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[3~';
|
||||
}
|
||||
break;
|
||||
case 36:
|
||||
// home
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'H';
|
||||
} else if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OH';
|
||||
} else {
|
||||
result.key = C0.ESC + '[H';
|
||||
}
|
||||
break;
|
||||
case 35:
|
||||
// end
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'F';
|
||||
} else if (this.applicationCursor) {
|
||||
result.key = C0.ESC + 'OF';
|
||||
} else {
|
||||
result.key = C0.ESC + '[F';
|
||||
}
|
||||
break;
|
||||
case 33:
|
||||
// page up
|
||||
if (ev.shiftKey) {
|
||||
result.scrollLines = -(this.rows - 1);
|
||||
} else {
|
||||
result.key = C0.ESC + '[5~';
|
||||
}
|
||||
break;
|
||||
case 34:
|
||||
// page down
|
||||
if (ev.shiftKey) {
|
||||
result.scrollLines = this.rows - 1;
|
||||
} else {
|
||||
result.key = C0.ESC + '[6~';
|
||||
}
|
||||
break;
|
||||
case 112:
|
||||
// F1-F12
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'P';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OP';
|
||||
}
|
||||
break;
|
||||
case 113:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'Q';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OQ';
|
||||
}
|
||||
break;
|
||||
case 114:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'R';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OR';
|
||||
}
|
||||
break;
|
||||
case 115:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'S';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OS';
|
||||
}
|
||||
break;
|
||||
case 116:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[15;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[15~';
|
||||
}
|
||||
break;
|
||||
case 117:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[17;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[17~';
|
||||
}
|
||||
break;
|
||||
case 118:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[18;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[18~';
|
||||
}
|
||||
break;
|
||||
case 119:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[19;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[19~';
|
||||
}
|
||||
break;
|
||||
case 120:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[20;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[20~';
|
||||
}
|
||||
break;
|
||||
case 121:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[21;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[21~';
|
||||
}
|
||||
break;
|
||||
case 122:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[23;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[23~';
|
||||
}
|
||||
break;
|
||||
case 123:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[24;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[24~';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// a-z and space
|
||||
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
|
||||
if (ev.keyCode >= 65 && ev.keyCode <= 90) {
|
||||
result.key = String.fromCharCode(ev.keyCode - 64);
|
||||
} else if (ev.keyCode === 32) {
|
||||
// NUL
|
||||
result.key = String.fromCharCode(0);
|
||||
} else if (ev.keyCode >= 51 && ev.keyCode <= 55) {
|
||||
// escape, file sep, group sep, record sep, unit sep
|
||||
result.key = String.fromCharCode(ev.keyCode - 51 + 27);
|
||||
} else if (ev.keyCode === 56) {
|
||||
// delete
|
||||
result.key = String.fromCharCode(127);
|
||||
} else if (ev.keyCode === 219) {
|
||||
// ^[ - Control Sequence Introducer (CSI)
|
||||
result.key = String.fromCharCode(27);
|
||||
} else if (ev.keyCode === 220) {
|
||||
// ^\ - String Terminator (ST)
|
||||
result.key = String.fromCharCode(28);
|
||||
} else if (ev.keyCode === 221) {
|
||||
// ^] - Operating System Command (OSC)
|
||||
result.key = String.fromCharCode(29);
|
||||
}
|
||||
} else if ((!this.browser.isMac || this.options.macOptionIsMeta) && ev.altKey && !ev.metaKey) {
|
||||
// On macOS this is a third level shift when !macOptionIsMeta. Use <Esc> instead.
|
||||
const keyMapping = KEYCODE_KEY_MAPPINGS[ev.keyCode];
|
||||
const key = keyMapping && keyMapping[!ev.shiftKey ? 0 : 1];
|
||||
if (key) {
|
||||
result.key = C0.ESC + key;
|
||||
} else if (ev.keyCode >= 65 && ev.keyCode <= 90) {
|
||||
const keyCode = ev.ctrlKey ? ev.keyCode - 64 : ev.keyCode + 32;
|
||||
result.key = C0.ESC + String.fromCharCode(keyCode);
|
||||
}
|
||||
} else if (this.browser.isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {
|
||||
if (ev.keyCode === 65) { // cmd + a
|
||||
this.selectAll();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the G level of the terminal
|
||||
* @param g
|
||||
|
||||
+1
-4
@@ -6,6 +6,7 @@
|
||||
import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter } from 'xterm';
|
||||
import { IColorSet, IRenderer } from './renderer/Types';
|
||||
import { IMouseZoneManager } from './input/Types';
|
||||
import { ICharset } from './core/Types';
|
||||
|
||||
export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
|
||||
|
||||
@@ -191,10 +192,6 @@ export interface ILinkMatcher {
|
||||
willLinkActivate?: (event: MouseEvent, uri: string) => boolean;
|
||||
}
|
||||
|
||||
export interface ICharset {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface ILinkHoverEvent {
|
||||
x1: number;
|
||||
y1: number;
|
||||
|
||||
@@ -37,10 +37,10 @@ export function proposeGeometry(term: Terminal): IGeometry {
|
||||
const elementPaddingVer = elementPadding.top + elementPadding.bottom;
|
||||
const elementPaddingHor = elementPadding.right + elementPadding.left;
|
||||
const availableHeight = parentElementHeight - elementPaddingVer;
|
||||
const availableWidth = parentElementWidth - elementPaddingHor - (<any>term).viewport.scrollBarWidth;
|
||||
const availableWidth = parentElementWidth - elementPaddingHor - (<any>term)._core.viewport.scrollBarWidth;
|
||||
const geometry = {
|
||||
cols: Math.floor(availableWidth / (<any>term).renderer.dimensions.actualCellWidth),
|
||||
rows: Math.floor(availableHeight / (<any>term).renderer.dimensions.actualCellHeight)
|
||||
cols: Math.floor(availableWidth / (<any>term)._core.renderer.dimensions.actualCellWidth),
|
||||
rows: Math.floor(availableHeight / (<any>term)._core.renderer.dimensions.actualCellHeight)
|
||||
};
|
||||
return geometry;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export function fit(term: Terminal): void {
|
||||
if (geometry) {
|
||||
// Force a full render
|
||||
if (term.rows !== geometry.rows || term.cols !== geometry.cols) {
|
||||
(<any>term).renderer.clear();
|
||||
(<any>term)._core.renderer.clear();
|
||||
term.resize(geometry.cols, geometry.rows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,17 @@
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
export interface ISearchAddonTerminal extends Terminal {
|
||||
__searchHelper?: ISearchHelper;
|
||||
|
||||
// TODO: Reuse ITerminal from core
|
||||
// TODO: Don't rely on this private API
|
||||
export interface ITerminalCore {
|
||||
buffer: any;
|
||||
selectionManager: any;
|
||||
}
|
||||
|
||||
export interface ISearchAddonTerminal extends Terminal {
|
||||
__searchHelper?: ISearchHelper;
|
||||
_core: ITerminalCore;
|
||||
}
|
||||
|
||||
export interface ISearchHelper {
|
||||
findNext(term: string): boolean;
|
||||
findPrevious(term: string): boolean;
|
||||
|
||||
@@ -35,14 +35,14 @@ export class SearchHelper implements ISearchHelper {
|
||||
|
||||
let result: ISearchResult;
|
||||
|
||||
let startRow = this._terminal.buffer.ydisp;
|
||||
if (this._terminal.selectionManager.selectionEnd) {
|
||||
let startRow = this._terminal._core.buffer.ydisp;
|
||||
if (this._terminal._core.selectionManager.selectionEnd) {
|
||||
// Start from the selection end if there is a selection
|
||||
startRow = this._terminal.selectionManager.selectionEnd[1];
|
||||
startRow = this._terminal._core.selectionManager.selectionEnd[1];
|
||||
}
|
||||
|
||||
// Search from ydisp + 1 to end
|
||||
for (let y = startRow + 1; y < this._terminal.buffer.ybase + this._terminal.rows; y++) {
|
||||
for (let y = startRow + 1; y < this._terminal._core.buffer.ybase + this._terminal.rows; y++) {
|
||||
result = this._findInLine(term, y);
|
||||
if (result) {
|
||||
break;
|
||||
@@ -76,10 +76,10 @@ export class SearchHelper implements ISearchHelper {
|
||||
|
||||
let result: ISearchResult;
|
||||
|
||||
let startRow = this._terminal.buffer.ydisp;
|
||||
if (this._terminal.selectionManager.selectionStart) {
|
||||
let startRow = this._terminal._core.buffer.ydisp;
|
||||
if (this._terminal._core.selectionManager.selectionStart) {
|
||||
// Start from the selection end if there is a selection
|
||||
startRow = this._terminal.selectionManager.selectionStart[1];
|
||||
startRow = this._terminal._core.selectionManager.selectionStart[1];
|
||||
}
|
||||
|
||||
// Search from ydisp + 1 to end
|
||||
@@ -92,7 +92,7 @@ export class SearchHelper implements ISearchHelper {
|
||||
|
||||
// Search from the top to the current ydisp
|
||||
if (!result) {
|
||||
for (let y = this._terminal.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {
|
||||
for (let y = this._terminal._core.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {
|
||||
result = this._findInLine(term, y);
|
||||
if (result) {
|
||||
break;
|
||||
@@ -111,11 +111,11 @@ export class SearchHelper implements ISearchHelper {
|
||||
* @return The search result if it was found.
|
||||
*/
|
||||
private _findInLine(term: string, y: number): ISearchResult {
|
||||
const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase();
|
||||
const lowerStringLine = this._terminal._core.buffer.translateBufferLineToString(y, true).toLowerCase();
|
||||
const lowerTerm = term.toLowerCase();
|
||||
let searchIndex = lowerStringLine.indexOf(lowerTerm);
|
||||
if (searchIndex >= 0) {
|
||||
const line = this._terminal.buffer.lines.get(y);
|
||||
const line = this._terminal._core.buffer.lines.get(y);
|
||||
for (let i = 0; i < searchIndex; i++) {
|
||||
const charData = line[i];
|
||||
// Adjust the searchIndex to normalize emoji into single chars
|
||||
@@ -147,8 +147,8 @@ export class SearchHelper implements ISearchHelper {
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length);
|
||||
this._terminal.scrollLines(result.row - this._terminal.buffer.ydisp);
|
||||
this._terminal._core.selectionManager.setSelection(result.col, result.row, result.term.length);
|
||||
this._terminal.scrollLines(result.row - this._terminal._core.buffer.ydisp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
export interface IWinptyCompatAddonTerminal extends Terminal {
|
||||
export interface ITerminalCore {
|
||||
buffer: any;
|
||||
}
|
||||
|
||||
export interface IWinptyCompatAddonTerminal extends Terminal {
|
||||
_core: ITerminalCore;
|
||||
}
|
||||
|
||||
@@ -26,11 +26,11 @@ export function winptyCompatInit(terminal: Terminal): void {
|
||||
// Windows when text reaches the end of the terminal it's likely going to be
|
||||
// wrapped.
|
||||
addonTerminal.on('linefeed', () => {
|
||||
const line = addonTerminal.buffer.lines.get(addonTerminal.buffer.ybase + addonTerminal.buffer.y - 1);
|
||||
const line = addonTerminal._core.buffer.lines.get(addonTerminal._core.buffer.ybase + addonTerminal._core.buffer.y - 1);
|
||||
const lastChar = line[addonTerminal.cols - 1];
|
||||
|
||||
if (lastChar[3] !== 32 /* ' ' */) {
|
||||
const nextLine = addonTerminal.buffer.lines.get(addonTerminal.buffer.ybase + addonTerminal.buffer.y);
|
||||
const nextLine = addonTerminal._core.buffer.lines.get(addonTerminal._core.buffer.ybase + addonTerminal._core.buffer.y);
|
||||
(<any>nextLine).isWrapped = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* A keyboard event interface which does not depend on the DOM, KeyboardEvent implicitly extends
|
||||
* this event.
|
||||
*/
|
||||
export interface IKeyboardEvent {
|
||||
altKey: boolean;
|
||||
ctrlKey: boolean;
|
||||
shiftKey: boolean;
|
||||
metaKey: boolean;
|
||||
keyCode: number;
|
||||
key: string;
|
||||
type: string;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export const enum KeyboardResultType {
|
||||
SEND_KEY,
|
||||
SELECT_ALL,
|
||||
PAGE_UP,
|
||||
PAGE_DOWN
|
||||
}
|
||||
|
||||
export interface IKeyboardResult {
|
||||
type: KeyboardResultType;
|
||||
cancel: boolean;
|
||||
key: string | undefined;
|
||||
}
|
||||
|
||||
export interface ICharset {
|
||||
[key: string]: string;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ICharset } from './Types';
|
||||
import { ICharset } from '../Types';
|
||||
|
||||
/**
|
||||
* The character sets supported by the terminal. These enable several languages
|
||||
@@ -0,0 +1,284 @@
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { evaluateKeyboardEvent } from './Keyboard';
|
||||
import { IKeyboardResult } from '../Types';
|
||||
|
||||
/**
|
||||
* A helper function for testing which allows passing in a partial event and defaults will be filled
|
||||
* in on it.
|
||||
*/
|
||||
function testEvaluateKeyboardEvent(partialEvent: {
|
||||
altKey?: boolean;
|
||||
ctrlKey?: boolean;
|
||||
shiftKey?: boolean;
|
||||
metaKey?: boolean;
|
||||
keyCode?: number;
|
||||
key?: string;
|
||||
type?: string;
|
||||
}, partialOptions: {
|
||||
applicationCursorMode?: boolean;
|
||||
isMac?: boolean;
|
||||
macOptionIsMeta?: boolean;
|
||||
} = {}): IKeyboardResult {
|
||||
const event = {
|
||||
altKey: partialEvent.altKey || false,
|
||||
ctrlKey: partialEvent.ctrlKey || false,
|
||||
shiftKey: partialEvent.shiftKey || false,
|
||||
metaKey: partialEvent.metaKey || false,
|
||||
keyCode: partialEvent.keyCode !== undefined ? partialEvent.keyCode : undefined,
|
||||
key: partialEvent.key || '',
|
||||
type: partialEvent.type || ''
|
||||
};
|
||||
const options = {
|
||||
applicationCursorMode: partialOptions.applicationCursorMode || false,
|
||||
isMac: partialOptions.isMac || false,
|
||||
macOptionIsMeta: partialOptions.macOptionIsMeta || false
|
||||
};
|
||||
return evaluateKeyboardEvent(event, options.applicationCursorMode, options.isMac, options.macOptionIsMeta);
|
||||
}
|
||||
|
||||
describe('Keyboard', () => {
|
||||
describe('evaluateKeyEscapeSequence', () => {
|
||||
it('should return the correct escape sequence for unmodified keys', () => {
|
||||
// Backspace
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 8 }).key, '\x7f'); // ^?
|
||||
// Tab
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 9 }).key, '\t');
|
||||
// Return/enter
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 13 }).key, '\r'); // CR
|
||||
// Escape
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 27 }).key, '\x1b');
|
||||
// Page up, page down
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 33 }).key, '\x1b[5~'); // CSI 5 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 34 }).key, '\x1b[6~'); // CSI 6 ~
|
||||
// End, Home
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 35 }).key, '\x1b[F'); // SS3 F
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 36 }).key, '\x1b[H'); // SS3 H
|
||||
// Left, up, right, down arrows
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 37 }).key, '\x1b[D'); // CSI D
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 38 }).key, '\x1b[A'); // CSI A
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 39 }).key, '\x1b[C'); // CSI C
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 40 }).key, '\x1b[B'); // CSI B
|
||||
// Insert
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 45 }).key, '\x1b[2~'); // CSI 2 ~
|
||||
// Delete
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 46 }).key, '\x1b[3~'); // CSI 3 ~
|
||||
// F1-F12
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 112 }).key, '\x1bOP'); // SS3 P
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 113 }).key, '\x1bOQ'); // SS3 Q
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 114 }).key, '\x1bOR'); // SS3 R
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 115 }).key, '\x1bOS'); // SS3 S
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 116 }).key, '\x1b[15~'); // CSI 1 5 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 117 }).key, '\x1b[17~'); // CSI 1 7 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 118 }).key, '\x1b[18~'); // CSI 1 8 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 119 }).key, '\x1b[19~'); // CSI 1 9 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 120 }).key, '\x1b[20~'); // CSI 2 0 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 121 }).key, '\x1b[21~'); // CSI 2 1 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 122 }).key, '\x1b[23~'); // CSI 2 3 ~
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 123 }).key, '\x1b[24~'); // CSI 2 4 ~
|
||||
});
|
||||
it('should return \\x1b[3;5~ for ctrl+delete', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 46 }).key, '\x1b[3;5~');
|
||||
});
|
||||
it('should return \\x1b[3;2~ for shift+delete', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 46 }).key, '\x1b[3;2~');
|
||||
});
|
||||
it('should return \\x1b[3;3~ for alt+delete', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~');
|
||||
});
|
||||
it('should return \\x1b[5D for ctrl+left', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D
|
||||
});
|
||||
it('should return \\x1b[5C for ctrl+right', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C
|
||||
});
|
||||
it('should return \\x1b[5A for ctrl+up', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A
|
||||
});
|
||||
it('should return \\x1b[5B for ctrl+down', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B
|
||||
});
|
||||
|
||||
describe('On non-macOS platforms', () => {
|
||||
// Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
it('should return \\x1b[5D for alt+left', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 37 }, { isMac: false }).key, '\x1b[1;5D'); // CSI 5 D
|
||||
});
|
||||
it('should return \\x1b[5C for alt+right', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 39 }, { isMac: false }).key, '\x1b[1;5C'); // CSI 5 C
|
||||
});
|
||||
it('should return \\x1ba for alt+a', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 65 }, { isMac: false }).key, '\x1ba');
|
||||
});
|
||||
});
|
||||
|
||||
describe('On macOS platforms', () => {
|
||||
it('should return \\x1bb for alt+left', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 37 }, { isMac: true }).key, '\x1bb'); // CSI 5 D
|
||||
});
|
||||
it('should return \\x1bf for alt+right', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 39 }, { isMac: true }).key, '\x1bf'); // CSI 5 C
|
||||
});
|
||||
it('should return undefined for alt+a', () => {
|
||||
assert.strictEqual(testEvaluateKeyboardEvent({ altKey: true, keyCode: 65 }, { isMac: true }).key, undefined), { isMac: true };
|
||||
});
|
||||
});
|
||||
|
||||
describe('with macOptionIsMeta', () => {
|
||||
it('should return \\x1ba for alt+a', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 65 }, { isMac: true, macOptionIsMeta: true }).key, '\x1ba');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return \\x1b[5A for alt+up', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A
|
||||
});
|
||||
it('should return \\x1b[5B for alt+down', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B
|
||||
});
|
||||
it('should return the correct escape sequence for modified F1-F12 keys', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 112 }).key, '\x1b[1;2P');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 113 }).key, '\x1b[1;2Q');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 114 }).key, '\x1b[1;2R');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 115 }).key, '\x1b[1;2S');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 116 }).key, '\x1b[15;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 117 }).key, '\x1b[17;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 118 }).key, '\x1b[18;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 119 }).key, '\x1b[19;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 120 }).key, '\x1b[20;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 121 }).key, '\x1b[21;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 122 }).key, '\x1b[23;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 123 }).key, '\x1b[24;2~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 112 }).key, '\x1b[1;3P');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 113 }).key, '\x1b[1;3Q');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 114 }).key, '\x1b[1;3R');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 115 }).key, '\x1b[1;3S');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 116 }).key, '\x1b[15;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 117 }).key, '\x1b[17;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 118 }).key, '\x1b[18;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 119 }).key, '\x1b[19;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 120 }).key, '\x1b[20;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 121 }).key, '\x1b[21;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 122 }).key, '\x1b[23;3~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 123 }).key, '\x1b[24;3~');
|
||||
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 112 }).key, '\x1b[1;5P');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 113 }).key, '\x1b[1;5Q');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 114 }).key, '\x1b[1;5R');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 115 }).key, '\x1b[1;5S');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 116 }).key, '\x1b[15;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 117 }).key, '\x1b[17;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 118 }).key, '\x1b[18;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 119 }).key, '\x1b[19;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 120 }).key, '\x1b[20;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 121 }).key, '\x1b[21;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 122 }).key, '\x1b[23;5~');
|
||||
assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 123 }).key, '\x1b[24;5~');
|
||||
});
|
||||
|
||||
// Characters using ctrl+alt sequences
|
||||
it('should return proper sequence for ctrl+alt+a', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, ctrlKey: true, keyCode: 65 }).key, '\x1b\x01');
|
||||
});
|
||||
|
||||
// Characters using alt sequences (numbers)
|
||||
it('should return proper sequences for alt+0', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 48 }).key, '\x1b0');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 48 }).key, '\x1b)');
|
||||
});
|
||||
it('should return proper sequences for alt+1', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 49 }).key, '\x1b1');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 49 }).key, '\x1b!');
|
||||
});
|
||||
it('should return proper sequences for alt+2', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 50 }).key, '\x1b2');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 50 }).key, '\x1b@');
|
||||
});
|
||||
it('should return proper sequences for alt+3', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 51 }).key, '\x1b3');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 51 }).key, '\x1b#');
|
||||
});
|
||||
it('should return proper sequences for alt+4', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 52 }).key, '\x1b4');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 52 }).key, '\x1b$');
|
||||
});
|
||||
it('should return proper sequences for alt+5', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 53 }).key, '\x1b5');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 53 }).key, '\x1b%');
|
||||
});
|
||||
it('should return proper sequences for alt+6', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 54 }).key, '\x1b6');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 54 }).key, '\x1b^');
|
||||
});
|
||||
it('should return proper sequences for alt+7', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 55 }).key, '\x1b7');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 55 }).key, '\x1b&');
|
||||
});
|
||||
it('should return proper sequences for alt+8', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 56 }).key, '\x1b8');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 56 }).key, '\x1b*');
|
||||
});
|
||||
it('should return proper sequences for alt+9', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 57 }).key, '\x1b9');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 57 }).key, '\x1b(');
|
||||
});
|
||||
|
||||
// Characters using alt sequences (special chars)
|
||||
it('should return proper sequences for alt+;', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 186 }).key, '\x1b;');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 186 }).key, '\x1b:');
|
||||
});
|
||||
it('should return proper sequences for alt+=', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 187 }).key, '\x1b=');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 187 }).key, '\x1b+');
|
||||
});
|
||||
it('should return proper sequences for alt+,', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 188 }).key, '\x1b,');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 188 }).key, '\x1b<');
|
||||
});
|
||||
it('should return proper sequences for alt+-', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 189 }).key, '\x1b-');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 189 }).key, '\x1b_');
|
||||
});
|
||||
it('should return proper sequences for alt+.', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 190 }).key, '\x1b.');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 190 }).key, '\x1b>');
|
||||
});
|
||||
it('should return proper sequences for alt+/', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 191 }).key, '\x1b/');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 191 }).key, '\x1b?');
|
||||
});
|
||||
it('should return proper sequences for alt+~', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 192 }).key, '\x1b`');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 192 }).key, '\x1b~');
|
||||
});
|
||||
it('should return proper sequences for alt+[', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 219 }).key, '\x1b[');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 219 }).key, '\x1b{');
|
||||
});
|
||||
it('should return proper sequences for alt+\\', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 220 }).key, '\x1b\\');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 220 }).key, '\x1b|');
|
||||
});
|
||||
it('should return proper sequences for alt+]', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 221 }).key, '\x1b]');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 221 }).key, '\x1b}');
|
||||
});
|
||||
it('should return proper sequences for alt+\'', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: false, keyCode: 222 }).key, '\x1b\'');
|
||||
assert.equal(testEvaluateKeyboardEvent({ altKey: true, shiftKey: true, keyCode: 222 }).key, '\x1b"');
|
||||
});
|
||||
|
||||
it('should handle mobile arrow events', () => {
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputUpArrow' }).key, '\x1b[A');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputUpArrow' }, { applicationCursorMode: true }).key, '\x1bOA');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputLeftArrow' }).key, '\x1b[D');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputLeftArrow' }, { applicationCursorMode: true }).key, '\x1bOD');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputRightArrow' }).key, '\x1b[C');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputRightArrow' }, { applicationCursorMode: true }).key, '\x1bOC');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputDownArrow' }).key, '\x1b[B');
|
||||
assert.equal(testEvaluateKeyboardEvent({ keyCode: 0, key: 'UIKeyInputDownArrow' }, { applicationCursorMode: true }).key, '\x1bOB');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IKeyboardEvent } from '../../common/Types';
|
||||
import { IKeyboardResult, KeyboardResultType } from '../Types';
|
||||
import { C0 } from '../../common/data/EscapeSequences';
|
||||
|
||||
// reg + shift key mappings for digits and special chars
|
||||
const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = {
|
||||
// digits 0-9
|
||||
48: ['0', ')'],
|
||||
49: ['1', '!'],
|
||||
50: ['2', '@'],
|
||||
51: ['3', '#'],
|
||||
52: ['4', '$'],
|
||||
53: ['5', '%'],
|
||||
54: ['6', '^'],
|
||||
55: ['7', '&'],
|
||||
56: ['8', '*'],
|
||||
57: ['9', '('],
|
||||
|
||||
// special chars
|
||||
186: [';', ':'],
|
||||
187: ['=', '+'],
|
||||
188: [',', '<'],
|
||||
189: ['-', '_'],
|
||||
190: ['.', '>'],
|
||||
191: ['/', '?'],
|
||||
192: ['`', '~'],
|
||||
219: ['[', '{'],
|
||||
220: ['\\', '|'],
|
||||
221: [']', '}'],
|
||||
222: ['\'', '"']
|
||||
};
|
||||
|
||||
export function evaluateKeyboardEvent(
|
||||
ev: IKeyboardEvent,
|
||||
applicationCursorMode: boolean,
|
||||
isMac: boolean,
|
||||
macOptionIsMeta: boolean
|
||||
): IKeyboardResult {
|
||||
const result: IKeyboardResult = {
|
||||
type: KeyboardResultType.SEND_KEY,
|
||||
// Whether to cancel event propogation (NOTE: this may not be needed since the event is
|
||||
// canceled at the end of keyDown
|
||||
cancel: false,
|
||||
// The new key even to emit
|
||||
key: undefined
|
||||
};
|
||||
const modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0);
|
||||
switch (ev.keyCode) {
|
||||
case 0:
|
||||
if (ev.key === 'UIKeyInputUpArrow') {
|
||||
if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OA';
|
||||
} else {
|
||||
result.key = C0.ESC + '[A';
|
||||
}
|
||||
}
|
||||
else if (ev.key === 'UIKeyInputLeftArrow') {
|
||||
if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OD';
|
||||
} else {
|
||||
result.key = C0.ESC + '[D';
|
||||
}
|
||||
}
|
||||
else if (ev.key === 'UIKeyInputRightArrow') {
|
||||
if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OC';
|
||||
} else {
|
||||
result.key = C0.ESC + '[C';
|
||||
}
|
||||
}
|
||||
else if (ev.key === 'UIKeyInputDownArrow') {
|
||||
if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OB';
|
||||
} else {
|
||||
result.key = C0.ESC + '[B';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// backspace
|
||||
if (ev.shiftKey) {
|
||||
result.key = C0.BS; // ^H
|
||||
break;
|
||||
} else if (ev.altKey) {
|
||||
result.key = C0.ESC + C0.DEL; // \e ^?
|
||||
break;
|
||||
}
|
||||
result.key = C0.DEL; // ^?
|
||||
break;
|
||||
case 9:
|
||||
// tab
|
||||
if (ev.shiftKey) {
|
||||
result.key = C0.ESC + '[Z';
|
||||
break;
|
||||
}
|
||||
result.key = C0.HT;
|
||||
result.cancel = true;
|
||||
break;
|
||||
case 13:
|
||||
// return/enter
|
||||
result.key = C0.CR;
|
||||
result.cancel = true;
|
||||
break;
|
||||
case 27:
|
||||
// escape
|
||||
result.key = C0.ESC;
|
||||
result.cancel = true;
|
||||
break;
|
||||
case 37:
|
||||
// left-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'D';
|
||||
// HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
// macOS uses different escape sequences than linux
|
||||
if (result.key === C0.ESC + '[1;3D') {
|
||||
result.key = isMac ? C0.ESC + 'b' : C0.ESC + '[1;5D';
|
||||
}
|
||||
} else if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OD';
|
||||
} else {
|
||||
result.key = C0.ESC + '[D';
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
// right-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'C';
|
||||
// HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
// macOS uses different escape sequences than linux
|
||||
if (result.key === C0.ESC + '[1;3C') {
|
||||
result.key = isMac ? C0.ESC + 'f' : C0.ESC + '[1;5C';
|
||||
}
|
||||
} else if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OC';
|
||||
} else {
|
||||
result.key = C0.ESC + '[C';
|
||||
}
|
||||
break;
|
||||
case 38:
|
||||
// up-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'A';
|
||||
// HACK: Make Alt + up-arrow behave like Ctrl + up-arrow
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
if (result.key === C0.ESC + '[1;3A') {
|
||||
result.key = C0.ESC + '[1;5A';
|
||||
}
|
||||
} else if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OA';
|
||||
} else {
|
||||
result.key = C0.ESC + '[A';
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
// down-arrow
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'B';
|
||||
// HACK: Make Alt + down-arrow behave like Ctrl + down-arrow
|
||||
// http://unix.stackexchange.com/a/108106
|
||||
if (result.key === C0.ESC + '[1;3B') {
|
||||
result.key = C0.ESC + '[1;5B';
|
||||
}
|
||||
} else if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OB';
|
||||
} else {
|
||||
result.key = C0.ESC + '[B';
|
||||
}
|
||||
break;
|
||||
case 45:
|
||||
// insert
|
||||
if (!ev.shiftKey && !ev.ctrlKey) {
|
||||
// <Ctrl> or <Shift> + <Insert> are used to
|
||||
// copy-paste on some systems.
|
||||
result.key = C0.ESC + '[2~';
|
||||
}
|
||||
break;
|
||||
case 46:
|
||||
// delete
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[3;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[3~';
|
||||
}
|
||||
break;
|
||||
case 36:
|
||||
// home
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'H';
|
||||
} else if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OH';
|
||||
} else {
|
||||
result.key = C0.ESC + '[H';
|
||||
}
|
||||
break;
|
||||
case 35:
|
||||
// end
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'F';
|
||||
} else if (applicationCursorMode) {
|
||||
result.key = C0.ESC + 'OF';
|
||||
} else {
|
||||
result.key = C0.ESC + '[F';
|
||||
}
|
||||
break;
|
||||
case 33:
|
||||
// page up
|
||||
if (ev.shiftKey) {
|
||||
result.type = KeyboardResultType.PAGE_UP;
|
||||
} else {
|
||||
result.key = C0.ESC + '[5~';
|
||||
}
|
||||
break;
|
||||
case 34:
|
||||
// page down
|
||||
if (ev.shiftKey) {
|
||||
result.type = KeyboardResultType.PAGE_DOWN;
|
||||
} else {
|
||||
result.key = C0.ESC + '[6~';
|
||||
}
|
||||
break;
|
||||
case 112:
|
||||
// F1-F12
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'P';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OP';
|
||||
}
|
||||
break;
|
||||
case 113:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'Q';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OQ';
|
||||
}
|
||||
break;
|
||||
case 114:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'R';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OR';
|
||||
}
|
||||
break;
|
||||
case 115:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[1;' + (modifiers + 1) + 'S';
|
||||
} else {
|
||||
result.key = C0.ESC + 'OS';
|
||||
}
|
||||
break;
|
||||
case 116:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[15;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[15~';
|
||||
}
|
||||
break;
|
||||
case 117:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[17;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[17~';
|
||||
}
|
||||
break;
|
||||
case 118:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[18;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[18~';
|
||||
}
|
||||
break;
|
||||
case 119:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[19;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[19~';
|
||||
}
|
||||
break;
|
||||
case 120:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[20;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[20~';
|
||||
}
|
||||
break;
|
||||
case 121:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[21;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[21~';
|
||||
}
|
||||
break;
|
||||
case 122:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[23;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[23~';
|
||||
}
|
||||
break;
|
||||
case 123:
|
||||
if (modifiers) {
|
||||
result.key = C0.ESC + '[24;' + (modifiers + 1) + '~';
|
||||
} else {
|
||||
result.key = C0.ESC + '[24~';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// a-z and space
|
||||
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
|
||||
if (ev.keyCode >= 65 && ev.keyCode <= 90) {
|
||||
result.key = String.fromCharCode(ev.keyCode - 64);
|
||||
} else if (ev.keyCode === 32) {
|
||||
// NUL
|
||||
result.key = String.fromCharCode(0);
|
||||
} else if (ev.keyCode >= 51 && ev.keyCode <= 55) {
|
||||
// escape, file sep, group sep, record sep, unit sep
|
||||
result.key = String.fromCharCode(ev.keyCode - 51 + 27);
|
||||
} else if (ev.keyCode === 56) {
|
||||
// delete
|
||||
result.key = String.fromCharCode(127);
|
||||
} else if (ev.keyCode === 219) {
|
||||
// ^[ - Control Sequence Introducer (CSI)
|
||||
result.key = String.fromCharCode(27);
|
||||
} else if (ev.keyCode === 220) {
|
||||
// ^\ - String Terminator (ST)
|
||||
result.key = String.fromCharCode(28);
|
||||
} else if (ev.keyCode === 221) {
|
||||
// ^] - Operating System Command (OSC)
|
||||
result.key = String.fromCharCode(29);
|
||||
}
|
||||
} else if ((!isMac || macOptionIsMeta) && ev.altKey && !ev.metaKey) {
|
||||
// On macOS this is a third level shift when !macOptionIsMeta. Use <Esc> instead.
|
||||
const keyMapping = KEYCODE_KEY_MAPPINGS[ev.keyCode];
|
||||
const key = keyMapping && keyMapping[!ev.shiftKey ? 0 : 1];
|
||||
if (key) {
|
||||
result.key = C0.ESC + key;
|
||||
} else if (ev.keyCode >= 65 && ev.keyCode <= 90) {
|
||||
const keyCode = ev.ctrlKey ? ev.keyCode - 64 : ev.keyCode + 32;
|
||||
result.key = C0.ESC + String.fromCharCode(keyCode);
|
||||
}
|
||||
} else if (isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {
|
||||
if (ev.keyCode === 65) { // cmd + a
|
||||
result.type = KeyboardResultType.SELECT_ALL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { ITerminal, ICircularList, LineData } from '../Types';
|
||||
import { C0 } from '../EscapeSequences';
|
||||
import { C0 } from '../common/data/EscapeSequences';
|
||||
|
||||
const enum Direction {
|
||||
UP = 'A',
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2016 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { Terminal } from './Terminal';
|
||||
import * as attach from '../addons/attach/attach';
|
||||
|
||||
describe('Terminal', () => {
|
||||
it('should apply addons with Terminal.applyAddon', () => {
|
||||
Terminal.applyAddon(attach);
|
||||
// Test that addon was applied successfully, adding attach to Terminal's
|
||||
// prototype.
|
||||
assert.equal(typeof (<any>Terminal).prototype.attach, 'function');
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user