From b75ae0f7b13c28e8fa001cd403f2cb3ad6adc95c Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Fri, 14 Feb 2020 20:00:03 +0530 Subject: [PATCH 001/130] Support alt+Enter key signal by default --- src/InputHandler.ts | 6 ++++++ src/Terminal.ts | 2 +- src/common/TestUtils.test.ts | 1 + src/common/Types.d.ts | 1 + src/common/input/Keyboard.test.ts | 7 ++++++- src/common/input/Keyboard.ts | 8 +++++++- src/common/services/CoreService.ts | 1 + 7 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index fb37f4ab1..356f3b3da 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1788,6 +1788,9 @@ export class InputHandler extends Disposable implements IInputHandler { case 25: // show cursor this._coreService.isCursorHidden = false; break; + case 1039: + this._coreService.decPrivateModes.altEnterMode = true; + break; case 1048: // alt screen cursor this.saveCursor(); break; @@ -2003,6 +2006,9 @@ export class InputHandler extends Disposable implements IInputHandler { case 25: // hide cursor this._coreService.isCursorHidden = true; break; + case 1039: + this._coreService.decPrivateModes.altEnterMode = false; + break; case 1048: // alt screen cursor this.restoreCursor(); break; diff --git a/src/Terminal.ts b/src/Terminal.ts index 1bcac1f05..0ca1b186d 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1222,7 +1222,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp return false; } - const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta); + const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.altEnterMode, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta); this.updateCursorStyle(event); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 4d9070cd8..b4636ebf2 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -59,6 +59,7 @@ export class MockCoreService implements ICoreService { isCursorHidden: boolean = false; isFocused: boolean = false; decPrivateModes: IDecPrivateModes = { + altEnterMode: true, applicationCursorKeys: false, applicationKeypad: false, origin: false, diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index b250b45ea..4df53bd42 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -152,6 +152,7 @@ export interface IMarker extends IDisposable { } export interface IDecPrivateModes { + altEnterMode: boolean; applicationCursorKeys: boolean; applicationKeypad: boolean; origin: boolean; diff --git a/src/common/input/Keyboard.test.ts b/src/common/input/Keyboard.test.ts index a304923e8..ce492f0c1 100644 --- a/src/common/input/Keyboard.test.ts +++ b/src/common/input/Keyboard.test.ts @@ -16,6 +16,7 @@ function testEvaluateKeyboardEvent(partialEvent: { key?: string; type?: string; }, partialOptions: { + altEnterMode?: boolean; applicationCursorMode?: boolean; isMac?: boolean; macOptionIsMeta?: boolean; @@ -30,11 +31,12 @@ function testEvaluateKeyboardEvent(partialEvent: { type: partialEvent.type || '' }; const options = { + altEnterMode: partialOptions.altEnterMode || true, applicationCursorMode: partialOptions.applicationCursorMode || false, isMac: partialOptions.isMac || false, macOptionIsMeta: partialOptions.macOptionIsMeta || false }; - return evaluateKeyboardEvent(event, options.applicationCursorMode, options.isMac, options.macOptionIsMeta); + return evaluateKeyboardEvent(event, options.altEnterMode, options.applicationCursorMode, options.isMac, options.macOptionIsMeta); } describe('Keyboard', () => { @@ -86,6 +88,9 @@ describe('Keyboard', () => { it('should return \\x1b[3;3~ for alt+delete', () => { assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~'); }); + it('should return \\x1b\\r for alt+enter', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 13 }).key, '\x1b\r'); + }); it('should return \\x1b[5D for ctrl+left', () => { assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D }); diff --git a/src/common/input/Keyboard.ts b/src/common/input/Keyboard.ts index 1bf378c17..34433deab 100644 --- a/src/common/input/Keyboard.ts +++ b/src/common/input/Keyboard.ts @@ -37,6 +37,7 @@ const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = { export function evaluateKeyboardEvent( ev: IKeyboardEvent, + altEnterMode: boolean, applicationCursorMode: boolean, isMac: boolean, macOptionIsMeta: boolean @@ -103,7 +104,12 @@ export function evaluateKeyboardEvent( break; case 13: // return/enter - result.key = C0.CR; + if (altEnterMode && modifiers === 2) { + result.key = C0.ESC + C0.CR; + } + else { + result.key = C0.CR; + } result.cancel = true; break; case 27: diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index df9161e9c..1ae906cc3 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -9,6 +9,7 @@ import { IDecPrivateModes, ICharset } from 'common/Types'; import { clone } from 'common/Clone'; const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ + altEnterMode: true, applicationCursorKeys: false, applicationKeypad: false, origin: false, From 6f886fe1672cfca93f76516de76fb9cf54db8c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 16 Feb 2020 20:41:55 +0100 Subject: [PATCH 002/130] working draft --- src/InputHandler.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index fb37f4ab1..863fea1ba 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -717,9 +717,19 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y C0 BS "Backspace" "\b, \x08" "Move the cursor one position to the left." */ public backspace(): void { - this._restrictCursor(); - if (this._bufferService.buffer.x > 0) { - this._bufferService.buffer.x--; + //this._restrictCursor(); + const buffer = this._bufferService.buffer; + if (buffer.x > 0) { + buffer.x--; + } else { + // reverse wraparound + if (buffer.x === 0 && buffer.y && buffer.lines.get(buffer.y + buffer.ybase).isWrapped) { + buffer.y--; + buffer.x = this._bufferService.cols - 1; + } + } + if (buffer.x >= this._bufferService.cols) { + buffer.x = this._bufferService.cols - 1; } } From f736b6c29980dcd64667b2add037292bd4b77c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 16 Feb 2020 20:53:53 +0100 Subject: [PATCH 003/130] comment missing empty cell handling --- src/InputHandler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 863fea1ba..605e97f12 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -726,6 +726,7 @@ export class InputHandler extends Disposable implements IInputHandler { if (buffer.x === 0 && buffer.y && buffer.lines.get(buffer.y + buffer.ybase).isWrapped) { buffer.y--; buffer.x = this._bufferService.cols - 1; + // TODO: skip last col if it is empty after wide char } } if (buffer.x >= this._bufferService.cols) { From 0c703276b18ef3e812cc9a3f7d74d4eabf8c6fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Mon, 17 Feb 2020 12:22:53 +0100 Subject: [PATCH 004/130] fix behavior, first BS tests --- src/InputHandler.test.ts | 57 ++++++++++++++++++++++++++++++ src/InputHandler.ts | 55 +++++++++++++++++++++++----- src/common/TestUtils.test.ts | 1 + src/common/Types.d.ts | 1 + src/common/services/CoreService.ts | 1 + 5 files changed, 107 insertions(+), 8 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index de43022b1..7bac8d0b0 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -1445,4 +1445,61 @@ describe('InputHandler', () => { assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); }); }); + describe('BS with reverseWraparound set/unset', () => { + const ttyBS = '\x08 \x08'; // tty ICANON sends on pressing BS + let term: TestTerminal; + beforeEach(() => { + term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); + }); + describe('reverseWraparound unset (default)', () => { + it('cannot delete last cell', () => { + term.writeSync('12345'); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 1), ['123 5']); + term.writeSync(ttyBS.repeat(10)); + assert.deepEqual(getLines(term, 1), [' 5']); + }); + it('cannot access prev line', () => { + term.writeSync('12345'.repeat(2)); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), ['12345', '123 5']); + term.writeSync(ttyBS.repeat(10)); + assert.deepEqual(getLines(term, 2), ['12345', ' 5']); + }); + }); + describe('reverseWraparound set', () => { + it('can delete last cell', () => { + term.writeSync('\x1b[?45h'); + term.writeSync('12345'); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 1), ['1234 ']); + term.writeSync(ttyBS.repeat(7)); + assert.deepEqual(getLines(term, 1), [' ']); + }); + it('can access prev line if wrapped', () => { + term.writeSync('\x1b[?45h'); + term.writeSync('12345'.repeat(2)); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), ['12345', '1234 ']); + term.writeSync(ttyBS.repeat(7)); + assert.deepEqual(getLines(term, 2), ['12 ', ' ']); + }); + it('should lift isWrapped', () => { + term.writeSync('\x1b[?45h'); + term.writeSync('12345'.repeat(2)); + assert.equal(term.buffer.lines.get(1).isWrapped, true); + term.writeSync(ttyBS.repeat(7)); + assert.equal(term.buffer.lines.get(1).isWrapped, false); + }); + it('stops at hard NLs', () => { + term.writeSync('\x1b[?45h'); + term.writeSync('12345\r\n'); + term.writeSync('12345'.repeat(2)); + term.writeSync(ttyBS.repeat(50)); + assert.deepEqual(getLines(term, 3), ['12345', ' ', ' ']); + assert.equal(term.buffer.x, 0); + assert.equal(term.buffer.y, 1); + }); + }); + }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 605e97f12..9963b96e1 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -544,6 +544,10 @@ export class InputHandler extends Disposable implements IInputHandler { // autowrap - DECAWM // automatically wraps to the beginning of the next line if (wraparoundMode) { + // clear left over cells to the right + while (buffer.x < cols) { + bufferRow.setCellFromCodePoint(buffer.x++, 0, 1, curAttr.fg, curAttr.bg); + } buffer.x = 0; buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { @@ -717,21 +721,48 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y C0 BS "Backspace" "\b, \x08" "Move the cursor one position to the left." */ public backspace(): void { - //this._restrictCursor(); + // xterm allows deleting of the last col if reverseWraparound is set + // otherwise the last cell cannot be deleted by BS + if (!this._coreService.decPrivateModes.reverseWraparound) { + this._restrictCursor(); + } else { + // we still clamp the cursor to sane values here, but have to allow x=cols as well + this._bufferService.buffer.x = Math.min(this._bufferService.cols, Math.max(0, this._bufferService.buffer.x)); + this._bufferService.buffer.y = this._coreService.decPrivateModes.origin + ? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y)) + : Math.min(this._bufferService.rows - 1, Math.max(0, this._bufferService.buffer.y)); + this._dirtyRowService.markDirty(this._bufferService.buffer.y); + } const buffer = this._bufferService.buffer; if (buffer.x > 0) { buffer.x--; } else { // reverse wraparound - if (buffer.x === 0 && buffer.y && buffer.lines.get(buffer.y + buffer.ybase).isWrapped) { - buffer.y--; - buffer.x = this._bufferService.cols - 1; - // TODO: skip last col if it is empty after wide char + // TODO: test in xterm - should we peek/unshift from scrollback if y == 0? + if (this._coreService.decPrivateModes.reverseWraparound + && buffer.x === 0 + && buffer.y > 0 + && buffer.lines.get(buffer.y + buffer.ybase).isWrapped) + { + // unset isWrapped + buffer.lines.get(buffer.y + buffer.ybase).isWrapped = false; + buffer.y--; + buffer.x = this._bufferService.cols - 1; + // find last taken cell - last cell can have 3 different states: + // - hasContent(true) + hasWidth(1): narrow char - we are done + // - hasWidth(0): second part of wide char - we are done + // - hasContent(false) + hasWidth(1): empty cell due to early wrapping wide char, go one cell further back + const line = buffer.lines.get(buffer.y + buffer.ybase); + if (line.hasWidth(buffer.x) && !line.hasContent(buffer.x)) { + buffer.x--; + // We do this only once, since width=1 + hasContent=false currently happens only once before + // early wrapping of a wide char. + // This needs to be fixed once we support graphemes taking more than 2 cells. } + } } - if (buffer.x >= this._bufferService.cols) { - buffer.x = this._bufferService.cols - 1; - } + // should we use _restrictCursor() here? FIXME: how about origin mode / scroll margins? + buffer.x = Math.max(Math.min(buffer.x, this._bufferService.cols - 1), 0); } /** @@ -1710,6 +1741,7 @@ export class InputHandler extends Disposable implements IInputHandler { * | 9 | X10 xterm mouse protocol. | #Y | * | 12 | Start Blinking Cursor. | #Y | * | 25 | Show Cursor (DECTCEM). | #Y | + * | 45 | Reverse wrap-around. | #Y | * | 47 | Use Alternate Screen Buffer. | #Y | * | 66 | Application keypad (DECNKM). | #Y | * | 1000 | X11 xterm mouse protocol. | #Y | @@ -1761,6 +1793,9 @@ export class InputHandler extends Disposable implements IInputHandler { case 12: // this.cursorBlink = true; break; + case 45: + this._coreService.decPrivateModes.reverseWraparound = true; + break; case 66: this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; @@ -1944,6 +1979,7 @@ export class InputHandler extends Disposable implements IInputHandler { * | 9 | Don't send Mouse X & Y on button press. | #Y | * | 12 | Stop Blinking Cursor. | #Y | * | 25 | Hide Cursor (DECTCEM). | #Y | + * | 45 | No reverse wrap-around. | #Y | * | 47 | Use Normal Screen Buffer. | #Y | * | 66 | Numeric keypad (DECNKM). | #Y | * | 1000 | Don't send Mouse reports. | #Y | @@ -1988,6 +2024,9 @@ export class InputHandler extends Disposable implements IInputHandler { case 12: // this.cursorBlink = false; break; + case 45: + this._coreService.decPrivateModes.reverseWraparound = false; + break; case 66: this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 4d9070cd8..fce5ee6e8 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -62,6 +62,7 @@ export class MockCoreService implements ICoreService { applicationCursorKeys: false, applicationKeypad: false, origin: false, + reverseWraparound: false, wraparound: true }; onData: IEvent = new EventEmitter().event; diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index b250b45ea..d8a6b4d5e 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -155,6 +155,7 @@ export interface IDecPrivateModes { applicationCursorKeys: boolean; applicationKeypad: boolean; origin: boolean; + reverseWraparound: boolean; wraparound: boolean; // defaults: xterm - true, vt100 - false } diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index df9161e9c..bc58a688d 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -12,6 +12,7 @@ const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ applicationCursorKeys: false, applicationKeypad: false, origin: false, + reverseWraparound: false, wraparound: true // defaults: xterm - true, vt100 - false }); From 7de600cc64d75cf24afa5d8b6815e5e2f775214b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Mon, 17 Feb 2020 12:30:35 +0100 Subject: [PATCH 005/130] test case for clearing cells to the right on early wrap-around --- src/InputHandler.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 7bac8d0b0..645a905db 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -372,6 +372,13 @@ describe('InputHandler', () => { container[0] = 0x200B; inputHandler.print(container, 0, 1); }); + it('should clear cells to the right on early wrap-around', () => { + const term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); + term.writeSync('12345'); + term.buffer.x = 0; + term.writeSync('¥¥¥'); + assert.deepEqual(getLines(term, 2), ['¥¥', '¥']); + }); }); describe('alt screen', () => { From 62ea2c691e9a0e288bd3733f9e3c7f2b97dbf48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Mon, 17 Feb 2020 12:39:36 +0100 Subject: [PATCH 006/130] wide char tests --- src/InputHandler.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 645a905db..6b98d61e8 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -1507,6 +1507,29 @@ describe('InputHandler', () => { assert.equal(term.buffer.x, 0); assert.equal(term.buffer.y, 1); }); + it('handles wide chars correctly', () => { + term.writeSync('\x1b[?45h'); + term.writeSync('¥¥¥'); + assert.deepEqual(getLines(term, 2), ['¥¥', '¥']); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), ['¥¥', ' ']); + assert.equal(term.buffer.x, 1); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), ['¥¥', ' ']); + assert.equal(term.buffer.x, 0); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), ['¥ ', ' ']); + assert.equal(term.buffer.x, 3); // x=4 skipped due to early wrap-around + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), ['¥ ', ' ']); + assert.equal(term.buffer.x, 2); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), [' ', ' ']); + assert.equal(term.buffer.x, 1); + term.writeSync(ttyBS); + assert.deepEqual(getLines(term, 2), [' ', ' ']); + assert.equal(term.buffer.x, 0); + }); }); }); }); From 5896a05ca664adacd5c391c72c64c8ce4cdd33f2 Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Thu, 20 Feb 2020 00:21:33 +0530 Subject: [PATCH 007/130] Change decset flag to altEscMode --- src/InputHandler.ts | 4 ++-- src/Terminal.ts | 2 +- src/common/TestUtils.test.ts | 2 +- src/common/Types.d.ts | 2 +- src/common/input/Keyboard.ts | 4 ++-- src/common/services/CoreService.ts | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 356f3b3da..a651440a0 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1789,7 +1789,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._coreService.isCursorHidden = false; break; case 1039: - this._coreService.decPrivateModes.altEnterMode = true; + this._coreService.decPrivateModes.altEscMode = true; break; case 1048: // alt screen cursor this.saveCursor(); @@ -2007,7 +2007,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._coreService.isCursorHidden = true; break; case 1039: - this._coreService.decPrivateModes.altEnterMode = false; + this._coreService.decPrivateModes.altEscMode = false; break; case 1048: // alt screen cursor this.restoreCursor(); diff --git a/src/Terminal.ts b/src/Terminal.ts index 0ca1b186d..606466178 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1222,7 +1222,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp return false; } - const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.altEnterMode, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta); + const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.altEscMode, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta); this.updateCursorStyle(event); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index b4636ebf2..2257530c1 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -59,7 +59,7 @@ export class MockCoreService implements ICoreService { isCursorHidden: boolean = false; isFocused: boolean = false; decPrivateModes: IDecPrivateModes = { - altEnterMode: true, + altEscMode: true, applicationCursorKeys: false, applicationKeypad: false, origin: false, diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 4df53bd42..0a2d4252a 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -152,7 +152,7 @@ export interface IMarker extends IDisposable { } export interface IDecPrivateModes { - altEnterMode: boolean; + altEscMode: boolean; applicationCursorKeys: boolean; applicationKeypad: boolean; origin: boolean; diff --git a/src/common/input/Keyboard.ts b/src/common/input/Keyboard.ts index 34433deab..67b5ee44d 100644 --- a/src/common/input/Keyboard.ts +++ b/src/common/input/Keyboard.ts @@ -37,7 +37,7 @@ const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = { export function evaluateKeyboardEvent( ev: IKeyboardEvent, - altEnterMode: boolean, + altEscMode: boolean, applicationCursorMode: boolean, isMac: boolean, macOptionIsMeta: boolean @@ -104,7 +104,7 @@ export function evaluateKeyboardEvent( break; case 13: // return/enter - if (altEnterMode && modifiers === 2) { + if (altEscMode && modifiers === 2) { result.key = C0.ESC + C0.CR; } else { diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index 1ae906cc3..c8c77c7d1 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -9,7 +9,7 @@ import { IDecPrivateModes, ICharset } from 'common/Types'; import { clone } from 'common/Clone'; const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ - altEnterMode: true, + altEscMode: true, applicationCursorKeys: false, applicationKeypad: false, origin: false, From c9277c3c721d600aa5cfef72e4af9c6e37addc22 Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Fri, 21 Feb 2020 13:13:46 +0530 Subject: [PATCH 008/130] Remove altEscape DECSET mode and add support for alt+esc key --- src/InputHandler.ts | 6 ------ src/Terminal.ts | 2 +- src/common/TestUtils.test.ts | 1 - src/common/Types.d.ts | 1 - src/common/input/Keyboard.test.ts | 11 ++++++++--- src/common/input/Keyboard.ts | 6 ++++-- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index a651440a0..fb37f4ab1 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1788,9 +1788,6 @@ export class InputHandler extends Disposable implements IInputHandler { case 25: // show cursor this._coreService.isCursorHidden = false; break; - case 1039: - this._coreService.decPrivateModes.altEscMode = true; - break; case 1048: // alt screen cursor this.saveCursor(); break; @@ -2006,9 +2003,6 @@ export class InputHandler extends Disposable implements IInputHandler { case 25: // hide cursor this._coreService.isCursorHidden = true; break; - case 1039: - this._coreService.decPrivateModes.altEscMode = false; - break; case 1048: // alt screen cursor this.restoreCursor(); break; diff --git a/src/Terminal.ts b/src/Terminal.ts index 606466178..1bcac1f05 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1222,7 +1222,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp return false; } - const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.altEscMode, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta); + const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta); this.updateCursorStyle(event); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 2257530c1..4d9070cd8 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -59,7 +59,6 @@ export class MockCoreService implements ICoreService { isCursorHidden: boolean = false; isFocused: boolean = false; decPrivateModes: IDecPrivateModes = { - altEscMode: true, applicationCursorKeys: false, applicationKeypad: false, origin: false, diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 0a2d4252a..b250b45ea 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -152,7 +152,6 @@ export interface IMarker extends IDisposable { } export interface IDecPrivateModes { - altEscMode: boolean; applicationCursorKeys: boolean; applicationKeypad: boolean; origin: boolean; diff --git a/src/common/input/Keyboard.test.ts b/src/common/input/Keyboard.test.ts index ce492f0c1..0bb0e24c1 100644 --- a/src/common/input/Keyboard.test.ts +++ b/src/common/input/Keyboard.test.ts @@ -16,7 +16,6 @@ function testEvaluateKeyboardEvent(partialEvent: { key?: string; type?: string; }, partialOptions: { - altEnterMode?: boolean; applicationCursorMode?: boolean; isMac?: boolean; macOptionIsMeta?: boolean; @@ -31,12 +30,11 @@ function testEvaluateKeyboardEvent(partialEvent: { type: partialEvent.type || '' }; const options = { - altEnterMode: partialOptions.altEnterMode || true, applicationCursorMode: partialOptions.applicationCursorMode || false, isMac: partialOptions.isMac || false, macOptionIsMeta: partialOptions.macOptionIsMeta || false }; - return evaluateKeyboardEvent(event, options.altEnterMode, options.applicationCursorMode, options.isMac, options.macOptionIsMeta); + return evaluateKeyboardEvent(event, options.applicationCursorMode, options.isMac, options.macOptionIsMeta); } describe('Keyboard', () => { @@ -91,6 +89,9 @@ describe('Keyboard', () => { it('should return \\x1b\\r for alt+enter', () => { assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 13 }).key, '\x1b\r'); }); + it('should return \\x1b\\x1b for alt+esc', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 27 }).key, '\x1b\x1b'); + }); it('should return \\x1b[5D for ctrl+left', () => { assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D }); @@ -146,6 +147,10 @@ describe('Keyboard', () => { it('should return \\x1ba for alt+a', () => { assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 65 }, { isMac: true, macOptionIsMeta: true }).key, '\x1ba'); }); + + it('should return \\x1b\\x1b for alt+enter', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 13 }, { isMac: true, macOptionIsMeta: true }).key, '\x1b\r'); + }); }); it('should return \\x1b[5A for alt+up', () => { diff --git a/src/common/input/Keyboard.ts b/src/common/input/Keyboard.ts index 67b5ee44d..d07ea6251 100644 --- a/src/common/input/Keyboard.ts +++ b/src/common/input/Keyboard.ts @@ -37,7 +37,6 @@ const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = { export function evaluateKeyboardEvent( ev: IKeyboardEvent, - altEscMode: boolean, applicationCursorMode: boolean, isMac: boolean, macOptionIsMeta: boolean @@ -104,7 +103,7 @@ export function evaluateKeyboardEvent( break; case 13: // return/enter - if (altEscMode && modifiers === 2) { + if (ev.altKey) { result.key = C0.ESC + C0.CR; } else { @@ -115,6 +114,9 @@ export function evaluateKeyboardEvent( case 27: // escape result.key = C0.ESC; + if (ev.altKey) { + result.key = C0.ESC + C0.ESC; + } result.cancel = true; break; case 37: From cb31179274cfa891ebf7c4e1a2c57ca839dc8506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 21 Feb 2020 18:23:00 +0100 Subject: [PATCH 009/130] respect scroll margins, tests --- src/InputHandler.test.ts | 37 ++++++++++++++++++++++++++++++++++ src/InputHandler.ts | 43 ++++++++++++++++++++++++++-------------- src/Terminal2.test.ts | 2 +- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 6b98d61e8..aae042f6d 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -1530,6 +1530,43 @@ describe('InputHandler', () => { assert.deepEqual(getLines(term, 2), [' ', ' ']); assert.equal(term.buffer.x, 0); }); + it('should not reverse outside of scroll margins', () => { + // prepare buffer content + term.writeSync('#####abcdefghijklmnopqrstuvwxy'); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']); + assert.equal(term.buffer.ydisp, 1); + assert.equal(term.buffer.x, 5); + assert.equal(term.buffer.y, 4); + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']); + + term.writeSync('\x1b[?45h'); + term.writeSync('uvwxy'); + + // set top/bottom to 1/3 (0-based) + term.writeSync('\x1b[2;4r'); + // place cursor below scroll bottom + term.buffer.x = 5; + term.buffer.y = 4; + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']); + + term.writeSync('uvwxy'); + // place cursor within scroll margins + term.buffer.x = 5; + term.buffer.y = 3; + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']); + assert.equal(term.buffer.x, 0); + assert.equal(term.buffer.y, term.buffer.scrollTop); // stops at 0, scrollTop + + term.writeSync('fghijklmnopqrst'); + // place cursor above scroll top + term.buffer.x = 5; + term.buffer.y = 0; + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']); + }); }); }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 9963b96e1..d6e33c2ca 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -719,32 +719,46 @@ export class InputHandler extends Disposable implements IInputHandler { * Backspace (Ctrl-H). * * @vt: #Y C0 BS "Backspace" "\b, \x08" "Move the cursor one position to the left." + * By default it is not possible to move the cursor past the leftmost position. + * If `reverse wrap-around` (`CSI ? 45 h`) is set, a previous soft line wrap (DECAWM) + * can be undone with BS within the scroll margins. In that case the cursor will wrap back + * to the end of the previous row. Note that it is not possible to peek back into the scrollbuffer + * with the cursor, thus at the home position (top-leftmost cell) this has no effect. */ public backspace(): void { - // xterm allows deleting of the last col if reverseWraparound is set - // otherwise the last cell cannot be deleted by BS + const buffer = this._bufferService.buffer; + + // by default (resverse wrap-around not set) we restrict the cursor to 0 .. rows/cols - 1 + // thus the last cell of a row cannot be accessed by BS if (!this._coreService.decPrivateModes.reverseWraparound) { this._restrictCursor(); } else { - // we still clamp the cursor to sane values here, but have to allow x=cols as well - this._bufferService.buffer.x = Math.min(this._bufferService.cols, Math.max(0, this._bufferService.buffer.x)); - this._bufferService.buffer.y = this._coreService.decPrivateModes.origin - ? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y)) - : Math.min(this._bufferService.rows - 1, Math.max(0, this._bufferService.buffer.y)); - this._dirtyRowService.markDirty(this._bufferService.buffer.y); + // copy of _restrictCursor(), but with x=cols as allowed max cursor position + // to make last cell accessible by BS + buffer.x = Math.min(this._bufferService.cols, Math.max(0, this._bufferService.buffer.x)); + buffer.y = this._coreService.decPrivateModes.origin + ? Math.min(buffer.scrollBottom, Math.max(buffer.scrollTop, buffer.y)) + : Math.min(this._bufferService.rows - 1, Math.max(0, buffer.y)); + this._dirtyRowService.markDirty(buffer.y); } - const buffer = this._bufferService.buffer; + if (buffer.x > 0) { buffer.x--; } else { - // reverse wraparound - // TODO: test in xterm - should we peek/unshift from scrollback if y == 0? + /** + * reverse wrap-around: + * Our implementation deviates from xterm on purpose. Details: + * - only previous soft NLs can be reversed (isWrapped=true) + * - only works within scrollborders (top/bottom, left/right not yet supported) + * - cannot peek into scrollbuffer + * - any cursor movement sequence keeps working as expected + */ if (this._coreService.decPrivateModes.reverseWraparound && buffer.x === 0 - && buffer.y > 0 + && buffer.y > buffer.scrollTop + && buffer.y <= buffer.scrollBottom && buffer.lines.get(buffer.y + buffer.ybase).isWrapped) { - // unset isWrapped buffer.lines.get(buffer.y + buffer.ybase).isWrapped = false; buffer.y--; buffer.x = this._bufferService.cols - 1; @@ -761,8 +775,7 @@ export class InputHandler extends Disposable implements IInputHandler { } } } - // should we use _restrictCursor() here? FIXME: how about origin mode / scroll margins? - buffer.x = Math.max(Math.min(buffer.x, this._bufferService.cols - 1), 0); + this._restrictCursor(); } /** diff --git a/src/Terminal2.test.ts b/src/Terminal2.test.ts index f7046240b..ff7ed8808 100644 --- a/src/Terminal2.test.ts +++ b/src/Terminal2.test.ts @@ -19,7 +19,7 @@ const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__ const SKIP_FILES = [ 't0084-CBT.in', 't0101-NLM.in', - 't0103-reverse_wrap.in', + 't0103-reverse_wrap.in', // not comparable, we deviate from xterm reverse wrap on purpose 't0504-vim.in' ]; if (os.platform() === 'darwin') { From 5fdbd7428bbdabca9f2c70457f758fbc02e06f71 Mon Sep 17 00:00:00 2001 From: javacs3 Date: Wed, 12 Feb 2020 12:45:40 +0800 Subject: [PATCH 010/130] expose IBufferSet API --- src/public/Terminal.ts | 24 ++++++++++++++++++++++-- typings/xterm.d.ts | 13 +++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index da03c127d..5535bd47c 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -3,10 +3,10 @@ * @license MIT */ -import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; +import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferSet as IBufferSetApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; import { ITerminal } from '../Types'; import { IBufferLine, ICellData } from 'common/Types'; -import { IBuffer } from 'common/buffer/Types'; +import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { CellData } from 'common/buffer/CellData'; import { Terminal as TerminalCore } from '../Terminal'; import * as Strings from '../browser/LocalizableStrings'; @@ -49,6 +49,7 @@ export class Terminal implements ITerminalApi { public get rows(): number { return this._core.rows; } public get cols(): number { return this._core.cols; } public get buffer(): IBufferApi { return new BufferApiView(this._core.buffer); } + public get buffers(): IBufferSetApi { return new BufferSetApiView(this._core.buffers); } public get markers(): ReadonlyArray { return this._core.markers; } public blur(): void { this._core.blur(); @@ -210,6 +211,25 @@ class BufferApiView implements IBufferApi { public getNullCell(): IBufferCellApi { return new CellData(); } } +class BufferSetApiView implements IBufferSetApi { + constructor(private _buffers: IBufferSet) { } + + public get alt(): IBufferApi { return new BufferApiView(this._buffers.alt); } + public get active(): IBufferApi { return new BufferApiView(this._buffers.active); } + public get normal(): IBufferApi { return new BufferApiView(this._buffers.normal); } + + public get onBufferActivate(): IEvent<{ activeBuffer: IBufferApi, inactiveBuffer: IBufferApi }> { + return (listener: (arg1: { activeBuffer: IBufferApi, inactiveBuffer: IBufferApi }, arg2: void) => any) => { + return this._buffers.onBufferActivate((innerArg: { activeBuffer: IBuffer, inactiveBuffer: IBuffer }) => { + listener({ + activeBuffer: new BufferApiView(innerArg.activeBuffer), + inactiveBuffer: new BufferApiView(innerArg.inactiveBuffer) + }); + }); + }; + } +} + class BufferLineApiView implements IBufferLineApi { constructor(private _line: IBufferLine) { } diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index bed7e8837..4613677d7 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -576,6 +576,11 @@ declare module 'xterm' { */ readonly buffer: IBuffer; + /** + * (EXPERIMENTAL) The terminal's current bufferSet. + */ + readonly buffers: IBufferSet; + /** * (EXPERIMENTAL) Get all markers registered against the buffer. If the alt * buffer is active this will always return []. @@ -1217,6 +1222,14 @@ declare module 'xterm' { getNullCell(): IBufferCell; } + interface IBufferSet { + readonly alt: IBuffer; + readonly normal: IBuffer; + readonly active: IBuffer; + + onBufferActivate: IEvent<{ activeBuffer: IBuffer, inactiveBuffer: IBuffer }>; + } + /** * Represents a line in the terminal's buffer. */ From 44ff7b0f5f6c7ff4e3e081269b2b88587326f597 Mon Sep 17 00:00:00 2001 From: javacs3 Date: Thu, 13 Feb 2020 12:19:15 +0800 Subject: [PATCH 011/130] change buffer interface from IBuffer to IBufferNamespace --- .../xterm-addon-attach/src/AttachAddon.api.ts | 4 +- .../xterm-addon-search/src/SearchAddon.api.ts | 8 +- addons/xterm-addon-search/src/SearchAddon.ts | 22 +-- .../src/SerializeAddon.ts | 4 +- .../src/WebLinkProvider.ts | 6 +- addons/xterm-addon-webgl/src/GlyphRenderer.ts | 4 +- addons/xterm-addon-webgl/src/WebglRenderer.ts | 4 +- .../src/renderLayer/CursorRenderLayer.ts | 12 +- src/public/Terminal.ts | 31 ++-- test/api/CharWidth.api.ts | 2 +- test/api/InputHandler.api.ts | 18 +-- test/api/Terminal.api.ts | 144 +++++++++--------- typings/xterm.d.ts | 17 +-- 13 files changed, 138 insertions(+), 138 deletions(-) diff --git a/addons/xterm-addon-attach/src/AttachAddon.api.ts b/addons/xterm-addon-attach/src/AttachAddon.api.ts index 625e1b4d1..7f2ce5c12 100644 --- a/addons/xterm-addon-attach/src/AttachAddon.api.ts +++ b/addons/xterm-addon-attach/src/AttachAddon.api.ts @@ -37,7 +37,7 @@ describe('AttachAddon', () => { const server = new WebSocket.Server({ port }); server.on('connection', socket => socket.send('foo')); await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); server.close(); }); @@ -48,7 +48,7 @@ describe('AttachAddon', () => { const data = new Uint8Array([102, 111, 111]); server.on('connection', socket => socket.send(data)); await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); server.close(); }); }); diff --git a/addons/xterm-addon-search/src/SearchAddon.api.ts b/addons/xterm-addon-search/src/SearchAddon.api.ts index 21238332c..521e6dfe3 100644 --- a/addons/xterm-addon-search/src/SearchAddon.api.ts +++ b/addons/xterm-addon-search/src/SearchAddon.api.ts @@ -61,7 +61,7 @@ describe('Search Tests', function(): void { await page.evaluate(`window.term.writeln('package.jsonc\\n')`); await writeSync(page, 'package.json pack package.lock'); await page.evaluate(`window.search.findPrevious('pack', {incremental: true})`); - let line: string = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + let line: string = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); let selectionPosition: { startColumn: number, startRow: number, endColumn: number, endRow: number } = await page.evaluate(`window.term.getSelectionPosition()`); // We look further ahead in the line to ensure that pack was selected from package.lock assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 8), 'package.lock'); @@ -70,7 +70,7 @@ describe('Search Tests', function(): void { assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 3), 'package.json'); await page.evaluate(`window.search.findPrevious('package.jsonc', {incremental: true})`); // We have to reevaluate line because it should have switched starting rows at this point - line = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + line = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`); assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn), 'package.jsonc'); }); @@ -78,7 +78,7 @@ describe('Search Tests', function(): void { await page.evaluate(`window.term.writeln('package.lock pack package.json package.ups\\n')`); await writeSync(page, 'package.jsonc'); await page.evaluate(`window.search.findNext('pack', {incremental: true})`); - let line: string = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + let line: string = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); let selectionPosition: { startColumn: number, startRow: number, endColumn: number, endRow: number } = await page.evaluate(`window.term.getSelectionPosition()`); // We look further ahead in the line to ensure that pack was selected from package.lock assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 8), 'package.lock'); @@ -87,7 +87,7 @@ describe('Search Tests', function(): void { assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 3), 'package.json'); await page.evaluate(`window.search.findNext('package.jsonc', {incremental: true})`); // We have to reevaluate line because it should have switched starting rows at this point - line = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + line = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`); assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn), 'package.jsonc'); }); diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index 183687ac1..ba8dbc072 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -87,7 +87,7 @@ export class SearchAddon implements ITerminalAddon { // Search from startRow + 1 to end if (!result) { - for (let y = startRow + 1; y < this._terminal.buffer.baseY + this._terminal.rows; y++) { + for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) { searchPosition.startRow = y; searchPosition.startCol = 0; // If the current line is wrapped line, increase index of column to ignore the previous scan @@ -135,7 +135,7 @@ export class SearchAddon implements ITerminalAddon { } const isReverseSearch = true; - let startRow = this._terminal.buffer.baseY + this._terminal.rows; + let startRow = this._terminal.buffer.active.baseY + this._terminal.rows; let startCol = this._terminal.cols; let result: ISearchResult | undefined; const incremental = searchOptions ? searchOptions.incremental : false; @@ -174,8 +174,8 @@ export class SearchAddon implements ITerminalAddon { } } // If we hit the top and didn't search from the very bottom wrap back down - if (!result && startRow !== (this._terminal.buffer.baseY + this._terminal.rows)) { - for (let y = (this._terminal.buffer.baseY + this._terminal.rows); y > startRow; y--) { + if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows)) { + for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows); y > startRow; y--) { searchPosition.startRow = y; result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch); if (result) { @@ -197,7 +197,7 @@ export class SearchAddon implements ITerminalAddon { private _initLinesCache(): void { const terminal = this._terminal!; if (!this._linesCache) { - this._linesCache = new Array(terminal.buffer.length); + this._linesCache = new Array(terminal.buffer.active.length); this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache()); this._resizeListener = terminal.onResize(() => this._destroyLinesCache()); } @@ -249,7 +249,7 @@ export class SearchAddon implements ITerminalAddon { const col = searchPosition.startCol; // Ignore wrapped lines, only consider on unwrapped line (first row of command string). - const firstLine = terminal.buffer.getLine(row); + const firstLine = terminal.buffer.active.getLine(row); if (firstLine && firstLine.isWrapped) { if (isReverseSearch) { searchPosition.startCol += terminal.cols; @@ -311,7 +311,7 @@ export class SearchAddon implements ITerminalAddon { return; } - const line = terminal.buffer.getLine(row); + const line = terminal.buffer.active.getLine(row); if (line) { for (let i = 0; i < resultIndex; i++) { @@ -354,9 +354,9 @@ export class SearchAddon implements ITerminalAddon { let lineWrapsToNext: boolean; do { - const nextLine = terminal.buffer.getLine(lineIndex + 1); + const nextLine = terminal.buffer.active.getLine(lineIndex + 1); lineWrapsToNext = nextLine ? nextLine.isWrapped : false; - const line = terminal.buffer.getLine(lineIndex); + const line = terminal.buffer.active.getLine(lineIndex); if (!line) { break; } @@ -380,8 +380,8 @@ export class SearchAddon implements ITerminalAddon { } terminal.select(result.col, result.row, result.term.length); // If it is not in the viewport then we scroll else it just gets selected - if (result.row >= (terminal.buffer.viewportY + terminal.rows) || result.row < terminal.buffer.viewportY) { - let scroll = result.row - terminal.buffer.viewportY; + if (result.row >= (terminal.buffer.active.viewportY + terminal.rows) || result.row < terminal.buffer.active.viewportY) { + let scroll = result.row - terminal.buffer.active.viewportY; scroll = scroll - Math.floor(terminal.rows / 2); terminal.scrollLines(scroll); } diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 1d011726c..445c48602 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -175,8 +175,8 @@ export class SerializeAddon implements ITerminalAddon { throw new Error('Cannot use addon until it has been loaded'); } - const maxRows = this._terminal.buffer.length; - const handler = new StringSerializeHandler(this._terminal.buffer); + const maxRows = this._terminal.buffer.active.length; + const handler = new StringSerializeHandler(this._terminal.buffer.active); rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows); diff --git a/addons/xterm-addon-web-links/src/WebLinkProvider.ts b/addons/xterm-addon-web-links/src/WebLinkProvider.ts index ea43aae64..23dc8560f 100644 --- a/addons/xterm-addon-web-links/src/WebLinkProvider.ts +++ b/addons/xterm-addon-web-links/src/WebLinkProvider.ts @@ -84,7 +84,7 @@ export class LinkComputer { let prevLinesToWrap: boolean; do { - const line = terminal.buffer.getLine(lineIndex); + const line = terminal.buffer.active.getLine(lineIndex); if (!line) { break; } @@ -99,9 +99,9 @@ export class LinkComputer { const startLineIndex = lineIndex; do { - const nextLine = terminal.buffer.getLine(lineIndex + 1); + const nextLine = terminal.buffer.active.getLine(lineIndex + 1); lineWrapsToNext = nextLine ? nextLine.isWrapped : false; - const line = terminal.buffer.getLine(lineIndex); + const line = terminal.buffer.active.getLine(lineIndex); if (!line) { break; } diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index 6c67febb5..f8eed3ae8 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -250,7 +250,7 @@ export class GlyphRenderer { private _updateSelectionRange(startCol: number, endCol: number, y: number, model: IRenderModel, bg: number): void { const terminal = this._terminal; - const row = y + terminal.buffer.viewportY; + const row = y + terminal.buffer.active.viewportY; let line: IBufferLine | undefined; for (let x = startCol; x < endCol; x++) { const offset = (y * this._terminal.cols + x) * RENDER_MODEL_INDICIES_PER_CELL; @@ -281,7 +281,7 @@ export class GlyphRenderer { } if (code & COMBINED_CHAR_BIT_MASK) { if (!line) { - line = terminal.buffer.getLine(row); + line = terminal.buffer.active.getLine(row); } const chars = line!.getCell(x)!.getChars(); this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], bg, fg, chars); diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index aba9c456c..08754efab 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -302,8 +302,8 @@ export class WebglRenderer extends Disposable implements IRenderer { } // Translate from buffer position to viewport position - const viewportStartRow = start[1] - terminal.buffer.viewportY; - const viewportEndRow = end[1] - terminal.buffer.viewportY; + const viewportStartRow = start[1] - terminal.buffer.active.viewportY; + const viewportEndRow = end[1] - terminal.buffer.active.viewportY; const viewportCappedStartRow = Math.max(viewportStartRow, 0); const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); diff --git a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts index 2ade8007d..6af2b7d76 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts @@ -76,14 +76,14 @@ export class CursorRenderLayer extends BaseRenderLayer { if (this._cursorBlinkStateManager) { this._cursorBlinkStateManager.pause(); } - this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.cursorY, end: terminal.buffer.cursorY }); + this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY }); } public onFocus(terminal: Terminal): void { if (this._cursorBlinkStateManager) { this._cursorBlinkStateManager.resume(terminal); } else { - this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.cursorY, end: terminal.buffer.cursorY }); + this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY }); } } @@ -100,7 +100,7 @@ export class CursorRenderLayer extends BaseRenderLayer { } // Request a refresh from the terminal as management of rendering is being // moved back to the terminal - this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.cursorY, end: terminal.buffer.cursorY }); + this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY }); } public onCursorMove(terminal: Terminal): void { @@ -125,11 +125,11 @@ export class CursorRenderLayer extends BaseRenderLayer { return; } - const cursorY = terminal.buffer.baseY + terminal.buffer.cursorY; - const viewportRelativeCursorY = cursorY - terminal.buffer.viewportY; + const cursorY = terminal.buffer.active.baseY + terminal.buffer.active.cursorY; + const viewportRelativeCursorY = cursorY - terminal.buffer.active.viewportY; // in case cursor.x == cols adjust visual cursor to cols - 1 - const cursorX = Math.min(terminal.buffer.cursorX, terminal.cols - 1); + const cursorX = Math.min(terminal.buffer.active.cursorX, terminal.cols - 1); // Don't draw the cursor if it's off-screen if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) { diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index 5535bd47c..a4d841b4d 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferSet as IBufferSetApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; +import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; import { ITerminal } from '../Types'; import { IBufferLine, ICellData } from 'common/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; @@ -48,8 +48,7 @@ export class Terminal implements ITerminalApi { public get textarea(): HTMLTextAreaElement | undefined { return this._core.textarea; } public get rows(): number { return this._core.rows; } public get cols(): number { return this._core.cols; } - public get buffer(): IBufferApi { return new BufferApiView(this._core.buffer); } - public get buffers(): IBufferSetApi { return new BufferSetApiView(this._core.buffers); } + public get buffer(): IBufferNamespaceApi { return new BufferNamespaceApi(this._core.buffers); } public get markers(): ReadonlyArray { return this._core.markers; } public blur(): void { this._core.blur(); @@ -194,8 +193,13 @@ export class Terminal implements ITerminalApi { } class BufferApiView implements IBufferApi { - constructor(private _buffer: IBuffer) { } + constructor(private _buffer: IBuffer, private _buffers: IBufferSet) { } + public get type(): 'normal' | 'alternate' { + if (this._buffers.normal === this._buffer) { return 'normal'; } + else if (this._buffers.alt === this._buffer) { return 'alternate'; } + throw new Error('Unknown buffer type'); + } public get cursorY(): number { return this._buffer.y; } public get cursorX(): number { return this._buffer.x; } public get viewportY(): number { return this._buffer.ydisp; } @@ -211,20 +215,17 @@ class BufferApiView implements IBufferApi { public getNullCell(): IBufferCellApi { return new CellData(); } } -class BufferSetApiView implements IBufferSetApi { +class BufferNamespaceApi implements IBufferNamespaceApi { constructor(private _buffers: IBufferSet) { } - public get alt(): IBufferApi { return new BufferApiView(this._buffers.alt); } - public get active(): IBufferApi { return new BufferApiView(this._buffers.active); } - public get normal(): IBufferApi { return new BufferApiView(this._buffers.normal); } + public get alternate(): IBufferApi { return new BufferApiView(this._buffers.alt, this._buffers); } + public get active(): IBufferApi { return new BufferApiView(this._buffers.active, this._buffers); } + public get normal(): IBufferApi { return new BufferApiView(this._buffers.normal, this._buffers); } - public get onBufferActivate(): IEvent<{ activeBuffer: IBufferApi, inactiveBuffer: IBufferApi }> { - return (listener: (arg1: { activeBuffer: IBufferApi, inactiveBuffer: IBufferApi }, arg2: void) => any) => { - return this._buffers.onBufferActivate((innerArg: { activeBuffer: IBuffer, inactiveBuffer: IBuffer }) => { - listener({ - activeBuffer: new BufferApiView(innerArg.activeBuffer), - inactiveBuffer: new BufferApiView(innerArg.inactiveBuffer) - }); + public get onBufferChange(): IEvent { + return (listener: (buffer: IBufferApi, unused: void) => any): IDisposable => { + return this._buffers.onBufferActivate((arg1: { activeBuffer: IBuffer, inactiveBuffer: IBuffer }) => { + listener(new BufferApiView(arg1.activeBuffer, this._buffers)); }); }; } diff --git a/test/api/CharWidth.api.ts b/test/api/CharWidth.api.ts index b5cb58388..fbc71b46b 100644 --- a/test/api/CharWidth.api.ts +++ b/test/api/CharWidth.api.ts @@ -79,7 +79,7 @@ async function sumWidths(start: number, end: number, sentinel: string): Promise< await page.evaluate(` (function() { window.result = 0; - const buffer = window.term.buffer; + const buffer = window.term.buffer.active; for (let i = ${start}; i < ${end}; i++) { const line = buffer.getLine(i); let j = 0; diff --git a/test/api/InputHandler.api.ts b/test/api/InputHandler.api.ts index d4018d901..c6d9939c3 100644 --- a/test/api/InputHandler.api.ts +++ b/test/api/InputHandler.api.ts @@ -165,7 +165,7 @@ describe('InputHandler Integration Tests', function(): void { window.term.reset() window.term.write('1\\n2\\n3\\n4\\n5${fixture}\x1b[3J') `); - await pollFor(page, () => page.evaluate(`window.term.buffer.length`), 5); + await pollFor(page, () => page.evaluate(`window.term.buffer.active.length`), 5); await pollFor(page, () => getLinesAsArray(5), [' 4', ' 5', 'abc', 'def', 'ghi']); }); @@ -194,7 +194,7 @@ describe('InputHandler Integration Tests', function(): void { window.term.reset() window.term.write('1\\n2\\n3\\n4\\n5${fixture}\x1b[?3J') `); - await pollFor(page, () => page.evaluate(`window.term.buffer.length`), 5); + await pollFor(page, () => page.evaluate(`window.term.buffer.active.length`), 5); await pollFor(page, () => getLinesAsArray(5), [' 4', ' 5', 'abc', 'def', 'ghi']); }); @@ -240,7 +240,7 @@ describe('InputHandler Integration Tests', function(): void { it('Report Cursor Position (CPR) - CSI 6 n', async function(): Promise { await page.evaluate(`window.term.write('\\n\\nfoo')`); await pollFor(page, () => page.evaluate(` - [window.term.buffer.cursorY, window.term.buffer.cursorX] + [window.term.buffer.active.cursorY, window.term.buffer.active.cursorX] `), [2, 3]); await page.evaluate(` window.term.onData(e => window.result = e); @@ -252,7 +252,7 @@ describe('InputHandler Integration Tests', function(): void { it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise { await page.evaluate(`window.term.write('\\n\\nfoo')`); await pollFor(page, () => page.evaluate(` - [window.term.buffer.cursorY, window.term.buffer.cursorX] + [window.term.buffer.active.cursorY, window.term.buffer.active.cursorX] `), [2, 3]); await page.evaluate(` window.term.onData(e => window.result = e); @@ -410,7 +410,7 @@ describe('InputHandler Integration Tests', function(): void { async function getLinesAsArray(count: number, start: number = 0): Promise { let text = ''; for (let i = start; i < start + count; i++) { - text += `window.term.buffer.getLine(${i}).translateToString(true), `; + text += `window.term.buffer.active.getLine(${i}).translateToString(true),`; } return await page.evaluate(`[${text}]`); } @@ -430,10 +430,10 @@ async function simulatePaste(text: string): Promise { async function getCursor(): Promise<{ col: number, row: number }> { return page.evaluate(` - (function() { - return { col: term.buffer.cursorX, row: term.buffer.cursorY }; - })(); - `); + (function() { + return {col: term.buffer.active.cursorX, row: term.buffer.active.cursorY}; + })(); + `); } async function getDimensions(): Promise { diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index fce175118..2798f6531 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -41,7 +41,7 @@ describe('API Integration Tests', function(): void { window.term.write('bar'); window.term.write('文'); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); }); it('write with callback', async () => { @@ -51,7 +51,7 @@ describe('API Integration Tests', function(): void { window.term.write('bar', () => { window.__x += 'b'; }); window.term.write('文', () => { window.__x += 'c'; }); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); await pollFor(page, `window.__x`, 'abc'); }); @@ -65,7 +65,7 @@ describe('API Integration Tests', function(): void { // 文 window.term.write(new Uint8Array([230, 150, 135])); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); }); it('write - bytes (UTF8) with callback', async () => { @@ -78,7 +78,7 @@ describe('API Integration Tests', function(): void { // 文 window.term.write(new Uint8Array([230, 150, 135]), () => { window.__x += 'C'; }); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); await pollFor(page, `window.__x`, 'ABC'); }); @@ -89,9 +89,9 @@ describe('API Integration Tests', function(): void { window.term.writeln('bar'); window.term.writeln('文'); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); - await pollFor(page, `window.term.buffer.getLine(1).translateToString(true)`, 'bar'); - await pollFor(page, `window.term.buffer.getLine(2).translateToString(true)`, '文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(1).translateToString(true)`, 'bar'); + await pollFor(page, `window.term.buffer.active.getLine(2).translateToString(true)`, '文'); }); it('writeln with callback', async () => { @@ -101,9 +101,9 @@ describe('API Integration Tests', function(): void { window.term.writeln('bar', () => { window.__x += '2'; }); window.term.writeln('文', () => { window.__x += '3'; }); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); - await pollFor(page, `window.term.buffer.getLine(1).translateToString(true)`, 'bar'); - await pollFor(page, `window.term.buffer.getLine(2).translateToString(true)`, '文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(1).translateToString(true)`, 'bar'); + await pollFor(page, `window.term.buffer.active.getLine(2).translateToString(true)`, '文'); await pollFor(page, `window.__x`, '123'); }); @@ -114,9 +114,9 @@ describe('API Integration Tests', function(): void { window.term.writeln(new Uint8Array([98, 97, 114])); window.term.writeln(new Uint8Array([230, 150, 135])); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); - await pollFor(page, `window.term.buffer.getLine(1).translateToString(true)`, 'bar'); - await pollFor(page, `window.term.buffer.getLine(2).translateToString(true)`, '文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(1).translateToString(true)`, 'bar'); + await pollFor(page, `window.term.buffer.active.getLine(2).translateToString(true)`, '文'); }); it('paste', async () => { @@ -144,10 +144,10 @@ describe('API Integration Tests', function(): void { `); await pollFor(page, `window.parsed`, 9); await page.evaluate(`window.term.clear()`); - await pollFor(page, `window.term.buffer.length`, 5); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'test9'); + await pollFor(page, `window.term.buffer.active.length`, 5); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'test9'); for (let i = 1; i < 5; i++) { - await pollFor(page, `window.term.buffer.getLine(${i}).translateToString(true)`, ''); + await pollFor(page, `window.term.buffer.active.getLine(${i}).translateToString(true)`, ''); } }); @@ -400,113 +400,113 @@ describe('API Integration Tests', function(): void { describe('buffer', () => { it('cursorX, cursorY', async () => { await openTerminal(page, { rows: 5, cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 0); await writeSync(page, 'foo'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 3); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 3); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 0); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 3); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 3); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 1); await writeSync(page, '\\r'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 1); await writeSync(page, 'abcde'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 5); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 1); await writeSync(page, '\\n\\r\\n\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 4); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 4); }); it('viewportY', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 0); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 0); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 1); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 5); await page.evaluate(`window.term.scrollLines(-1)`); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 4); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 4); await page.evaluate(`window.term.scrollToTop()`); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 0); }); it('baseY', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 0); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 0); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 1); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 5); await page.evaluate(`window.term.scrollLines(-1)`); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 5); await page.evaluate(`window.term.scrollToTop()`); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 5); }); it('length', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.length`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 5); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.length`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 5); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.length`), 6); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 6); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.length`), 10); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 10); }); describe('getLine', () => { it('invalid index', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(-1)`), undefined); - assert.equal(await page.evaluate(`window.term.buffer.getLine(5)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(-1)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(5)`), undefined); }); it('isWrapped', async () => { await openTerminal(page, { cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).isWrapped`), false); await writeSync(page, 'abcde'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).isWrapped`), false); await writeSync(page, 'f'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), true); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).isWrapped`), true); }); it('translateToString', async () => { await openTerminal(page, { cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), ' '); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), ''); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), ' '); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(true)`), ''); await writeSync(page, 'foo'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), 'foo '); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), 'foo'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'foo '); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(true)`), 'foo'); await writeSync(page, 'bar'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), 'fooba'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), 'fooba'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).translateToString(true)`), 'r'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(false, 1)`), 'ooba'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(false, 1, 3)`), 'oo'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'fooba'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(true)`), 'fooba'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).translateToString(true)`), 'r'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(false, 1)`), 'ooba'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(false, 1, 3)`), 'oo'); }); it('getCell', async () => { await openTerminal(page, { cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(-1)`), undefined); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(5)`), undefined); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getChars()`), ''); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getWidth()`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(-1)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(5)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getChars()`), ''); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getWidth()`), 1); await writeSync(page, 'a文'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getChars()`), 'a'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getWidth()`), 1); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(1).getChars()`), '文'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(1).getWidth()`), 2); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(2).getChars()`), ''); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(2).getWidth()`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getChars()`), 'a'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getWidth()`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(1).getChars()`), '文'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(1).getWidth()`), 2); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(2).getChars()`), ''); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(2).getWidth()`), 0); }); }); }); @@ -634,7 +634,7 @@ describe('API Integration Tests', function(): void { window.calls.push('provide ' + position.x + ',' + position.y); cb({ range: { start: position, end: position }, - text: window.term.buffer.getLine(position.y - 1).getCell(position.x - 1).getChars(), + text: window.term.buffer.active.getLine(position.y - 1).getCell(position.x - 1).getChars(), activate: (_, text) => window.calls.push('activate ' + text), hover: () => window.calls.push('hover'), leave: () => window.calls.push('leave') diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 4613677d7..a7ac9fe6d 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -574,12 +574,7 @@ declare module 'xterm' { * normal buffer or the alt buffer depending on what's running in the * terminal. */ - readonly buffer: IBuffer; - - /** - * (EXPERIMENTAL) The terminal's current bufferSet. - */ - readonly buffers: IBufferSet; + readonly buffer: IBufferNamespace; /** * (EXPERIMENTAL) Get all markers registered against the buffer. If the alt @@ -1173,6 +1168,10 @@ declare module 'xterm' { * Represents a terminal buffer. */ interface IBuffer { + /** + * The type of the buffer. + */ + readonly type: 'normal' | 'alternate'; /** * The y position of the cursor. This ranges between `0` (when the * cursor is at baseY) and `Terminal.rows - 1` (when the cursor is on the @@ -1222,12 +1221,12 @@ declare module 'xterm' { getNullCell(): IBufferCell; } - interface IBufferSet { - readonly alt: IBuffer; + interface IBufferNamespace { + readonly alternate: IBuffer; readonly normal: IBuffer; readonly active: IBuffer; - onBufferActivate: IEvent<{ activeBuffer: IBuffer, inactiveBuffer: IBuffer }>; + onBufferChange: IEvent; } /** From c2df14cfa074503a7a1588d7010d9c49c6e9808a Mon Sep 17 00:00:00 2001 From: javacs3 Date: Sat, 15 Feb 2020 17:18:11 +0800 Subject: [PATCH 012/130] reduce BufferApiView object creation times --- src/public/Terminal.ts | 28 +++++++++++++++++++++------- test/api/Terminal.api.ts | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index a4d841b4d..216bc1478 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -195,6 +195,12 @@ export class Terminal implements ITerminalApi { class BufferApiView implements IBufferApi { constructor(private _buffer: IBuffer, private _buffers: IBufferSet) { } + init(buffer: IBuffer, buffers: IBufferSet): BufferApiView { + this._buffer = buffer; + this._buffers = buffers; + return this; + } + public get type(): 'normal' | 'alternate' { if (this._buffers.normal === this._buffer) { return 'normal'; } else if (this._buffers.alt === this._buffer) { return 'alternate'; } @@ -216,17 +222,25 @@ class BufferApiView implements IBufferApi { } class BufferNamespaceApi implements IBufferNamespaceApi { - constructor(private _buffers: IBufferSet) { } + private _normal: BufferApiView; + private _alternate: BufferApiView; - public get alternate(): IBufferApi { return new BufferApiView(this._buffers.alt, this._buffers); } - public get active(): IBufferApi { return new BufferApiView(this._buffers.active, this._buffers); } - public get normal(): IBufferApi { return new BufferApiView(this._buffers.normal, this._buffers); } + constructor(private _buffers: IBufferSet) { + this._normal = new BufferApiView(this._buffers.normal, this._buffers); + this._alternate = new BufferApiView(this._buffers.alt, this._buffers); + } + + public get active(): IBufferApi { + if (this._buffers.active === this._buffers.normal) { return this.normal; } + else if (this._buffers.active === this._buffers.alt) { return this.alternate; } + throw new Error('Active Buffer is neither normal nor alternate'); + } + public get normal(): IBufferApi { return this._normal.init(this._buffers.normal, this._buffers); } + public get alternate(): IBufferApi { return this._alternate.init(this._buffers.alt, this._buffers); } public get onBufferChange(): IEvent { return (listener: (buffer: IBufferApi, unused: void) => any): IDisposable => { - return this._buffers.onBufferActivate((arg1: { activeBuffer: IBuffer, inactiveBuffer: IBuffer }) => { - listener(new BufferApiView(arg1.activeBuffer, this._buffers)); - }); + return this._buffers.onBufferActivate(() => listener(this.active)); }; } } diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index 2798f6531..9f16bfcd2 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -509,6 +509,38 @@ describe('API Integration Tests', function(): void { assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(2).getWidth()`), 0); }); }); + + it('active, normal, alternate', async () => { + await openTerminal(page, { cols: 5 }); + assert.equal(await page.evaluate(`window.term.buffer.active.type`), 'normal'); + assert.equal(await page.evaluate(`window.term.buffer.normal.type`), 'normal'); + assert.equal(await page.evaluate(`window.term.buffer.alternate.type`), 'alternate'); + + await writeSync(page, 'norm '); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'norm '); + assert.equal(await page.evaluate(`window.term.buffer.normal.getLine(0).translateToString()`), 'norm '); + assert.equal(await page.evaluate(`window.term.buffer.alternate.getLine(0)`), undefined); + + await writeSync(page, '\\x1b[?47h\\r'); // use alternate screen buffer + assert.equal(await page.evaluate(`window.term.buffer.active.type`), 'alternate'); + assert.equal(await page.evaluate(`window.term.buffer.normal.type`), 'normal'); + assert.equal(await page.evaluate(`window.term.buffer.alternate.type`), 'alternate'); + + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), ' '); + await writeSync(page, 'alt '); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'alt '); + assert.equal(await page.evaluate(`window.term.buffer.normal.getLine(0).translateToString()`), 'norm '); + assert.equal(await page.evaluate(`window.term.buffer.alternate.getLine(0).translateToString()`), 'alt '); + + await writeSync(page, '\\x1b[?47l\\r'); // use normal screen buffer + assert.equal(await page.evaluate(`window.term.buffer.active.type`), 'normal'); + assert.equal(await page.evaluate(`window.term.buffer.normal.type`), 'normal'); + assert.equal(await page.evaluate(`window.term.buffer.alternate.type`), 'alternate'); + + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'norm '); + assert.equal(await page.evaluate(`window.term.buffer.normal.getLine(0).translateToString()`), 'norm '); + assert.equal(await page.evaluate(`window.term.buffer.alternate.getLine(0)`), undefined); + }) }); it('dispose', async () => { From 0f64847351023af1589e86aff8132fb7256a2650 Mon Sep 17 00:00:00 2001 From: javacs3 Date: Sun, 5 Apr 2020 12:49:04 +0800 Subject: [PATCH 013/130] fix lint error --- src/public/Terminal.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index 216bc1478..5fa4d2519 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -203,7 +203,7 @@ class BufferApiView implements IBufferApi { public get type(): 'normal' | 'alternate' { if (this._buffers.normal === this._buffer) { return 'normal'; } - else if (this._buffers.alt === this._buffer) { return 'alternate'; } + if (this._buffers.alt === this._buffer) { return 'alternate'; } throw new Error('Unknown buffer type'); } public get cursorY(): number { return this._buffer.y; } @@ -232,8 +232,8 @@ class BufferNamespaceApi implements IBufferNamespaceApi { public get active(): IBufferApi { if (this._buffers.active === this._buffers.normal) { return this.normal; } - else if (this._buffers.active === this._buffers.alt) { return this.alternate; } - throw new Error('Active Buffer is neither normal nor alternate'); + if (this._buffers.active === this._buffers.alt) { return this.alternate; } + throw new Error('Active buffer is neither normal nor alternate'); } public get normal(): IBufferApi { return this._normal.init(this._buffers.normal, this._buffers); } public get alternate(): IBufferApi { return this._alternate.init(this._buffers.alt, this._buffers); } From 886af692e277f0dd8f01f6cb195b51ad523023cd Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 09:53:51 -0700 Subject: [PATCH 014/130] Use a separate emitter for BufferNamespaceApi.onBufferChange --- src/public/Terminal.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index 5fa4d2519..fbf3fb487 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -10,7 +10,7 @@ import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { CellData } from 'common/buffer/CellData'; import { Terminal as TerminalCore } from '../Terminal'; import * as Strings from '../browser/LocalizableStrings'; -import { IEvent } from 'common/EventEmitter'; +import { IEvent, EventEmitter } from 'common/EventEmitter'; import { AddonManager } from './AddonManager'; import { IParams } from 'common/parser/Types'; @@ -224,10 +224,13 @@ class BufferApiView implements IBufferApi { class BufferNamespaceApi implements IBufferNamespaceApi { private _normal: BufferApiView; private _alternate: BufferApiView; + private _onBufferChange = new EventEmitter(); + public get onBufferChange(): IEvent { return this._onBufferChange.event; } constructor(private _buffers: IBufferSet) { this._normal = new BufferApiView(this._buffers.normal, this._buffers); this._alternate = new BufferApiView(this._buffers.alt, this._buffers); + this._buffers.onBufferActivate(() => this._onBufferChange.fire(this.active)); } public get active(): IBufferApi { @@ -237,12 +240,6 @@ class BufferNamespaceApi implements IBufferNamespaceApi { } public get normal(): IBufferApi { return this._normal.init(this._buffers.normal, this._buffers); } public get alternate(): IBufferApi { return this._alternate.init(this._buffers.alt, this._buffers); } - - public get onBufferChange(): IEvent { - return (listener: (buffer: IBufferApi, unused: void) => any): IDisposable => { - return this._buffers.onBufferActivate(() => listener(this.active)); - }; - } } class BufferLineApiView implements IBufferLineApi { From 4c36ef9d24d0ab899d094a94bc5e20beb6b54afd Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 09:56:26 -0700 Subject: [PATCH 015/130] Don't pass buffers to BufferApiView --- src/public/Terminal.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index fbf3fb487..61334f08a 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -193,19 +193,16 @@ export class Terminal implements ITerminalApi { } class BufferApiView implements IBufferApi { - constructor(private _buffer: IBuffer, private _buffers: IBufferSet) { } + constructor( + private _buffer: IBuffer, + public readonly type: 'normal' | 'alternate' + ) { } - init(buffer: IBuffer, buffers: IBufferSet): BufferApiView { + public init(buffer: IBuffer): BufferApiView { this._buffer = buffer; - this._buffers = buffers; return this; } - public get type(): 'normal' | 'alternate' { - if (this._buffers.normal === this._buffer) { return 'normal'; } - if (this._buffers.alt === this._buffer) { return 'alternate'; } - throw new Error('Unknown buffer type'); - } public get cursorY(): number { return this._buffer.y; } public get cursorX(): number { return this._buffer.x; } public get viewportY(): number { return this._buffer.ydisp; } @@ -228,18 +225,21 @@ class BufferNamespaceApi implements IBufferNamespaceApi { public get onBufferChange(): IEvent { return this._onBufferChange.event; } constructor(private _buffers: IBufferSet) { - this._normal = new BufferApiView(this._buffers.normal, this._buffers); - this._alternate = new BufferApiView(this._buffers.alt, this._buffers); + this._normal = new BufferApiView(this._buffers.normal, 'normal'); + this._alternate = new BufferApiView(this._buffers.alt, 'alternate'); this._buffers.onBufferActivate(() => this._onBufferChange.fire(this.active)); } - public get active(): IBufferApi { if (this._buffers.active === this._buffers.normal) { return this.normal; } if (this._buffers.active === this._buffers.alt) { return this.alternate; } throw new Error('Active buffer is neither normal nor alternate'); } - public get normal(): IBufferApi { return this._normal.init(this._buffers.normal, this._buffers); } - public get alternate(): IBufferApi { return this._alternate.init(this._buffers.alt, this._buffers); } + public get normal(): IBufferApi { + return this._normal.init(this._buffers.normal); + } + public get alternate(): IBufferApi { + return this._alternate.init(this._buffers.alt); + } } class BufferLineApiView implements IBufferLineApi { From f4f15ee5e9fdb4d5305b4462078d1a109d554bdf Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 09:57:10 -0700 Subject: [PATCH 016/130] Add missing line in api --- typings/xterm.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index bd540d40c..24c7ffaa6 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1172,6 +1172,7 @@ declare module 'xterm' { * The type of the buffer. */ readonly type: 'normal' | 'alternate'; + /** * The y position of the cursor. This ranges between `0` (when the * cursor is at baseY) and `Terminal.rows - 1` (when the cursor is on the From 89daacac32506e91265b48ac1685798da8a95fed Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 10:02:09 -0700 Subject: [PATCH 017/130] Add missing api docs --- typings/xterm.d.ts | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 24c7ffaa6..9445d0754 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1222,11 +1222,30 @@ declare module 'xterm' { getNullCell(): IBufferCell; } + /** + * Represents the terminal's set of buffers. + */ interface IBufferNamespace { - readonly alternate: IBuffer; - readonly normal: IBuffer; + /** + * The active buffer, this will either be the normal or alternate buffers. + */ readonly active: IBuffer; + /** + * The normal buffer. + */ + readonly normal: IBuffer; + + /** + * The alternate buffer, this becomes the active buffer when an application + * enters this mode via DECSET (`CSI ? 4 7 h`) + */ + readonly alternate: IBuffer; + + /** + * Adds an event listener for when the active buffer changes. + * @returns an `IDisposable` to stop listening. + */ onBufferChange: IEvent; } From ef0d834db8711ba8aa3991aab1891c596af65383 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 10:03:55 -0700 Subject: [PATCH 018/130] Convert eslintrc to json and fix errors --- .eslintrc.js => .eslintrc.json | 13 +++++++------ package.json | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) rename .eslintrc.js => .eslintrc.json (96%) diff --git a/.eslintrc.js b/.eslintrc.json similarity index 96% rename from .eslintrc.js rename to .eslintrc.json index 20c84b9e5..5d5061d55 100644 --- a/.eslintrc.js +++ b/.eslintrc.json @@ -1,4 +1,4 @@ -module.exports = { +{ "env": { "browser": true, "es6": true, @@ -23,7 +23,9 @@ module.exports = { ], "sourceType": "module" }, - "ignorePatterns": "**/typings/*.d.ts", + "ignorePatterns": [ + "**/typings/*.d.ts" + ], "plugins": [ "@typescript-eslint" ], @@ -79,7 +81,7 @@ module.exports = { { "selector": "method", "modifiers": ["public"], "format": ["camelCase", "UPPER_CASE"] }, // typeLike { "selector": "typeLike", "format": ["PascalCase"] }, - { "selector": "interface", "format": ["PascalCase"], "prefix": ["I"] }, + { "selector": "interface", "format": ["PascalCase"], "prefix": ["I"] } ], "@typescript-eslint/prefer-namespace-keyword": "error", "@typescript-eslint/type-annotation-spacing": "error", @@ -92,7 +94,6 @@ module.exports = { "error", "always" ], - "@typescript-eslint/type-annotation-spacing": "error", "comma-dangle": [ "error", { @@ -116,7 +117,7 @@ module.exports = { "no-else-return": [ "error", { - allowElseIf: false + "allowElseIf": false } ], "no-eval": "error", @@ -146,4 +147,4 @@ module.exports = { } ] } -}; +} diff --git a/package.json b/package.json index 804d5f27d..b177851a2 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "prepackage": "npm run build", "package": "webpack", "start": "node demo/start", - "lint": "eslint -c .eslintrc.js --ext .ts src/ addons/", + "lint": "eslint -c .eslintrc.json --ext .ts src/ addons/", "test": "npm run test-unit", "posttest": "npm run lint", "test-api": "npm run test-api-chromium", From 3ef41f2b1d454fcb07d65ddb99944cc000905547 Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Fri, 10 Apr 2020 23:19:31 +0530 Subject: [PATCH 019/130] Remove decset modes from coreservices --- src/common/services/CoreService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index c8c77c7d1..df9161e9c 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -9,7 +9,6 @@ import { IDecPrivateModes, ICharset } from 'common/Types'; import { clone } from 'common/Clone'; const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ - altEscMode: true, applicationCursorKeys: false, applicationKeypad: false, origin: false, From f61d6320a3a5fcc86a20b485880cc4976ad5e56b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 12:44:39 -0700 Subject: [PATCH 020/130] v4.5.0 --- addons/xterm-addon-search/package.json | 2 +- addons/xterm-addon-serialize/package.json | 2 +- addons/xterm-addon-web-links/package.json | 2 +- addons/xterm-addon-webgl/package.json | 2 +- package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/xterm-addon-search/package.json b/addons/xterm-addon-search/package.json index 1913f1777..445f70c9f 100644 --- a/addons/xterm-addon-search/package.json +++ b/addons/xterm-addon-search/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-search", - "version": "0.5.0", + "version": "0.6.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-serialize/package.json b/addons/xterm-addon-serialize/package.json index fbf1614e5..4b52e814c 100644 --- a/addons/xterm-addon-serialize/package.json +++ b/addons/xterm-addon-serialize/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-serialize", - "version": "0.1.2", + "version": "0.2.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-web-links/package.json b/addons/xterm-addon-web-links/package.json index 6167de749..febcfab41 100644 --- a/addons/xterm-addon-web-links/package.json +++ b/addons/xterm-addon-web-links/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-web-links", - "version": "0.2.1", + "version": "0.3.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-webgl/package.json b/addons/xterm-addon-webgl/package.json index ca49e7951..7a1a9ee50 100644 --- a/addons/xterm-addon-webgl/package.json +++ b/addons/xterm-addon-webgl/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-webgl", - "version": "0.5.1", + "version": "0.6.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/package.json b/package.json index b177851a2..df6208c8c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xterm", "description": "Full xterm terminal, in your browser", - "version": "4.4.0", + "version": "4.5.0", "main": "lib/xterm.js", "style": "css/xterm.css", "types": "typings/xterm.d.ts", From ba0dc60b09bb5a8c5f34a33933b209466c2cc238 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 12:53:02 -0700 Subject: [PATCH 021/130] Combine into ternary --- src/common/input/Keyboard.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/common/input/Keyboard.ts b/src/common/input/Keyboard.ts index d07ea6251..fdb777b42 100644 --- a/src/common/input/Keyboard.ts +++ b/src/common/input/Keyboard.ts @@ -103,12 +103,7 @@ export function evaluateKeyboardEvent( break; case 13: // return/enter - if (ev.altKey) { - result.key = C0.ESC + C0.CR; - } - else { - result.key = C0.CR; - } + result.key = ev.altKey ? C0.ESC + C0.CR : C0.CR; result.cancel = true; break; case 27: From 7609a5456ef0374e9e8bba4a0b58d354823afcef Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 Apr 2020 14:08:28 -0700 Subject: [PATCH 022/130] Fix most lgtm warnings --- .../xterm-addon-web-links/src/WebLinkProvider.ts | 2 +- addons/xterm-addon-web-links/src/WebLinksAddon.ts | 2 +- addons/xterm-addon-webgl/src/WebglRenderer.api.ts | 5 ----- bin/extract_vtfeatures.js | 14 +++++++------- src/browser/input/MoveToCell.ts | 5 ----- src/common/services/CoreService.ts | 2 +- 6 files changed, 10 insertions(+), 20 deletions(-) diff --git a/addons/xterm-addon-web-links/src/WebLinkProvider.ts b/addons/xterm-addon-web-links/src/WebLinkProvider.ts index 23dc8560f..5f6460bf9 100644 --- a/addons/xterm-addon-web-links/src/WebLinkProvider.ts +++ b/addons/xterm-addon-web-links/src/WebLinkProvider.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ILinkProvider, IBufferCellPosition, ILink, Terminal, IBuffer } from 'xterm'; +import { ILinkProvider, IBufferCellPosition, ILink, Terminal } from 'xterm'; export class WebLinkProvider implements ILinkProvider { diff --git a/addons/xterm-addon-web-links/src/WebLinksAddon.ts b/addons/xterm-addon-web-links/src/WebLinksAddon.ts index dbc664a8b..4e700b574 100644 --- a/addons/xterm-addon-web-links/src/WebLinksAddon.ts +++ b/addons/xterm-addon-web-links/src/WebLinksAddon.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal, ILinkMatcherOptions, ITerminalAddon, ILinkProvider, IDisposable } from 'xterm'; +import { Terminal, ILinkMatcherOptions, ITerminalAddon, IDisposable } from 'xterm'; import { WebLinkProvider } from './WebLinkProvider'; const protocolClause = '(https?:\\/\\/)'; diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index 591d7fff6..daf7f6fca 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -341,10 +341,6 @@ describe('WebGL Renderer Integration Tests', async () => { await writeSync(page, data); for (let y = 0; y < 240 / 16; y++) { for (let x = 0; x < 16; x++) { - const cssColor = COLORS_16_TO_255[y * 16 + x]; - const r = parseInt(cssColor.substr(1, 2), 16); - const g = parseInt(cssColor.substr(3, 2), 16); - const b = parseInt(cssColor.substr(5, 2), 16); await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, 0, 255]); } } @@ -670,7 +666,6 @@ describe('WebGL Renderer Integration Tests', async () => { await writeSync(page, data); for (let y = 0; y < 16; y++) { for (let x = 0; x < 16; x++) { - const i = y * 16 + x; await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, 0, 255]); } } diff --git a/bin/extract_vtfeatures.js b/bin/extract_vtfeatures.js index e575aeab5..63d09684e 100644 --- a/bin/extract_vtfeatures.js +++ b/bin/extract_vtfeatures.js @@ -1,7 +1,7 @@ /** * Copyright (c) 2019 The xterm.js authors. All rights reserved. * @license MIT - * + * * Script to extract vt features documented in docstrings. */ const fs = require('fs'); @@ -265,7 +265,7 @@ To denote the sequences the tables use the same abbreviations as xterm does: function hideDetailSections() { for (let section of document.getElementsByClassName('sequence-details')) section.style.display = 'none'; } - + function decorateDetailLinks() { for (let link of document.getElementsByClassName('link-details')) { link.addEventListener("click", toggleDetails, false); @@ -344,11 +344,11 @@ function applyMacros(s) { return s; } -function replaceStatus(s) { - if (s === 'supported') return '✓'; - if (s === 'unsupported') return '✗'; - return s; -} +// function replaceStatus(s) { +// if (s === 'supported') return '✓'; +// if (s === 'unsupported') return '✗'; +// return s; +// } function createAnchorSlug(s) { return s.toLowerCase().split(' ').join('-'); diff --git a/src/browser/input/MoveToCell.ts b/src/browser/input/MoveToCell.ts index d8f5a498c..25e1844d4 100644 --- a/src/browser/input/MoveToCell.ts +++ b/src/browser/input/MoveToCell.ts @@ -105,11 +105,6 @@ function moveToRequestedCol(startX: number, startY: number, targetX: number, tar ).length, sequence(direction, applicationCursor)); } -function moveHorizontallyOnly(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string { - const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor); - return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor)); -} - /** * Utility functions */ diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index df9161e9c..883266ec5 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -5,7 +5,7 @@ import { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { IDecPrivateModes, ICharset } from 'common/Types'; +import { IDecPrivateModes } from 'common/Types'; import { clone } from 'common/Clone'; const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ From f9b2f3e87d082d30ef3d04bbcc49edf840d4864e Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Sat, 11 Apr 2020 11:54:58 +0530 Subject: [PATCH 023/130] Add api-test script to log poll result on passing --debug flag --- bin/test.js | 10 +++++++++ bin/test_api.js | 49 +++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- test/api/TestUtils.ts | 5 +++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 bin/test_api.js diff --git a/bin/test.js b/bin/test.js index 1380a5122..e19a2ad92 100644 --- a/bin/test.js +++ b/bin/test.js @@ -51,6 +51,16 @@ if (checkCoverage) { process.exit(run.status); } +const checkDebug = flagArgs.indexOf('--debug') >= 0; + +if (checkDebug) { + env.DEBUG = 'debug'; +} + +if (env.DEBUG) { + console.log('poll result', result); +} + const run = cp.spawnSync( npmBinScript('mocha'), [...testFiles, ...flagArgs], diff --git a/bin/test_api.js b/bin/test_api.js new file mode 100644 index 000000000..2eb3fc3e1 --- /dev/null +++ b/bin/test_api.js @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +const cp = require('child_process'); +const path = require('path'); + + +// Add `out` to the NODE_PATH so absolute paths can be resolved. +const env = { ...process.env }; +env.NODE_PATH = path.resolve(__dirname, '../out'); + +let testFiles = [ + './addons/**/out/*api.js', + './out-test/**/*api.js', +]; + + +let flagArgs = []; + +if (process.argv.length > 2) { + const args = process.argv.slice(2); + flagArgs = args.filter(e => e.startsWith('--')); + // ability to inject particular test files via + // yarn test [testFileA testFileB ...] + files = args.filter(e => !e.startsWith('--')); + if (files.length) { + testFiles = files; + } +} + +env.DEBUG = flagArgs.indexOf('--debug') >= 0 ? 'debug' : ''; + +const run = cp.spawnSync( + npmBinScript('mocha'), + [...testFiles, ...flagArgs], + { + cwd: path.resolve(__dirname, '..'), + env, + stdio: 'inherit' + } +); + +function npmBinScript(script) { + return path.resolve(__dirname, `../node_modules/.bin/` + (process.platform === 'win32' ? `${script}.cmd` : script)); +} + +process.exit(run.status); diff --git a/package.json b/package.json index 956cdbb11..192d8ca10 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "lint": "tslint 'src/**/*.ts' 'addons/*/src/**/*.ts'", "test": "npm run test-unit", "posttest": "npm run lint", - "test-api": "mocha \"**/*.api.js\"", + "test-api": "node ./bin/test_api.js", "test-unit": "node ./bin/test.js", "test-unit-coverage": "node ./bin/test.js --coverage", "build": "tsc -b ./tsconfig.all.json", diff --git a/test/api/TestUtils.ts b/test/api/TestUtils.ts index d36748122..ba2c43fd9 100644 --- a/test/api/TestUtils.ts +++ b/test/api/TestUtils.ts @@ -11,6 +11,11 @@ export async function pollFor(page: puppeteer.Page, evalOrFn: string | (() => await preFn(); } const result = typeof evalOrFn === 'string' ? await page.evaluate(evalOrFn) : await evalOrFn(); + + if (process.env.DEBUG) { + console.log('pollFor result: ', result); + } + if (!deepEqual(result, val)) { return new Promise(r => { setTimeout(() => r(pollFor(page, evalOrFn, val, preFn)), 1); From ae72994cfb8ab915ae23df107ae7845c3b584798 Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Sat, 11 Apr 2020 12:02:27 +0530 Subject: [PATCH 024/130] Undo changes on ./bin/test.js --- bin/test.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/bin/test.js b/bin/test.js index e19a2ad92..1380a5122 100644 --- a/bin/test.js +++ b/bin/test.js @@ -51,16 +51,6 @@ if (checkCoverage) { process.exit(run.status); } -const checkDebug = flagArgs.indexOf('--debug') >= 0; - -if (checkDebug) { - env.DEBUG = 'debug'; -} - -if (env.DEBUG) { - console.log('poll result', result); -} - const run = cp.spawnSync( npmBinScript('mocha'), [...testFiles, ...flagArgs], From 714daba393dfea6ee1a2c4695de6b420b70cba54 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 11 Apr 2020 06:31:58 -0700 Subject: [PATCH 025/130] Fix selection wrapping to end when not beyond viewport This was happening as the devicePixelRatio wasn't being taken into account, the fix was to rely on IRenderService to get the right canvas height. Fixes #2833 --- src/browser/TestUtils.test.ts | 73 ++++++++++++++++++- src/browser/services/SelectionService.test.ts | 13 +++- src/browser/services/SelectionService.ts | 8 +- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 60861112e..3e304bcfc 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -4,7 +4,9 @@ */ import { IEvent, EventEmitter } from 'common/EventEmitter'; -import { ICharSizeService, IMouseService } from 'browser/services/Services'; +import { ICharSizeService, IMouseService, IRenderService } from 'browser/services/Services'; +import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; +import { IColorSet } from 'browser/Types'; export class MockCharSizeService implements ICharSizeService { serviceBrand: any; @@ -24,3 +26,72 @@ export class MockMouseService implements IMouseService { throw new Error('Not implemented'); } } + +export class MockRenderService implements IRenderService { + serviceBrand: any; + onDimensionsChange: IEvent = new EventEmitter().event; + onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; + onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; + dimensions: IRenderDimensions = { + scaledCharWidth: 0, + scaledCharHeight: 0, + scaledCellWidth: 0, + scaledCellHeight: 0, + scaledCharLeft: 0, + scaledCharTop: 0, + scaledCanvasWidth: 0, + scaledCanvasHeight: 0, + canvasWidth: 0, + canvasHeight: 0, + actualCellWidth: 0, + actualCellHeight: 0 + }; + refreshRows(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + resize(cols: number, rows: number): void { + throw new Error('Method not implemented.'); + } + changeOptions(): void { + throw new Error('Method not implemented.'); + } + setRenderer(renderer: IRenderer): void { + throw new Error('Method not implemented.'); + } + setColors(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + onDevicePixelRatioChange(): void { + throw new Error('Method not implemented.'); + } + onResize(cols: number, rows: number): void { + throw new Error('Method not implemented.'); + } + onCharSizeChanged(): void { + throw new Error('Method not implemented.'); + } + onBlur(): void { + throw new Error('Method not implemented.'); + } + onFocus(): void { + throw new Error('Method not implemented.'); + } + onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + throw new Error('Method not implemented.'); + } + onCursorMove(): void { + throw new Error('Method not implemented.'); + } + clear(): void { + throw new Error('Method not implemented.'); + } + registerCharacterJoiner(handler: CharacterJoinerHandler): number { + throw new Error('Method not implemented.'); + } + deregisterCharacterJoiner(joinerId: number): boolean { + throw new Error('Method not implemented.'); + } + dispose(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/src/browser/services/SelectionService.test.ts b/src/browser/services/SelectionService.test.ts index 62ca38193..cd787531d 100644 --- a/src/browser/services/SelectionService.test.ts +++ b/src/browser/services/SelectionService.test.ts @@ -10,16 +10,18 @@ import { IBufferLine } from 'common/Types'; import { MockBufferService, MockOptionsService, MockCoreService } from 'common/TestUtils.test'; import { BufferLine } from 'common/buffer/BufferLine'; import { IBufferService, IOptionsService } from 'common/services/Services'; -import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test'; +import { MockMouseService, MockRenderService } from 'browser/TestUtils.test'; import { CellData } from 'common/buffer/CellData'; import { IBuffer } from 'common/buffer/Types'; +import { IRenderService } from 'browser/services/Services'; class TestSelectionService extends SelectionService { constructor( bufferService: IBufferService, - optionsService: IOptionsService + optionsService: IOptionsService, + renderService: IRenderService ) { - super(() => {}, null!, null!, new MockCharSizeService(10, 10), bufferService, new MockCoreService(), new MockMouseService(), optionsService); + super(() => {}, null!, null!, bufferService, new MockCoreService(), new MockMouseService(), optionsService, renderService); } public get model(): SelectionModel { return this._model; } @@ -46,7 +48,10 @@ describe('SelectionService', () => { optionsService = new MockOptionsService(); bufferService = new MockBufferService(20, 20, optionsService); buffer = bufferService.buffer; - selectionService = new TestSelectionService(bufferService, optionsService); + const renderService = new MockRenderService(); + renderService.dimensions.canvasHeight = 10 * 20; + renderService.dimensions.canvasWidth = 10 * 20; + selectionService = new TestSelectionService(bufferService, optionsService, renderService); }); function stringToRow(text: string): IBufferLine { diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index f2f46a94c..45424d164 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -10,7 +10,7 @@ import * as Browser from 'common/Platform'; import { SelectionModel } from 'browser/selection/SelectionModel'; import { CellData } from 'common/buffer/CellData'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { ICharSizeService, IMouseService, ISelectionService } from 'browser/services/Services'; +import { ICharSizeService, IMouseService, ISelectionService, IRenderService } from 'browser/services/Services'; import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services'; import { getCoordsRelativeToElement } from 'browser/input/Mouse'; import { moveToCellSequence } from 'browser/input/MoveToCell'; @@ -116,11 +116,11 @@ export class SelectionService implements ISelectionService { private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void, private readonly _element: HTMLElement, private readonly _screenElement: HTMLElement, - @ICharSizeService private readonly _charSizeService: ICharSizeService, @IBufferService private readonly _bufferService: IBufferService, @ICoreService private readonly _coreService: ICoreService, @IMouseService private readonly _mouseService: IMouseService, - @IOptionsService private readonly _optionsService: IOptionsService + @IOptionsService private readonly _optionsService: IOptionsService, + @IRenderService private readonly _renderService: IRenderService ) { // Init listeners this._mouseMoveListener = event => this._onMouseMove(event); @@ -374,7 +374,7 @@ export class SelectionService implements ISelectionService { */ private _getMouseEventScrollAmount(event: MouseEvent): number { let offset = getCoordsRelativeToElement(event, this._screenElement)[1]; - const terminalHeight = this._bufferService.rows * Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight); + const terminalHeight = this._renderService.dimensions.canvasHeight; if (offset >= 0 && offset <= terminalHeight) { return 0; } From 3408a0537f6c89d2155c933669830455c6562012 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 11 Apr 2020 07:22:20 -0700 Subject: [PATCH 026/130] Add linkTooltipHoverDuration setting Fixes #2822 --- src/browser/MouseZoneManager.ts | 9 ++++----- src/common/services/OptionsService.ts | 1 + src/common/services/Services.ts | 1 + typings/xterm.d.ts | 11 +++++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/browser/MouseZoneManager.ts b/src/browser/MouseZoneManager.ts index d697c1334..59b6b0f1d 100644 --- a/src/browser/MouseZoneManager.ts +++ b/src/browser/MouseZoneManager.ts @@ -7,9 +7,7 @@ import { Disposable } from 'common/Lifecycle'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { IMouseService, ISelectionService } from 'browser/services/Services'; import { IMouseZoneManager, IMouseZone } from 'browser/Types'; -import { IBufferService } from 'common/services/Services'; - -const HOVER_DURATION = 500; +import { IBufferService, IOptionsService } from 'common/services/Services'; /** * The MouseZoneManager allows components to register zones within the terminal @@ -37,7 +35,8 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager { private readonly _screenElement: HTMLElement, @IBufferService private readonly _bufferService: IBufferService, @IMouseService private readonly _mouseService: IMouseService, - @ISelectionService private readonly _selectionService: ISelectionService + @ISelectionService private readonly _selectionService: ISelectionService, + @IOptionsService private readonly _optionsService: IOptionsService ) { super(); @@ -151,7 +150,7 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager { } // Restart the tooltip timeout - this._tooltipTimeout = setTimeout(() => this._onTooltip(e), HOVER_DURATION); + this._tooltipTimeout = window.setTimeout(() => this._onTooltip(e), this._optionsService.options.linkTooltipHoverDuration); } private _onTooltip(e: MouseEvent): void { diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 44a55d33d..614eee3a1 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -31,6 +31,7 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ fontWeight: 'normal', fontWeightBold: 'bold', lineHeight: 1.0, + linkTooltipHoverDuration: 500, letterSpacing: 0, logLevel: 'info', scrollback: 1000, diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index fc9f9e203..0f3ab374f 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -262,6 +262,7 @@ export interface ITerminalOptions { fontWeightBold: FontWeight; letterSpacing: number; lineHeight: number; + linkTooltipHoverDuration: number; logLevel: LogLevel; macOptionIsMeta: boolean; macOptionClickForcesSelection: boolean; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 9445d0754..9a06448c8 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -118,7 +118,7 @@ declare module 'xterm' { fontWeightBold?: FontWeight; /** - * The spacing in whole pixels between characters.. + * The spacing in whole pixels between characters. */ letterSpacing?: number; @@ -127,6 +127,12 @@ declare module 'xterm' { */ lineHeight?: number; + /** + * The duration in milliseconds before link tooltip events fire when + * hovering on a link. + */ + linkTooltipHoverDuration?: number; + /** * What log level to use, this will log for all levels below and including * what is set: @@ -305,7 +311,8 @@ declare module 'xterm' { validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void; /** - * A callback that fires when the mouse hovers over a link for a moment. + * A callback that fires when the mouse hovers over a link for a period of + * time (defined by {@link ITerminalOptions.linkTooltipHoverDuration}). */ tooltipCallback?: (event: MouseEvent, uri: string, location: IViewportRange) => boolean | void; From f070be8dd347041cf26c676cd7bf921dbcda71c4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 11 Apr 2020 07:23:53 -0700 Subject: [PATCH 027/130] Add deprecated with explanation --- typings/xterm.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 9a06448c8..79379058c 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -130,6 +130,7 @@ declare module 'xterm' { /** * The duration in milliseconds before link tooltip events fire when * hovering on a link. + * @deprecated This will be removed when the link matcher API is removed. */ linkTooltipHoverDuration?: number; From df7ba37d57a5a4a548a1fec627eb9f8147d77473 Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Sat, 11 Apr 2020 21:15:24 +0530 Subject: [PATCH 028/130] Update args parser to allow flag values --- bin/test_api.js | 5 ++++- package.json | 7 +++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/bin/test_api.js b/bin/test_api.js index 2eb3fc3e1..38e9af3e8 100644 --- a/bin/test_api.js +++ b/bin/test_api.js @@ -21,7 +21,8 @@ let flagArgs = []; if (process.argv.length > 2) { const args = process.argv.slice(2); - flagArgs = args.filter(e => e.startsWith('--')); + flagArgs = args.filter(e => e.startsWith('--')).flatMap(arg => arg.split('=')); + console.info(flagArgs); // ability to inject particular test files via // yarn test [testFileA testFileB ...] files = args.filter(e => !e.startsWith('--')); @@ -30,6 +31,8 @@ if (process.argv.length > 2) { } } + + env.DEBUG = flagArgs.indexOf('--debug') >= 0 ? 'debug' : ''; const run = cp.spawnSync( diff --git a/package.json b/package.json index 535712dbf..31771a888 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,10 @@ "lint": "eslint -c .eslintrc.json --ext .ts src/ addons/", "test": "npm run test-unit", "posttest": "npm run lint", - "api-test": "node ./bin/test_api.js", "test-api": "npm run test-api-chromium", - "test-api-chromium": "mocha \"**/*.api.js\" --browser chromium --timeout 20000", - "test-api-firefox": "mocha \"**/*.api.js\" --browser firefox --timeout 20000", - "test-api-webkit": "mocha \"**/*.api.js\" --browser webkit --timeout 20000", + "test-api-chromium": "node ./bin/test_api.js --browser=chromium --timeout=20000", + "test-api-firefox": "node ./bin/test_api.js --browser=firefox --timeout=20000", + "test-api-webkit": "node ./bin/test_api.js --browser=webkit --timeout=20000", "pretest-api-chromium": "node ./bin/download_browser.js --browser chromium", "pretest-api-firefox": "node ./bin/download_browser.js --browser firefox", "pretest-api-webkit": "node ./bin/download_browser.js --browser webkit", From 55f9203f60e8e74557a536c8efcf3c4e504ae9db Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 11 Apr 2020 09:51:28 -0700 Subject: [PATCH 029/130] Only fire IRenderService.onRender when buffer changes occurred Fixes #2836 --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 10 +++++----- .../src/renderLayer/CursorRenderLayer.ts | 4 ++-- src/TestUtils.test.ts | 4 ++-- src/browser/Linkifier2.ts | 4 ++-- src/browser/renderer/CursorRenderLayer.ts | 10 +++++----- src/browser/renderer/Renderer.ts | 8 ++++---- src/browser/renderer/Types.d.ts | 8 ++++++-- src/browser/renderer/dom/DomRenderer.ts | 5 ++--- src/browser/services/RenderService.ts | 15 +++++++++++---- src/browser/services/Services.ts | 4 ++++ 10 files changed, 43 insertions(+), 29 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index b06ff3c38..8d52a35e6 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -16,7 +16,7 @@ import { Disposable } from 'common/Lifecycle'; import { NULL_CELL_CODE } from 'common/buffer/Constants'; import { Terminal, IEvent } from 'xterm'; import { IRenderLayer } from './renderLayer/Types'; -import { IRenderDimensions, IRenderer, IRequestRefreshRowsEvent } from 'browser/renderer/Types'; +import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types'; import { IColorSet } from 'browser/Types'; import { EventEmitter } from 'common/EventEmitter'; import { CellData } from 'common/buffer/CellData'; @@ -39,8 +39,8 @@ export class WebglRenderer extends Disposable implements IRenderer { private _core: ITerminal; private _isAttached: boolean; - private _onRequestRefreshRows = new EventEmitter(); - public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; } + private _onRequestRedraw = new EventEmitter(); + public get onRequestRedraw(): IEvent { return this._onRequestRedraw.event; } constructor( private _terminal: Terminal, @@ -53,7 +53,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._renderLayers = [ new LinkRenderLayer(this._core.screenElement, 2, this._colors, this._core), - new CursorRenderLayer(this._core.screenElement, 3, this._colors, this._onRequestRefreshRows) + new CursorRenderLayer(this._core.screenElement, 3, this._colors, this._onRequestRedraw) ]; this.dimensions = { scaledCharWidth: 0, @@ -178,7 +178,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._rectangleRenderer.updateSelection(this._model.selection, columnSelectMode); this._glyphRenderer.updateSelection(this._model, columnSelectMode); - this._onRequestRefreshRows.fire({ start: 0, end: this._terminal.rows - 1 }); + this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 }); } public onCursorMove(): void { diff --git a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts index 75201f47d..b2e834d30 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts @@ -8,7 +8,7 @@ import { BaseRenderLayer } from './BaseRenderLayer'; import { ICellData } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; import { IColorSet } from 'browser/Types'; -import { IRenderDimensions, IRequestRefreshRowsEvent } from 'browser/renderer/Types'; +import { IRenderDimensions, IRequestRedrawEvent } from 'browser/renderer/Types'; import { IEventEmitter } from 'common/EventEmitter'; interface ICursorState { @@ -34,7 +34,7 @@ export class CursorRenderLayer extends BaseRenderLayer { container: HTMLElement, zIndex: number, colors: IColorSet, - private _onRequestRefreshRowsEvent: IEventEmitter + private _onRequestRefreshRowsEvent: IEventEmitter ) { super(container, 'cursor', zIndex, true, colors); this._state = { diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 5d8347abb..9f0b2701c 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRefreshRowsEvent } from 'browser/renderer/Types'; +import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions } from './Types'; import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset } from 'common/Types'; @@ -281,7 +281,7 @@ export class MockBuffer implements IBuffer { } export class MockRenderer implements IRenderer { - onRequestRefreshRows: IEvent; + onRequestRedraw: IEvent; onCanvasResize: IEvent<{ width: number, height: number }>; onRender: IEvent<{ start: number, end: number }>; dispose(): void { diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 893677188..1a076bc55 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -50,7 +50,7 @@ export class Linkifier2 implements ILinkifier2 { this._renderService = renderService; this._element.addEventListener('mousemove', this._onMouseMove.bind(this)); - this._element.addEventListener('click', this._onMouseDown.bind(this)); + this._element.addEventListener('click', this._onClick.bind(this)); } private _onMouseMove(event: MouseEvent): void { @@ -125,7 +125,7 @@ export class Linkifier2 implements ILinkifier2 { }); } - private _onMouseDown(event: MouseEvent): void { + private _onClick(event: MouseEvent): void { if (!this._element || !this._mouseService || !this._currentLink) { return; } diff --git a/src/browser/renderer/CursorRenderLayer.ts b/src/browser/renderer/CursorRenderLayer.ts index 607180ae0..123075c66 100644 --- a/src/browser/renderer/CursorRenderLayer.ts +++ b/src/browser/renderer/CursorRenderLayer.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IRenderDimensions, IRequestRefreshRowsEvent } from 'browser/renderer/Types'; +import { IRenderDimensions, IRequestRedrawEvent } from 'browser/renderer/Types'; import { BaseRenderLayer } from 'browser/renderer/BaseRenderLayer'; import { ICellData } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; @@ -36,7 +36,7 @@ export class CursorRenderLayer extends BaseRenderLayer { zIndex: number, colors: IColorSet, rendererId: number, - private _onRequestRefreshRowsEvent: IEventEmitter, + private _onRequestRedraw: IEventEmitter, readonly bufferService: IBufferService, readonly optionsService: IOptionsService, private readonly _coreService: ICoreService, @@ -83,14 +83,14 @@ export class CursorRenderLayer extends BaseRenderLayer { if (this._cursorBlinkStateManager) { this._cursorBlinkStateManager.pause(); } - this._onRequestRefreshRowsEvent.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y }); + this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y }); } public onFocus(): void { if (this._cursorBlinkStateManager) { this._cursorBlinkStateManager.resume(); } else { - this._onRequestRefreshRowsEvent.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y }); + this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y }); } } @@ -107,7 +107,7 @@ export class CursorRenderLayer extends BaseRenderLayer { } // Request a refresh from the terminal as management of rendering is being // moved back to the terminal - this._onRequestRefreshRowsEvent.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y }); + this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y }); } public onCursorMove(): void { diff --git a/src/browser/renderer/Renderer.ts b/src/browser/renderer/Renderer.ts index a1161d4f2..4259add4e 100644 --- a/src/browser/renderer/Renderer.ts +++ b/src/browser/renderer/Renderer.ts @@ -6,7 +6,7 @@ import { TextRenderLayer } from 'browser/renderer/TextRenderLayer'; import { SelectionRenderLayer } from 'browser/renderer/SelectionRenderLayer'; import { CursorRenderLayer } from 'browser/renderer/CursorRenderLayer'; -import { IRenderLayer, IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry, IRequestRefreshRowsEvent } from 'browser/renderer/Types'; +import { IRenderLayer, IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry, IRequestRedrawEvent } from 'browser/renderer/Types'; import { LinkRenderLayer } from 'browser/renderer/LinkRenderLayer'; import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry'; import { Disposable } from 'common/Lifecycle'; @@ -27,8 +27,8 @@ export class Renderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - private _onRequestRefreshRows = new EventEmitter(); - public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; } + private _onRequestRedraw = new EventEmitter(); + public get onRequestRedraw(): IEvent { return this._onRequestRedraw.event; } constructor( private _colors: IColorSet, @@ -49,7 +49,7 @@ export class Renderer extends Disposable implements IRenderer { new TextRenderLayer(this._screenElement, 0, this._colors, this._characterJoinerRegistry, allowTransparency, this._id, this._bufferService, _optionsService), new SelectionRenderLayer(this._screenElement, 1, this._colors, this._id, this._bufferService, _optionsService), new LinkRenderLayer(this._screenElement, 2, this._colors, this._id, linkifier, linkifier2, this._bufferService, _optionsService), - new CursorRenderLayer(this._screenElement, 3, this._colors, this._id, this._onRequestRefreshRows, this._bufferService, _optionsService, coreService, coreBrowserService) + new CursorRenderLayer(this._screenElement, 3, this._colors, this._id, this._onRequestRedraw, this._bufferService, _optionsService, coreService, coreBrowserService) ]; this.dimensions = { scaledCharWidth: 0, diff --git a/src/browser/renderer/Types.d.ts b/src/browser/renderer/Types.d.ts index b4c321a19..02c62ab2e 100644 --- a/src/browser/renderer/Types.d.ts +++ b/src/browser/renderer/Types.d.ts @@ -24,7 +24,7 @@ export interface IRenderDimensions { actualCellHeight: number; } -export interface IRequestRefreshRowsEvent { +export interface IRequestRedrawEvent { start: number; end: number; } @@ -36,7 +36,11 @@ export interface IRequestRefreshRowsEvent { export interface IRenderer extends IDisposable { readonly dimensions: IRenderDimensions; - readonly onRequestRefreshRows: IEvent; + /** + * Fires when the renderer is requesting to be redrawn on the next animation + * frame but is _not_ a result of content changing (eg. selection changes). + */ + readonly onRequestRedraw: IEvent; dispose(): void; setColors(colors: IColorSet): void; diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index f8ad717bd..a2e370fc4 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRefreshRowsEvent } from 'browser/renderer/Types'; +import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory'; import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { Disposable } from 'common/Lifecycle'; @@ -39,8 +39,7 @@ export class DomRenderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - private _onRequestRefreshRows = new EventEmitter(); - public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; } + public get onRequestRedraw(): IEvent { return new EventEmitter().event; } constructor( private _colors: IColorSet, diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 2949c2c50..4d195585f 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -21,6 +21,7 @@ export class RenderService extends Disposable implements IRenderService { private _isPaused: boolean = false; private _needsFullRefresh: boolean = false; + private _isNextRenderRedrawOnly: boolean = true; private _canvasWidth: number = 0; private _canvasHeight: number = 0; @@ -52,7 +53,7 @@ export class RenderService extends Disposable implements IRenderService { this.register(charSizeService.onCharSizeChange(() => this.onCharSizeChanged())); // No need to register this as renderer is explicitly disposed in RenderService.dispose - this._renderer.onRequestRefreshRows(e => this.refreshRows(e.start, e.end)); + this._renderer.onRequestRedraw(e => this.refreshRows(e.start, e.end, true)); // dprchange should handle this case, we need this as well for browsers that don't support the // matchMedia query. @@ -75,17 +76,23 @@ export class RenderService extends Disposable implements IRenderService { } } - public refreshRows(start: number, end: number): void { + public refreshRows(start: number, end: number, isRedrawOnly: boolean = false): void { if (this._isPaused) { this._needsFullRefresh = true; return; } + if (!isRedrawOnly) { + this._isNextRenderRedrawOnly = false; + } this._renderDebouncer.refresh(start, end, this._rowCount); } private _renderRows(start: number, end: number): void { this._renderer.renderRows(start, end); - this._onRender.fire({ start, end }); + if (!this._isNextRenderRedrawOnly) { + this._onRender.fire({ start, end }); + } + this._isNextRenderRedrawOnly = true; } public resize(cols: number, rows: number): void { @@ -116,7 +123,7 @@ export class RenderService extends Disposable implements IRenderService { // TODO: RenderService should be the only one to dispose the renderer this._renderer.dispose(); this._renderer = renderer; - this._renderer.onRequestRefreshRows(e => this.refreshRows(e.start, e.end)); + this._renderer.onRequestRedraw(e => this.refreshRows(e.start, e.end, true)); this.refreshRows(0, this._rowCount - 1); } diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index 785fec34e..e79d0c9f7 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -43,6 +43,10 @@ export interface IRenderService extends IDisposable { serviceBrand: any; onDimensionsChange: IEvent; + /** + * Fires when buffer changes are rendered. This does not fire when only cursor + * or selections are rendered. + */ onRender: IEvent<{ start: number, end: number }>; onRefreshRequest: IEvent<{ start: number, end: number }>; From 309bdf3d7085107b698ba44d58b2c602e7ed8812 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 11 Apr 2020 09:53:22 -0700 Subject: [PATCH 030/130] Rename onRender --- src/Terminal.ts | 2 +- src/browser/Linkifier2.ts | 2 +- src/browser/TestUtils.test.ts | 2 +- src/browser/services/RenderService.ts | 2 +- src/browser/services/Services.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index ee2261151..ea6898775 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -543,7 +543,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp const renderer = this._createRenderer(); this._renderService = this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement); this._instantiationService.setService(IRenderService, this._renderService); - this._renderService.onRender(e => this._onRender.fire(e)); + this._renderService.onRenderedBufferChange(e => this._onRender.fire(e)); this.onResize(e => this._renderService.resize(e.cols, e.rows)); this._soundService = this._instantiationService.createInstance(SoundService); diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 1a076bc55..7030e5d2b 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -173,7 +173,7 @@ export class Linkifier2 implements ILinkifier2 { // Add listener for rerendering if (this._renderService) { - this._linkCacheDisposables.push(this._renderService.onRender(e => { + this._linkCacheDisposables.push(this._renderService.onRenderedBufferChange(e => { this._clearCurrentLink(e.start + 1 + this._bufferService.buffer.ydisp, e.end + 1 + this._bufferService.buffer.ydisp); })); } diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 3e304bcfc..6ca12d9c3 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -30,7 +30,7 @@ export class MockMouseService implements IMouseService { export class MockRenderService implements IRenderService { serviceBrand: any; onDimensionsChange: IEvent = new EventEmitter().event; - onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; + onRenderedBufferChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; dimensions: IRenderDimensions = { scaledCharWidth: 0, diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 4d195585f..1413f0d30 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -28,7 +28,7 @@ export class RenderService extends Disposable implements IRenderService { private _onDimensionsChange = new EventEmitter(); public get onDimensionsChange(): IEvent { return this._onDimensionsChange.event; } private _onRender = new EventEmitter<{ start: number, end: number }>(); - public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } + public get onRenderedBufferChange(): IEvent<{ start: number, end: number }> { return this._onRender.event; } private _onRefreshRequest = new EventEmitter<{ start: number, end: number }>(); public get onRefreshRequest(): IEvent<{ start: number, end: number }> { return this._onRefreshRequest.event; } diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index e79d0c9f7..3754e6fed 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -47,7 +47,7 @@ export interface IRenderService extends IDisposable { * Fires when buffer changes are rendered. This does not fire when only cursor * or selections are rendered. */ - onRender: IEvent<{ start: number, end: number }>; + onRenderedBufferChange: IEvent<{ start: number, end: number }>; onRefreshRequest: IEvent<{ start: number, end: number }>; dimensions: IRenderDimensions; From f5c4c3e45049a9e900149e874da290a31fc4b0e4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2020 08:19:05 +0000 Subject: [PATCH 031/130] Bump @types/webpack from 4.41.10 to 4.41.11 Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.10 to 4.41.11. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index df6208c8c..d997a6877 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "@types/mocha": "^7.0.2", "@types/node": "^10.17.17", "@types/utf8": "^2.1.6", - "@types/webpack": "^4.41.10", + "@types/webpack": "^4.41.11", "@types/ws": "^7.2.3", "@typescript-eslint/eslint-plugin": "^2.27.0", "@typescript-eslint/parser": "^2.27.0", diff --git a/yarn.lock b/yarn.lock index fb86558ba..340abff7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -352,10 +352,10 @@ "@types/source-list-map" "*" source-map "^0.6.1" -"@types/webpack@^4.41.10": - version "4.41.10" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.10.tgz#2e1f6b3508a249854efe3dcc7690905ac5ee10be" - integrity sha512-vIy0qaq8AjOjZLuFPqpo7nAJzcoVXMdw3mvpNN07Uvdy0p1IpJeLNBe3obdRP7FX2jIusDE7z1pZa0A6qYUgnA== +"@types/webpack@^4.41.11": + version "4.41.11" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.11.tgz#7b7f725397d3b630bede05415d34e9ff30d9771f" + integrity sha512-PtEZISfBMWL05qOpZN19hztZPt0rPuGQh5sbBP3bB4RrJgzdb0SScn47hdcMaoN1IgaU7NZWeDO6reFcKTK2iQ== dependencies: "@types/anymatch" "*" "@types/node" "*" From c396518736c6ab88d27c0ecf933a4c340299486f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2020 12:34:17 +0000 Subject: [PATCH 032/130] Bump @types/jsdom from 16.2.0 to 16.2.1 Bumps [@types/jsdom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsdom) from 16.2.0 to 16.2.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsdom) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d997a6877..83b1bc4db 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@types/debug": "^4.1.5", "@types/deep-equal": "^1.0.1", "@types/glob": "^7.1.1", - "@types/jsdom": "^16.2.0", + "@types/jsdom": "^16.2.1", "@types/mocha": "^7.0.2", "@types/node": "^10.17.17", "@types/utf8": "^2.1.6", diff --git a/yarn.lock b/yarn.lock index 340abff7b..616cbe5cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -253,10 +253,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/jsdom@^16.2.0": - version "16.2.0" - resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.0.tgz#5a371a2efc1e0feec02c4bd2b3ce689e6ae691a2" - integrity sha512-I+qrFCzB97VlGJgvzGEwcUqmajpwqwTalmMvVfgJqFRVsY80lcCEQEGLJuVvge+whQyB1xcqTstAdxJshVVq0g== +"@types/jsdom@^16.2.1": + version "16.2.1" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.1.tgz#9e6eee6a578f74eed5997558ab430dbc11aac753" + integrity sha512-KCEq427OsWfpX7FRyEMb3i2XIuz8Pt3XPls4nmX0iMTDJWsHD4Kzoa3v4Uv9c9IDf11ALeHUtPcyAjTz/HV03Q== dependencies: "@types/node" "*" "@types/parse5" "*" From 1f4b2607cca815ffb72f3e6e37af06202c6facc2 Mon Sep 17 00:00:00 2001 From: kumaran-14 Date: Mon, 13 Apr 2020 22:36:33 +0530 Subject: [PATCH 033/130] Replace flatMap method with reduce and map --- bin/test_api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/test_api.js b/bin/test_api.js index 38e9af3e8..1f40363f7 100644 --- a/bin/test_api.js +++ b/bin/test_api.js @@ -21,7 +21,7 @@ let flagArgs = []; if (process.argv.length > 2) { const args = process.argv.slice(2); - flagArgs = args.filter(e => e.startsWith('--')).flatMap(arg => arg.split('=')); + flagArgs = args.filter(e => e.startsWith('--')).map(arg => arg.split('=')).reduce((arr, val) => arr.concat([...val], [])); console.info(flagArgs); // ability to inject particular test files via // yarn test [testFileA testFileB ...] From f8f9c06ed8db5fa485d5f3efe300e2c9fbdb819c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2020 08:14:38 +0000 Subject: [PATCH 034/130] Bump @types/ws from 7.2.3 to 7.2.4 Bumps [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) from 7.2.3 to 7.2.4. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 83b1bc4db..388d468b9 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@types/node": "^10.17.17", "@types/utf8": "^2.1.6", "@types/webpack": "^4.41.11", - "@types/ws": "^7.2.3", + "@types/ws": "^7.2.4", "@typescript-eslint/eslint-plugin": "^2.27.0", "@typescript-eslint/parser": "^2.27.0", "chai": "^4.2.0", diff --git a/yarn.lock b/yarn.lock index 616cbe5cf..a17b12f78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -364,10 +364,10 @@ "@types/webpack-sources" "*" source-map "^0.6.0" -"@types/ws@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.2.3.tgz#a3add56077ac6cc9396b9502c7252a1635922032" - integrity sha512-VT/GK7nvDA7lfHy40G3LKM+ICqmdIsBLBHGXcWD97MtqQEjNMX+7Gudo8YGpaSlYdTX7IFThhCE8Jx09HegymQ== +"@types/ws@^7.2.4": + version "7.2.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.2.4.tgz#b3859f7b9c243b220efac9716ec42c716a72969d" + integrity sha512-9S6Ask71vujkVyeEXKxjBSUV8ZUB0mjL5la4IncBoheu04bDaYyUKErh1BQcY9+WzOUOiKqz/OnpJHYckbMfNg== dependencies: "@types/node" "*" From 04c1e4b57db860b7b55d8a8033ada6b08a9b5050 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 14 Apr 2020 06:03:31 -0700 Subject: [PATCH 035/130] Remove readonly from ctors --- src/browser/renderer/CursorRenderLayer.ts | 4 ++-- src/browser/renderer/LinkRenderLayer.ts | 4 ++-- src/browser/renderer/Renderer.ts | 8 ++++---- src/browser/renderer/SelectionRenderLayer.ts | 4 ++-- src/browser/services/RenderService.ts | 6 +++--- src/common/buffer/AttributeData.ts | 1 + src/common/buffer/BufferSet.ts | 4 ++-- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/browser/renderer/CursorRenderLayer.ts b/src/browser/renderer/CursorRenderLayer.ts index 607180ae0..bab785073 100644 --- a/src/browser/renderer/CursorRenderLayer.ts +++ b/src/browser/renderer/CursorRenderLayer.ts @@ -37,8 +37,8 @@ export class CursorRenderLayer extends BaseRenderLayer { colors: IColorSet, rendererId: number, private _onRequestRefreshRowsEvent: IEventEmitter, - readonly bufferService: IBufferService, - readonly optionsService: IOptionsService, + bufferService: IBufferService, + optionsService: IOptionsService, private readonly _coreService: ICoreService, private readonly _coreBrowserService: ICoreBrowserService ) { diff --git a/src/browser/renderer/LinkRenderLayer.ts b/src/browser/renderer/LinkRenderLayer.ts index 73e9f85f0..33f80cdc3 100644 --- a/src/browser/renderer/LinkRenderLayer.ts +++ b/src/browser/renderer/LinkRenderLayer.ts @@ -20,8 +20,8 @@ export class LinkRenderLayer extends BaseRenderLayer { rendererId: number, linkifier: ILinkifier, linkifier2: ILinkifier2, - readonly bufferService: IBufferService, - readonly optionsService: IOptionsService + bufferService: IBufferService, + optionsService: IOptionsService ) { super(container, 'link', zIndex, true, colors, rendererId, bufferService, optionsService); linkifier.onLinkHover(e => this._onLinkHover(e)); diff --git a/src/browser/renderer/Renderer.ts b/src/browser/renderer/Renderer.ts index a1161d4f2..4b982f9c8 100644 --- a/src/browser/renderer/Renderer.ts +++ b/src/browser/renderer/Renderer.ts @@ -33,13 +33,13 @@ export class Renderer extends Disposable implements IRenderer { constructor( private _colors: IColorSet, private readonly _screenElement: HTMLElement, - readonly linkifier: ILinkifier, - readonly linkifier2: ILinkifier2, + linkifier: ILinkifier, + linkifier2: ILinkifier2, @IBufferService private readonly _bufferService: IBufferService, @ICharSizeService private readonly _charSizeService: ICharSizeService, @IOptionsService private readonly _optionsService: IOptionsService, - @ICoreService readonly coreService: ICoreService, - @ICoreBrowserService readonly coreBrowserService: ICoreBrowserService + @ICoreService coreService: ICoreService, + @ICoreBrowserService coreBrowserService: ICoreBrowserService ) { super(); const allowTransparency = this._optionsService.options.allowTransparency; diff --git a/src/browser/renderer/SelectionRenderLayer.ts b/src/browser/renderer/SelectionRenderLayer.ts index 5cd2fd913..257944fcb 100644 --- a/src/browser/renderer/SelectionRenderLayer.ts +++ b/src/browser/renderer/SelectionRenderLayer.ts @@ -23,8 +23,8 @@ export class SelectionRenderLayer extends BaseRenderLayer { zIndex: number, colors: IColorSet, rendererId: number, - readonly bufferService: IBufferService, - readonly optionsService: IOptionsService + bufferService: IBufferService, + optionsService: IOptionsService ) { super(container, 'selection', zIndex, true, colors, rendererId, bufferService, optionsService); this._clearState(); diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 2949c2c50..03db0a854 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -36,9 +36,9 @@ export class RenderService extends Disposable implements IRenderService { constructor( private _renderer: IRenderer, private _rowCount: number, - readonly screenElement: HTMLElement, - @IOptionsService readonly optionsService: IOptionsService, - @ICharSizeService readonly charSizeService: ICharSizeService + screenElement: HTMLElement, + @IOptionsService optionsService: IOptionsService, + @ICharSizeService charSizeService: ICharSizeService ) { super(); this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end)); diff --git a/src/common/buffer/AttributeData.ts b/src/common/buffer/AttributeData.ts index 0b2679ee4..22e9d2b84 100644 --- a/src/common/buffer/AttributeData.ts +++ b/src/common/buffer/AttributeData.ts @@ -14,6 +14,7 @@ export class AttributeData implements IAttributeData { value & 255 ]; } + static fromColorRGB(value: IColorRGB): number { return (value[0] & 255) << Attributes.RED_SHIFT | (value[1] & 255) << Attributes.GREEN_SHIFT | value[2] & 255; } diff --git a/src/common/buffer/BufferSet.ts b/src/common/buffer/BufferSet.ts index 50e6e5050..26fc1d09f 100644 --- a/src/common/buffer/BufferSet.ts +++ b/src/common/buffer/BufferSet.ts @@ -27,8 +27,8 @@ export class BufferSet implements IBufferSet { * @param _terminal - The terminal the BufferSet will belong to */ constructor( - readonly optionsService: IOptionsService, - readonly bufferService: IBufferService + optionsService: IOptionsService, + bufferService: IBufferService ) { this._normal = new Buffer(true, optionsService, bufferService); this._normal.fillViewportRows(); From a5ebb6d98c74402ee5bfcc5c31333a073fb9b3f1 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 14 Apr 2020 06:03:47 -0700 Subject: [PATCH 036/130] Add member access eslint rule --- .eslintrc.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.eslintrc.json b/.eslintrc.json index 5d5061d55..41767bedf 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -45,6 +45,15 @@ "allowExpressions": true } ], + "@typescript-eslint/explicit-member-accessibility": [ + "error", + { + "accessibility": "explicit", + "overrides": { + "constructors": "off" + } + } + ], "@typescript-eslint/indent": [ "error", 2 From 05f1959c83826aa88bd411b2279defddda795327 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:08:53 +0000 Subject: [PATCH 037/130] Bump @typescript-eslint/eslint-plugin from 2.27.0 to 2.28.0 Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.27.0 to 2.28.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.28.0/packages/eslint-plugin) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 388d468b9..fd14131bb 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@types/utf8": "^2.1.6", "@types/webpack": "^4.41.11", "@types/ws": "^7.2.4", - "@typescript-eslint/eslint-plugin": "^2.27.0", + "@typescript-eslint/eslint-plugin": "^2.28.0", "@typescript-eslint/parser": "^2.27.0", "chai": "^4.2.0", "deep-equal": "^2.0.2", diff --git a/yarn.lock b/yarn.lock index a17b12f78..aa9a404c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -371,12 +371,12 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.27.0.tgz#e479cdc4c9cf46f96b4c287755733311b0d0ba4b" - integrity sha512-/my+vVHRN7zYgcp0n4z5A6HAK7bvKGBiswaM5zIlOQczsxj/aiD7RcgD+dvVFuwFaGh5+kM7XA6Q6PN0bvb1tw== +"@typescript-eslint/eslint-plugin@^2.28.0": + version "2.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz#4431bc6d3af41903e5255770703d4e55a0ccbdec" + integrity sha512-w0Ugcq2iatloEabQP56BRWJowliXUP5Wv6f9fKzjJmDW81hOTBxRoJ4LoEOxRpz9gcY51Libytd2ba3yLmSOfg== dependencies: - "@typescript-eslint/experimental-utils" "2.27.0" + "@typescript-eslint/experimental-utils" "2.28.0" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" tsutils "^3.17.1" @@ -391,6 +391,16 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" +"@typescript-eslint/experimental-utils@2.28.0": + version "2.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d" + integrity sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.28.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + "@typescript-eslint/parser@^2.27.0": version "2.27.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.27.0.tgz#d91664335b2c46584294e42eb4ff35838c427287" @@ -414,6 +424,19 @@ semver "^6.3.0" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@2.28.0": + version "2.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00" + integrity sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" From 9817754f92519322bec076b56644f5ec8c0e597a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 14 Apr 2020 06:23:11 -0700 Subject: [PATCH 038/130] Fix explicit access --- .../benchmark/SerializeAddon.benchmark.ts | 2 +- .../src/SerializeAddon.ts | 2 +- .../src/WebLinkProvider.ts | 2 +- src/InputHandler.test.ts | 2 +- src/InputHandler.ts | 6 +- src/Terminal.test.ts | 6 +- src/TestUtils.test.ts | 332 +++++++++--------- src/browser/Linkifier.test.ts | 6 +- src/browser/TestUtils.test.ts | 52 +-- src/browser/renderer/TextRenderLayer.ts | 4 +- src/browser/services/CharSizeService.ts | 6 +- src/browser/services/CoreBrowserService.ts | 2 +- src/browser/services/MouseService.ts | 2 +- src/browser/services/RenderService.ts | 2 +- src/browser/services/SelectionService.ts | 2 +- src/browser/services/SoundService.ts | 4 +- src/common/TestUtils.test.ts | 104 +++--- src/common/buffer/AttributeData.ts | 6 +- src/common/input/TextDecoder.ts | 4 +- src/common/parser/DcsParser.test.ts | 6 +- .../parser/EscapeSequenceParser.test.ts | 8 +- src/common/parser/OscParser.test.ts | 6 +- src/common/services/BufferService.ts | 2 +- src/common/services/CharsetService.ts | 2 +- src/common/services/CoreService.ts | 2 +- src/common/services/DirtyRowService.ts | 2 +- src/common/services/InstantiationService.ts | 8 +- src/common/services/LogService.ts | 10 +- src/common/services/OptionsService.ts | 2 +- src/common/services/UnicodeService.test.ts | 4 +- src/public/AddonManager.test.ts | 8 +- 31 files changed, 303 insertions(+), 303 deletions(-) diff --git a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts b/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts index 3fa00c0c0..fbc16e03d 100644 --- a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts +++ b/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts @@ -11,7 +11,7 @@ import { Terminal } from 'public/Terminal'; import { SerializeAddon } from 'SerializeAddon'; class TestTerminal extends Terminal { - writeSync(data: string): void { + public writeSync(data: string): void { (this as any)._core.writeSync(data); } } diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 445c48602..d89177429 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -15,7 +15,7 @@ function constrain(value: number, low: number, high: number): number { abstract class BaseSerializeHandler { constructor(private _buffer: IBuffer) { } - serialize(startRow: number, endRow: number): string { + public serialize(startRow: number, endRow: number): string { // we need two of them to flip between old and new cell const cell1 = this._buffer.getNullCell(); const cell2 = this._buffer.getNullCell(); diff --git a/addons/xterm-addon-web-links/src/WebLinkProvider.ts b/addons/xterm-addon-web-links/src/WebLinkProvider.ts index 5f6460bf9..563108d29 100644 --- a/addons/xterm-addon-web-links/src/WebLinkProvider.ts +++ b/addons/xterm-addon-web-links/src/WebLinkProvider.ts @@ -15,7 +15,7 @@ export class WebLinkProvider implements ILinkProvider { } - provideLink(position: IBufferCellPosition, callback: (link: ILink | undefined) => void): void { + public provideLink(position: IBufferCellPosition, callback: (link: ILink | undefined) => void): void { callback(LinkComputer.computeLink(position, this._regex, this._terminal, this._handler)); } } diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 9b3320b67..84d4dae51 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -34,7 +34,7 @@ function getLines(term: TestTerminal, limit: number = term.rows): string[] { } class TestInputHandler extends InputHandler { - get curAttrData(): IAttributeData { return (this as any)._curAttrData; } + public get curAttrData(): IAttributeData { return (this as any)._curAttrData; } } describe('InputHandler', () => { diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 95738f651..3717256e8 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -137,15 +137,15 @@ class DECRQSS implements IDcsHandler { private _optionsService: IOptionsService ) { } - hook(params: IParams): void { + public hook(params: IParams): void { this._data = new Uint32Array(0); } - put(data: Uint32Array, start: number, end: number): void { + public put(data: Uint32Array, start: number, end: number): void { this._data = concat(this._data, data.subarray(start, end)); } - unhook(success: boolean): void { + public unhook(success: boolean): void { if (!success) { this._data = new Uint32Array(0); return; diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index 84879b764..e2bd4d56c 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -1416,14 +1416,14 @@ class TestLinkifier extends Linkifier { } class TestMouseZoneManager implements IMouseZoneManager { - dispose(): void { + public dispose(): void { } public clears: number = 0; public zones: IMouseZone[] = []; - add(zone: IMouseZone): void { + public add(zone: IMouseZone): void { this.zones.push(zone); } - clearAll(): void { + public clearAll(): void { this.clears++; } } diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 5d8347abb..d62de14c0 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -19,342 +19,342 @@ import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { ISelectionService } from 'browser/services/Services'; export class TestTerminal extends Terminal { - get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } - keyDown(ev: any): boolean { return this._keyDown(ev); } - keyPress(ev: any): boolean { return this._keyPress(ev); } + public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } + public keyDown(ev: any): boolean { return this._keyDown(ev); } + public keyPress(ev: any): boolean { return this._keyPress(ev); } } export class MockTerminal implements ITerminal { - onBlur: IEvent; - onFocus: IEvent; - onA11yChar: IEvent; - onA11yTab: IEvent; - onCursorMove: IEvent; - onLineFeed: IEvent; - onSelectionChange: IEvent; - onData: IEvent; - onBinary: IEvent; - onTitleChange: IEvent; - onScroll: IEvent; - onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; - onRender: IEvent<{ start: number, end: number }>; - onResize: IEvent<{ cols: number, rows: number }>; - markers: IMarker[]; - optionsService: IOptionsService; - unicodeService: IUnicodeService; - addMarker(cursorYOffset: number): IMarker { + public onBlur: IEvent; + public onFocus: IEvent; + public onA11yChar: IEvent; + public onA11yTab: IEvent; + public onCursorMove: IEvent; + public onLineFeed: IEvent; + public onSelectionChange: IEvent; + public onData: IEvent; + public onBinary: IEvent; + public onTitleChange: IEvent; + public onScroll: IEvent; + public onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; + public onRender: IEvent<{ start: number, end: number }>; + public onResize: IEvent<{ cols: number, rows: number }>; + public markers: IMarker[]; + public optionsService: IOptionsService; + public unicodeService: IUnicodeService; + public addMarker(cursorYOffset: number): IMarker { throw new Error('Method not implemented.'); } - selectLines(start: number, end: number): void { + public selectLines(start: number, end: number): void { throw new Error('Method not implemented.'); } - scrollToLine(line: number): void { + public scrollToLine(line: number): void { throw new Error('Method not implemented.'); } - static string: any; - setOption(key: any, value: any): void { + public static string: any; + public setOption(key: any, value: any): void { throw new Error('Method not implemented.'); } - blur(): void { + public blur(): void { throw new Error('Method not implemented.'); } - focus(): void { + public focus(): void { throw new Error('Method not implemented.'); } - resize(columns: number, rows: number): void { + public resize(columns: number, rows: number): void { throw new Error('Method not implemented.'); } - writeln(data: string): void { + public writeln(data: string): void { throw new Error('Method not implemented.'); } - paste(data: string): void { + public paste(data: string): void { throw new Error('Method not implemented.'); } - open(parent: HTMLElement): void { + public open(parent: HTMLElement): void { throw new Error('Method not implemented.'); } - attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { + public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { throw new Error('Method not implemented.'); } - addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { + public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { throw new Error('Method not implemented.'); } - addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { + public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { throw new Error('Method not implemented.'); } - addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable { + public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable { throw new Error('Method not implemented.'); } - addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { + public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { throw new Error('Method not implemented.'); } - registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { + public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { throw new Error('Method not implemented.'); } - deregisterLinkMatcher(matcherId: number): void { + public deregisterLinkMatcher(matcherId: number): void { throw new Error('Method not implemented.'); } - registerLinkProvider(linkProvider: ILinkProvider): IDisposable { + public registerLinkProvider(linkProvider: ILinkProvider): IDisposable { throw new Error('Method not implemented.'); } - hasSelection(): boolean { + public hasSelection(): boolean { throw new Error('Method not implemented.'); } - getSelection(): string { + public getSelection(): string { throw new Error('Method not implemented.'); } - getSelectionPosition(): ISelectionPosition | undefined { + public getSelectionPosition(): ISelectionPosition | undefined { throw new Error('Method not implemented.'); } - clearSelection(): void { + public clearSelection(): void { throw new Error('Method not implemented.'); } - select(column: number, row: number, length: number): void { + public select(column: number, row: number, length: number): void { throw new Error('Method not implemented.'); } - selectAll(): void { + public selectAll(): void { throw new Error('Method not implemented.'); } - dispose(): void { + public dispose(): void { throw new Error('Method not implemented.'); } - scrollPages(pageCount: number): void { + public scrollPages(pageCount: number): void { throw new Error('Method not implemented.'); } - scrollToTop(): void { + public scrollToTop(): void { throw new Error('Method not implemented.'); } - scrollToBottom(): void { + public scrollToBottom(): void { throw new Error('Method not implemented.'); } - clear(): void { + public clear(): void { throw new Error('Method not implemented.'); } - write(data: string): void { + public write(data: string): void { throw new Error('Method not implemented.'); } - writeUtf8(data: Uint8Array): void { + public writeUtf8(data: Uint8Array): void { throw new Error('Method not implemented.'); } - bracketedPasteMode: boolean; - renderer: IRenderer; - linkifier: ILinkifier; - linkifier2: ILinkifier2; - isFocused: boolean; - options: ITerminalOptions = {}; - element: HTMLElement; - screenElement: HTMLElement; - rowContainer: HTMLElement; - selectionContainer: HTMLElement; - selectionService: ISelectionService; - textarea: HTMLTextAreaElement; - rows: number; - cols: number; - browser: IBrowser = Browser; - writeBuffer: string[]; - children: HTMLElement[]; - cursorHidden: boolean; - cursorState: number; - scrollback: number; - buffers: IBufferSet; - buffer: IBuffer; - viewport: IViewport; - applicationCursor: boolean; - handler(data: string): void { + public bracketedPasteMode: boolean; + public renderer: IRenderer; + public linkifier: ILinkifier; + public linkifier2: ILinkifier2; + public isFocused: boolean; + public options: ITerminalOptions = {}; + public element: HTMLElement; + public screenElement: HTMLElement; + public rowContainer: HTMLElement; + public selectionContainer: HTMLElement; + public selectionService: ISelectionService; + public textarea: HTMLTextAreaElement; + public rows: number; + public cols: number; + public browser: IBrowser = Browser; + public writeBuffer: string[]; + public children: HTMLElement[]; + public cursorHidden: boolean; + public cursorState: number; + public scrollback: number; + public buffers: IBufferSet; + public buffer: IBuffer; + public viewport: IViewport; + public applicationCursor: boolean; + public handler(data: string): void { throw new Error('Method not implemented.'); } - on(event: string, callback: (...args: any[]) => void): void { + public on(event: string, callback: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } - off(type: string, listener: XtermListener): void { + public off(type: string, listener: XtermListener): void { throw new Error('Method not implemented.'); } - addDisposableListener(type: string, handler: XtermListener): IDisposable { + public addDisposableListener(type: string, handler: XtermListener): IDisposable { throw new Error('Method not implemented.'); } - scrollLines(disp: number, suppressScrollEvent: boolean): void { + public scrollLines(disp: number, suppressScrollEvent: boolean): void { throw new Error('Method not implemented.'); } - scrollToRow(absoluteRow: number): number { + public scrollToRow(absoluteRow: number): number { throw new Error('Method not implemented.'); } - cancel(ev: Event, force?: boolean): void { + public cancel(ev: Event, force?: boolean): void { throw new Error('Method not implemented.'); } - log(text: string): void { + public log(text: string): void { throw new Error('Method not implemented.'); } - emit(event: string, data: any): void { + public emit(event: string, data: any): void { throw new Error('Method not implemented.'); } - reset(): void { + public reset(): void { throw new Error('Method not implemented.'); } - showCursor(): void { + public showCursor(): void { throw new Error('Method not implemented.'); } - refresh(start: number, end: number): void { + public refresh(start: number, end: number): void { throw new Error('Method not implemented.'); } - registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } - deregisterCharacterJoiner(joinerId: number): void { } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public deregisterCharacterJoiner(joinerId: number): void { } } export class MockInputHandlingTerminal implements IInputHandlingTerminal { - onA11yCharEmitter: EventEmitter; - onA11yTabEmitter: EventEmitter; - insertMode: boolean; - bracketedPasteMode: boolean; - sendFocus: boolean; - buffers: IBufferSet; - buffer: IBuffer = new MockBuffer(); - viewport: IViewport; - scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void { + public onA11yCharEmitter: EventEmitter; + public onA11yTabEmitter: EventEmitter; + public insertMode: boolean; + public bracketedPasteMode: boolean; + public sendFocus: boolean; + public buffers: IBufferSet; + public buffer: IBuffer = new MockBuffer(); + public viewport: IViewport; + public scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void { throw new Error('Method not implemented.'); } - is(term: string): boolean { + public is(term: string): boolean { throw new Error('Method not implemented.'); } - resize(x: number, y: number): void { + public resize(x: number, y: number): void { throw new Error('Method not implemented.'); } - showCursor(): void { + public showCursor(): void { throw new Error('Method not implemented.'); } - handler(data: string): void { + public handler(data: string): void { throw new Error('Method not implemented.'); } - handleTitle(title: string): void { + public handleTitle(title: string): void { throw new Error('Method not implemented.'); } } export class MockBuffer implements IBuffer { - markers: IMarker[]; - addMarker(y: number): IMarker { + public markers: IMarker[]; + public addMarker(y: number): IMarker { throw new Error('Method not implemented.'); } - isCursorInViewport: boolean; - lines: ICircularList; - ydisp: number; - ybase: number; - hasScrollback: boolean; - y: number; - x: number; - tabs: any; - scrollBottom: number; - scrollTop: number; - savedY: number; - savedX: number; - savedCharset: ICharset | null; - savedCurAttrData = new AttributeData(); - translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { + public isCursorInViewport: boolean; + public lines: ICircularList; + public ydisp: number; + public ybase: number; + public hasScrollback: boolean; + public y: number; + public x: number; + public tabs: any; + public scrollBottom: number; + public scrollTop: number; + public savedY: number; + public savedX: number; + public savedCharset: ICharset | null; + public savedCurAttrData = new AttributeData(); + public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { return Buffer.prototype.translateBufferLineToString.apply(this, arguments); } - getWrappedRangeForLine(y: number): { first: number, last: number } { + public getWrappedRangeForLine(y: number): { first: number, last: number } { return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments); } - nextStop(x?: number): number { + public nextStop(x?: number): number { throw new Error('Method not implemented.'); } - prevStop(x?: number): number { + public prevStop(x?: number): number { throw new Error('Method not implemented.'); } - setLines(lines: ICircularList): void { + public setLines(lines: ICircularList): void { this.lines = lines; } - getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine { + public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine { return Buffer.prototype.getBlankLine.apply(this, arguments); } - stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] { + public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] { return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments); } - iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator { + public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator { return Buffer.prototype.iterator.apply(this, arguments); } - getNullCell(attr?: IAttributeData): ICellData { + public getNullCell(attr?: IAttributeData): ICellData { throw new Error('Method not implemented.'); } - getWhitespaceCell(attr?: IAttributeData): ICellData { + public getWhitespaceCell(attr?: IAttributeData): ICellData { throw new Error('Method not implemented.'); } } export class MockRenderer implements IRenderer { - onRequestRefreshRows: IEvent; - onCanvasResize: IEvent<{ width: number, height: number }>; - onRender: IEvent<{ start: number, end: number }>; - dispose(): void { + public onRequestRefreshRows: IEvent; + public onCanvasResize: IEvent<{ width: number, height: number }>; + public onRender: IEvent<{ start: number, end: number }>; + public dispose(): void { throw new Error('Method not implemented.'); } - colorManager: IColorManager; - on(type: string, listener: XtermListener): void { + public colorManager: IColorManager; + public on(type: string, listener: XtermListener): void { throw new Error('Method not implemented.'); } - off(type: string, listener: XtermListener): void { + public off(type: string, listener: XtermListener): void { throw new Error('Method not implemented.'); } - emit(type: string, data?: any): void { + public emit(type: string, data?: any): void { throw new Error('Method not implemented.'); } - addDisposableListener(type: string, handler: XtermListener): IDisposable { + public addDisposableListener(type: string, handler: XtermListener): IDisposable { throw new Error('Method not implemented.'); } - dimensions: IRenderDimensions; - setColors(colors: IColorSet): void { + public dimensions: IRenderDimensions; + public setColors(colors: IColorSet): void { throw new Error('Method not implemented.'); } - onResize(cols: number, rows: number): void { } - onCharSizeChanged(): void { } - onBlur(): void { } - onFocus(): void { } - onSelectionChanged(start: [number, number], end: [number, number]): void { } - onCursorMove(): void { } - onOptionsChanged(): void { } - onDevicePixelRatioChange(): void { } - clear(): void { } - renderRows(start: number, end: number): void { } - registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } - deregisterCharacterJoiner(): boolean { return true; } + public onResize(cols: number, rows: number): void { } + public onCharSizeChanged(): void { } + public onBlur(): void { } + public onFocus(): void { } + public onSelectionChanged(start: [number, number], end: [number, number]): void { } + public onCursorMove(): void { } + public onOptionsChanged(): void { } + public onDevicePixelRatioChange(): void { } + public clear(): void { } + public renderRows(start: number, end: number): void { } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public deregisterCharacterJoiner(): boolean { return true; } } export class MockViewport implements IViewport { - dispose(): void { + public dispose(): void { throw new Error('Method not implemented.'); } - scrollBarWidth: number = 0; - onThemeChange(colors: IColorSet): void { + public scrollBarWidth: number = 0; + public onThemeChange(colors: IColorSet): void { throw new Error('Method not implemented.'); } - onWheel(ev: WheelEvent): boolean { + public onWheel(ev: WheelEvent): boolean { throw new Error('Method not implemented.'); } - onTouchStart(ev: TouchEvent): void { + public onTouchStart(ev: TouchEvent): void { throw new Error('Method not implemented.'); } - onTouchMove(ev: TouchEvent): boolean { + public onTouchMove(ev: TouchEvent): boolean { throw new Error('Method not implemented.'); } - syncScrollArea(): void { } - getLinesScrolled(ev: WheelEvent): number { + public syncScrollArea(): void { } + public getLinesScrolled(ev: WheelEvent): number { throw new Error('Method not implemented.'); } } export class MockCompositionHelper implements ICompositionHelper { - compositionstart(): void { + public compositionstart(): void { throw new Error('Method not implemented.'); } - compositionupdate(ev: CompositionEvent): void { + public compositionupdate(ev: CompositionEvent): void { throw new Error('Method not implemented.'); } - compositionend(): void { + public compositionend(): void { throw new Error('Method not implemented.'); } - updateCompositionElements(dontRecurse?: boolean): void { + public updateCompositionElements(dontRecurse?: boolean): void { throw new Error('Method not implemented.'); } - keydown(ev: KeyboardEvent): boolean { + public keydown(ev: KeyboardEvent): boolean { return true; } } diff --git a/src/browser/Linkifier.test.ts b/src/browser/Linkifier.test.ts index f107d646d..c0dc6bf6d 100644 --- a/src/browser/Linkifier.test.ts +++ b/src/browser/Linkifier.test.ts @@ -24,14 +24,14 @@ class TestLinkifier extends Linkifier { } class TestMouseZoneManager implements IMouseZoneManager { - dispose(): void { + public dispose(): void { } public clears: number = 0; public zones: IMouseZone[] = []; - add(zone: IMouseZone): void { + public add(zone: IMouseZone): void { this.zones.push(zone); } - clearAll(): void { + public clearAll(): void { this.clears++; } } diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 3e304bcfc..e1f45564b 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -9,15 +9,15 @@ import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/re import { IColorSet } from 'browser/Types'; export class MockCharSizeService implements ICharSizeService { - serviceBrand: any; - get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } - onCharSizeChange: IEvent = new EventEmitter().event; + public serviceBrand: any; + public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } + public onCharSizeChange: IEvent = new EventEmitter().event; constructor(public width: number, public height: number) {} - measure(): void {} + public measure(): void {} } export class MockMouseService implements IMouseService { - serviceBrand: any; + public serviceBrand: any; public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined { throw new Error('Not implemented'); } @@ -28,11 +28,11 @@ export class MockMouseService implements IMouseService { } export class MockRenderService implements IRenderService { - serviceBrand: any; - onDimensionsChange: IEvent = new EventEmitter().event; - onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; - onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; - dimensions: IRenderDimensions = { + public serviceBrand: any; + public onDimensionsChange: IEvent = new EventEmitter().event; + public onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; + public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; + public dimensions: IRenderDimensions = { scaledCharWidth: 0, scaledCharHeight: 0, scaledCellWidth: 0, @@ -46,52 +46,52 @@ export class MockRenderService implements IRenderService { actualCellWidth: 0, actualCellHeight: 0 }; - refreshRows(start: number, end: number): void { + public refreshRows(start: number, end: number): void { throw new Error('Method not implemented.'); } - resize(cols: number, rows: number): void { + public resize(cols: number, rows: number): void { throw new Error('Method not implemented.'); } - changeOptions(): void { + public changeOptions(): void { throw new Error('Method not implemented.'); } - setRenderer(renderer: IRenderer): void { + public setRenderer(renderer: IRenderer): void { throw new Error('Method not implemented.'); } - setColors(colors: IColorSet): void { + public setColors(colors: IColorSet): void { throw new Error('Method not implemented.'); } - onDevicePixelRatioChange(): void { + public onDevicePixelRatioChange(): void { throw new Error('Method not implemented.'); } - onResize(cols: number, rows: number): void { + public onResize(cols: number, rows: number): void { throw new Error('Method not implemented.'); } - onCharSizeChanged(): void { + public onCharSizeChanged(): void { throw new Error('Method not implemented.'); } - onBlur(): void { + public onBlur(): void { throw new Error('Method not implemented.'); } - onFocus(): void { + public onFocus(): void { throw new Error('Method not implemented.'); } - onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { throw new Error('Method not implemented.'); } - onCursorMove(): void { + public onCursorMove(): void { throw new Error('Method not implemented.'); } - clear(): void { + public clear(): void { throw new Error('Method not implemented.'); } - registerCharacterJoiner(handler: CharacterJoinerHandler): number { + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { throw new Error('Method not implemented.'); } - deregisterCharacterJoiner(joinerId: number): boolean { + public deregisterCharacterJoiner(joinerId: number): boolean { throw new Error('Method not implemented.'); } - dispose(): void { + public dispose(): void { throw new Error('Method not implemented.'); } } diff --git a/src/browser/renderer/TextRenderLayer.ts b/src/browser/renderer/TextRenderLayer.ts index fee261f60..67f0d4842 100644 --- a/src/browser/renderer/TextRenderLayer.ts +++ b/src/browser/renderer/TextRenderLayer.ts @@ -36,8 +36,8 @@ export class TextRenderLayer extends BaseRenderLayer { characterJoinerRegistry: ICharacterJoinerRegistry, alpha: boolean, rendererId: number, - readonly bufferService: IBufferService, - readonly optionsService: IOptionsService + bufferService: IBufferService, + optionsService: IOptionsService ) { super(container, 'text', zIndex, alpha, colors, rendererId, bufferService, optionsService); this._state = new GridCache(); diff --git a/src/browser/services/CharSizeService.ts b/src/browser/services/CharSizeService.ts index 0749a4204..7623109ce 100644 --- a/src/browser/services/CharSizeService.ts +++ b/src/browser/services/CharSizeService.ts @@ -8,7 +8,7 @@ import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICharSizeService } from 'browser/services/Services'; export class CharSizeService implements ICharSizeService { - serviceBrand: any; + public serviceBrand: any; public width: number = 0; public height: number = 0; @@ -20,8 +20,8 @@ export class CharSizeService implements ICharSizeService { public get onCharSizeChange(): IEvent { return this._onCharSizeChange.event; } constructor( - readonly document: Document, - readonly parentElement: HTMLElement, + document: Document, + parentElement: HTMLElement, @IOptionsService private readonly _optionsService: IOptionsService ) { this._measureStrategy = new DomMeasureStrategy(document, parentElement, this._optionsService); diff --git a/src/browser/services/CoreBrowserService.ts b/src/browser/services/CoreBrowserService.ts index e585f44ab..e3207d7bb 100644 --- a/src/browser/services/CoreBrowserService.ts +++ b/src/browser/services/CoreBrowserService.ts @@ -6,7 +6,7 @@ import { ICoreBrowserService } from './Services'; export class CoreBrowserService implements ICoreBrowserService { - serviceBrand: any; + public serviceBrand: any; constructor( private _textarea: HTMLTextAreaElement diff --git a/src/browser/services/MouseService.ts b/src/browser/services/MouseService.ts index b0f8c3580..39df63839 100644 --- a/src/browser/services/MouseService.ts +++ b/src/browser/services/MouseService.ts @@ -7,7 +7,7 @@ import { ICharSizeService, IRenderService, IMouseService } from './Services'; import { getCoords, getRawByteCoords } from 'browser/input/Mouse'; export class MouseService implements IMouseService { - serviceBrand: any; + public serviceBrand: any; constructor( @IRenderService private readonly _renderService: IRenderService, diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 03db0a854..791308916 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -14,7 +14,7 @@ import { IOptionsService } from 'common/services/Services'; import { ICharSizeService, IRenderService } from 'browser/services/Services'; export class RenderService extends Disposable implements IRenderService { - serviceBrand: any; + public serviceBrand: any; private _renderDebouncer: RenderDebouncer; private _screenDprMonitor: ScreenDprMonitor; diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index 45424d164..43875f1b2 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -67,7 +67,7 @@ export const enum SelectionMode { * when the selection is ready to be redrawn (on an animation frame). */ export class SelectionService implements ISelectionService { - serviceBrand: any; + public serviceBrand: any; protected _model: SelectionModel; diff --git a/src/browser/services/SoundService.ts b/src/browser/services/SoundService.ts index 1772c7504..4b54c9990 100644 --- a/src/browser/services/SoundService.ts +++ b/src/browser/services/SoundService.ts @@ -7,11 +7,11 @@ import { IOptionsService } from 'common/services/Services'; import { ISoundService } from 'browser/services/Services'; export class SoundService implements ISoundService { - serviceBrand: any; + public serviceBrand: any; private static _audioContext: AudioContext; - static get audioContext(): AudioContext | null { + public static get audioContext(): AudioContext | null { if (!SoundService._audioContext) { const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext; if (!audioContextCtor) { diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index cf0979f76..7e024140a 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -13,7 +13,7 @@ import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType, ICharset } from import { UnicodeV6 } from 'common/input/UnicodeV6'; export class MockBufferService implements IBufferService { - serviceBrand: any; + public serviceBrand: any; public get buffer(): IBuffer { return this.buffers.active; } public buffers: IBufferSet = {} as any; constructor( @@ -23,86 +23,86 @@ export class MockBufferService implements IBufferService { ) { this.buffers = new BufferSet(optionsService, this); } - resize(cols: number, rows: number): void { + public resize(cols: number, rows: number): void { this.cols = cols; this.rows = rows; } - reset(): void {} + public reset(): void {} } export class MockCoreMouseService implements ICoreMouseService { - activeEncoding: string = ''; - activeProtocol: string = ''; - addEncoding(name: string): void {} - addProtocol(name: string): void {} - reset(): void {} - triggerMouseEvent(event: ICoreMouseEvent): boolean { return false; } - onProtocolChange: IEvent = new EventEmitter().event; - explainEvents(events: CoreMouseEventType): {[event: string]: boolean} { + public activeEncoding: string = ''; + public activeProtocol: string = ''; + public addEncoding(name: string): void {} + public addProtocol(name: string): void {} + public reset(): void {} + public triggerMouseEvent(event: ICoreMouseEvent): boolean { return false; } + public onProtocolChange: IEvent = new EventEmitter().event; + public explainEvents(events: CoreMouseEventType): {[event: string]: boolean} { throw new Error('Method not implemented.'); } } export class MockCharsetService implements ICharsetService { - serviceBrand: any; - charset: ICharset | undefined; - glevel: number = 0; - charsets: ReadonlyArray = []; - reset(): void {} - setgLevel(g: number): void {} - setgCharset(g: number, charset: ICharset): void {} + public serviceBrand: any; + public charset: ICharset | undefined; + public glevel: number = 0; + public charsets: ReadonlyArray = []; + public reset(): void {} + public setgLevel(g: number): void {} + public setgCharset(g: number, charset: ICharset): void {} } export class MockCoreService implements ICoreService { - serviceBrand: any; - isCursorInitialized: boolean = false; - isCursorHidden: boolean = false; - isFocused: boolean = false; - decPrivateModes: IDecPrivateModes = { + public serviceBrand: any; + public isCursorInitialized: boolean = false; + public isCursorHidden: boolean = false; + public isFocused: boolean = false; + public decPrivateModes: IDecPrivateModes = { applicationCursorKeys: false, applicationKeypad: false, origin: false, wraparound: true }; - onData: IEvent = new EventEmitter().event; - onUserInput: IEvent = new EventEmitter().event; - onBinary: IEvent = new EventEmitter().event; - reset(): void {} - triggerDataEvent(data: string, wasUserInput?: boolean): void {} - triggerBinaryEvent(data: string): void {} + public onData: IEvent = new EventEmitter().event; + public onUserInput: IEvent = new EventEmitter().event; + public onBinary: IEvent = new EventEmitter().event; + public reset(): void {} + public triggerDataEvent(data: string, wasUserInput?: boolean): void {} + public triggerBinaryEvent(data: string): void {} } export class MockDirtyRowService implements IDirtyRowService { - serviceBrand: any; - start: number = 0; - end: number = 0; - clearRange(): void {} - markDirty(y: number): void {} - markRangeDirty(y1: number, y2: number): void {} - markAllDirty(): void {} + public serviceBrand: any; + public start: number = 0; + public end: number = 0; + public clearRange(): void {} + public markDirty(y: number): void {} + public markRangeDirty(y1: number, y2: number): void {} + public markAllDirty(): void {} } export class MockLogService implements ILogService { - serviceBrand: any; - debug(message: any, ...optionalParams: any[]): void {} - info(message: any, ...optionalParams: any[]): void {} - warn(message: any, ...optionalParams: any[]): void {} - error(message: any, ...optionalParams: any[]): void {} + public serviceBrand: any; + public debug(message: any, ...optionalParams: any[]): void {} + public info(message: any, ...optionalParams: any[]): void {} + public warn(message: any, ...optionalParams: any[]): void {} + public error(message: any, ...optionalParams: any[]): void {} } export class MockOptionsService implements IOptionsService { - serviceBrand: any; - options: ITerminalOptions = clone(DEFAULT_OPTIONS); - onOptionChange: IEvent = new EventEmitter().event; + public serviceBrand: any; + public options: ITerminalOptions = clone(DEFAULT_OPTIONS); + public onOptionChange: IEvent = new EventEmitter().event; constructor(testOptions?: IPartialTerminalOptions) { if (testOptions) { Object.keys(testOptions).forEach(key => this.options[key] = (testOptions)[key]); } } - setOption(key: string, value: T): void { + public setOption(key: string, value: T): void { throw new Error('Method not implemented.'); } - getOption(key: string): T { + public getOption(key: string): T { throw new Error('Method not implemented.'); } } @@ -110,14 +110,14 @@ export class MockOptionsService implements IOptionsService { // defaults to V6 always to keep tests passing export class MockUnicodeService implements IUnicodeService { private _provider = new UnicodeV6(); - register(provider: IUnicodeVersionProvider): void { + public register(provider: IUnicodeVersionProvider): void { throw new Error('Method not implemented.'); } - versions: string[] = []; - activeVersion: string = ''; - onChange: IEvent = new EventEmitter().event; - wcwidth = (codepoint: number): number => this._provider.wcwidth(codepoint); - getStringCellWidth(s: string): number { + public versions: string[] = []; + public activeVersion: string = ''; + public onChange: IEvent = new EventEmitter().event; + public wcwidth = (codepoint: number): number => this._provider.wcwidth(codepoint); + public getStringCellWidth(s: string): number { throw new Error('Method not implemented.'); } } diff --git a/src/common/buffer/AttributeData.ts b/src/common/buffer/AttributeData.ts index 22e9d2b84..52bd0b15b 100644 --- a/src/common/buffer/AttributeData.ts +++ b/src/common/buffer/AttributeData.ts @@ -7,15 +7,15 @@ import { IAttributeData, IColorRGB } from 'common/Types'; import { Attributes, FgFlags, BgFlags } from 'common/buffer/Constants'; export class AttributeData implements IAttributeData { - static toColorRGB(value: number): IColorRGB { + public static toColorRGB(value: number): IColorRGB { return [ value >>> Attributes.RED_SHIFT & 255, value >>> Attributes.GREEN_SHIFT & 255, value & 255 ]; } - - static fromColorRGB(value: IColorRGB): number { + + public static fromColorRGB(value: IColorRGB): number { return (value[0] & 255) << Attributes.RED_SHIFT | (value[1] & 255) << Attributes.GREEN_SHIFT | value[2] & 255; } diff --git a/src/common/input/TextDecoder.ts b/src/common/input/TextDecoder.ts index 397d25a78..6ecab011d 100644 --- a/src/common/input/TextDecoder.ts +++ b/src/common/input/TextDecoder.ts @@ -64,7 +64,7 @@ export class StringToUtf32 { * the provided input data does not exceed the size of `target`. * Returns the number of written codepoints in `target`. */ - decode(input: string, target: Uint32Array): number { + public decode(input: string, target: Uint32Array): number { const length = input.length; if (!length) { @@ -132,7 +132,7 @@ export class Utf8ToUtf32 { * the provided data chunk does not exceed the size of `target`. * Returns the number of written codepoints in `target`. */ - decode(input: Uint8Array, target: Uint32Array): number { + public decode(input: Uint8Array, target: Uint32Array): number { const length = input.length; if (!length) { diff --git a/src/common/parser/DcsParser.test.ts b/src/common/parser/DcsParser.test.ts index 4d6dce110..dbabb4fac 100644 --- a/src/common/parser/DcsParser.test.ts +++ b/src/common/parser/DcsParser.test.ts @@ -55,13 +55,13 @@ function identifier(id: IFunctionIdentifier): number { class TestHandler implements IDcsHandler { constructor(public output: any[], public msg: string, public returnFalse: boolean = false) {} - hook(params: IParams): void { + public hook(params: IParams): void { this.output.push([this.msg, 'HOOK', params.toArray()]); } - put(data: Uint32Array, start: number, end: number): void { + public put(data: Uint32Array, start: number, end: number): void { this.output.push([this.msg, 'PUT', utf32ToString(data, start, end)]); } - unhook(success: boolean): void | boolean { + public unhook(success: boolean): void | boolean { this.output.push([this.msg, 'UNHOOK', success]); if (this.returnFalse) { return false; diff --git a/src/common/parser/EscapeSequenceParser.test.ts b/src/common/parser/EscapeSequenceParser.test.ts index 3b6910a60..8254212b2 100644 --- a/src/common/parser/EscapeSequenceParser.test.ts +++ b/src/common/parser/EscapeSequenceParser.test.ts @@ -41,16 +41,16 @@ class MockOscPutParser implements IOscParser { this._fallback(id, 'END', this.data.slice(this.data.indexOf(';') + 1)); } } - addHandler(ident: number, handler: IOscHandler): IDisposable { + public addHandler(ident: number, handler: IOscHandler): IDisposable { throw new Error('not implemented'); } - setHandler(ident: number, handler: IOscHandler): void { + public setHandler(ident: number, handler: IOscHandler): void { throw new Error('not implemented'); } - clearHandler(ident: number): void { + public clearHandler(ident: number): void { throw new Error('not implemented'); } - setHandlerFallback(handler: OscFallbackHandlerType): void { + public setHandlerFallback(handler: OscFallbackHandlerType): void { this._fallback = handler; } } diff --git a/src/common/parser/OscParser.test.ts b/src/common/parser/OscParser.test.ts index 6969d6f33..127bd83a7 100644 --- a/src/common/parser/OscParser.test.ts +++ b/src/common/parser/OscParser.test.ts @@ -17,13 +17,13 @@ function toUtf32(s: string): Uint32Array { class TestHandler implements IOscHandler { constructor(public id: number, public output: any[], public msg: string, public returnFalse: boolean = false) {} - start(): void { + public start(): void { this.output.push([this.msg, this.id, 'START']); } - put(data: Uint32Array, start: number, end: number): void { + public put(data: Uint32Array, start: number, end: number): void { this.output.push([this.msg, this.id, 'PUT', utf32ToString(data, start, end)]); } - end(success: boolean): void | boolean { + public end(success: boolean): void | boolean { this.output.push([this.msg, this.id, 'END', success]); if (this.returnFalse) { return false; diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts index c7b6afce4..1b6da7922 100644 --- a/src/common/services/BufferService.ts +++ b/src/common/services/BufferService.ts @@ -11,7 +11,7 @@ export const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars export const MINIMUM_ROWS = 1; export class BufferService implements IBufferService { - serviceBrand: any; + public serviceBrand: any; public cols: number; public rows: number; diff --git a/src/common/services/CharsetService.ts b/src/common/services/CharsetService.ts index 5d20628f3..47a015f6f 100644 --- a/src/common/services/CharsetService.ts +++ b/src/common/services/CharsetService.ts @@ -7,7 +7,7 @@ import { ICharsetService } from 'common/services/Services'; import { ICharset } from 'common/Types'; export class CharsetService implements ICharsetService { - serviceBrand: any; + public serviceBrand: any; public charset: ICharset | undefined; public charsets: ICharset[] = []; diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index 883266ec5..2f0ff72f6 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -16,7 +16,7 @@ const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ }); export class CoreService implements ICoreService { - serviceBrand: any; + public serviceBrand: any; public isCursorInitialized: boolean = false; public isCursorHidden: boolean = false; diff --git a/src/common/services/DirtyRowService.ts b/src/common/services/DirtyRowService.ts index 0f2f14f50..1c43b67ef 100644 --- a/src/common/services/DirtyRowService.ts +++ b/src/common/services/DirtyRowService.ts @@ -6,7 +6,7 @@ import { IBufferService, IDirtyRowService } from 'common/services/Services'; export class DirtyRowService implements IDirtyRowService { - serviceBrand: any; + public serviceBrand: any; private _start!: number; private _end!: number; diff --git a/src/common/services/InstantiationService.ts b/src/common/services/InstantiationService.ts index dd011d981..e5727fa6d 100644 --- a/src/common/services/InstantiationService.ts +++ b/src/common/services/InstantiationService.ts @@ -22,21 +22,21 @@ export class ServiceCollection { } } - set(id: IServiceIdentifier, instance: T): T { + public set(id: IServiceIdentifier, instance: T): T { const result = this._entries.get(id); this._entries.set(id, instance); return result; } - forEach(callback: (id: IServiceIdentifier, instance: any) => any): void { + public forEach(callback: (id: IServiceIdentifier, instance: any) => any): void { this._entries.forEach((value, key) => callback(key, value)); } - has(id: IServiceIdentifier): boolean { + public has(id: IServiceIdentifier): boolean { return this._entries.has(id); } - get(id: IServiceIdentifier): T | undefined { + public get(id: IServiceIdentifier): T | undefined { return this._entries.get(id); } } diff --git a/src/common/services/LogService.ts b/src/common/services/LogService.ts index 4f48d8fe6..3c0ccaf14 100644 --- a/src/common/services/LogService.ts +++ b/src/common/services/LogService.ts @@ -39,7 +39,7 @@ const optionsKeyToLogLevel: { [key: string]: LogLevel } = { const LOG_PREFIX = 'xterm.js: '; export class LogService implements ILogService { - serviceBrand: any; + public serviceBrand: any; private _logLevel!: LogLevel; @@ -71,25 +71,25 @@ export class LogService implements ILogService { type.call(console, LOG_PREFIX + message, ...optionalParams); } - debug(message: string, ...optionalParams: any[]): void { + public debug(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.DEBUG) { this._log(console.log, message, optionalParams); } } - info(message: string, ...optionalParams: any[]): void { + public info(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.INFO) { this._log(console.info, message, optionalParams); } } - warn(message: string, ...optionalParams: any[]): void { + public warn(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.WARN) { this._log(console.warn, message, optionalParams); } } - error(message: string, ...optionalParams: any[]): void { + public error(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.ERROR) { this._log(console.error, message, optionalParams); } diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 44a55d33d..2263e7c3f 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -60,7 +60,7 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ const CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows']; export class OptionsService implements IOptionsService { - serviceBrand: any; + public serviceBrand: any; public options: ITerminalOptions; diff --git a/src/common/services/UnicodeService.test.ts b/src/common/services/UnicodeService.test.ts index cb03b09b0..a2c4b6367 100644 --- a/src/common/services/UnicodeService.test.ts +++ b/src/common/services/UnicodeService.test.ts @@ -8,8 +8,8 @@ import { UnicodeService } from 'common/services/UnicodeService'; import { IUnicodeVersionProvider } from 'common/services/Services'; class DummyProvider implements IUnicodeVersionProvider { - version = '123'; - wcwidth(n: number): 0 | 1 | 2 { + public version = '123'; + public wcwidth(n: number): 0 | 1 | 2 { return 2; } } diff --git a/src/public/AddonManager.test.ts b/src/public/AddonManager.test.ts index 8198ce316..ea2290954 100644 --- a/src/public/AddonManager.test.ts +++ b/src/public/AddonManager.test.ts @@ -24,11 +24,11 @@ describe('AddonManager', () => { it('should call addon constructor', () => { let called = false; class Addon implements ITerminalAddon { - activate(terminal: any): void { + public activate(terminal: any): void { assert.equal(terminal, 'foo', 'The first constructor arg should be Terminal'); called = true; } - dispose(): void { } + public dispose(): void { } } manager.loadAddon('foo' as any, new Addon()); assert.equal(called, true); @@ -39,8 +39,8 @@ describe('AddonManager', () => { it('should dispose all loaded addons', () => { let called = 0; class Addon implements ITerminalAddon { - activate(): void {} - dispose(): void { called++; } + public activate(): void {} + public dispose(): void { called++; } } manager.loadAddon(null, new Addon()); manager.loadAddon(null, new Addon()); From 46e9b9499cd0e473883310d364ebdfa4912143ec Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:26:53 +0000 Subject: [PATCH 039/130] Bump @typescript-eslint/parser from 2.27.0 to 2.28.0 Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.27.0 to 2.28.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.28.0/packages/parser) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 35 ++++++----------------------------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index fd14131bb..747ad3701 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/webpack": "^4.41.11", "@types/ws": "^7.2.4", "@typescript-eslint/eslint-plugin": "^2.28.0", - "@typescript-eslint/parser": "^2.27.0", + "@typescript-eslint/parser": "^2.28.0", "chai": "^4.2.0", "deep-equal": "^2.0.2", "eslint": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index aa9a404c0..e72ea39d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -381,16 +381,6 @@ regexpp "^3.0.0" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.27.0.tgz#801a952c10b58e486c9a0b36cf21e2aab1e9e01a" - integrity sha512-vOsYzjwJlY6E0NJRXPTeCGqjv5OHgRU1kzxHKWJVPjDYGbPgLudBXjIlc+OD1hDBZ4l1DLbOc5VjofKahsu9Jw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.27.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/experimental-utils@2.28.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d" @@ -401,29 +391,16 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.27.0.tgz#d91664335b2c46584294e42eb4ff35838c427287" - integrity sha512-HFUXZY+EdwrJXZo31DW4IS1ujQW3krzlRjBrFRrJcMDh0zCu107/nRfhk/uBasO8m0NVDbBF5WZKcIUMRO7vPg== +"@typescript-eslint/parser@^2.28.0": + version "2.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.28.0.tgz#bb761286efd2b0714761cab9d0ee5847cf080385" + integrity sha512-RqPybRDquui9d+K86lL7iPqH6Dfp9461oyqvlXMNtap+PyqYbkY5dB7LawQjDzot99fqzvS0ZLZdfe+1Bt3Jgw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.27.0" - "@typescript-eslint/typescript-estree" "2.27.0" + "@typescript-eslint/experimental-utils" "2.28.0" + "@typescript-eslint/typescript-estree" "2.28.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz#a288e54605412da8b81f1660b56c8b2e42966ce8" - integrity sha512-t2miCCJIb/FU8yArjAvxllxbTiyNqaXJag7UOpB5DVoM3+xnjeOngtqlJkLRnMtzaRcJhe3CIR9RmL40omubhg== - dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^6.3.0" - tsutils "^3.17.1" - "@typescript-eslint/typescript-estree@2.28.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00" From 2b874c581728762af0f95ff2c145c442a6b78928 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2020 08:12:32 +0000 Subject: [PATCH 040/130] Bump ts-loader from 6.2.2 to 7.0.0 Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 6.2.2 to 7.0.0. - [Release notes](https://github.com/TypeStrong/ts-loader/releases) - [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/TypeStrong/ts-loader/compare/v6.2.2...v7.0.0) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 747ad3701..8548e41f8 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "nyc": "^15.0.1", "playwright-core": "^0.11.1", "source-map-loader": "^0.2.4", - "ts-loader": "^6.0.4", + "ts-loader": "^7.0.0", "typescript": "3.8", "utf8": "^3.0.0", "webpack": "^4.35.3", diff --git a/yarn.lock b/yarn.lock index e72ea39d5..86e751692 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5440,10 +5440,10 @@ triple-beam@^1.2.0, triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-loader@^6.0.4: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" - integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== +ts-loader@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.0.tgz#7c74dfa8956e3e33b91d98d4ed7b6f7575c35c25" + integrity sha512-qq9iPK235Xf/uPS1I72CIwB8qpbW0rys3entnXO+rIo2km50lMmeHKCNn1m047W6Sk4kceF6n5NWEnq/V8xdYQ== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" From 0cd2b784250539574ef82e3fd68e3c1ab7a71e29 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 17 Apr 2020 17:30:53 -0700 Subject: [PATCH 041/130] Clear link when leaving xterm link Fixes #2851 --- src/browser/Linkifier2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 7030e5d2b..94e1ced14 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -49,6 +49,7 @@ export class Linkifier2 implements ILinkifier2 { this._mouseService = mouseService; this._renderService = renderService; + this._element.addEventListener('mouseleave', () => this._clearCurrentLink()); this._element.addEventListener('mousemove', this._onMouseMove.bind(this)); this._element.addEventListener('click', this._onClick.bind(this)); } From 48f579977ef9b7b5930e1712f5e5d0ba0fb01368 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 17 Apr 2020 18:46:01 -0700 Subject: [PATCH 042/130] Allow hiding of link underlines See microsoft/vscode#95080 --- src/browser/Linkifier2.ts | 4 +++- src/browser/Types.d.ts | 1 + typings/xterm.d.ts | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 7030e5d2b..90c9668c1 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -184,7 +184,9 @@ export class Linkifier2 implements ILinkifier2 { const range = link.range; const scrollOffset = this._bufferService.buffer.ydisp; - this._onLinkHover.fire(this._createLinkHoverEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined)); + if (!link.hideUnderline) { + this._onLinkHover.fire(this._createLinkHoverEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined)); + } element.classList.add('xterm-cursor-pointer'); if (link.hover) { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index c2b8604eb..fc790a7ec 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -172,6 +172,7 @@ interface ILinkProvider { interface ILink { range: IBufferRange; text: string; + hideUnderline?: boolean; activate(event: MouseEvent, text: string): void; hover?(event: MouseEvent, text: string): void; leave?(event: MouseEvent, text: string): void; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 79379058c..9830f4d9f 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1120,6 +1120,11 @@ declare module 'xterm' { */ text: string; + /** + * Whether to hide the link's underline. + */ + hideUnderline?: boolean; + /** * Calls when the link is activated. * @param event The mouse event triggering the callback. From f2ed01993dc4074e2ad012593cf230b2aeab600d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 18 Apr 2020 06:17:41 -0700 Subject: [PATCH 043/130] Track changes to hideUnderline --- .../src/renderLayer/LinkRenderLayer.ts | 12 ++--- src/browser/Linkifier.ts | 12 ++--- src/browser/Linkifier2.test.ts | 4 +- src/browser/Linkifier2.ts | 53 +++++++++++++++---- src/browser/Types.d.ts | 8 +-- src/browser/renderer/LinkRenderLayer.ts | 12 ++--- src/browser/renderer/dom/DomRenderer.ts | 8 +-- typings/xterm.d.ts | 3 +- 8 files changed, 73 insertions(+), 39 deletions(-) diff --git a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts index ebf773d3b..10cf9c1fe 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts @@ -16,11 +16,11 @@ export class LinkRenderLayer extends BaseRenderLayer { constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) { super(container, 'link', zIndex, true, colors); - terminal.linkifier.onLinkHover(e => this._onLinkHover(e)); - terminal.linkifier.onLinkLeave(e => this._onLinkLeave(e)); + terminal.linkifier.onShowLinkUnderline(e => this._onShowLinkUnderline(e)); + terminal.linkifier.onHideLinkUnderline(e => this._onHideLinkUnderline(e)); - terminal.linkifier2.onLinkHover(e => this._onLinkHover(e)); - terminal.linkifier2.onLinkLeave(e => this._onLinkLeave(e)); + terminal.linkifier2.onShowLinkUnderline(e => this._onShowLinkUnderline(e)); + terminal.linkifier2.onHideLinkUnderline(e => this._onHideLinkUnderline(e)); } public resize(terminal: Terminal, dim: IRenderDimensions): void { @@ -45,7 +45,7 @@ export class LinkRenderLayer extends BaseRenderLayer { } } - private _onLinkHover(e: ILinkifierEvent): void { + private _onShowLinkUnderline(e: ILinkifierEvent): void { if (e.fg === INVERTED_DEFAULT_COLOR) { this._ctx.fillStyle = this._colors.background.css; } else if (e.fg !== undefined && is256Color(e.fg)) { @@ -69,7 +69,7 @@ export class LinkRenderLayer extends BaseRenderLayer { this._state = e; } - private _onLinkLeave(e: ILinkifierEvent): void { + private _onHideLinkUnderline(e: ILinkifierEvent): void { this._clearCurrentLink(); } } diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index 971501b70..ca45ef2a9 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -35,10 +35,10 @@ export class Linkifier implements ILinkifier { private _nextLinkMatcherId = 0; private _rowsToLinkify: { start: number | undefined, end: number | undefined }; - private _onLinkHover = new EventEmitter(); - public get onLinkHover(): IEvent { return this._onLinkHover.event; } - private _onLinkLeave = new EventEmitter(); - public get onLinkLeave(): IEvent { return this._onLinkLeave.event; } + private _onShowLinkUnderline = new EventEmitter(); + public get onShowLinkUnderline(): IEvent { return this._onShowLinkUnderline.event; } + private _onHideLinkUnderline = new EventEmitter(); + public get onHideLinkUnderline(): IEvent { return this._onHideLinkUnderline.event; } private _onLinkTooltip = new EventEmitter(); public get onLinkTooltip(): IEvent { return this._onLinkTooltip.event; } @@ -307,7 +307,7 @@ export class Linkifier implements ILinkifier { } }, () => { - this._onLinkHover.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); + this._onShowLinkUnderline.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); this._element!.classList.add('xterm-cursor-pointer'); }, e => { @@ -319,7 +319,7 @@ export class Linkifier implements ILinkifier { } }, () => { - this._onLinkLeave.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); + this._onHideLinkUnderline.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); this._element!.classList.remove('xterm-cursor-pointer'); if (matcher.hoverLeaveCallback) { matcher.hoverLeaveCallback(); diff --git a/src/browser/Linkifier2.test.ts b/src/browser/Linkifier2.test.ts index bcf068a84..36a6da431 100644 --- a/src/browser/Linkifier2.test.ts +++ b/src/browser/Linkifier2.test.ts @@ -48,7 +48,7 @@ describe('Linkifier2', () => { }; it('onLinkHover event range is correct', done => { - linkifier.onLinkHover(e => { + linkifier.onShowLinkUnderline(e => { assert.equal(link.range.start.x - 1, e.x1); assert.equal(link.range.start.y - 1, e.y1); assert.equal(link.range.end.x, e.x2); @@ -61,7 +61,7 @@ describe('Linkifier2', () => { }); it('onLinkLeave event range is correct', done => { - linkifier.onLinkLeave(e => { + linkifier.onHideLinkUnderline(e => { assert.equal(link.range.start.x - 1, e.x1); assert.equal(link.range.start.y - 1, e.y1); assert.equal(link.range.end.x, e.x2); diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 128c21eec..b4db56b3a 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -9,20 +9,25 @@ import { IMouseService, IRenderService } from './services/Services'; import { IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; +interface ILinkState { + isHovered: boolean; +} + export class Linkifier2 implements ILinkifier2 { private _element: HTMLElement | undefined; private _mouseService: IMouseService | undefined; private _renderService: IRenderService | undefined; private _linkProviders: ILinkProvider[] = []; private _currentLink: ILink | undefined; + private _currentLinkState: ILinkState | undefined; private _lastMouseEvent: MouseEvent | undefined; private _linkCacheDisposables: IDisposable[] = []; private _lastBufferCell: IBufferCellPosition | undefined; - private _onLinkHover = new EventEmitter(); - public get onLinkHover(): IEvent { return this._onLinkHover.event; } - private _onLinkLeave = new EventEmitter(); - public get onLinkLeave(): IEvent { return this._onLinkLeave.event; } + private _onShowLinkUnderline = new EventEmitter(); + public get onShowLinkUnderline(): IEvent { return this._onShowLinkUnderline.event; } + private _onHideLinkUnderline = new EventEmitter(); + public get onHideLinkUnderline(): IEvent { return this._onHideLinkUnderline.event; } constructor( private readonly _bufferService: IBufferService @@ -151,6 +156,7 @@ export class Linkifier2 implements ILinkifier2 { if (!startRow || !endRow || (this._currentLink.range.start.y >= startRow && this._currentLink.range.end.y <= endRow)) { this._linkLeave(this._element, this._currentLink, this._lastMouseEvent); this._currentLink = undefined; + this._currentLinkState = undefined; this._linkCacheDisposables.forEach(l => l.dispose()); this._linkCacheDisposables = []; } @@ -170,8 +176,25 @@ export class Linkifier2 implements ILinkifier2 { // Trigger hover if the we have a link at the position if (this._linkAtPosition(link, position)) { this._currentLink = link; + this._currentLinkState = { isHovered: true }; this._linkHover(this._element, link, this._lastMouseEvent); + // Add listener for tracking hideUnderline changes + let hideUnderlineValue = link.hideUnderline || false; + Object.defineProperties(link, { + hideUnderline: { + get: () => hideUnderlineValue, + set: v => { + if (hideUnderlineValue !== v) { + hideUnderlineValue = v; + if (this._currentLinkState?.isHovered) { + this._fireUnderlineEvent(link, !v); + } + } + } + } + }); + // Add listener for rerendering if (this._renderService) { this._linkCacheDisposables.push(this._renderService.onRenderedBufferChange(e => { @@ -182,11 +205,11 @@ export class Linkifier2 implements ILinkifier2 { } protected _linkHover(element: HTMLElement, link: ILink, event: MouseEvent): void { - const range = link.range; - const scrollOffset = this._bufferService.buffer.ydisp; - if (!link.hideUnderline) { - this._onLinkHover.fire(this._createLinkHoverEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined)); + this._fireUnderlineEvent(link, true); + } + if (this._currentLinkState) { + this._currentLinkState.isHovered = true; } element.classList.add('xterm-cursor-pointer'); @@ -195,11 +218,21 @@ export class Linkifier2 implements ILinkifier2 { } } - protected _linkLeave(element: HTMLElement, link: ILink, event: MouseEvent): void { + private _fireUnderlineEvent(link: ILink, showEvent: boolean): void { const range = link.range; const scrollOffset = this._bufferService.buffer.ydisp; + const event = this._createLinkHoverEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined); + const emitter = showEvent ? this._onShowLinkUnderline : this._onHideLinkUnderline; + emitter.fire(event); + } - this._onLinkLeave.fire(this._createLinkHoverEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined)); + protected _linkLeave(element: HTMLElement, link: ILink, event: MouseEvent): void { + if (!link.hideUnderline) { + this._fireUnderlineEvent(link, false); + } + if (this._currentLinkState) { + this._currentLinkState.isHovered = false; + } element.classList.remove('xterm-cursor-pointer'); if (link.leave) { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index fc790a7ec..b443e486e 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -96,8 +96,8 @@ export interface ILinkifierEvent { } export interface ILinkifier { - onLinkHover: IEvent; - onLinkLeave: IEvent; + onShowLinkUnderline: IEvent; + onHideLinkUnderline: IEvent; onLinkTooltip: IEvent; attachToDom(element: HTMLElement, mouseZoneManager: IMouseZoneManager): void; @@ -107,8 +107,8 @@ export interface ILinkifier { } export interface ILinkifier2 { - onLinkHover: IEvent; - onLinkLeave: IEvent; + onShowLinkUnderline: IEvent; + onHideLinkUnderline: IEvent; attachToDom(element: HTMLElement, mouseService: IMouseService, renderService: IRenderService): void; registerLinkProvider(linkProvider: ILinkProvider): IDisposable; diff --git a/src/browser/renderer/LinkRenderLayer.ts b/src/browser/renderer/LinkRenderLayer.ts index 33f80cdc3..c41955d93 100644 --- a/src/browser/renderer/LinkRenderLayer.ts +++ b/src/browser/renderer/LinkRenderLayer.ts @@ -24,11 +24,11 @@ export class LinkRenderLayer extends BaseRenderLayer { optionsService: IOptionsService ) { super(container, 'link', zIndex, true, colors, rendererId, bufferService, optionsService); - linkifier.onLinkHover(e => this._onLinkHover(e)); - linkifier.onLinkLeave(e => this._onLinkLeave(e)); + linkifier.onShowLinkUnderline(e => this._onShowLinkUnderline(e)); + linkifier.onHideLinkUnderline(e => this._onHideLinkUnderline(e)); - linkifier2.onLinkHover(e => this._onLinkHover(e)); - linkifier2.onLinkLeave(e => this._onLinkLeave(e)); + linkifier2.onShowLinkUnderline(e => this._onShowLinkUnderline(e)); + linkifier2.onHideLinkUnderline(e => this._onHideLinkUnderline(e)); } public resize(dim: IRenderDimensions): void { @@ -53,7 +53,7 @@ export class LinkRenderLayer extends BaseRenderLayer { } } - private _onLinkHover(e: ILinkifierEvent): void { + private _onShowLinkUnderline(e: ILinkifierEvent): void { if (e.fg === INVERTED_DEFAULT_COLOR) { this._ctx.fillStyle = this._colors.background.css; } else if (e.fg && is256Color(e.fg)) { @@ -77,7 +77,7 @@ export class LinkRenderLayer extends BaseRenderLayer { this._state = e; } - private _onLinkLeave(e: ILinkifierEvent): void { + private _onHideLinkUnderline(e: ILinkifierEvent): void { this._clearCurrentLink(); } } diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index a2e370fc4..1303ec1b5 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -86,11 +86,11 @@ export class DomRenderer extends Disposable implements IRenderer { this._screenElement.appendChild(this._rowContainer); this._screenElement.appendChild(this._selectionContainer); - this._linkifier.onLinkHover(e => this._onLinkHover(e)); - this._linkifier.onLinkLeave(e => this._onLinkLeave(e)); + this._linkifier.onShowLinkUnderline(e => this._onLinkHover(e)); + this._linkifier.onHideLinkUnderline(e => this._onLinkLeave(e)); - this._linkifier2.onLinkHover(e => this._onLinkHover(e)); - this._linkifier2.onLinkLeave(e => this._onLinkLeave(e)); + this._linkifier2.onShowLinkUnderline(e => this._onLinkHover(e)); + this._linkifier2.onHideLinkUnderline(e => this._onLinkLeave(e)); } public dispose(): void { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 9830f4d9f..7570a521c 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1121,7 +1121,8 @@ declare module 'xterm' { text: string; /** - * Whether to hide the link's underline. + * Whether to hide the underline, this property is tracked and changes after the link is + * provided will trigger changes. */ hideUnderline?: boolean; From 832312e095b32c0c955dd5c3ff78cd730352f492 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 18 Apr 2020 06:23:46 -0700 Subject: [PATCH 044/130] Change hideUnderline to hideDecorations Also track cursor style --- src/browser/Linkifier2.ts | 30 +++++++++++++++++------------- src/browser/Types.d.ts | 2 +- typings/xterm.d.ts | 6 +++--- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index b4db56b3a..085b02004 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -10,6 +10,7 @@ import { IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; interface ILinkState { + hideDecorations: boolean; isHovered: boolean; } @@ -176,19 +177,22 @@ export class Linkifier2 implements ILinkifier2 { // Trigger hover if the we have a link at the position if (this._linkAtPosition(link, position)) { this._currentLink = link; - this._currentLinkState = { isHovered: true }; + this._currentLinkState = { + hideDecorations: link.hideDecorations || false, + isHovered: true + }; this._linkHover(this._element, link, this._lastMouseEvent); - // Add listener for tracking hideUnderline changes - let hideUnderlineValue = link.hideUnderline || false; + // Add listener for tracking hideDecorations changes Object.defineProperties(link, { - hideUnderline: { - get: () => hideUnderlineValue, + hideDecorations: { + get: () => this._currentLinkState?.hideDecorations, set: v => { - if (hideUnderlineValue !== v) { - hideUnderlineValue = v; + if (this._currentLinkState && this._currentLinkState.hideDecorations !== v) { + this._currentLinkState.hideDecorations = v; if (this._currentLinkState?.isHovered) { this._fireUnderlineEvent(link, !v); + this._element?.classList.toggle('xterm-cursor-pointer', !v); } } } @@ -205,13 +209,13 @@ export class Linkifier2 implements ILinkifier2 { } protected _linkHover(element: HTMLElement, link: ILink, event: MouseEvent): void { - if (!link.hideUnderline) { + if (!link.hideDecorations) { this._fireUnderlineEvent(link, true); + element.classList.add('xterm-cursor-pointer'); } if (this._currentLinkState) { this._currentLinkState.isHovered = true; } - element.classList.add('xterm-cursor-pointer'); if (link.hover) { link.hover(event, link.text); @@ -221,19 +225,19 @@ export class Linkifier2 implements ILinkifier2 { private _fireUnderlineEvent(link: ILink, showEvent: boolean): void { const range = link.range; const scrollOffset = this._bufferService.buffer.ydisp; - const event = this._createLinkHoverEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined); + const event = this._createLinkUnderlineEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined); const emitter = showEvent ? this._onShowLinkUnderline : this._onHideLinkUnderline; emitter.fire(event); } protected _linkLeave(element: HTMLElement, link: ILink, event: MouseEvent): void { - if (!link.hideUnderline) { + if (!link.hideDecorations) { this._fireUnderlineEvent(link, false); + element.classList.remove('xterm-cursor-pointer'); } if (this._currentLinkState) { this._currentLinkState.isHovered = false; } - element.classList.remove('xterm-cursor-pointer'); if (link.leave) { link.leave(event, link.text); @@ -273,7 +277,7 @@ export class Linkifier2 implements ILinkifier2 { return { x: coords[0], y: coords[1] + this._bufferService.buffer.ydisp }; } - private _createLinkHoverEvent(x1: number, y1: number, x2: number, y2: number, fg: number | undefined): ILinkifierEvent { + private _createLinkUnderlineEvent(x1: number, y1: number, x2: number, y2: number, fg: number | undefined): ILinkifierEvent { return { x1, y1, x2, y2, cols: this._bufferService.cols, fg }; } } diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index b443e486e..382d1c429 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -172,7 +172,7 @@ interface ILinkProvider { interface ILink { range: IBufferRange; text: string; - hideUnderline?: boolean; + hideDecorations?: boolean; activate(event: MouseEvent, text: string): void; hover?(event: MouseEvent, text: string): void; leave?(event: MouseEvent, text: string): void; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 7570a521c..24c069612 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1121,10 +1121,10 @@ declare module 'xterm' { text: string; /** - * Whether to hide the underline, this property is tracked and changes after the link is - * provided will trigger changes. + * Whether to hide the underline and cursor styles, this property is tracked and changes made + * after the link is provided will trigger changes. */ - hideUnderline?: boolean; + hideDecorations?: boolean; /** * Calls when the link is activated. From 88ff19383b0edc2bcc1d153606a0c5933ad730ea Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 18 Apr 2020 09:13:09 -0700 Subject: [PATCH 045/130] Allow embedders to designate link hover elements --- src/browser/Linkifier2.ts | 14 ++++++++++++++ typings/xterm.d.ts | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 085b02004..3f45e6573 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -73,6 +73,20 @@ export class Linkifier2 implements ILinkifier2 { return; } + // Ignore the event if it's an embedder created hover widget + const composedPath = event.composedPath() as HTMLElement[]; + for (let i = 0; i < composedPath.length; i++) { + const target = composedPath[i]; + // Hit Terminal.element, break and continue + if (target.classList.contains('xterm')) { + break; + } + // It's a hover, don't respect hover event + if (target.classList.contains('xterm-hover')) { + return; + } + } + if (!this._lastBufferCell || (position.x !== this._lastBufferCell.x || position.y !== this._lastBufferCell.y)) { this._onHover(position); this._lastBufferCell = position; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 24c069612..c89011766 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1134,7 +1134,9 @@ declare module 'xterm' { activate(event: MouseEvent, text: string): void; /** - * Called when the mouse hovers the link. + * Called when the mouse hovers the link. To use this to create a DOM-based hover tooltip, + * create the hover element within `Terminal.element` and add the `xterm-hover` class to it, + * that will cause mouse events to not fall through and activate other links. * @param event The mouse event triggering the callback. * @param text The text of the link. */ From 1282c060fcc8a5c0225a38a60bf3ee5940106a61 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 18 Apr 2020 18:02:12 -0700 Subject: [PATCH 046/130] Prevent hover callbacks firing if the mouse is outside the viewport Fixes #2849 --- src/browser/Linkifier2.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 3f45e6573..8b8e28949 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -24,6 +24,7 @@ export class Linkifier2 implements ILinkifier2 { private _lastMouseEvent: MouseEvent | undefined; private _linkCacheDisposables: IDisposable[] = []; private _lastBufferCell: IBufferCellPosition | undefined; + private _isMouseOut: boolean = true; private _onShowLinkUnderline = new EventEmitter(); public get onShowLinkUnderline(): IEvent { return this._onShowLinkUnderline.event; } @@ -55,7 +56,10 @@ export class Linkifier2 implements ILinkifier2 { this._mouseService = mouseService; this._renderService = renderService; - this._element.addEventListener('mouseleave', () => this._clearCurrentLink()); + this._element.addEventListener('mouseleave', () => { + this._isMouseOut = true; + this._clearCurrentLink(); + }); this._element.addEventListener('mousemove', this._onMouseMove.bind(this)); this._element.addEventListener('click', this._onClick.bind(this)); } @@ -68,10 +72,10 @@ export class Linkifier2 implements ILinkifier2 { } const position = this._positionFromMouseEvent(event, this._element, this._mouseService); - if (!position) { return; } + this._isMouseOut = false; // Ignore the event if it's an embedder created hover widget const composedPath = event.composedPath() as HTMLElement[]; @@ -115,6 +119,9 @@ export class Linkifier2 implements ILinkifier2 { // There is no link cached, so ask for one this._linkProviders.forEach((linkProvider, i) => { linkProvider.provideLink(position, (link: ILink | undefined) => { + if (this._isMouseOut) { + return; + } providerReplies.set(i, link); // Check if every provider before this one has come back undefined From 2ce435f98d84f7f4baeaee4ac5a8511abe5d3997 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 19 Apr 2020 03:54:28 -0700 Subject: [PATCH 047/130] Allow embedders to customize link decorations independently See microsoft/vscode#95631 --- src/browser/Linkifier2.ts | 58 +++++++++++++++++++++++++-------------- src/browser/Types.d.ts | 7 ++++- typings/xterm.d.ts | 22 +++++++++++++-- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 8b8e28949..f3e49500a 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -3,14 +3,14 @@ * @license MIT */ -import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent } from './Types'; +import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from './Types'; import { IDisposable } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; import { IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; interface ILinkState { - hideDecorations: boolean; + decorations: ILinkDecorations; isHovered: boolean; } @@ -199,21 +199,35 @@ export class Linkifier2 implements ILinkifier2 { if (this._linkAtPosition(link, position)) { this._currentLink = link; this._currentLinkState = { - hideDecorations: link.hideDecorations || false, + decorations: { + underline: link.decorations?.underline || true, + pointerCursor: link.decorations?.pointerCursor || true + }, isHovered: true }; this._linkHover(this._element, link, this._lastMouseEvent); - // Add listener for tracking hideDecorations changes - Object.defineProperties(link, { - hideDecorations: { - get: () => this._currentLinkState?.hideDecorations, + // Add listener for tracking decorations changes + link.decorations = {} as ILinkDecorations; + Object.defineProperties(link.decorations, { + pointerCursor: { + get: () => this._currentLinkState?.decorations.pointerCursor, set: v => { - if (this._currentLinkState && this._currentLinkState.hideDecorations !== v) { - this._currentLinkState.hideDecorations = v; - if (this._currentLinkState?.isHovered) { - this._fireUnderlineEvent(link, !v); - this._element?.classList.toggle('xterm-cursor-pointer', !v); + if (this._currentLinkState && this._currentLinkState?.decorations.pointerCursor !== v) { + this._currentLinkState.decorations.pointerCursor = v; + if (this._currentLinkState.isHovered) { + this._element?.classList.toggle('xterm-cursor-pointer', v); + } + } + } + }, + underline: { + get: () => this._currentLinkState?.decorations.underline, + set: v => { + if (this._currentLinkState && this._currentLinkState?.decorations.underline !== v) { + this._currentLinkState.decorations.underline = v; + if (this._currentLinkState.isHovered) { + this._fireUnderlineEvent(link, v); } } } @@ -230,12 +244,14 @@ export class Linkifier2 implements ILinkifier2 { } protected _linkHover(element: HTMLElement, link: ILink, event: MouseEvent): void { - if (!link.hideDecorations) { - this._fireUnderlineEvent(link, true); - element.classList.add('xterm-cursor-pointer'); - } if (this._currentLinkState) { this._currentLinkState.isHovered = true; + if (this._currentLinkState.decorations.underline) { + this._fireUnderlineEvent(link, true); + } + if (this._currentLinkState.decorations.pointerCursor) { + element.classList.add('xterm-cursor-pointer'); + } } if (link.hover) { @@ -252,12 +268,14 @@ export class Linkifier2 implements ILinkifier2 { } protected _linkLeave(element: HTMLElement, link: ILink, event: MouseEvent): void { - if (!link.hideDecorations) { - this._fireUnderlineEvent(link, false); - element.classList.remove('xterm-cursor-pointer'); - } if (this._currentLinkState) { this._currentLinkState.isHovered = false; + if (this._currentLinkState.decorations.underline) { + this._fireUnderlineEvent(link, false); + } + if (this._currentLinkState.decorations.pointerCursor) { + element.classList.remove('xterm-cursor-pointer'); + } } if (link.leave) { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 382d1c429..f4645543f 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -172,12 +172,17 @@ interface ILinkProvider { interface ILink { range: IBufferRange; text: string; - hideDecorations?: boolean; + decorations?: ILinkDecorations; activate(event: MouseEvent, text: string): void; hover?(event: MouseEvent, text: string): void; leave?(event: MouseEvent, text: string): void; } +interface ILinkDecorations { + pointerCursor: boolean; + underline: boolean; +} + interface IBufferRange { start: IBufferCellPosition; end: IBufferCellPosition; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index c89011766..3487c4104 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1121,10 +1121,11 @@ declare module 'xterm' { text: string; /** - * Whether to hide the underline and cursor styles, this property is tracked and changes made - * after the link is provided will trigger changes. + * What link decorations to show when hovering the link, this property is tracked and changes + * made after the link is provided will trigger changes. If not set, all decroations will be + * enabled. */ - hideDecorations?: boolean; + decorations?: ILinkDecorations; /** * Calls when the link is activated. @@ -1150,6 +1151,21 @@ declare module 'xterm' { leave?(event: MouseEvent, text: string): void; } + /** + * A set of decorations that can be applied to links. + */ + interface ILinkDecorations { + /** + * Whether the cursor is set to pointer. + */ + pointerCursor: boolean; + + /** + * Whether the underline is visible + */ + underline: boolean; + } + /** * A range within a buffer. */ From d0519d6c25acb4bd29a2317682c0fe64f4f0cb72 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 19 Apr 2020 04:20:10 -0700 Subject: [PATCH 048/130] Fix tests --- src/browser/Linkifier2.test.ts | 12 ++++++++++-- src/browser/Linkifier2.ts | 6 +++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/browser/Linkifier2.test.ts b/src/browser/Linkifier2.test.ts index 36a6da431..fb71b6aaa 100644 --- a/src/browser/Linkifier2.test.ts +++ b/src/browser/Linkifier2.test.ts @@ -10,6 +10,14 @@ import { MockBufferService } from 'common/TestUtils.test'; import { ILink } from 'browser/Types'; class TestLinkifier2 extends Linkifier2 { + protected _currentLinkState = { + decorations: { + underline: true, + pointerCursor: true + }, + isHovered: true + }; + constructor(bufferService: IBufferService) { super(bufferService); } @@ -47,7 +55,7 @@ describe('Linkifier2', () => { activate: () => { } }; - it('onLinkHover event range is correct', done => { + it('onShowLinkUnderline event range is correct', done => { linkifier.onShowLinkUnderline(e => { assert.equal(link.range.start.x - 1, e.x1); assert.equal(link.range.start.y - 1, e.y1); @@ -60,7 +68,7 @@ describe('Linkifier2', () => { linkifier.linkHover({ classList: { add: () => { } } } as any, link, {} as any); }); - it('onLinkLeave event range is correct', done => { + it('onHideLinkUnderline event range is correct', done => { linkifier.onHideLinkUnderline(e => { assert.equal(link.range.start.x - 1, e.x1); assert.equal(link.range.start.y - 1, e.y1); diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index f3e49500a..a21f76216 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -20,7 +20,7 @@ export class Linkifier2 implements ILinkifier2 { private _renderService: IRenderService | undefined; private _linkProviders: ILinkProvider[] = []; private _currentLink: ILink | undefined; - private _currentLinkState: ILinkState | undefined; + protected _currentLinkState: ILinkState | undefined; private _lastMouseEvent: MouseEvent | undefined; private _linkCacheDisposables: IDisposable[] = []; private _lastBufferCell: IBufferCellPosition | undefined; @@ -200,8 +200,8 @@ export class Linkifier2 implements ILinkifier2 { this._currentLink = link; this._currentLinkState = { decorations: { - underline: link.decorations?.underline || true, - pointerCursor: link.decorations?.pointerCursor || true + underline: link.decorations === undefined ? true : link.decorations.underline, + pointerCursor: link.decorations === undefined ? true : link.decorations.pointerCursor }, isHovered: true }; From edac29fe51d91eca42b8345819fc872b1ca69e83 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 08:35:06 +0000 Subject: [PATCH 049/130] Bump @types/webpack from 4.41.11 to 4.41.12 Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.11 to 4.41.12. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cfd83fc98..da440ba77 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "@types/mocha": "^7.0.2", "@types/node": "^10.17.17", "@types/utf8": "^2.1.6", - "@types/webpack": "^4.41.11", + "@types/webpack": "^4.41.12", "@types/ws": "^7.2.4", "@typescript-eslint/eslint-plugin": "^2.28.0", "@typescript-eslint/parser": "^2.28.0", diff --git a/yarn.lock b/yarn.lock index 86e751692..94829d05e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -352,10 +352,10 @@ "@types/source-list-map" "*" source-map "^0.6.1" -"@types/webpack@^4.41.11": - version "4.41.11" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.11.tgz#7b7f725397d3b630bede05415d34e9ff30d9771f" - integrity sha512-PtEZISfBMWL05qOpZN19hztZPt0rPuGQh5sbBP3bB4RrJgzdb0SScn47hdcMaoN1IgaU7NZWeDO6reFcKTK2iQ== +"@types/webpack@^4.41.12": + version "4.41.12" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.12.tgz#0386ee2a2814368e2f2397abb036c0bf173ff6c3" + integrity sha512-BpCtM4NnBen6W+KEhrL9jKuZCXVtiH6+0b6cxdvNt2EwU949Al334PjQSl2BeAyvAX9mgoNNG21wvjP3xZJJ5w== dependencies: "@types/anymatch" "*" "@types/node" "*" From 92e5c8d2283da2ccf7c1e18a1be01fcaee68d037 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 13:06:59 +0000 Subject: [PATCH 050/130] Bump ts-loader from 7.0.0 to 7.0.1 Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/TypeStrong/ts-loader/releases) - [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/TypeStrong/ts-loader/compare/v7.0.0...v7.0.1) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index da440ba77..261b92669 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "nyc": "^15.0.1", "playwright-core": "^0.11.1", "source-map-loader": "^0.2.4", - "ts-loader": "^7.0.0", + "ts-loader": "^7.0.1", "typescript": "3.8", "utf8": "^3.0.0", "webpack": "^4.35.3", diff --git a/yarn.lock b/yarn.lock index 94829d05e..5ad983420 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5440,10 +5440,10 @@ triple-beam@^1.2.0, triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-loader@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.0.tgz#7c74dfa8956e3e33b91d98d4ed7b6f7575c35c25" - integrity sha512-qq9iPK235Xf/uPS1I72CIwB8qpbW0rys3entnXO+rIo2km50lMmeHKCNn1m047W6Sk4kceF6n5NWEnq/V8xdYQ== +ts-loader@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.1.tgz#ac9ae9eb8f5ebd0aa7b78b44db20691b6e31251b" + integrity sha512-wdGs9xO8UnwASwbluehzXciBtc9HfGlYA8Aiv856etLmdv8mJfAxCkt3YpS4g7G1IsGxaCVKQ102Qh0zycpeZQ== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" From 7efb141f88f901ab435b92ad13ed8d3c205a9730 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2020 08:13:30 +0000 Subject: [PATCH 051/130] Bump @typescript-eslint/eslint-plugin from 2.28.0 to 2.29.0 Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.28.0 to 2.29.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.29.0/packages/eslint-plugin) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 261b92669..57131649b 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@types/utf8": "^2.1.6", "@types/webpack": "^4.41.12", "@types/ws": "^7.2.4", - "@typescript-eslint/eslint-plugin": "^2.28.0", + "@typescript-eslint/eslint-plugin": "^2.29.0", "@typescript-eslint/parser": "^2.28.0", "chai": "^4.2.0", "deep-equal": "^2.0.2", diff --git a/yarn.lock b/yarn.lock index 5ad983420..5826280d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -371,12 +371,12 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^2.28.0": - version "2.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz#4431bc6d3af41903e5255770703d4e55a0ccbdec" - integrity sha512-w0Ugcq2iatloEabQP56BRWJowliXUP5Wv6f9fKzjJmDW81hOTBxRoJ4LoEOxRpz9gcY51Libytd2ba3yLmSOfg== +"@typescript-eslint/eslint-plugin@^2.29.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.29.0.tgz#c9efab7624e3dd6d144a0e4577a541d1bd42c2ac" + integrity sha512-X/YAY7azKirENm4QRpT7OVmzok02cSkqeIcLmdz6gXUQG4Hk0Fi9oBAynSAyNXeGdMRuZvjBa0c1Lu0dn/u6VA== dependencies: - "@typescript-eslint/experimental-utils" "2.28.0" + "@typescript-eslint/experimental-utils" "2.29.0" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" tsutils "^3.17.1" @@ -391,6 +391,16 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" +"@typescript-eslint/experimental-utils@2.29.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.29.0.tgz#3cb8060de9265ba131625a96bbfec31ba6d4a0fe" + integrity sha512-H/6VJr6eWYstyqjWXBP2Nn1hQJyvJoFdDtsHxGiD+lEP7piGnGpb/ZQd+z1ZSB1F7dN+WsxUDh8+S4LwI+f3jw== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.29.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + "@typescript-eslint/parser@^2.28.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.28.0.tgz#bb761286efd2b0714761cab9d0ee5847cf080385" @@ -414,6 +424,19 @@ semver "^6.3.0" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@2.29.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.29.0.tgz#1be6612bb02fc37ac9f466521c1459a4744e8d3a" + integrity sha512-3YGbtnWy4az16Egy5Fj5CckkVlpIh0MADtAQza+jiMADRSKkjdpzZp/5WuvwK/Qib3Z0HtzrDFeWanS99dNhnA== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" From 0465ba24a2fdf3984fcbc7705a269b3ed1cdd32a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2020 10:22:18 +0000 Subject: [PATCH 052/130] Bump @typescript-eslint/parser from 2.28.0 to 2.29.0 Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.28.0 to 2.29.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.29.0/packages/parser) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 35 ++++++----------------------------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 57131649b..0b954166c 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/webpack": "^4.41.12", "@types/ws": "^7.2.4", "@typescript-eslint/eslint-plugin": "^2.29.0", - "@typescript-eslint/parser": "^2.28.0", + "@typescript-eslint/parser": "^2.29.0", "chai": "^4.2.0", "deep-equal": "^2.0.2", "eslint": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index 5826280d4..3e0e37fe0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -381,16 +381,6 @@ regexpp "^3.0.0" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.28.0": - version "2.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d" - integrity sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.28.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/experimental-utils@2.29.0": version "2.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.29.0.tgz#3cb8060de9265ba131625a96bbfec31ba6d4a0fe" @@ -401,29 +391,16 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.28.0": - version "2.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.28.0.tgz#bb761286efd2b0714761cab9d0ee5847cf080385" - integrity sha512-RqPybRDquui9d+K86lL7iPqH6Dfp9461oyqvlXMNtap+PyqYbkY5dB7LawQjDzot99fqzvS0ZLZdfe+1Bt3Jgw== +"@typescript-eslint/parser@^2.29.0": + version "2.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.29.0.tgz#6e3c4e21ed6393dc05b9d8b47f0b7e731ef21c9c" + integrity sha512-H78M+jcu5Tf6m/5N8iiFblUUv+HJDguMSdFfzwa6vSg9lKR8Mk9BsgeSjO8l2EshKnJKcbv0e8IDDOvSNjl0EA== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.28.0" - "@typescript-eslint/typescript-estree" "2.28.0" + "@typescript-eslint/experimental-utils" "2.29.0" + "@typescript-eslint/typescript-estree" "2.29.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.28.0": - version "2.28.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00" - integrity sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q== - dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^6.3.0" - tsutils "^3.17.1" - "@typescript-eslint/typescript-estree@2.29.0": version "2.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.29.0.tgz#1be6612bb02fc37ac9f466521c1459a4744e8d3a" From 9ece6b1fbcb057fcd9973136ebeade4e69b2cda7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 Apr 2020 18:20:05 -0700 Subject: [PATCH 053/130] Center webgl text vertically Fixes #2613 --- addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts index 6c3369f0d..d9475cb44 100644 --- a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts +++ b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts @@ -349,7 +349,7 @@ export class WebglCharAtlas implements IDisposable { const fontStyle = italic ? 'italic' : ''; this._tmpCtx.font = `${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`; - this._tmpCtx.textBaseline = 'top'; + this._tmpCtx.textBaseline = 'middle'; this._tmpCtx.fillStyle = this._getForegroundCss(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, bold); @@ -359,7 +359,7 @@ export class WebglCharAtlas implements IDisposable { } // Draw the character - this._tmpCtx.fillText(chars, TMP_CANVAS_GLYPH_PADDING, TMP_CANVAS_GLYPH_PADDING); + this._tmpCtx.fillText(chars, TMP_CANVAS_GLYPH_PADDING, TMP_CANVAS_GLYPH_PADDING + this._config.scaledCharHeight / 2); this._tmpCtx.restore(); // clear the background from the character to avoid issues with drawing over the previous From a76a8899247806494b12e6f6e91e7da3ff41bd57 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2020 08:27:07 +0000 Subject: [PATCH 054/130] Bump webpack from 4.42.1 to 4.43.0 Bumps [webpack](https://github.com/webpack/webpack) from 4.42.1 to 4.43.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v4.42.1...v4.43.0) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 0b954166c..812da28ac 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "ts-loader": "^7.0.1", "typescript": "3.8", "utf8": "^3.0.0", - "webpack": "^4.35.3", + "webpack": "^4.43.0", "webpack-cli": "^3.3.11", "ws": "^7.0.0", "xterm-benchmark": "^0.1.3" diff --git a/yarn.lock b/yarn.lock index 3e0e37fe0..503e95b6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -600,7 +600,7 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== -acorn@^6.2.1: +acorn@^6.4.1: version "6.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== @@ -5702,7 +5702,7 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -watchpack@^1.6.0: +watchpack@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.1.tgz#280da0a8718592174010c078c7585a74cd8cd0e2" integrity sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA== @@ -5753,16 +5753,16 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.35.3: - version "4.42.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.1.tgz#ae707baf091f5ca3ef9c38b884287cfe8f1983ef" - integrity sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg== +webpack@^4.43.0: + version "4.43.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" + integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" "@webassemblyjs/wasm-edit" "1.9.0" "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.2.1" + acorn "^6.4.1" ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" @@ -5779,7 +5779,7 @@ webpack@^4.35.3: schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.0" + watchpack "^1.6.1" webpack-sources "^1.4.1" whatwg-encoding@^1.0.5: From 49bf22ace4f361d45bc92d7fece5a5a2c079da70 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2020 08:02:20 +0000 Subject: [PATCH 055/130] Bump deep-equal from 2.0.2 to 2.0.3 Bumps [deep-equal](https://github.com/inspect-js/node-deep-equal) from 2.0.2 to 2.0.3. - [Release notes](https://github.com/inspect-js/node-deep-equal/releases) - [Changelog](https://github.com/inspect-js/node-deep-equal/blob/master/CHANGELOG.md) - [Commits](https://github.com/inspect-js/node-deep-equal/compare/v2.0.2...v2.0.3) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 39 ++++++++++++++++++++++----------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 812da28ac..1878a0bbf 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@typescript-eslint/eslint-plugin": "^2.29.0", "@typescript-eslint/parser": "^2.29.0", "chai": "^4.2.0", - "deep-equal": "^2.0.2", + "deep-equal": "^2.0.3", "eslint": "^6.8.0", "express": "^4.17.1", "express-ws": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 503e95b6d..c51b8b9f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -838,7 +838,7 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.1: +available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== @@ -1638,10 +1638,10 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-equal@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.2.tgz#e68291e245493ae908ca7190c1deea57a01ed82b" - integrity sha512-kX0bjV7tdMuhrhzKPEnVwqfQCuf+IEfN+4Xqv4eKd75xGRyn8yzdQ9ujPY6a221rgJKyQC4KBu1PibDTpa6m9w== +deep-equal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0" + integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA== dependencies: es-abstract "^1.17.5" es-get-iterator "^1.1.0" @@ -1649,13 +1649,14 @@ deep-equal@^2.0.2: is-date-object "^1.0.2" is-regex "^1.0.5" isarray "^2.0.5" - object-is "^1.0.2" + object-is "^1.1.2" object-keys "^1.1.1" + object.assign "^4.1.0" regexp.prototype.flags "^1.3.0" side-channel "^1.0.2" which-boxed-primitive "^1.0.1" which-collection "^1.0.1" - which-typed-array "^1.1.1" + which-typed-array "^1.1.2" deep-is@~0.1.3: version "0.1.3" @@ -4029,10 +4030,13 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-is@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" - integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== +object-is@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" + integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -5829,13 +5833,14 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which-typed-array@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.1.tgz#bff075fd975faedad9ed9355ee0d15452d068794" - integrity sha512-IWlkoJZ4Zdfi4YBn2wnYB8AVox+4A2+Kmr4kHFAraffHYrQZFiTOjgjk9et8e6RSPZOV1QjZOC51PVCK9SkR/A== +which-typed-array@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" + integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== dependencies: - available-typed-arrays "^1.0.1" - es-abstract "^1.17.4" + available-typed-arrays "^1.0.2" + es-abstract "^1.17.5" + foreach "^2.0.5" function-bind "^1.1.1" has-symbols "^1.0.1" is-typed-array "^1.1.3" From 50ba6bfa1b32093241070ec2ce89443226ba6f27 Mon Sep 17 00:00:00 2001 From: rishab Date: Sat, 25 Apr 2020 03:13:19 -0700 Subject: [PATCH 056/130] Wrap search back if there exists a result in search Search must wrap back as it does when there are multiple lines. --- addons/xterm-addon-search/src/SearchAddon.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index ba8dbc072..fa473a71b 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -110,8 +110,16 @@ export class SearchAddon implements ITerminalAddon { } } - // If there is only one result, return true. if (!result && currentSelection) return true; + // If there is only one result, wrap back and return selection if exists. + if (!result && currentSelection) { + searchPosition.startRow = currentSelection.startRow; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); + if (result) { + return this._selectResult(result); + } + } // Set selection and scroll if a result was found return this._selectResult(result); From 45ff3ee6379c2fb1c775fa953cd12eed77c932b5 Mon Sep 17 00:00:00 2001 From: rishab Date: Sat, 25 Apr 2020 03:13:32 -0700 Subject: [PATCH 057/130] Update SearchAddon.ts --- addons/xterm-addon-search/src/SearchAddon.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index fa473a71b..e22c8b7c8 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -110,7 +110,6 @@ export class SearchAddon implements ITerminalAddon { } } - if (!result && currentSelection) return true; // If there is only one result, wrap back and return selection if exists. if (!result && currentSelection) { searchPosition.startRow = currentSelection.startRow; From 1134d0d7d4ab86093be74861768a1006161f9f9a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 06:22:08 -0700 Subject: [PATCH 058/130] Refresh model colors after changing theme Fixes #2595 --- addons/xterm-addon-webgl/src/GlyphRenderer.ts | 4 ++-- addons/xterm-addon-webgl/src/RectangleRenderer.ts | 4 ++-- addons/xterm-addon-webgl/src/RenderModel.ts | 1 + addons/xterm-addon-webgl/src/Types.d.ts | 1 + addons/xterm-addon-webgl/src/WebglRenderer.ts | 12 ++++++++---- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index f8eed3ae8..8be4c011e 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -213,14 +213,14 @@ export class GlyphRenderer { // a_cellpos only changes on resize } - public updateSelection(model: IRenderModel, columnSelectMode: boolean): void { + public updateSelection(model: IRenderModel): void { const terminal = this._terminal; this._vertices.selectionAttributes = slice(this._vertices.attributes, 0); const bg = (this._colors.selectionOpaque.rgba >>> 8) | Attributes.CM_RGB; - if (columnSelectMode) { + if (model.selection.columnSelectMode) { const startCol = model.selection.startCol; const width = model.selection.endCol - startCol; const height = model.selection.viewportCappedEndRow - model.selection.viewportCappedStartRow + 1; diff --git a/addons/xterm-addon-webgl/src/RectangleRenderer.ts b/addons/xterm-addon-webgl/src/RectangleRenderer.ts index 2246cddd9..2b216f0dd 100644 --- a/addons/xterm-addon-webgl/src/RectangleRenderer.ts +++ b/addons/xterm-addon-webgl/src/RectangleRenderer.ts @@ -171,7 +171,7 @@ export class RectangleRenderer { ); } - public updateSelection(model: ISelectionRenderModel, columnSelectMode: boolean): void { + public updateSelection(model: ISelectionRenderModel): void { const terminal = this._terminal; if (!model.hasSelection) { @@ -179,7 +179,7 @@ export class RectangleRenderer { return; } - if (columnSelectMode) { + if (model.columnSelectMode) { const startCol = model.startCol; const width = model.endCol - startCol; const height = model.viewportCappedEndRow - model.viewportCappedStartRow + 1; diff --git a/addons/xterm-addon-webgl/src/RenderModel.ts b/addons/xterm-addon-webgl/src/RenderModel.ts index 2b48047f8..194f1778d 100644 --- a/addons/xterm-addon-webgl/src/RenderModel.ts +++ b/addons/xterm-addon-webgl/src/RenderModel.ts @@ -22,6 +22,7 @@ export class RenderModel implements IRenderModel { this.lineLengths = new Uint32Array(0); this.selection = { hasSelection: false, + columnSelectMode: false, viewportStartRow: 0, viewportEndRow: 0, viewportCappedStartRow: 0, diff --git a/addons/xterm-addon-webgl/src/Types.d.ts b/addons/xterm-addon-webgl/src/Types.d.ts index f01092eec..d8a27aa78 100644 --- a/addons/xterm-addon-webgl/src/Types.d.ts +++ b/addons/xterm-addon-webgl/src/Types.d.ts @@ -56,6 +56,7 @@ export interface IRenderModel { export interface ISelectionRenderModel { hasSelection: boolean; + columnSelectMode: boolean; viewportStartRow: number; viewportEndRow: number; viewportCappedStartRow: number; diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 8d52a35e6..326329186 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -117,6 +117,9 @@ export class WebglRenderer extends Disposable implements IRenderer { this._refreshCharAtlas(); + this._rectangleRenderer.updateSelection(this._model.selection); + this._glyphRenderer.updateSelection(this._model); + // Force a full refresh this._model.clear(); } @@ -173,10 +176,10 @@ export class WebglRenderer extends Disposable implements IRenderer { public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end, columnSelectMode)); - this._updateSelectionModel(start, end); + this._updateSelectionModel(start, end, columnSelectMode); - this._rectangleRenderer.updateSelection(this._model.selection, columnSelectMode); - this._glyphRenderer.updateSelection(this._model, columnSelectMode); + this._rectangleRenderer.updateSelection(this._model.selection); + this._glyphRenderer.updateSelection(this._model); this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 }); } @@ -292,7 +295,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._rectangleRenderer.updateBackgrounds(this._model); } - private _updateSelectionModel(start: [number, number], end: [number, number]): void { + private _updateSelectionModel(start: [number, number], end: [number, number], columnSelectMode: boolean): void { const terminal = this._terminal; // Selection does not exist @@ -314,6 +317,7 @@ export class WebglRenderer extends Disposable implements IRenderer { } this._model.selection.hasSelection = true; + this._model.selection.columnSelectMode = columnSelectMode; this._model.selection.viewportStartRow = viewportStartRow; this._model.selection.viewportEndRow = viewportEndRow; this._model.selection.viewportCappedStartRow = viewportCappedStartRow; From 22aaf0471a0911ec3c0158636dc1bdb199a1430f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 06:41:25 -0700 Subject: [PATCH 059/130] Invalidate all links above when the terminal scrolls See microsoft/vscode#95556 --- src/browser/Linkifier2.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index a21f76216..bcdbffe63 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -237,7 +237,10 @@ export class Linkifier2 implements ILinkifier2 { // Add listener for rerendering if (this._renderService) { this._linkCacheDisposables.push(this._renderService.onRenderedBufferChange(e => { - this._clearCurrentLink(e.start + 1 + this._bufferService.buffer.ydisp, e.end + 1 + this._bufferService.buffer.ydisp); + // When start is 0 a scroll most likely occurred, make sure links above the fold also get + // cleared. + const start = e.start === 0 ? 0 : e.start + 1 + this._bufferService.buffer.ydisp; + this._clearCurrentLink(start, e.end + 1 + this._bufferService.buffer.ydisp); })); } } From 3a5def98e574909ad34385c0bcaa3112a6807e0e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 06:56:00 -0700 Subject: [PATCH 060/130] Correct selection types being optional --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 4 ++-- addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts | 2 +- addons/xterm-addon-webgl/src/renderLayer/Types.ts | 2 +- src/browser/renderer/BaseRenderLayer.ts | 2 +- src/browser/renderer/Renderer.ts | 2 +- src/browser/renderer/SelectionRenderLayer.ts | 4 ++-- src/browser/renderer/Types.d.ts | 4 ++-- src/browser/renderer/dom/DomRenderer.ts | 2 +- src/browser/services/RenderService.ts | 2 +- src/browser/services/Services.ts | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 8d52a35e6..4ea4589a0 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -170,7 +170,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._renderLayers.forEach(l => l.onFocus(this._terminal)); } - public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void { this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end, columnSelectMode)); this._updateSelectionModel(start, end); @@ -292,7 +292,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._rectangleRenderer.updateBackgrounds(this._model); } - private _updateSelectionModel(start: [number, number], end: [number, number]): void { + private _updateSelectionModel(start: [number, number] | undefined, end: [number, number] | undefined): void { const terminal = this._terminal; // Selection does not exist diff --git a/addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts index 93f844927..da3b4d418 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts @@ -58,7 +58,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { public onFocus(terminal: Terminal): void {} public onCursorMove(terminal: Terminal): void {} public onGridChanged(terminal: Terminal, startRow: number, endRow: number): void {} - public onSelectionChanged(terminal: Terminal, start: [number, number], end: [number, number], columnSelectMode: boolean = false): void {} + public onSelectionChanged(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {} public setColors(terminal: Terminal, colorSet: IColorSet): void { this._refreshCharAtlas(terminal, colorSet); diff --git a/addons/xterm-addon-webgl/src/renderLayer/Types.ts b/addons/xterm-addon-webgl/src/renderLayer/Types.ts index 148ea4695..70acff340 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/Types.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/Types.ts @@ -42,7 +42,7 @@ export interface IRenderLayer extends IDisposable { /** * Calls when the selection changes. */ - onSelectionChanged(terminal: Terminal, start: [number, number], end: [number, number], columnSelectMode: boolean): void; + onSelectionChanged(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void; /** * Registers a handler to join characters to render as a group diff --git a/src/browser/renderer/BaseRenderLayer.ts b/src/browser/renderer/BaseRenderLayer.ts index 595aa1a52..837f18e42 100644 --- a/src/browser/renderer/BaseRenderLayer.ts +++ b/src/browser/renderer/BaseRenderLayer.ts @@ -77,7 +77,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { public onFocus(): void {} public onCursorMove(): void {} public onGridChanged(startRow: number, endRow: number): void {} - public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean = false): void {} + public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {} public setColors(colorSet: IColorSet): void { this._refreshCharAtlas(colorSet); diff --git a/src/browser/renderer/Renderer.ts b/src/browser/renderer/Renderer.ts index 0856553f1..5142e4cb4 100644 --- a/src/browser/renderer/Renderer.ts +++ b/src/browser/renderer/Renderer.ts @@ -119,7 +119,7 @@ export class Renderer extends Disposable implements IRenderer { this._runOperation(l => l.onFocus()); } - public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean = false): void { + public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { this._runOperation(l => l.onSelectionChanged(start, end, columnSelectMode)); } diff --git a/src/browser/renderer/SelectionRenderLayer.ts b/src/browser/renderer/SelectionRenderLayer.ts index 257944fcb..5689ce932 100644 --- a/src/browser/renderer/SelectionRenderLayer.ts +++ b/src/browser/renderer/SelectionRenderLayer.ts @@ -52,7 +52,7 @@ export class SelectionRenderLayer extends BaseRenderLayer { } } - public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void { // Selection has not changed if (!this._didStateChange(start, end, columnSelectMode, this._bufferService.buffer.ydisp)) { return; @@ -110,7 +110,7 @@ export class SelectionRenderLayer extends BaseRenderLayer { this._state.ydisp = this._bufferService.buffer.ydisp; } - private _didStateChange(start: [number, number], end: [number, number], columnSelectMode: boolean, ydisp: number): boolean { + private _didStateChange(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean, ydisp: number): boolean { return !this._areCoordinatesEqual(start, this._state.start) || !this._areCoordinatesEqual(end, this._state.end) || columnSelectMode !== this._state.columnSelectMode || diff --git a/src/browser/renderer/Types.d.ts b/src/browser/renderer/Types.d.ts index 02c62ab2e..cab14b88e 100644 --- a/src/browser/renderer/Types.d.ts +++ b/src/browser/renderer/Types.d.ts @@ -49,7 +49,7 @@ export interface IRenderer extends IDisposable { onCharSizeChanged(): void; onBlur(): void; onFocus(): void; - onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void; + onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void; onCursorMove(): void; onOptionsChanged(): void; clear(): void; @@ -104,7 +104,7 @@ export interface IRenderLayer extends IDisposable { /** * Calls when the selection changes. */ - onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void; + onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void; /** * Registers a handler to join characters to render as a group diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 1303ec1b5..ff9551404 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -273,7 +273,7 @@ export class DomRenderer extends Disposable implements IRenderer { this._rowContainer.classList.add(FOCUS_CLASS); } - public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void { // Remove all selections while (this._selectionContainer.children.length) { this._selectionContainer.removeChild(this._selectionContainer.children[0]); diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index d7ff58147..109db2e6d 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -163,7 +163,7 @@ export class RenderService extends Disposable implements IRenderService { this._renderer.onFocus(); } - public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void { this._renderer.onSelectionChanged(start, end, columnSelectMode); } diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index 3754e6fed..7a559dabd 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -63,7 +63,7 @@ export interface IRenderService extends IDisposable { onCharSizeChanged(): void; onBlur(): void; onFocus(): void; - onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void; + onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void; onCursorMove(): void; clear(): void; registerCharacterJoiner(handler: CharacterJoinerHandler): number; From c185529ad5e1fe6cade88ca98159d882c992f97d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 07:11:43 -0700 Subject: [PATCH 061/130] Make sure selection gets redrawn when switching renderers Fixes #2555 --- src/browser/RenderDebouncer.ts | 12 ++++++------ src/browser/services/RenderService.ts | 28 ++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/browser/RenderDebouncer.ts b/src/browser/RenderDebouncer.ts index 27c866dfd..814afcef4 100644 --- a/src/browser/RenderDebouncer.ts +++ b/src/browser/RenderDebouncer.ts @@ -49,15 +49,15 @@ export class RenderDebouncer implements IDisposable { } // Clamp values - this._rowStart = Math.max(this._rowStart, 0); - this._rowEnd = Math.min(this._rowEnd, this._rowCount - 1); + const start = Math.max(this._rowStart, 0); + const end = Math.min(this._rowEnd, this._rowCount - 1); - // Run render callback - this._renderCallback(this._rowStart, this._rowEnd); - - // Reset debouncer + // Reset debouncer (this happens before render callback as the render could trigger it again) this._rowStart = undefined; this._rowEnd = undefined; this._animationFrame = undefined; + + // Run render callback + this._renderCallback(start, end); } } diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 109db2e6d..7c8a13cc6 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -13,6 +13,12 @@ import { IColorSet } from 'browser/Types'; import { IOptionsService } from 'common/services/Services'; import { ICharSizeService, IRenderService } from 'browser/services/Services'; +interface ISelectionState { + start: [number, number] | undefined; + end: [number, number] | undefined; + columnSelectMode: boolean; +} + export class RenderService extends Disposable implements IRenderService { public serviceBrand: any; @@ -22,8 +28,14 @@ export class RenderService extends Disposable implements IRenderService { private _isPaused: boolean = false; private _needsFullRefresh: boolean = false; private _isNextRenderRedrawOnly: boolean = true; + private _needsSelectionRefresh: boolean = false; private _canvasWidth: number = 0; private _canvasHeight: number = 0; + private _selectionState: ISelectionState = { + start: undefined, + end: undefined, + columnSelectMode: false + }; private _onDimensionsChange = new EventEmitter(); public get onDimensionsChange(): IEvent { return this._onDimensionsChange.event; } @@ -89,6 +101,14 @@ export class RenderService extends Disposable implements IRenderService { private _renderRows(start: number, end: number): void { this._renderer.renderRows(start, end); + + // Update selection if needed + if (this._needsSelectionRefresh) { + this._renderer.onSelectionChanged(this._selectionState.start, this._selectionState.end, this._selectionState.columnSelectMode); + this._needsSelectionRefresh = false; + } + + // Fire render event only if it was not a redraw if (!this._isNextRenderRedrawOnly) { this._onRender.fire({ start, end }); } @@ -124,7 +144,10 @@ export class RenderService extends Disposable implements IRenderService { this._renderer.dispose(); this._renderer = renderer; this._renderer.onRequestRedraw(e => this.refreshRows(e.start, e.end, true)); - this.refreshRows(0, this._rowCount - 1); + + // Force a refresh + this._needsSelectionRefresh = true; + this._fullRefresh(); } private _fullRefresh(): void { @@ -164,6 +187,9 @@ export class RenderService extends Disposable implements IRenderService { } public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void { + this._selectionState.start = start; + this._selectionState.end = end; + this._selectionState.columnSelectMode = columnSelectMode; this._renderer.onSelectionChanged(start, end, columnSelectMode); } From a5d50960a73705996c5f4691cf3efd8dc4833f35 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 07:27:09 -0700 Subject: [PATCH 062/130] Support DI in UnicodeService --- src/Terminal.test.ts | 4 ++-- src/Terminal.ts | 2 +- src/browser/Linkifier.test.ts | 4 ++-- src/browser/Linkifier.ts | 7 +++---- src/common/TestUtils.test.ts | 1 + src/common/services/Services.ts | 1 + src/common/services/UnicodeService.ts | 2 ++ 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index e2bd4d56c..4d590699b 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -9,7 +9,7 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { IBufferService, IUnicodeService } from 'common/services/Services'; import { Linkifier } from 'browser/Linkifier'; -import { MockLogService, MockOptionsService, MockUnicodeService } from 'common/TestUtils.test'; +import { MockLogService, MockUnicodeService } from 'common/TestUtils.test'; import { IRegisteredLinkMatcher, IMouseZoneManager, IMouseZone } from 'browser/Types'; const INIT_COLS = 80; @@ -1407,7 +1407,7 @@ describe('Terminal', () => { class TestLinkifier extends Linkifier { constructor(bufferService: IBufferService, unicodeService: IUnicodeService) { - super(bufferService, new MockLogService(), new MockOptionsService(), unicodeService); + super(bufferService, new MockLogService(), unicodeService); Linkifier._timeBeforeLatency = 0; } diff --git a/src/Terminal.ts b/src/Terminal.ts index ea6898775..e71881641 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -257,7 +257,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp } if (!this.linkifier) { - this.linkifier = new Linkifier(this._bufferService, this._logService, this.optionsService, this.unicodeService); + this.linkifier = this._instantiationService.createInstance(Linkifier); } if (!this.linkifier2) { this.linkifier2 = new Linkifier2(this._bufferService); diff --git a/src/browser/Linkifier.test.ts b/src/browser/Linkifier.test.ts index c0dc6bf6d..81741df49 100644 --- a/src/browser/Linkifier.test.ts +++ b/src/browser/Linkifier.test.ts @@ -9,13 +9,13 @@ import { IBufferLine } from 'common/Types'; import { Linkifier } from 'browser/Linkifier'; import { BufferLine } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; -import { MockLogService, MockBufferService, MockOptionsService } from 'common/TestUtils.test'; +import { MockLogService, MockBufferService } from 'common/TestUtils.test'; import { IBufferService } from 'common/services/Services'; import { UnicodeService } from 'common/services/UnicodeService'; class TestLinkifier extends Linkifier { constructor(bufferService: IBufferService) { - super(bufferService, new MockLogService(), new MockOptionsService(), new UnicodeService()); + super(bufferService, new MockLogService(), new UnicodeService()); Linkifier._timeBeforeLatency = 0; } diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index ca45ef2a9..6d25e7303 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -43,10 +43,9 @@ export class Linkifier implements ILinkifier { public get onLinkTooltip(): IEvent { return this._onLinkTooltip.event; } constructor( - protected readonly _bufferService: IBufferService, - private readonly _logService: ILogService, - private readonly _optionsService: IOptionsService, - private readonly _unicodeService: IUnicodeService + @IBufferService protected readonly _bufferService: IBufferService, + @ILogService private readonly _logService: ILogService, + @IUnicodeService private readonly _unicodeService: IUnicodeService ) { this._rowsToLinkify = { start: undefined, diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 7e024140a..cfa1abd77 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -109,6 +109,7 @@ export class MockOptionsService implements IOptionsService { // defaults to V6 always to keep tests passing export class MockUnicodeService implements IUnicodeService { + public serviceBrand: any; private _provider = new UnicodeV6(); public register(provider: IUnicodeVersionProvider): void { throw new Error('Method not implemented.'); diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 0f3ab374f..8a3e9b287 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -311,6 +311,7 @@ export interface ITheme { export const IUnicodeService = createDecorator('UnicodeService'); export interface IUnicodeService { + serviceBrand: any; /** Register an Unicode version provider. */ register(provider: IUnicodeVersionProvider): void; /** Registered Unicode versions. */ diff --git a/src/common/services/UnicodeService.ts b/src/common/services/UnicodeService.ts index 14b9979f6..e96b75793 100644 --- a/src/common/services/UnicodeService.ts +++ b/src/common/services/UnicodeService.ts @@ -8,6 +8,8 @@ import { UnicodeV6 } from 'common/input/UnicodeV6'; export class UnicodeService implements IUnicodeService { + public serviceBrand: any; + private _providers: {[key: string]: IUnicodeVersionProvider} = Object.create(null); private _active: string = ''; private _activeProvider: IUnicodeVersionProvider; From e3c81048af17b8a37b8cd2a643d4ecf493de1b25 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 07:29:07 -0700 Subject: [PATCH 063/130] Use DI with Linkifier2 --- src/Terminal.ts | 2 +- src/browser/Linkifier2.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index e71881641..e3a3801d9 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -260,7 +260,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this.linkifier = this._instantiationService.createInstance(Linkifier); } if (!this.linkifier2) { - this.linkifier2 = new Linkifier2(this._bufferService); + this.linkifier2 = this._instantiationService.createInstance(Linkifier2); } if (this.options.windowsMode) { diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index bcdbffe63..548121699 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -32,7 +32,7 @@ export class Linkifier2 implements ILinkifier2 { public get onHideLinkUnderline(): IEvent { return this._onHideLinkUnderline.event; } constructor( - private readonly _bufferService: IBufferService + @IBufferService private readonly _bufferService: IBufferService ) { } From 353a8c5388e3242af4957da5b89fc50a6e8ab663 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 10:21:31 -0700 Subject: [PATCH 064/130] Create CoreTerminal, fix createInstance in strict mode --- .vscode/settings.json | 3 +- .../src/WebglRenderer.api.ts | 2 +- src/Terminal.ts | 29 ++----- src/TestUtils.test.ts | 4 +- src/Types.d.ts | 10 +-- src/browser/TestUtils.test.ts | 6 +- src/browser/services/CharSizeService.ts | 2 +- src/browser/services/CoreBrowserService.ts | 2 +- src/browser/services/MouseService.ts | 2 +- src/browser/services/RenderService.ts | 2 +- src/browser/services/SelectionService.ts | 2 +- src/browser/services/Services.ts | 12 +-- src/browser/services/SoundService.ts | 2 +- src/browser/tsconfig.json | 5 +- src/common/CoreTerminal.ts | 56 ++++++++++++++ src/common/Types.d.ts | 9 +++ src/common/services/Services.ts | 75 ++++++------------- src/common/tsconfig.json | 5 +- src/tsconfig-base.json | 3 +- 19 files changed, 127 insertions(+), 104 deletions(-) create mode 100644 src/common/CoreTerminal.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index f07ca5457..38f4dd110 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "typescript.preferences.importModuleSpecifier": "non-relative", - "typescript.preferences.quoteStyle": "single" + "typescript.preferences.quoteStyle": "single", + "eslint.enable": true } diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index daf7f6fca..7165edb32 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminalOptions } from '../../../src/Types'; +import { ITerminalOptions } from '../../../src/common/Types'; import { ITheme } from 'xterm'; import { assert } from 'chai'; import { openTerminal, pollFor, writeSync, getBrowserType } from '../../../out-test/api/TestUtils'; diff --git a/src/Terminal.ts b/src/Terminal.ts index e3a3801d9..4a0bd82c8 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -21,7 +21,7 @@ * http://linux.die.net/man/7/urxvt */ -import { IInputHandlingTerminal, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; +import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; @@ -39,39 +39,36 @@ import { MouseZoneManager } from 'browser/MouseZoneManager'; import { AccessibilityManager } from './AccessibilityManager'; import { ITheme, IMarker, IDisposable, ISelectionPosition, ILinkProvider } from 'xterm'; import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; -import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types'; +import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { EventEmitter, IEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { updateWindowsModeWrappedState } from 'common/WindowsMode'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; -import { IOptionsService, IBufferService, ICoreMouseService, ICoreService, ILogService, IDirtyRowService, IInstantiationService, ICharsetService, IUnicodeService } from 'common/services/Services'; -import { OptionsService } from 'common/services/OptionsService'; +import { ICoreMouseService, ICoreService, IDirtyRowService, ICharsetService, IUnicodeService } from 'common/services/Services'; import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services'; import { CharSizeService } from 'browser/services/CharSizeService'; -import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; -import { Disposable } from 'common/Lifecycle'; +import { MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { CoreService } from 'common/services/CoreService'; -import { LogService } from 'common/services/LogService'; import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { DirtyRowService } from 'common/services/DirtyRowService'; -import { InstantiationService } from 'common/services/InstantiationService'; import { CoreMouseService } from 'common/services/CoreMouseService'; import { WriteBuffer } from 'common/input/WriteBuffer'; import { Linkifier2 } from 'browser/Linkifier2'; import { CoreBrowserService } from 'browser/services/CoreBrowserService'; import { UnicodeService } from 'common/services/UnicodeService'; import { CharsetService } from 'common/services/CharsetService'; +import { CoreTerminal } from 'common/CoreTerminal'; // Let it work inside Node.js for automated testing purposes. const document = (typeof window !== 'undefined') ? window.document : null; -export class Terminal extends Disposable implements ITerminal, IDisposable, IInputHandlingTerminal { +export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingTerminal { public textarea: HTMLTextAreaElement; public element: HTMLElement; public screenElement: HTMLElement; @@ -92,14 +89,10 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp private _customKeyEventHandler: CustomKeyEventHandler; // common services - private _bufferService: IBufferService; private _coreService: ICoreService; private _charsetService: ICharsetService; private _coreMouseService: ICoreMouseService; private _dirtyRowService: IDirtyRowService; - private _instantiationService: IInstantiationService; - private _logService: ILogService; - public optionsService: IOptionsService; public unicodeService: IUnicodeService; // browser services @@ -192,16 +185,10 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp constructor( options: ITerminalOptions = {} ) { - super(); + super(options); + // TODO: Move these to CoreTerminal.ts // Setup and initialize common services - this._instantiationService = new InstantiationService(); - this.optionsService = new OptionsService(options); - this._instantiationService.setService(IOptionsService, this.optionsService); - this._bufferService = this._instantiationService.createInstance(BufferService); - this._instantiationService.setService(IBufferService, this._bufferService); - this._logService = this._instantiationService.createInstance(LogService); - this._instantiationService.setService(ILogService, this._logService); this._coreService = this._instantiationService.createInstance(CoreService, () => this.scrollToBottom()); this._instantiationService.setService(ICoreService, this._coreService); this._coreService.onData(e => this._onData.fire(e)); diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index cac0a43de..f0c56f156 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -4,9 +4,9 @@ */ import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; -import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions } from './Types'; +import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser } from './Types'; import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; -import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset } from 'common/Types'; +import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; import { Buffer } from 'common/buffer/Buffer'; import * as Browser from 'common/Platform'; import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm'; diff --git a/src/Types.d.ts b/src/Types.d.ts index cb0ba8444..14494e898 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -4,7 +4,7 @@ */ import { ITerminalOptions as IPublicTerminalOptions, IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; -import { ICharset, IAttributeData, CharData, CoreMouseEventType } from 'common/Types'; +import { ICharset, IAttributeData, CharData, CoreMouseEventType, ITerminalOptions } from 'common/Types'; import { IEvent, IEventEmitter } from 'common/EventEmitter'; import { IColorSet, ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { IOptionsService, IUnicodeService } from 'common/services/Services'; @@ -216,14 +216,6 @@ export interface ILinkifierAccessor { linkifier2: ILinkifier2; } -// TODO: The options that are not in the public API should be reviewed -export interface ITerminalOptions extends IPublicTerminalOptions { - [key: string]: any; - cancelEvents?: boolean; - convertEol?: boolean; - termName?: string; -} - export interface IBrowser { isNode: boolean; userAgent: string; diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 96d1eae09..1869ab874 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -9,7 +9,7 @@ import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/re import { IColorSet } from 'browser/Types'; export class MockCharSizeService implements ICharSizeService { - public serviceBrand: any; + public serviceBrand: undefined; public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } public onCharSizeChange: IEvent = new EventEmitter().event; constructor(public width: number, public height: number) {} @@ -17,7 +17,7 @@ export class MockCharSizeService implements ICharSizeService { } export class MockMouseService implements IMouseService { - public serviceBrand: any; + public serviceBrand: undefined; public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined { throw new Error('Not implemented'); } @@ -28,7 +28,7 @@ export class MockMouseService implements IMouseService { } export class MockRenderService implements IRenderService { - public serviceBrand: any; + public serviceBrand: undefined; public onDimensionsChange: IEvent = new EventEmitter().event; public onRenderedBufferChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; diff --git a/src/browser/services/CharSizeService.ts b/src/browser/services/CharSizeService.ts index 7623109ce..79696a281 100644 --- a/src/browser/services/CharSizeService.ts +++ b/src/browser/services/CharSizeService.ts @@ -8,7 +8,7 @@ import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICharSizeService } from 'browser/services/Services'; export class CharSizeService implements ICharSizeService { - public serviceBrand: any; + public serviceBrand: undefined; public width: number = 0; public height: number = 0; diff --git a/src/browser/services/CoreBrowserService.ts b/src/browser/services/CoreBrowserService.ts index e3207d7bb..985253d9a 100644 --- a/src/browser/services/CoreBrowserService.ts +++ b/src/browser/services/CoreBrowserService.ts @@ -6,7 +6,7 @@ import { ICoreBrowserService } from './Services'; export class CoreBrowserService implements ICoreBrowserService { - public serviceBrand: any; + public serviceBrand: undefined; constructor( private _textarea: HTMLTextAreaElement diff --git a/src/browser/services/MouseService.ts b/src/browser/services/MouseService.ts index 39df63839..348ba64e6 100644 --- a/src/browser/services/MouseService.ts +++ b/src/browser/services/MouseService.ts @@ -7,7 +7,7 @@ import { ICharSizeService, IRenderService, IMouseService } from './Services'; import { getCoords, getRawByteCoords } from 'browser/input/Mouse'; export class MouseService implements IMouseService { - public serviceBrand: any; + public serviceBrand: undefined; constructor( @IRenderService private readonly _renderService: IRenderService, diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index d7ff58147..61ba35ab0 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -14,7 +14,7 @@ import { IOptionsService } from 'common/services/Services'; import { ICharSizeService, IRenderService } from 'browser/services/Services'; export class RenderService extends Disposable implements IRenderService { - public serviceBrand: any; + public serviceBrand: undefined; private _renderDebouncer: RenderDebouncer; private _screenDprMonitor: ScreenDprMonitor; diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index 43875f1b2..d70cfa11a 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -67,7 +67,7 @@ export const enum SelectionMode { * when the selection is ready to be redrawn (on an animation frame). */ export class SelectionService implements ISelectionService { - public serviceBrand: any; + public serviceBrand: undefined; protected _model: SelectionModel; diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index 3754e6fed..28b839852 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -12,7 +12,7 @@ import { IDisposable } from 'common/Types'; export const ICharSizeService = createDecorator('CharSizeService'); export interface ICharSizeService { - serviceBrand: any; + serviceBrand: undefined; readonly width: number; readonly height: number; @@ -25,14 +25,14 @@ export interface ICharSizeService { export const ICoreBrowserService = createDecorator('CoreBrowserService'); export interface ICoreBrowserService { - serviceBrand: any; + serviceBrand: undefined; readonly isFocused: boolean; } export const IMouseService = createDecorator('MouseService'); export interface IMouseService { - serviceBrand: any; + serviceBrand: undefined; getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined; getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined; @@ -40,7 +40,7 @@ export interface IMouseService { export const IRenderService = createDecorator('RenderService'); export interface IRenderService extends IDisposable { - serviceBrand: any; + serviceBrand: undefined; onDimensionsChange: IEvent; /** @@ -72,7 +72,7 @@ export interface IRenderService extends IDisposable { export const ISelectionService = createDecorator('SelectionService'); export interface ISelectionService { - serviceBrand: any; + serviceBrand: undefined; readonly selectionText: string; readonly hasSelection: boolean; @@ -100,7 +100,7 @@ export interface ISelectionService { export const ISoundService = createDecorator('SoundService'); export interface ISoundService { - serviceBrand: any; + serviceBrand: undefined; playBellSound(): void; } diff --git a/src/browser/services/SoundService.ts b/src/browser/services/SoundService.ts index 4b54c9990..8d940c13d 100644 --- a/src/browser/services/SoundService.ts +++ b/src/browser/services/SoundService.ts @@ -7,7 +7,7 @@ import { IOptionsService } from 'common/services/Services'; import { ISoundService } from 'browser/services/Services'; export class SoundService implements ISoundService { - public serviceBrand: any; + public serviceBrand: undefined; private static _audioContext: AudioContext; diff --git a/src/browser/tsconfig.json b/src/browser/tsconfig.json index 7465bbd3f..74b4c0577 100644 --- a/src/browser/tsconfig.json +++ b/src/browser/tsconfig.json @@ -14,7 +14,10 @@ "common/*": [ "./common/*" ] } }, - "include": [ "./**/*" ], + "include": [ + "./**/*", + "../../typings/xterm.d.ts" + ], "references": [ { "path": "../common" } ] diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts new file mode 100644 index 000000000..6930ce072 --- /dev/null +++ b/src/common/CoreTerminal.ts @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2014-2020 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * @license MIT + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + * + * Terminal Emulation References: + * http://vt100.net/ + * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt + * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * http://invisible-island.net/vttest/ + * http://www.inwap.com/pdp10/ansicode.txt + * http://linux.die.net/man/4/console_codes + * http://linux.die.net/man/7/urxvt + */ + +import { Disposable } from 'common/Lifecycle'; +import { IInstantiationService, IOptionsService, IBufferService, ILogService } from 'common/services/Services'; +import { InstantiationService } from 'common/services/InstantiationService'; +import { LogService } from 'common/services/LogService'; +import { BufferService } from 'common/services/BufferService'; +import { OptionsService } from 'common/services/OptionsService'; +import { ITerminalOptions } from './Types'; + +export class CoreTerminal extends Disposable { + protected readonly _instantiationService: IInstantiationService; + protected readonly _bufferService: IBufferService; + protected readonly _logService: ILogService; + + public readonly optionsService: IOptionsService; + + constructor( + options: ITerminalOptions + ) { + super(); + + // Setup and initialize services + this._instantiationService = new InstantiationService(); + this.optionsService = new OptionsService(options); + this._instantiationService.setService(IOptionsService, this.optionsService); + this._bufferService = this._instantiationService.createInstance(BufferService); + this._instantiationService.setService(IBufferService, this._bufferService); + this._logService = this._instantiationService.createInstance(LogService); + this._instantiationService.setService(ILogService, this._logService); + } + + public get cols(): number { return this._bufferService.cols; } + public get rows(): number { return this._bufferService.rows; } +} diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index b250b45ea..159c08767 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -3,6 +3,7 @@ * @license MIT */ +import { ITerminalOptions as IPublicTerminalOptions } from 'xterm'; import { IEvent, IEventEmitter } from 'common/EventEmitter'; import { IDeleteEvent, IInsertEvent } from 'common/CircularList'; @@ -10,6 +11,14 @@ export interface IDisposable { dispose(): void; } +// TODO: The options that are not in the public API should be reviewed +export interface ITerminalOptions extends IPublicTerminalOptions { + [key: string]: any; + cancelEvents?: boolean; + convertEol?: boolean; + termName?: string; +} + export type XtermListener = (...args: any[]) => void; /** diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 8a3e9b287..97a9f78f0 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -10,7 +10,7 @@ import { createDecorator } from 'common/services/ServiceRegistry'; export const IBufferService = createDecorator('BufferService'); export interface IBufferService { - serviceBrand: any; + serviceBrand: undefined; readonly cols: number; readonly rows: number; @@ -51,12 +51,12 @@ export interface ICoreMouseService { /** * Human readable version of mouse events. */ - explainEvents(events: CoreMouseEventType): {[event: string]: boolean}; + explainEvents(events: CoreMouseEventType): { [event: string]: boolean }; } export const ICoreService = createDecorator('CoreService'); export interface ICoreService { - serviceBrand: any; + serviceBrand: undefined; /** * Initially the cursor will not be visible until the first time the terminal @@ -92,7 +92,7 @@ export interface ICoreService { export const ICharsetService = createDecorator('CharsetService'); export interface ICharsetService { - serviceBrand: any; + serviceBrand: undefined; charset: ICharset | undefined; readonly glevel: number; @@ -116,7 +116,7 @@ export interface ICharsetService { export const IDirtyRowService = createDecorator('DirtyRowService'); export interface IDirtyRowService { - serviceBrand: any; + serviceBrand: undefined; readonly start: number; readonly end: number; @@ -132,61 +132,32 @@ export interface IServiceIdentifier { type: T; } -export interface IConstructorSignature0 { - new(...services: { serviceBrand: any }[]): T; -} +export interface IBrandedService { + serviceBrand: undefined; +}; -export interface IConstructorSignature1 { - new(first: A1, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature2 { - new(first: A1, second: A2, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature3 { - new(first: A1, second: A2, third: A3, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature4 { - new(first: A1, second: A2, third: A3, fourth: A4, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature5 { - new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature6 { - new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature7 { - new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, ...services: { serviceBrand: any }[]): T; -} - -export interface IConstructorSignature8 { - new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8, ...services: { serviceBrand: any }[]): T; -} +type GetLeadingNonServiceArgs = + Args extends [...IBrandedService[]] ? [] + : Args extends [infer A1, ...IBrandedService[]] ? [A1] + : Args extends [infer A1, infer A2, ...IBrandedService[]] ? [A1, A2] + : Args extends [infer A1, infer A2, infer A3, ...IBrandedService[]] ? [A1, A2, A3] + : Args extends [infer A1, infer A2, infer A3, infer A4, ...IBrandedService[]] ? [A1, A2, A3, A4] + : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, ...IBrandedService[]] ? [A1, A2, A3, A4, A5] + : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, ...IBrandedService[]] ? [A1, A2, A3, A4, A5, A6] + : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, ...IBrandedService[]] ? [A1, A2, A3, A4, A5, A6, A7] + : Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8, ...IBrandedService[]] ? [A1, A2, A3, A4, A5, A6, A7, A8] + : never; export const IInstantiationService = createDecorator('InstantiationService'); export interface IInstantiationService { setService(id: IServiceIdentifier, instance: T): void; getService(id: IServiceIdentifier): T | undefined; - - createInstance(ctor: IConstructorSignature0): T; - createInstance(ctor: IConstructorSignature1, first: A1): T; - createInstance(ctor: IConstructorSignature2, first: A1, second: A2): T; - createInstance(ctor: IConstructorSignature3, first: A1, second: A2, third: A3): T; - createInstance(ctor: IConstructorSignature4, first: A1, second: A2, third: A3, fourth: A4): T; - createInstance(ctor: IConstructorSignature5, first: A1, second: A2, third: A3, fourth: A4, fifth: A5): T; - createInstance(ctor: IConstructorSignature6, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6): T; - createInstance(ctor: IConstructorSignature7, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7): T; - createInstance(ctor: IConstructorSignature8, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8): T; + createInstance any, R extends InstanceType>(t: Ctor, ...args: GetLeadingNonServiceArgs>): R; } export const ILogService = createDecorator('LogService'); export interface ILogService { - serviceBrand: any; + serviceBrand: undefined; debug(message: any, ...optionalParams: any[]): void; info(message: any, ...optionalParams: any[]): void; @@ -196,7 +167,7 @@ export interface ILogService { export const IOptionsService = createDecorator('OptionsService'); export interface IOptionsService { - serviceBrand: any; + serviceBrand: undefined; readonly options: ITerminalOptions; @@ -311,7 +282,7 @@ export interface ITheme { export const IUnicodeService = createDecorator('UnicodeService'); export interface IUnicodeService { - serviceBrand: any; + serviceBrand: undefined; /** Register an Unicode version provider. */ register(provider: IUnicodeVersionProvider): void; /** Registered Unicode versions. */ diff --git a/src/common/tsconfig.json b/src/common/tsconfig.json index 59050a0ba..7f35c80c0 100644 --- a/src/common/tsconfig.json +++ b/src/common/tsconfig.json @@ -10,5 +10,8 @@ ], "baseUrl": ".." }, - "include": [ "./**/*" ] + "include": [ + "./**/*", + "../../typings/xterm.d.ts" + ] } diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index 84d0c924d..0cd951a70 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -8,6 +8,7 @@ "removeComments": true, "pretty": true, - "incremental": true + "incremental": true, + "experimentalDecorators": true } } From 0d3bd2052b89a348898dbebc8efd27ec1b03718f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 10:26:29 -0700 Subject: [PATCH 065/130] Remove remaining common service inits to common --- src/Terminal.ts | 35 ----------------------------------- src/common/CoreTerminal.ts | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 4a0bd82c8..19fd2a885 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -46,22 +46,16 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { updateWindowsModeWrappedState } from 'common/WindowsMode'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; -import { ICoreMouseService, ICoreService, IDirtyRowService, ICharsetService, IUnicodeService } from 'common/services/Services'; import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services'; import { CharSizeService } from 'browser/services/CharSizeService'; import { MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; -import { CoreService } from 'common/services/CoreService'; import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; -import { DirtyRowService } from 'common/services/DirtyRowService'; -import { CoreMouseService } from 'common/services/CoreMouseService'; import { WriteBuffer } from 'common/input/WriteBuffer'; import { Linkifier2 } from 'browser/Linkifier2'; import { CoreBrowserService } from 'browser/services/CoreBrowserService'; -import { UnicodeService } from 'common/services/UnicodeService'; -import { CharsetService } from 'common/services/CharsetService'; import { CoreTerminal } from 'common/CoreTerminal'; // Let it work inside Node.js for automated testing purposes. @@ -88,13 +82,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT private _customKeyEventHandler: CustomKeyEventHandler; - // common services - private _coreService: ICoreService; - private _charsetService: ICharsetService; - private _coreMouseService: ICoreMouseService; - private _dirtyRowService: IDirtyRowService; - public unicodeService: IUnicodeService; - // browser services private _charSizeService: ICharSizeService; private _mouseService: IMouseService; @@ -137,15 +124,8 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT // bufferline to clone/copy from for new blank lines private _blankLine: IBufferLine = null; - public get cols(): number { return this._bufferService.cols; } - public get rows(): number { return this._bufferService.rows; } - private _onCursorMove = new EventEmitter(); public get onCursorMove(): IEvent { return this._onCursorMove.event; } - private _onData = new EventEmitter(); - public get onData(): IEvent { return this._onData.event; } - private _onBinary = new EventEmitter(); - public get onBinary(): IEvent { return this._onBinary.event; } private _onKey = new EventEmitter<{ key: string, domEvent: KeyboardEvent }>(); public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; } private _onLineFeed = new EventEmitter(); @@ -187,21 +167,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT ) { super(options); - // TODO: Move these to CoreTerminal.ts - // Setup and initialize common services - this._coreService = this._instantiationService.createInstance(CoreService, () => this.scrollToBottom()); - this._instantiationService.setService(ICoreService, this._coreService); - this._coreService.onData(e => this._onData.fire(e)); - this._coreService.onBinary(e => this._onBinary.fire(e)); - this._coreMouseService = this._instantiationService.createInstance(CoreMouseService); - this._instantiationService.setService(ICoreMouseService, this._coreMouseService); - this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService); - this._instantiationService.setService(IDirtyRowService, this._dirtyRowService); - this.unicodeService = this._instantiationService.createInstance(UnicodeService); - this._instantiationService.setService(IUnicodeService, this.unicodeService); - this._charsetService = this._instantiationService.createInstance(CharsetService); - this._instantiationService.setService(ICharsetService, this._charsetService); - this._setupOptionsListeners(); this._setup(); diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 6930ce072..dfffa1d40 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -22,20 +22,36 @@ */ import { Disposable } from 'common/Lifecycle'; -import { IInstantiationService, IOptionsService, IBufferService, ILogService } from 'common/services/Services'; +import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, IDirtyRowService } from 'common/services/Services'; import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; import { ITerminalOptions } from './Types'; +import { CoreService } from 'common/services/CoreService'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { CoreMouseService } from 'common/services/CoreMouseService'; +import { DirtyRowService } from 'common/services/DirtyRowService'; +import { UnicodeService } from 'common/services/UnicodeService'; +import { CharsetService } from 'common/services/CharsetService'; -export class CoreTerminal extends Disposable { +export abstract class CoreTerminal extends Disposable { protected readonly _instantiationService: IInstantiationService; protected readonly _bufferService: IBufferService; protected readonly _logService: ILogService; + protected readonly _coreService: ICoreService; + protected readonly _charsetService: ICharsetService; + protected readonly _coreMouseService: ICoreMouseService; + protected readonly _dirtyRowService: IDirtyRowService; + public readonly unicodeService: IUnicodeService; public readonly optionsService: IOptionsService; + private _onData = new EventEmitter(); + public get onData(): IEvent { return this._onData.event; } + private _onBinary = new EventEmitter(); + public get onBinary(): IEvent { return this._onBinary.event; } + constructor( options: ITerminalOptions ) { @@ -49,8 +65,22 @@ export class CoreTerminal extends Disposable { this._instantiationService.setService(IBufferService, this._bufferService); this._logService = this._instantiationService.createInstance(LogService); this._instantiationService.setService(ILogService, this._logService); + this._coreService = this._instantiationService.createInstance(CoreService, () => this.scrollToBottom()); + this._instantiationService.setService(ICoreService, this._coreService); + this._coreService.onData(e => this._onData.fire(e)); + this._coreService.onBinary(e => this._onBinary.fire(e)); + this._coreMouseService = this._instantiationService.createInstance(CoreMouseService); + this._instantiationService.setService(ICoreMouseService, this._coreMouseService); + this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService); + this._instantiationService.setService(IDirtyRowService, this._dirtyRowService); + this.unicodeService = this._instantiationService.createInstance(UnicodeService); + this._instantiationService.setService(IUnicodeService, this.unicodeService); + this._charsetService = this._instantiationService.createInstance(CharsetService); + this._instantiationService.setService(ICharsetService, this._charsetService); } public get cols(): number { return this._bufferService.cols; } public get rows(): number { return this._bufferService.rows; } + + public abstract scrollToBottom(): void; } From b80c14639e8b7ffd473f058302f9262be4c3194d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 10:34:37 -0700 Subject: [PATCH 066/130] Move option listeners to core --- src/Terminal.ts | 138 ++++++++++++++----------------------- src/common/CoreTerminal.ts | 59 ++++++++++++++-- 2 files changed, 104 insertions(+), 93 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 19fd2a885..6192beec5 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -43,13 +43,12 @@ import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMo import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { EventEmitter, IEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; -import { updateWindowsModeWrappedState } from 'common/WindowsMode'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services'; import { CharSizeService } from 'browser/services/CharSizeService'; import { MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; -import { IBufferSet, IBuffer } from 'common/buffer/Types'; +import { IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; @@ -119,7 +118,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT private _accessibilityManager: AccessibilityManager; private _colorManager: ColorManager; private _theme: ITheme; - private _windowsMode: IDisposable | undefined; // bufferline to clone/copy from for new blank lines private _blankLine: IBufferLine = null; @@ -128,8 +126,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT public get onCursorMove(): IEvent { return this._onCursorMove.event; } private _onKey = new EventEmitter<{ key: string, domEvent: KeyboardEvent }>(); public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; } - private _onLineFeed = new EventEmitter(); - public get onLineFeed(): IEvent { return this._onLineFeed.event; } private _onRender = new EventEmitter<{ start: number, end: number }>(); public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } private _onResize = new EventEmitter<{ cols: number, rows: number }>(); @@ -167,7 +163,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT ) { super(options); - this._setupOptionsListeners(); this._setup(); this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data)); @@ -220,22 +215,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } } - private _enableWindowsMode(): void { - if (!this._windowsMode) { - const disposables: IDisposable[] = []; - disposables.push(this.onLineFeed(updateWindowsModeWrappedState.bind(null, this._bufferService))); - disposables.push(this.addCsiHandler({ final: 'H' }, () => { - updateWindowsModeWrappedState(this._bufferService); - return false; - })); - this._windowsMode = { - dispose: () => { - disposables.forEach(d => d.dispose()); - } - }; - } - } - /** * Convenience property to active buffer. */ @@ -243,10 +222,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT return this.buffers.active; } - public get buffers(): IBufferSet { - return this._bufferService.buffers; - } - /** * Focus the terminal. Delegates focus handling to the terminal's DOM element. */ @@ -256,68 +231,59 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } } - private _setupOptionsListeners(): void { + protected _updateOptions(key: string): void { + super._updateOptions(key); + // TODO: These listeners should be owned by individual components - this.optionsService.onOptionChange(key => { - switch (key) { - case 'fontFamily': - case 'fontSize': - // When the font changes the size of the cells may change which requires a renderer clear - this._renderService?.clear(); - this._charSizeService?.measure(); - break; - case 'cursorBlink': - case 'cursorStyle': - // The DOM renderer needs a row refresh to update the cursor styles - this.refresh(this.buffer.y, this.buffer.y); - break; - case 'drawBoldTextInBrightColors': - case 'letterSpacing': - case 'lineHeight': - case 'fontWeight': - case 'fontWeightBold': - case 'minimumContrastRatio': - // When the font changes the size of the cells may change which requires a renderer clear - if (this._renderService) { - this._renderService.clear(); - this._renderService.onResize(this.cols, this.rows); - this.refresh(0, this.rows - 1); + switch (key) { + case 'fontFamily': + case 'fontSize': + // When the font changes the size of the cells may change which requires a renderer clear + this._renderService?.clear(); + this._charSizeService?.measure(); + break; + case 'cursorBlink': + case 'cursorStyle': + // The DOM renderer needs a row refresh to update the cursor styles + this.refresh(this.buffer.y, this.buffer.y); + break; + case 'drawBoldTextInBrightColors': + case 'letterSpacing': + case 'lineHeight': + case 'fontWeight': + case 'fontWeightBold': + case 'minimumContrastRatio': + // When the font changes the size of the cells may change which requires a renderer clear + if (this._renderService) { + this._renderService.clear(); + this._renderService.onResize(this.cols, this.rows); + this.refresh(0, this.rows - 1); + } + break; + case 'rendererType': + if (this._renderService) { + this._renderService.setRenderer(this._createRenderer()); + this._renderService.onResize(this.cols, this.rows); + } + break; + case 'scrollback': + this.viewport?.syncScrollArea(); + break; + case 'screenReaderMode': + if (this.optionsService.options.screenReaderMode) { + if (!this._accessibilityManager && this._renderService) { + this._accessibilityManager = new AccessibilityManager(this, this._renderService); } - break; - case 'rendererType': - if (this._renderService) { - this._renderService.setRenderer(this._createRenderer()); - this._renderService.onResize(this.cols, this.rows); - } - break; - case 'scrollback': - this.buffers.resize(this.cols, this.rows); - this.viewport?.syncScrollArea(); - break; - case 'screenReaderMode': - if (this.optionsService.options.screenReaderMode) { - if (!this._accessibilityManager && this._renderService) { - this._accessibilityManager = new AccessibilityManager(this, this._renderService); - } - } else { - this._accessibilityManager?.dispose(); - this._accessibilityManager = null; - } - break; - case 'tabStopWidth': this.buffers.setupTabStops(); break; - case 'theme': - this._setTheme(this.optionsService.options.theme); - break; - case 'windowsMode': - if (this.optionsService.options.windowsMode) { - this._enableWindowsMode(); - } else { - this._windowsMode?.dispose(); - this._windowsMode = undefined; - } - break; - } - }); + } else { + this._accessibilityManager?.dispose(); + this._accessibilityManager = null; + } + break; + case 'tabStopWidth': this.buffers.setupTabStops(); break; + case 'theme': + this._setTheme(this.optionsService.options.theme); + break; + } } /** diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index dfffa1d40..7a8f5bffe 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -27,13 +27,16 @@ import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; -import { ITerminalOptions } from './Types'; +import { ITerminalOptions, IDisposable } from './Types'; import { CoreService } from 'common/services/CoreService'; import { EventEmitter, IEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; import { DirtyRowService } from 'common/services/DirtyRowService'; import { UnicodeService } from 'common/services/UnicodeService'; import { CharsetService } from 'common/services/CharsetService'; +import { updateWindowsModeWrappedState } from 'common/WindowsMode'; +import { IFunctionIdentifier, IParams } from 'common/parser/Types'; +import { IBufferSet } from 'common/buffer/Types'; export abstract class CoreTerminal extends Disposable { protected readonly _instantiationService: IInstantiationService; @@ -47,10 +50,18 @@ export abstract class CoreTerminal extends Disposable { public readonly unicodeService: IUnicodeService; public readonly optionsService: IOptionsService; - private _onData = new EventEmitter(); - public get onData(): IEvent { return this._onData.event; } + protected _windowsMode: IDisposable | undefined; + private _onBinary = new EventEmitter(); public get onBinary(): IEvent { return this._onBinary.event; } + private _onData = new EventEmitter(); + public get onData(): IEvent { return this._onData.event; } + protected _onLineFeed = new EventEmitter(); + public get onLineFeed(): IEvent { return this._onLineFeed.event; } + + public get cols(): number { return this._bufferService.cols; } + public get rows(): number { return this._bufferService.rows; } + public get buffers(): IBufferSet { return this._bufferService.buffers; } constructor( options: ITerminalOptions @@ -67,8 +78,6 @@ export abstract class CoreTerminal extends Disposable { this._instantiationService.setService(ILogService, this._logService); this._coreService = this._instantiationService.createInstance(CoreService, () => this.scrollToBottom()); this._instantiationService.setService(ICoreService, this._coreService); - this._coreService.onData(e => this._onData.fire(e)); - this._coreService.onBinary(e => this._onBinary.fire(e)); this._coreMouseService = this._instantiationService.createInstance(CoreMouseService); this._instantiationService.setService(ICoreMouseService, this._coreMouseService); this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService); @@ -77,10 +86,46 @@ export abstract class CoreTerminal extends Disposable { this._instantiationService.setService(IUnicodeService, this.unicodeService); this._charsetService = this._instantiationService.createInstance(CharsetService); this._instantiationService.setService(ICharsetService, this._charsetService); + + // Setup listeners + this._coreService.onData(e => this._onData.fire(e)); + this._coreService.onBinary(e => this._onBinary.fire(e)); + this.optionsService.onOptionChange(key => this._updateOptions(key)); } - public get cols(): number { return this._bufferService.cols; } - public get rows(): number { return this._bufferService.rows; } + protected _updateOptions(key: string): void { + // TODO: These listeners should be owned by individual components + switch (key) { + case 'scrollback': + this.buffers.resize(this.cols, this.rows); + break; + case 'windowsMode': + if (this.optionsService.options.windowsMode) { + this._enableWindowsMode(); + } else { + this._windowsMode?.dispose(); + this._windowsMode = undefined; + } + break; + } + } + + protected _enableWindowsMode(): void { + if (!this._windowsMode) { + const disposables: IDisposable[] = []; + disposables.push(this.onLineFeed(updateWindowsModeWrappedState.bind(null, this._bufferService))); + disposables.push(this.addCsiHandler({ final: 'H' }, () => { + updateWindowsModeWrappedState(this._bufferService); + return false; + })); + this._windowsMode = { + dispose: () => { + disposables.forEach(d => d.dispose()); + } + }; + } + } public abstract scrollToBottom(): void; + public abstract addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; } From 4cec11be9c28fc593780d8e0c7ee2188526d41b9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 11:11:05 -0700 Subject: [PATCH 067/130] Move bracketed paste mode to coreservice --- src/InputHandler.ts | 4 ++-- src/Terminal.ts | 16 +++++----------- src/Types.d.ts | 2 -- src/browser/Clipboard.ts | 8 ++++---- src/common/CoreTerminal.ts | 17 ++++++++++++++++- src/common/TestUtils.test.ts | 1 + src/common/Types.d.ts | 1 + src/common/services/CoreService.ts | 1 + 8 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 3717256e8..371391dab 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1802,7 +1802,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.showCursor(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) - this._terminal.bracketedPasteMode = true; + this._coreService.decPrivateModes.bracketedPasteMode = true; break; } } @@ -2020,7 +2020,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.showCursor(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) - this._terminal.bracketedPasteMode = false; + this._coreService.decPrivateModes.bracketedPasteMode = false; break; } } diff --git a/src/Terminal.ts b/src/Terminal.ts index 6192beec5..e97f3e58d 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -90,7 +90,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT // modes public insertMode: boolean; - public bracketedPasteMode: boolean; // mouse properties public mouseEvents: CoreMouseEventType = CoreMouseEventType.NONE; @@ -173,20 +172,19 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT return; } super.dispose(); - this._windowsMode?.dispose(); - this._windowsMode = undefined; this._renderService?.dispose(); this._customKeyEventHandler = null; this.write = () => { }; this.element?.parentNode?.removeChild(this.element); } - private _setup(): void { + protected _setup(): void { + super._setup(); + this._customKeyEventHandler = null; // modes this.insertMode = false; - this.bracketedPasteMode = false; this._userScrolling = false; @@ -209,10 +207,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT if (!this.linkifier2) { this.linkifier2 = this._instantiationService.createInstance(Linkifier2); } - - if (this.options.windowsMode) { - this._enableWindowsMode(); - } } /** @@ -337,7 +331,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } copyHandler(event, this._selectionService); })); - const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea, this.bracketedPasteMode, this._coreService); + const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea, this._coreService); this.register(addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper)); this.register(addDisposableDomListener(this.element, 'paste', pasteHandlerWrapper)); @@ -982,7 +976,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } public paste(data: string): void { - paste(data, this.textarea, this.bracketedPasteMode, this._coreService); + paste(data, this.textarea, this._coreService); } /** diff --git a/src/Types.d.ts b/src/Types.d.ts index 14494e898..4aaf9fa85 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -22,7 +22,6 @@ export type LineData = CharData[]; */ export interface IInputHandlingTerminal { insertMode: boolean; - bracketedPasteMode: boolean; sendFocus: boolean; buffers: IBufferSet; @@ -135,7 +134,6 @@ export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAcc buffer: IBuffer; buffers: IBufferSet; viewport: IViewport; - bracketedPasteMode: boolean; optionsService: IOptionsService; // TODO: We should remove options once components adopt optionsService options: ITerminalOptions; diff --git a/src/browser/Clipboard.ts b/src/browser/Clipboard.ts index a7c48bfb0..5fe1e8fc1 100644 --- a/src/browser/Clipboard.ts +++ b/src/browser/Clipboard.ts @@ -42,17 +42,17 @@ export function copyHandler(ev: ClipboardEvent, selectionService: ISelectionServ * @param ev The original paste event to be handled * @param term The terminal on which to apply the handled paste event */ -export function handlePasteEvent(ev: ClipboardEvent, textarea: HTMLTextAreaElement, bracketedPasteMode: boolean, coreService: ICoreService): void { +export function handlePasteEvent(ev: ClipboardEvent, textarea: HTMLTextAreaElement, coreService: ICoreService): void { ev.stopPropagation(); if (ev.clipboardData) { const text = ev.clipboardData.getData('text/plain'); - paste(text, textarea, bracketedPasteMode, coreService); + paste(text, textarea, coreService); } } -export function paste(text: string, textarea: HTMLTextAreaElement, bracketedPasteMode: boolean, coreService: ICoreService): void { +export function paste(text: string, textarea: HTMLTextAreaElement, coreService: ICoreService): void { text = prepareTextForTerminal(text); - text = bracketTextForPaste(text, bracketedPasteMode); + text = bracketTextForPaste(text, coreService.decPrivateModes.bracketedPasteMode); coreService.triggerDataEvent(text, true); textarea.value = ''; } diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 7a8f5bffe..5428a3bcf 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -50,7 +50,7 @@ export abstract class CoreTerminal extends Disposable { public readonly unicodeService: IUnicodeService; public readonly optionsService: IOptionsService; - protected _windowsMode: IDisposable | undefined; + private _windowsMode: IDisposable | undefined; private _onBinary = new EventEmitter(); public get onBinary(): IEvent { return this._onBinary.event; } @@ -93,6 +93,21 @@ export abstract class CoreTerminal extends Disposable { this.optionsService.onOptionChange(key => this._updateOptions(key)); } + public dispose(): void { + if (this._isDisposed) { + return; + } + super.dispose(); + this._windowsMode?.dispose(); + this._windowsMode = undefined; + } + + protected _setup(): void { + if (this.optionsService.options.windowsMode) { + this._enableWindowsMode(); + } + } + protected _updateOptions(key: string): void { // TODO: These listeners should be owned by individual components switch (key) { diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index cfa1abd77..6d47f05fb 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -61,6 +61,7 @@ export class MockCoreService implements ICoreService { public decPrivateModes: IDecPrivateModes = { applicationCursorKeys: false, applicationKeypad: false, + bracketedPasteMode: false, origin: false, wraparound: true }; diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 159c08767..c94093db6 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -163,6 +163,7 @@ export interface IMarker extends IDisposable { export interface IDecPrivateModes { applicationCursorKeys: boolean; applicationKeypad: boolean; + bracketedPasteMode: boolean; origin: boolean; wraparound: boolean; // defaults: xterm - true, vt100 - false } diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index 2f0ff72f6..56a0c04ff 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -11,6 +11,7 @@ import { clone } from 'common/Clone'; const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ applicationCursorKeys: false, applicationKeypad: false, + bracketedPasteMode: false, origin: false, wraparound: true // defaults: xterm - true, vt100 - false }); From d5729f9216af511d11b183fb2a7eaa58bf2f616b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 11:26:20 -0700 Subject: [PATCH 068/130] Move insertMode into core service --- src/InputHandler.test.ts | 14 +++++++------- src/InputHandler.ts | 10 +++------- src/Terminal.test.ts | 6 +++--- src/Terminal.ts | 17 +++++------------ src/TestUtils.test.ts | 2 -- src/Types.d.ts | 1 - src/common/TestUtils.test.ts | 5 ++++- src/common/Types.d.ts | 3 +++ src/common/services/CoreService.ts | 9 ++++++++- src/common/services/Services.ts | 3 ++- 10 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 84d4dae51..6c5b9cbb7 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -102,16 +102,16 @@ describe('InputHandler', () => { }); }); describe('setMode', () => { - it('should toggle Terminal.bracketedPasteMode', () => { + it('should toggle bracketedPasteMode', () => { const terminal = new MockInputHandlingTerminal(); - terminal.bracketedPasteMode = false; - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const coreService = new MockCoreService(); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); // Set bracketed paste mode inputHandler.setModePrivate(Params.fromArray([2004])); - assert.equal(terminal.bracketedPasteMode, true); + assert.equal(coreService.decPrivateModes.bracketedPasteMode, true); // Reset bracketed paste mode inputHandler.resetModePrivate(Params.fromArray([2004])); - assert.equal(terminal.bracketedPasteMode, false); + assert.equal(coreService.decPrivateModes.bracketedPasteMode, false); }); }); describe('regression tests', function(): void { @@ -1453,9 +1453,9 @@ describe('InputHandler', () => { }); it('should reset IRM', () => { term.writeSync('\x1b[4h'); - assert.equal(term.insertMode, true); + assert.equal((term as any)._coreService.modes.insertMode, true); term.writeSync('\x1b[!p'); - assert.equal(term.insertMode, false); + assert.equal((term as any)._coreService.modes.insertMode, false); }); it('should reset cursor visibility', () => { term.writeSync('\x1b[?25l'); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 371391dab..c5c165017 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -489,7 +489,7 @@ export class InputHandler extends Disposable implements IInputHandler { const screenReaderMode = this._optionsService.options.screenReaderMode; const cols = this._bufferService.cols; const wraparoundMode = this._coreService.decPrivateModes.wraparound; - const insertMode = this._terminal.insertMode; + const insertMode = this._coreService.modes.insertMode; const curAttr = this._curAttrData; let bufferRow = buffer.lines.get(buffer.y + buffer.ybase); @@ -1587,15 +1587,12 @@ export class InputHandler extends Disposable implements IInputHandler { * | 4 | Insert Mode (IRM). | #Y | * | 12 | Send/receive (SRM). Always off. | #N | * | 20 | Automatic Newline (LNM). Always off. | #N | - * - * - * FIXME: why is LNM commented out? */ public setMode(params: IParams): void { for (let i = 0; i < params.length; i++) { switch (params.params[i]) { case 4: - this._terminal.insertMode = true; + this._coreService.modes.insertMode = true; break; case 20: // this._t.convertEol = true; @@ -1833,7 +1830,7 @@ export class InputHandler extends Disposable implements IInputHandler { for (let i = 0; i < params.length; i++) { switch (params.params[i]) { case 4: - this._terminal.insertMode = false; + this._coreService.modes.insertMode = false; break; case 20: // this._t.convertEol = false; @@ -2356,7 +2353,6 @@ export class InputHandler extends Disposable implements IInputHandler { */ public softReset(params: IParams): void { this._coreService.isCursorHidden = false; - this._terminal.insertMode = false; this._terminal.viewport?.syncScrollArea(); this._bufferService.buffer.scrollTop = 0; this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1; diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index 4d590699b..d70ccb45a 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -991,7 +991,7 @@ describe('Terminal', () => { term.writeSync(Array(9).join('0123456789').slice(-80)); term.buffer.x = 10; term.buffer.y = 0; - term.insertMode = true; + term.write('\x1b[4h'); term.writeSync('abcde'); expect(term.buffer.lines.get(0).length).eql(term.cols); expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a'); @@ -1003,7 +1003,7 @@ describe('Terminal', () => { term.writeSync(Array(9).join('0123456789').slice(-80)); term.buffer.x = 10; term.buffer.y = 0; - term.insertMode = true; + term.write('\x1b[4h'); term.writeSync('¥¥¥'); expect(term.buffer.lines.get(0).length).eql(term.cols); expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('¥'); @@ -1016,7 +1016,7 @@ describe('Terminal', () => { term.writeSync(Array(41).join('¥')); term.buffer.x = 10; term.buffer.y = 0; - term.insertMode = true; + term.write('\x1b[4h'); term.writeSync('a'); expect(term.buffer.lines.get(0).length).eql(term.cols); expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a'); diff --git a/src/Terminal.ts b/src/Terminal.ts index e97f3e58d..5c2bbd7d8 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -88,9 +88,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT private _selectionService: ISelectionService; private _soundService: ISoundService; - // modes - public insertMode: boolean; - // mouse properties public mouseEvents: CoreMouseEventType = CoreMouseEventType.NONE; public sendFocus: boolean; @@ -179,15 +176,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } protected _setup(): void { - super._setup(); - - this._customKeyEventHandler = null; - - // modes - this.insertMode = false; - - this._userScrolling = false; - if (this._inputHandler) { this._inputHandler.reset(); } else { @@ -201,6 +189,11 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this.register(this._inputHandler); } + super._setup(); + + this._customKeyEventHandler = null; + + this._userScrolling = false; if (!this.linkifier) { this.linkifier = this._instantiationService.createInstance(Linkifier); } diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index f0c56f156..ea0a58844 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -203,8 +203,6 @@ export class MockTerminal implements ITerminal { export class MockInputHandlingTerminal implements IInputHandlingTerminal { public onA11yCharEmitter: EventEmitter; public onA11yTabEmitter: EventEmitter; - public insertMode: boolean; - public bracketedPasteMode: boolean; public sendFocus: boolean; public buffers: IBufferSet; public buffer: IBuffer = new MockBuffer(); diff --git a/src/Types.d.ts b/src/Types.d.ts index 4aaf9fa85..a2000551f 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -21,7 +21,6 @@ export type LineData = CharData[]; * InputHandler cleanly from the ITerminal interface. */ export interface IInputHandlingTerminal { - insertMode: boolean; sendFocus: boolean; buffers: IBufferSet; diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 6d47f05fb..389c53822 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -9,7 +9,7 @@ import { clone } from 'common/Clone'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; import { BufferSet } from 'common/buffer/BufferSet'; -import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType, ICharset } from 'common/Types'; +import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType, ICharset, IModes } from 'common/Types'; import { UnicodeV6 } from 'common/input/UnicodeV6'; export class MockBufferService implements IBufferService { @@ -58,6 +58,9 @@ export class MockCoreService implements ICoreService { public isCursorInitialized: boolean = false; public isCursorHidden: boolean = false; public isFocused: boolean = false; + public modes: IModes = { + insertMode: false + }; public decPrivateModes: IDecPrivateModes = { applicationCursorKeys: false, applicationKeypad: false, diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index c94093db6..1d616f54f 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -159,6 +159,9 @@ export interface IMarker extends IDisposable { readonly isDisposed: boolean; readonly line: number; } +export interface IModes { + insertMode: boolean; +} export interface IDecPrivateModes { applicationCursorKeys: boolean; diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index 56a0c04ff..285532b5d 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -5,9 +5,13 @@ import { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { IDecPrivateModes } from 'common/Types'; +import { IDecPrivateModes, IModes } from 'common/Types'; import { clone } from 'common/Clone'; +const DEFAULT_MODES: IModes = Object.freeze({ + insertMode: false +}); + const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ applicationCursorKeys: false, applicationKeypad: false, @@ -21,6 +25,7 @@ export class CoreService implements ICoreService { public isCursorInitialized: boolean = false; public isCursorHidden: boolean = false; + public modes: IModes; public decPrivateModes: IDecPrivateModes; private _onData = new EventEmitter(); @@ -37,10 +42,12 @@ export class CoreService implements ICoreService { @ILogService private readonly _logService: ILogService, @IOptionsService private readonly _optionsService: IOptionsService ) { + this.modes = clone(DEFAULT_MODES); this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES); } public reset(): void { + this.modes = clone(DEFAULT_MODES); this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES); } diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 97a9f78f0..62ab45fd8 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -5,7 +5,7 @@ import { IEvent } from 'common/EventEmitter'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; -import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions } from 'common/Types'; +import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions, IModes } from 'common/Types'; import { createDecorator } from 'common/services/ServiceRegistry'; export const IBufferService = createDecorator('BufferService'); @@ -65,6 +65,7 @@ export interface ICoreService { isCursorInitialized: boolean; isCursorHidden: boolean; + readonly modes: IModes; readonly decPrivateModes: IDecPrivateModes; readonly onData: IEvent; From 37996bcd15be021500db0e4ad6f32233f0a8d6e8 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 13:24:11 -0700 Subject: [PATCH 069/130] Move sendFocus to core service --- src/InputHandler.ts | 4 ++-- src/Terminal.ts | 5 ++--- src/TestUtils.test.ts | 1 - src/Types.d.ts | 2 -- src/common/TestUtils.test.ts | 1 + src/common/Types.d.ts | 1 + src/common/services/CoreService.ts | 1 + 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index c5c165017..7732d4cf7 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1771,7 +1771,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 1004: // send focusin/focusout events // focusin: ^[[I // focusout: ^[[O - this._terminal.sendFocus = true; + this._coreService.decPrivateModes.sendFocus = true; break; case 1005: // utf8 ext mode mouse - removed in #2507 this._logService.debug('DECSET 1005 not supported (see #2507)'); @@ -1986,7 +1986,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._coreMouseService.activeProtocol = 'NONE'; break; case 1004: // send focusin/focusout events - this._terminal.sendFocus = false; + this._coreService.decPrivateModes.sendFocus = false; break; case 1005: // utf8 ext mode mouse - removed in #2507 this._logService.debug('DECRST 1005 not supported (see #2507)'); diff --git a/src/Terminal.ts b/src/Terminal.ts index 5c2bbd7d8..bb02671fd 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -90,7 +90,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT // mouse properties public mouseEvents: CoreMouseEventType = CoreMouseEventType.NONE; - public sendFocus: boolean; // write buffer private _writeBuffer: WriteBuffer; @@ -277,7 +276,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT * Binds the desired focus behavior on a given terminal object. */ private _onTextAreaFocus(ev: KeyboardEvent): void { - if (this.sendFocus) { + if (this._coreService.decPrivateModes.sendFocus) { this._coreService.triggerDataEvent(C0.ESC + '[I'); } this.updateCursorStyle(ev); @@ -302,7 +301,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT // screen readers reading it out. this.textarea.value = ''; this.refresh(this.buffer.y, this.buffer.y); - if (this.sendFocus) { + if (this._coreService.decPrivateModes.sendFocus) { this._coreService.triggerDataEvent(C0.ESC + '[O'); } this.element.classList.remove('focus'); diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index ea0a58844..c15ce5607 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -203,7 +203,6 @@ export class MockTerminal implements ITerminal { export class MockInputHandlingTerminal implements IInputHandlingTerminal { public onA11yCharEmitter: EventEmitter; public onA11yTabEmitter: EventEmitter; - public sendFocus: boolean; public buffers: IBufferSet; public buffer: IBuffer = new MockBuffer(); public viewport: IViewport; diff --git a/src/Types.d.ts b/src/Types.d.ts index a2000551f..15eda648d 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -21,8 +21,6 @@ export type LineData = CharData[]; * InputHandler cleanly from the ITerminal interface. */ export interface IInputHandlingTerminal { - sendFocus: boolean; - buffers: IBufferSet; buffer: IBuffer; viewport: IViewport; diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 389c53822..55df896ee 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -66,6 +66,7 @@ export class MockCoreService implements ICoreService { applicationKeypad: false, bracketedPasteMode: false, origin: false, + sendFocus: false, wraparound: true }; public onData: IEvent = new EventEmitter().event; diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 1d616f54f..cc7928c30 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -168,6 +168,7 @@ export interface IDecPrivateModes { applicationKeypad: boolean; bracketedPasteMode: boolean; origin: boolean; + sendFocus: boolean; wraparound: boolean; // defaults: xterm - true, vt100 - false } diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index 285532b5d..55d425aa3 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -17,6 +17,7 @@ const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({ applicationKeypad: false, bracketedPasteMode: false, origin: false, + sendFocus: false, wraparound: true // defaults: xterm - true, vt100 - false }); From c5ba1d62e7a6375938026ede64ff09d6e1ac2528 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 13:31:45 -0700 Subject: [PATCH 070/130] Remove mouseEvents from Terminal Depend on CoreMouseService directly --- src/Terminal.ts | 12 ++++-------- src/common/TestUtils.test.ts | 1 + src/common/services/CoreMouseService.ts | 4 ++++ src/common/services/Services.ts | 1 + 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index bb02671fd..c88a07150 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -88,9 +88,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT private _selectionService: ISelectionService; private _soundService: ISoundService; - // mouse properties - public mouseEvents: CoreMouseEventType = CoreMouseEventType.NONE; - // write buffer private _writeBuffer: WriteBuffer; @@ -500,7 +497,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService.onMouseDown(e))); // apply mouse event classes set by escape codes before terminal was attached - if (this.mouseEvents) { + if (this._coreMouseService.areMouseEventsActive) { this._selectionService.disable(); this.element.classList.add('enable-mouse-events'); } else { @@ -675,7 +672,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT }; this._coreMouseService.onProtocolChange(events => { // apply global changes on events - this.mouseEvents = events; if (events) { if (this.optionsService.options.logLevel === 'debug') { this._logService.debug('Binding to mouse events:', this._coreMouseService.explainEvents(events)); @@ -733,7 +729,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT // Don't send the mouse button to the pty if mouse events are disabled or // if the selection manager is having selection forced (ie. a modifier is // held). - if (!this.mouseEvents || this._selectionService.shouldForceSelection(ev)) { + if (!this._coreMouseService.areMouseEventsActive || this._selectionService.shouldForceSelection(ev)) { return; } @@ -787,13 +783,13 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT })); this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => { - if (this.mouseEvents) return; + if (this._coreMouseService.areMouseEventsActive) return; this.viewport.onTouchStart(ev); return this.cancel(ev); })); this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => { - if (this.mouseEvents) return; + if (this._coreMouseService.areMouseEventsActive) return; if (!this.viewport.onTouchMove(ev)) { return this.cancel(ev); } diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 55df896ee..e5b3a4258 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -31,6 +31,7 @@ export class MockBufferService implements IBufferService { } export class MockCoreMouseService implements ICoreMouseService { + public areMouseEventsActive: boolean = false; public activeEncoding: string = ''; public activeProtocol: string = ''; public addEncoding(name: string): void {} diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index c0ed3c6a4..29a847615 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -192,6 +192,10 @@ export class CoreMouseService implements ICoreMouseService { return this._activeProtocol; } + public get areMouseEventsActive(): boolean { + return this._protocols[this._activeProtocol].events !== 0; + } + public set activeProtocol(name: string) { if (!this._protocols[name]) { throw new Error(`unknown protocol "${name}"`); diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 62ab45fd8..05a6f3ae5 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -27,6 +27,7 @@ export const ICoreMouseService = createDecorator('CoreMouseSe export interface ICoreMouseService { activeProtocol: string; activeEncoding: string; + areMouseEventsActive: boolean; addProtocol(name: string, protocol: ICoreMouseProtocol): void; addEncoding(name: string, encoding: CoreMouseEncoding): void; reset(): void; From 9346eba2f2916d4bad8e221dca7b85508915e160 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 16:18:43 -0700 Subject: [PATCH 071/130] Remove Terminal.showCursor dep from input handler --- src/InputHandler.ts | 4 ++-- src/Terminal.test.ts | 2 -- src/Terminal.ts | 8 ++++---- src/TestUtils.test.ts | 6 ------ src/Types.d.ts | 4 ---- src/browser/services/RenderService.ts | 6 ++++-- 6 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 7732d4cf7..c3f3446ea 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1794,9 +1794,9 @@ export class InputHandler extends Disposable implements IInputHandler { case 47: // alt screen buffer case 1047: // alt screen buffer this._bufferService.buffers.activateAltBuffer(this._eraseAttrData()); + this._coreService.isCursorInitialized = true; this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); this._terminal.viewport?.syncScrollArea(); - this._terminal.showCursor(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = true; @@ -2012,9 +2012,9 @@ export class InputHandler extends Disposable implements IInputHandler { if (params.params[i] === 1049) { this.restoreCursor(); } + this._coreService.isCursorInitialized = true; this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); this._terminal.viewport?.syncScrollArea(); - this._terminal.showCursor(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = false; diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index d70ccb45a..40e1b1415 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -140,7 +140,6 @@ describe('Terminal', () => { }; beforeEach(() => { - term.showCursor = () => { }; term.clearSelection = () => { }; }); @@ -531,7 +530,6 @@ describe('Terminal', () => { let evKeyPress: any; beforeEach(() => { - term.showCursor = () => { }; term.clearSelection = () => { }; // term.compositionHelper = { // isComposing: false, diff --git a/src/Terminal.ts b/src/Terminal.ts index c88a07150..dff303bb0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -278,7 +278,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } this.updateCursorStyle(ev); this.element.classList.add('focus'); - this.showCursor(); + this._showCursor(); this._onFocus.fire(); } @@ -830,7 +830,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT /** * Display the cursor element */ - public showCursor(): void { + private _showCursor(): void { if (!this._coreService.isCursorInitialized) { this._coreService.isCursorInitialized = true; this.refresh(this.buffer.y, this.buffer.y); @@ -1165,7 +1165,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } this._onKey.fire({ key: result.key, domEvent: event }); - this.showCursor(); + this._showCursor(); this._coreService.triggerDataEvent(result.key, true); // Cancel events when not in screen reader mode so events don't get bubbled up and handled by @@ -1242,7 +1242,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT key = String.fromCharCode(key); this._onKey.fire({ key, domEvent: ev }); - this.showCursor(); + this._showCursor(); this._coreService.triggerDataEvent(key, true); return true; diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index c15ce5607..1cdc4c493 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -190,9 +190,6 @@ export class MockTerminal implements ITerminal { public reset(): void { throw new Error('Method not implemented.'); } - public showCursor(): void { - throw new Error('Method not implemented.'); - } public refresh(start: number, end: number): void { throw new Error('Method not implemented.'); } @@ -215,9 +212,6 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { public resize(x: number, y: number): void { throw new Error('Method not implemented.'); } - public showCursor(): void { - throw new Error('Method not implemented.'); - } public handler(data: string): void { throw new Error('Method not implemented.'); } diff --git a/src/Types.d.ts b/src/Types.d.ts index 15eda648d..2b26c0701 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -21,8 +21,6 @@ export type LineData = CharData[]; * InputHandler cleanly from the ITerminal interface. */ export interface IInputHandlingTerminal { - buffers: IBufferSet; - buffer: IBuffer; viewport: IViewport; onA11yCharEmitter: IEventEmitter; @@ -31,7 +29,6 @@ export interface IInputHandlingTerminal { scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void; is(term: string): boolean; resize(x: number, y: number): void; - showCursor(): void; handleTitle(title: string): void; } @@ -143,7 +140,6 @@ export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAcc scrollLines(disp: number, suppressScrollEvent?: boolean): void; cancel(ev: Event, force?: boolean): boolean | void; - showCursor(): void; } // Portions of the public API that are required by the internal Terminal diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 61ba35ab0..d9aaf60ab 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -10,7 +10,7 @@ import { Disposable } from 'common/Lifecycle'; import { ScreenDprMonitor } from 'browser/ScreenDprMonitor'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { IColorSet } from 'browser/Types'; -import { IOptionsService } from 'common/services/Services'; +import { IOptionsService, IBufferService, ICoreService } from 'common/services/Services'; import { ICharSizeService, IRenderService } from 'browser/services/Services'; export class RenderService extends Disposable implements IRenderService { @@ -39,7 +39,9 @@ export class RenderService extends Disposable implements IRenderService { private _rowCount: number, screenElement: HTMLElement, @IOptionsService optionsService: IOptionsService, - @ICharSizeService charSizeService: ICharSizeService + @ICharSizeService charSizeService: ICharSizeService, + @IBufferService private readonly _bufferService: IBufferService, + @ICoreService private readonly _coreService: ICoreService ) { super(); this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end)); From e9db1ecd1f5dc33967c48935105f574860fa6324 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 16:37:31 -0700 Subject: [PATCH 072/130] Remove Terminal.handleTitle dep --- src/InputHandler.ts | 4 +++- src/Terminal.test.ts | 2 +- src/Terminal.ts | 9 +-------- src/TestUtils.test.ts | 3 --- src/Types.d.ts | 3 ++- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index c3f3446ea..f34ef1452 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -236,6 +236,8 @@ export class InputHandler extends Disposable implements IInputHandler { public get onLineFeed(): IEvent { return this._onLineFeed.event; } private _onScroll = new EventEmitter(); public get onScroll(): IEvent { return this._onScroll.event; } + private _onTitleChange = new EventEmitter(); + public get onTitleChange(): IEvent { return this._onTitleChange.event; } constructor( private _terminal: IInputHandlingTerminal, @@ -2569,7 +2571,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public setTitle(data: string): void { this._windowTitle = data; - this._terminal.handleTitle(data); + this._onTitleChange.fire(data); } /** diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index 40e1b1415..61b40d6c3 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -121,7 +121,7 @@ describe('Terminal', () => { assert.equal(e, 'title'); done(); }); - term.handleTitle('title'); + term.write('\x1b]2;title\x07'); }); }); diff --git a/src/Terminal.ts b/src/Terminal.ts index dff303bb0..683437a95 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -182,6 +182,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._inputHandler.onRequestReset(() => this.reset()); this._inputHandler.onCursorMove(() => this._onCursorMove.fire()); this._inputHandler.onLineFeed(() => this._onLineFeed.fire()); + this._inputHandler.onTitleChange(title => this._onTitleChange.fire(title)); this.register(this._inputHandler); } @@ -1353,14 +1354,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT // this._onData.fire(data); // } - /** - * Emit the 'title' event and populate the given title. - * @param title The title to populate in the event. - */ - public handleTitle(title: string): void { - this._onTitleChange.fire(title); - } - /** * Reset terminal. * Note: Calling this directly from JS is synchronous but does not clear diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 1cdc4c493..122640ff1 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -215,9 +215,6 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { public handler(data: string): void { throw new Error('Method not implemented.'); } - public handleTitle(title: string): void { - throw new Error('Method not implemented.'); - } } export class MockBuffer implements IBuffer { diff --git a/src/Types.d.ts b/src/Types.d.ts index 2b26c0701..0aebc813f 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -29,7 +29,6 @@ export interface IInputHandlingTerminal { scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void; is(term: string): boolean; resize(x: number, y: number): void; - handleTitle(title: string): void; } export interface ICompositionHelper { @@ -44,6 +43,8 @@ export interface ICompositionHelper { * Calls the parser and handles actions generated by the parser. */ export interface IInputHandler { + onTitleChange: IEvent; + parse(data: string | Uint8Array): void; print(data: Uint32Array, start: number, end: number): void; From 3897950e22246107f3edc3658aee4497e8f4a9e5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 16:45:46 -0700 Subject: [PATCH 073/130] Remove a11y event dep, introduce forwardEvent helper --- src/InputHandler.ts | 8 ++++++-- src/Terminal.ts | 18 ++++++++++-------- src/Types.d.ts | 3 --- src/common/EventEmitter.ts | 4 ++++ 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index f34ef1452..05d4a981e 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -238,6 +238,10 @@ export class InputHandler extends Disposable implements IInputHandler { public get onScroll(): IEvent { return this._onScroll.event; } private _onTitleChange = new EventEmitter(); public get onTitleChange(): IEvent { return this._onTitleChange.event; } + private _onA11yChar = new EventEmitter(); + public get onA11yChar(): IEvent { return this._onA11yChar.event; } + private _onA11yTab = new EventEmitter(); + public get onA11yTab(): IEvent { return this._onA11yTab.event; } constructor( private _terminal: IInputHandlingTerminal, @@ -520,7 +524,7 @@ export class InputHandler extends Disposable implements IInputHandler { } if (screenReaderMode) { - this._terminal.onA11yCharEmitter.fire(stringFromCodePoint(code)); + this._onA11yChar.fire(stringFromCodePoint(code)); } // insert combining char at last cursor position @@ -738,7 +742,7 @@ export class InputHandler extends Disposable implements IInputHandler { const originalX = this._bufferService.buffer.x; this._bufferService.buffer.x = this._bufferService.buffer.nextStop(); if (this._optionsService.options.screenReaderMode) { - this._terminal.onA11yTabEmitter.fire(this._bufferService.buffer.x - originalX); + this._onA11yTab.fire(this._bufferService.buffer.x - originalX); } } diff --git a/src/Terminal.ts b/src/Terminal.ts index 683437a95..76ebf31f3 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -41,7 +41,7 @@ import { ITheme, IMarker, IDisposable, ISelectionPosition, ILinkProvider } from import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; @@ -133,10 +133,10 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT public get onFocus(): IEvent { return this._onFocus.event; } private _onBlur = new EventEmitter(); public get onBlur(): IEvent { return this._onBlur.event; } - public onA11yCharEmitter = new EventEmitter(); - public get onA11yChar(): IEvent { return this.onA11yCharEmitter.event; } - public onA11yTabEmitter = new EventEmitter(); - public get onA11yTab(): IEvent { return this.onA11yTabEmitter.event; } + private _onA11yCharEmitter = new EventEmitter(); + public get onA11yChar(): IEvent { return this._onA11yCharEmitter.event; } + private _onA11yTabEmitter = new EventEmitter(); + public get onA11yTab(): IEvent { return this._onA11yTabEmitter.event; } /** * Creates a new `Terminal` object. @@ -180,9 +180,11 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._inputHandler.onRequestBell(() => this.bell()); this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)); this._inputHandler.onRequestReset(() => this.reset()); - this._inputHandler.onCursorMove(() => this._onCursorMove.fire()); - this._inputHandler.onLineFeed(() => this._onLineFeed.fire()); - this._inputHandler.onTitleChange(title => this._onTitleChange.fire(title)); + forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove); + forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed); + forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange); + forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter); + forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter); this.register(this._inputHandler); } diff --git a/src/Types.d.ts b/src/Types.d.ts index 0aebc813f..4e4142b0d 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -23,9 +23,6 @@ export type LineData = CharData[]; export interface IInputHandlingTerminal { viewport: IViewport; - onA11yCharEmitter: IEventEmitter; - onA11yTabEmitter: IEventEmitter; - scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void; is(term: string): boolean; resize(x: number, y: number): void; diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index 301574e42..847e32491 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -63,3 +63,7 @@ export class EventEmitter implements IEventEmitter { this._disposed = true; } } + +export function forwardEvent(from: IEvent, to: IEventEmitter): void { + from(e => to.fire(e)); +} From 08f8f51adee6dfbfa19e1e6cbf6a377da456719a Mon Sep 17 00:00:00 2001 From: rishab Date: Sat, 25 Apr 2020 17:33:48 -0700 Subject: [PATCH 074/130] handle wrap back with find previous wrap back search selection to last selected result when we hit top --- addons/xterm-addon-search/src/SearchAddon.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index e22c8b7c8..f5505689f 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -110,14 +110,11 @@ export class SearchAddon implements ITerminalAddon { } } - // If there is only one result, wrap back and return selection if exists. + // If there is only one result, wrap back and return selection if it exists. if (!result && currentSelection) { searchPosition.startRow = currentSelection.startRow; searchPosition.startCol = 0; result = this._findInLine(term, searchPosition, searchOptions); - if (result) { - return this._selectResult(result); - } } // Set selection and scroll if a result was found @@ -182,7 +179,7 @@ export class SearchAddon implements ITerminalAddon { } // If we hit the top and didn't search from the very bottom wrap back down if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows)) { - for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows); y > startRow; y--) { + for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows); y >= startRow; y--) { searchPosition.startRow = y; result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch); if (result) { From 0709b0dc3b5bfe67cd39346ccb716d386e83fc48 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 19:28:00 -0700 Subject: [PATCH 075/130] Break input handler dep on Terminal.scroll --- src/InputHandler.ts | 8 +++++--- src/Terminal.ts | 1 + src/TestUtils.test.ts | 11 ----------- src/Types.d.ts | 2 +- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 05d4a981e..6f160961c 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -236,6 +236,8 @@ export class InputHandler extends Disposable implements IInputHandler { public get onLineFeed(): IEvent { return this._onLineFeed.event; } private _onScroll = new EventEmitter(); public get onScroll(): IEvent { return this._onScroll.event; } + private _onScrollRequest = new EventEmitter(); + public get onScrollRequest(): IEvent { return this._onScrollRequest.event; } private _onTitleChange = new EventEmitter(); public get onTitleChange(): IEvent { return this._onTitleChange.event; } private _onA11yChar = new EventEmitter(); @@ -554,7 +556,7 @@ export class InputHandler extends Disposable implements IInputHandler { buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { buffer.y--; - this._terminal.scroll(this._eraseAttrData(), true); + this._onScrollRequest.fire(this._eraseAttrData(), true); } else { if (buffer.y >= this._bufferService.rows) { buffer.y = this._bufferService.rows - 1; @@ -693,7 +695,7 @@ export class InputHandler extends Disposable implements IInputHandler { buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { buffer.y--; - this._terminal.scroll(this._eraseAttrData()); + this._onScrollRequest.fire(this._eraseAttrData()); } else if (buffer.y >= this._bufferService.rows) { buffer.y = this._bufferService.rows - 1; } @@ -2676,7 +2678,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._bufferService.buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { buffer.y--; - this._terminal.scroll(this._eraseAttrData()); + this._onScrollRequest.fire(this._eraseAttrData()); } else if (buffer.y >= this._bufferService.rows) { buffer.y = this._bufferService.rows - 1; } diff --git a/src/Terminal.ts b/src/Terminal.ts index 76ebf31f3..c051f5413 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -180,6 +180,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._inputHandler.onRequestBell(() => this.bell()); this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)); this._inputHandler.onRequestReset(() => this.reset()); + this._inputHandler.onScrollRequest((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)); forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove); forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed); forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange); diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 122640ff1..2027f994b 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -14,7 +14,6 @@ import { Terminal } from './Terminal'; import { AttributeData } from 'common/buffer/AttributeData'; import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2 } from 'browser/Types'; import { IOptionsService, IUnicodeService } from 'common/services/Services'; -import { EventEmitter } from 'common/EventEmitter'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { ISelectionService } from 'browser/services/Services'; @@ -198,23 +197,13 @@ export class MockTerminal implements ITerminal { } export class MockInputHandlingTerminal implements IInputHandlingTerminal { - public onA11yCharEmitter: EventEmitter; - public onA11yTabEmitter: EventEmitter; - public buffers: IBufferSet; - public buffer: IBuffer = new MockBuffer(); public viewport: IViewport; - public scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void { - throw new Error('Method not implemented.'); - } public is(term: string): boolean { throw new Error('Method not implemented.'); } public resize(x: number, y: number): void { throw new Error('Method not implemented.'); } - public handler(data: string): void { - throw new Error('Method not implemented.'); - } } export class MockBuffer implements IBuffer { diff --git a/src/Types.d.ts b/src/Types.d.ts index 4e4142b0d..241d82281 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -23,7 +23,6 @@ export type LineData = CharData[]; export interface IInputHandlingTerminal { viewport: IViewport; - scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void; is(term: string): boolean; resize(x: number, y: number): void; } @@ -41,6 +40,7 @@ export interface ICompositionHelper { */ export interface IInputHandler { onTitleChange: IEvent; + onScrollRequest: IEvent; parse(data: string | Uint8Array): void; print(data: Uint32Array, start: number, end: number): void; From a3ac0d542da9bbcfe14a1caed9cfafa0a053c7b7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 20:39:55 -0700 Subject: [PATCH 076/130] Remove unused imports --- src/InputHandler.ts | 1 - src/Types.d.ts | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 6f160961c..dcdabe951 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -2479,7 +2479,6 @@ export class InputHandler extends Disposable implements IInputHandler { switch (params.params[0]) { case 14: // GetWinSizePixels, returns CSI 4 ; height ; width t if (rs && second !== 2) { - console.log(rs.dimensions); const w = rs.dimensions.scaledCanvasWidth.toFixed(0); const h = rs.dimensions.scaledCanvasHeight.toFixed(0); this._coreService.triggerDataEvent(`${C0.ESC}[4;${h};${w}t`); diff --git a/src/Types.d.ts b/src/Types.d.ts index 241d82281..047df8ec9 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -3,10 +3,10 @@ * @license MIT */ -import { ITerminalOptions as IPublicTerminalOptions, IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; -import { ICharset, IAttributeData, CharData, CoreMouseEventType, ITerminalOptions } from 'common/Types'; -import { IEvent, IEventEmitter } from 'common/EventEmitter'; -import { IColorSet, ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; +import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; +import { IAttributeData, CharData, ITerminalOptions } from 'common/Types'; +import { IEvent } from 'common/EventEmitter'; +import { ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { IOptionsService, IUnicodeService } from 'common/services/Services'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; From eba372e2cc8d47629f33d4679ebd68de6df83d5d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 25 Apr 2020 20:51:33 -0700 Subject: [PATCH 077/130] More some of Terminal.resize into bufferservice --- src/Terminal.ts | 3 --- src/common/services/BufferService.ts | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index c051f5413..102cc36e7 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1292,10 +1292,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT if (x < MINIMUM_COLS) x = MINIMUM_COLS; if (y < MINIMUM_ROWS) y = MINIMUM_ROWS; - this.buffers.resize(x, y); - this._bufferService.resize(x, y); - this.buffers.setupTabStops(this.cols); this._charSizeService?.measure(); diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts index 1b6da7922..a79fc3050 100644 --- a/src/common/services/BufferService.ts +++ b/src/common/services/BufferService.ts @@ -30,6 +30,8 @@ export class BufferService implements IBufferService { public resize(cols: number, rows: number): void { this.cols = cols; this.rows = rows; + this.buffers.resize(cols, rows); + this.buffers.setupTabStops(this.cols); } public reset(): void { From a6949d522ea702f284f17f19fcc14137d28a3235 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 06:16:13 -0700 Subject: [PATCH 078/130] Move resize event into bufferservice --- src/Terminal.ts | 11 ++++++----- src/common/CoreTerminal.ts | 9 ++++++--- src/common/services/BufferService.ts | 5 +++++ src/common/services/Services.ts | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 102cc36e7..41bbd1776 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -120,8 +120,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; } private _onRender = new EventEmitter<{ start: number, end: number }>(); public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } - private _onResize = new EventEmitter<{ cols: number, rows: number }>(); - public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } private _onScroll = new EventEmitter(); public get onScroll(): IEvent { return this._onScroll.event; } private _onSelectionChange = new EventEmitter(); @@ -1289,19 +1287,22 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT return; } - if (x < MINIMUM_COLS) x = MINIMUM_COLS; - if (y < MINIMUM_ROWS) y = MINIMUM_ROWS; + x = Math.max(x, MINIMUM_COLS); + y = Math.max(y, MINIMUM_ROWS); this._bufferService.resize(x, y); + // TODO: Have charsize, viewport and renderservice depend on IBufferService.onResize? + this._charSizeService?.measure(); + // TODO: Call on resize event? // Sync the scroll area to make sure scroll events don't fire and scroll the viewport to an // invalid location this.viewport?.syncScrollArea(true); + // TODO: Move to renderservice this.refresh(0, this.rows - 1); - this._onResize.fire({ cols: x, rows: y }); } /** diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 5428a3bcf..fd1d9309a 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -29,7 +29,7 @@ import { BufferService } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; import { ITerminalOptions, IDisposable } from './Types'; import { CoreService } from 'common/services/CoreService'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; import { DirtyRowService } from 'common/services/DirtyRowService'; import { UnicodeService } from 'common/services/UnicodeService'; @@ -58,6 +58,8 @@ export abstract class CoreTerminal extends Disposable { public get onData(): IEvent { return this._onData.event; } protected _onLineFeed = new EventEmitter(); public get onLineFeed(): IEvent { return this._onLineFeed.event; } + private _onResize = new EventEmitter<{ cols: number, rows: number }>(); + public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } public get cols(): number { return this._bufferService.cols; } public get rows(): number { return this._bufferService.rows; } @@ -88,8 +90,9 @@ export abstract class CoreTerminal extends Disposable { this._instantiationService.setService(ICharsetService, this._charsetService); // Setup listeners - this._coreService.onData(e => this._onData.fire(e)); - this._coreService.onBinary(e => this._onBinary.fire(e)); + forwardEvent(this._bufferService.onResize, this._onResize); + forwardEvent(this._coreService.onData, this._onData); + forwardEvent(this._coreService.onBinary, this._onBinary); this.optionsService.onOptionChange(key => this._updateOptions(key)); } diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts index a79fc3050..d62d2cb00 100644 --- a/src/common/services/BufferService.ts +++ b/src/common/services/BufferService.ts @@ -6,6 +6,7 @@ import { IBufferService, IOptionsService } from 'common/services/Services'; import { BufferSet } from 'common/buffer/BufferSet'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; export const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars export const MINIMUM_ROWS = 1; @@ -17,6 +18,9 @@ export class BufferService implements IBufferService { public rows: number; public buffers: IBufferSet; + private _onResize = new EventEmitter<{ cols: number, rows: number }>(); + public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } + public get buffer(): IBuffer { return this.buffers.active; } constructor( @@ -32,6 +36,7 @@ export class BufferService implements IBufferService { this.rows = rows; this.buffers.resize(cols, rows); this.buffers.setupTabStops(this.cols); + this._onResize.fire({ cols, rows }); } public reset(): void { diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 05a6f3ae5..8fa3f57b3 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -17,7 +17,7 @@ export interface IBufferService { readonly buffer: IBuffer; readonly buffers: IBufferSet; - // TODO: Move resize event here + onResize: IEvent<{ cols: number, rows: number }>; resize(cols: number, rows: number): void; reset(): void; From 451d9aab96df86f077ef39000490dc62ef654ce8 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 06:21:16 -0700 Subject: [PATCH 079/130] Register forwardEvent calls --- src/Terminal.ts | 18 +++++++++--------- src/common/CoreTerminal.ts | 8 ++++---- src/common/EventEmitter.ts | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 41bbd1776..9572345ee 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -175,15 +175,15 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT } else { // Register input handler and refire/handle events this._inputHandler = new InputHandler(this, this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService, this._instantiationService); - this._inputHandler.onRequestBell(() => this.bell()); - this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)); - this._inputHandler.onRequestReset(() => this.reset()); - this._inputHandler.onScrollRequest((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)); - forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove); - forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed); - forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange); - forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter); - forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter); + this.register(this._inputHandler.onRequestBell(() => this.bell())); + this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); + this.register(this._inputHandler.onRequestReset(() => this.reset())); + this.register(this._inputHandler.onScrollRequest((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined))); + this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); + this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); + this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); + this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); + this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); this.register(this._inputHandler); } diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index fd1d9309a..90cc7ade7 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -90,10 +90,10 @@ export abstract class CoreTerminal extends Disposable { this._instantiationService.setService(ICharsetService, this._charsetService); // Setup listeners - forwardEvent(this._bufferService.onResize, this._onResize); - forwardEvent(this._coreService.onData, this._onData); - forwardEvent(this._coreService.onBinary, this._onBinary); - this.optionsService.onOptionChange(key => this._updateOptions(key)); + this.register(forwardEvent(this._bufferService.onResize, this._onResize)); + this.register(forwardEvent(this._coreService.onData, this._onData)); + this.register(forwardEvent(this._coreService.onBinary, this._onBinary)); + this.register(this.optionsService.onOptionChange(key => this._updateOptions(key))); } public dispose(): void { diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index 847e32491..4684809f3 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -64,6 +64,6 @@ export class EventEmitter implements IEventEmitter { } } -export function forwardEvent(from: IEvent, to: IEventEmitter): void { - from(e => to.fire(e)); +export function forwardEvent(from: IEvent, to: IEventEmitter): IDisposable { + return from(e => to.fire(e)); } From 3a1a0d659069e5abbaf060da3f1f2f6f930ded88 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 06:34:36 -0700 Subject: [PATCH 080/130] Remove input handler Terminal.resize dep --- src/InputHandler.ts | 4 ++-- src/Terminal.ts | 21 ++++++--------------- src/Types.d.ts | 1 - src/browser/services/RenderService.ts | 4 ++-- src/common/CoreTerminal.ts | 13 ++++++++++++- src/common/TestUtils.test.ts | 1 + 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index dcdabe951..de6433143 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1741,7 +1741,7 @@ export class InputHandler extends Disposable implements IInputHandler { * through `options.windowsOptions`. */ if (this._optionsService.options.windowOptions.setWinLines) { - this._terminal.resize(132, this._bufferService.rows); + this._bufferService.resize(132, this._bufferService.rows); this._onRequestReset.fire(); } break; @@ -1968,7 +1968,7 @@ export class InputHandler extends Disposable implements IInputHandler { * through `options.windowsOptions`. */ if (this._optionsService.options.windowOptions.setWinLines) { - this._terminal.resize(80, this._bufferService.rows); + this._bufferService.resize(80, this._bufferService.rows); this._onRequestReset.fire(); } break; diff --git a/src/Terminal.ts b/src/Terminal.ts index 9572345ee..6e192320a 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -47,7 +47,6 @@ import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services'; import { CharSizeService } from 'browser/services/CharSizeService'; -import { MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; @@ -155,6 +154,9 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._setup(); + // Setup listeners + this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)); + this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data)); } @@ -1275,10 +1277,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT * @param y The number of rows to resize to. */ public resize(x: number, y: number): void { - if (isNaN(x) || isNaN(y)) { - return; - } - if (x === this.cols && y === this.rows) { // Check if we still need to measure the char size (fixes #785). if (this._charSizeService && !this._charSizeService.hasValidSize) { @@ -1287,22 +1285,15 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT return; } - x = Math.max(x, MINIMUM_COLS); - y = Math.max(y, MINIMUM_ROWS); - - this._bufferService.resize(x, y); - - // TODO: Have charsize, viewport and renderservice depend on IBufferService.onResize? + super.resize(x, y); + } + private _afterResize(x: number, y: number): void { this._charSizeService?.measure(); - // TODO: Call on resize event? // Sync the scroll area to make sure scroll events don't fire and scroll the viewport to an // invalid location this.viewport?.syncScrollArea(true); - - // TODO: Move to renderservice - this.refresh(0, this.rows - 1); } /** diff --git a/src/Types.d.ts b/src/Types.d.ts index 047df8ec9..c3e1c53dd 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -24,7 +24,6 @@ export interface IInputHandlingTerminal { viewport: IViewport; is(term: string): boolean; - resize(x: number, y: number): void; } export interface ICompositionHelper { diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index d9aaf60ab..27b66458b 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -40,8 +40,7 @@ export class RenderService extends Disposable implements IRenderService { screenElement: HTMLElement, @IOptionsService optionsService: IOptionsService, @ICharSizeService charSizeService: ICharSizeService, - @IBufferService private readonly _bufferService: IBufferService, - @ICoreService private readonly _coreService: ICoreService + @IBufferService private readonly _bufferService: IBufferService ) { super(); this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end)); @@ -51,6 +50,7 @@ export class RenderService extends Disposable implements IRenderService { this._screenDprMonitor.setListener(() => this.onDevicePixelRatioChange()); this.register(this._screenDprMonitor); + this.register(this._bufferService.onResize(e => this._fullRefresh())); this.register(optionsService.onOptionChange(() => this._renderer.onOptionsChanged())); this.register(charSizeService.onCharSizeChange(() => this.onCharSizeChanged())); diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 90cc7ade7..49f3509db 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -25,7 +25,7 @@ import { Disposable } from 'common/Lifecycle'; import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, IDirtyRowService } from 'common/services/Services'; import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; -import { BufferService } from 'common/services/BufferService'; +import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; import { ITerminalOptions, IDisposable } from './Types'; import { CoreService } from 'common/services/CoreService'; @@ -105,6 +105,17 @@ export abstract class CoreTerminal extends Disposable { this._windowsMode = undefined; } + public resize(x: number, y: number): void { + if (isNaN(x) || isNaN(y)) { + return; + } + + x = Math.max(x, MINIMUM_COLS); + y = Math.max(y, MINIMUM_ROWS); + + this._bufferService.resize(x, y); + } + protected _setup(): void { if (this.optionsService.options.windowsMode) { this._enableWindowsMode(); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index e5b3a4258..eacf92fe8 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -16,6 +16,7 @@ export class MockBufferService implements IBufferService { public serviceBrand: any; public get buffer(): IBuffer { return this.buffers.active; } public buffers: IBufferSet = {} as any; + public onResize: IEvent<{ cols: number, rows: number }> = new EventEmitter<{ cols: number, rows: number }>().event; constructor( public cols: number, public rows: number, From dbced5c1a442b60113083ca8c7099a7f9990f2b4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 06:38:10 -0700 Subject: [PATCH 081/130] Move Terminal.is into InputHandler --- src/InputHandler.ts | 20 ++++++++++++++------ src/Terminal.ts | 8 -------- src/Types.d.ts | 2 -- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index de6433143..f4a084e2c 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1528,9 +1528,9 @@ export class InputHandler extends Disposable implements IInputHandler { if (params.params[0] > 0) { return; } - if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) { + if (this._is('xterm') || this._is('rxvt-unicode') || this._is('screen')) { this._coreService.triggerDataEvent(C0.ESC + '[?1;2c'); - } else if (this._terminal.is('linux')) { + } else if (this._is('linux')) { this._coreService.triggerDataEvent(C0.ESC + '[?6c'); } } @@ -1566,19 +1566,27 @@ export class InputHandler extends Disposable implements IInputHandler { // xterm and urxvt // seem to spit this // out around ~370 times (?). - if (this._terminal.is('xterm')) { + if (this._is('xterm')) { this._coreService.triggerDataEvent(C0.ESC + '[>0;276;0c'); - } else if (this._terminal.is('rxvt-unicode')) { + } else if (this._is('rxvt-unicode')) { this._coreService.triggerDataEvent(C0.ESC + '[>85;95;0c'); - } else if (this._terminal.is('linux')) { + } else if (this._is('linux')) { // not supported by linux console. // linux console echoes parameters. this._coreService.triggerDataEvent(params.params[0] + 'c'); - } else if (this._terminal.is('screen')) { + } else if (this._is('screen')) { this._coreService.triggerDataEvent(C0.ESC + '[>83;40003;0c'); } } + /** + * Evaluate if the current terminal is the given argument. + * @param term The terminal name to evaluate + */ + private _is(term: string): boolean { + return (this._optionsService.options.termName + '').indexOf(term) === 0; + } + /** * CSI Pm h Set Mode (SM). * Ps = 2 -> Keyboard Action Mode (AM). diff --git a/src/Terminal.ts b/src/Terminal.ts index 6e192320a..9dab96516 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1316,14 +1316,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._onScroll.fire(this.buffer.ydisp); } - /** - * Evaluate if the current terminal is the given argument. - * @param term The terminal name to evaluate - */ - public is(term: string): boolean { - return (this.options.termName + '').indexOf(term) === 0; - } - /** * Emit the data event and populate the given data. * @param data The data to populate in the event. diff --git a/src/Types.d.ts b/src/Types.d.ts index c3e1c53dd..7861fc7f2 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -22,8 +22,6 @@ export type LineData = CharData[]; */ export interface IInputHandlingTerminal { viewport: IViewport; - - is(term: string): boolean; } export interface ICompositionHelper { From ba40fe4ff4a16e794190e8876fb3707cc086e13c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 06:46:37 -0700 Subject: [PATCH 082/130] Remove Terminal dependency from InputHandler :tada: --- src/InputHandler.test.ts | 29 ++++++++++------------------- src/InputHandler.ts | 23 ++++++++++++----------- src/Terminal.ts | 29 ++++------------------------- src/TestUtils.test.ts | 12 +----------- src/Types.d.ts | 9 --------- 5 files changed, 27 insertions(+), 75 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 6c5b9cbb7..fd07fcb2a 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; import { InputHandler } from './InputHandler'; -import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test'; +import { TestTerminal } from './TestUtils.test'; import { Terminal } from './Terminal'; import { IBufferLine, IAttributeData } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; @@ -39,12 +39,11 @@ class TestInputHandler extends InputHandler { describe('InputHandler', () => { describe('save and restore cursor', () => { - const terminal = new MockInputHandlingTerminal(); const bufferService = new MockBufferService(80, 30); bufferService.buffer.x = 1; bufferService.buffer.y = 2; bufferService.buffer.ybase = 0; - const inputHandler = new TestInputHandler(terminal, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); inputHandler.curAttrData.fg = 3; // Save cursor position inputHandler.saveCursor(); @@ -64,7 +63,7 @@ describe('InputHandler', () => { describe('setCursorStyle', () => { it('should call Terminal.setOption with correct params', () => { const optionsService = new MockOptionsService(); - const inputHandler = new InputHandler(new MockInputHandlingTerminal(), new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService(), {} as any); inputHandler.setCursorStyle(Params.fromArray([0])); assert.equal(optionsService.options['cursorStyle'], 'block'); @@ -103,9 +102,8 @@ describe('InputHandler', () => { }); describe('setMode', () => { it('should toggle bracketedPasteMode', () => { - const terminal = new MockInputHandlingTerminal(); const coreService = new MockCoreService(); - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); // Set bracketed paste mode inputHandler.setModePrivate(Params.fromArray([2004])); assert.equal(coreService.decPrivateModes.bracketedPasteMode, true); @@ -122,9 +120,8 @@ describe('InputHandler', () => { } it('insertChars', function(): void { - const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -160,9 +157,8 @@ describe('InputHandler', () => { expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a')); }); it('deleteChars', function(): void { - const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -201,9 +197,8 @@ describe('InputHandler', () => { expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a')); }); it('eraseInLine', function(): void { - const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); // fill 6 lines to test 3 different states inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -230,9 +225,8 @@ describe('InputHandler', () => { }); it('eraseInDisplay', function(): void { - const term = new Terminal({cols: 80, rows: 7}); const bufferService = new MockBufferService(80, 7); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); // fill display with a's for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -366,8 +360,7 @@ describe('InputHandler', () => { }); describe('print', () => { it('should not cause an infinite loop (regression test)', () => { - const term = new Terminal(); - const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); const container = new Uint32Array(10); container[0] = 0x200B; inputHandler.print(container, 0, 1); @@ -375,14 +368,12 @@ describe('InputHandler', () => { }); describe('alt screen', () => { - let term: Terminal; let bufferService: IBufferService; let handler: InputHandler; beforeEach(() => { - term = new Terminal(); bufferService = new MockBufferService(80, 30); - handler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + handler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); }); it('should handle DECSET/DECRST 47 (alt screen buffer)', () => { handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST'); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index f4a084e2c..bf05d5114 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { IInputHandler, IInputHandlingTerminal } from './Types'; +import { IInputHandler } from './Types'; import { C0, C1 } from 'common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; @@ -238,6 +238,8 @@ export class InputHandler extends Disposable implements IInputHandler { public get onScroll(): IEvent { return this._onScroll.event; } private _onScrollRequest = new EventEmitter(); public get onScrollRequest(): IEvent { return this._onScrollRequest.event; } + private _onSyncScrollBarRequest = new EventEmitter(); + public get onSyncScrollBarRequest(): IEvent { return this._onSyncScrollBarRequest.event; } private _onTitleChange = new EventEmitter(); public get onTitleChange(): IEvent { return this._onTitleChange.event; } private _onA11yChar = new EventEmitter(); @@ -246,7 +248,6 @@ export class InputHandler extends Disposable implements IInputHandler { public get onA11yTab(): IEvent { return this._onA11yTab.event; } constructor( - private _terminal: IInputHandlingTerminal, private readonly _bufferService: IBufferService, private readonly _charsetService: ICharsetService, private readonly _coreService: ICoreService, @@ -256,8 +257,8 @@ export class InputHandler extends Disposable implements IInputHandler { private readonly _coreMouseService: ICoreMouseService, private readonly _unicodeService: IUnicodeService, private readonly _instantiationService: IInstantiationService, - private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()) - { + private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser() + ) { super(); this.register(this._parser); @@ -1766,7 +1767,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 66: this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); break; case 9: // X10 Mouse // no release, no motion, no wheel, no modifiers. @@ -1812,7 +1813,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._bufferService.buffers.activateAltBuffer(this._eraseAttrData()); this._coreService.isCursorInitialized = true; this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = true; @@ -1993,7 +1994,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 66: this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); break; case 9: // X10 Mouse case 1000: // vt200 mouse @@ -2030,7 +2031,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._coreService.isCursorInitialized = true; this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = false; @@ -2369,7 +2370,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public softReset(params: IParams): void { this._coreService.isCursorHidden = false; - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); this._bufferService.buffer.scrollTop = 0; this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1; this._curAttrData = DEFAULT_ATTR_DATA.clone(); @@ -2617,7 +2618,7 @@ export class InputHandler extends Disposable implements IInputHandler { public keypadApplicationMode(): void { this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); } /** @@ -2628,7 +2629,7 @@ export class InputHandler extends Disposable implements IInputHandler { public keypadNumericMode(): void { this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; - this._terminal.viewport?.syncScrollArea(); + this._onSyncScrollBarRequest.fire(); } /** diff --git a/src/Terminal.ts b/src/Terminal.ts index 9dab96516..4606f1aa2 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -21,7 +21,7 @@ * http://linux.die.net/man/7/urxvt */ -import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; +import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; @@ -60,7 +60,7 @@ import { CoreTerminal } from 'common/CoreTerminal'; const document = (typeof window !== 'undefined') ? window.document : null; -export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingTerminal { +export class Terminal extends CoreTerminal implements ITerminal { public textarea: HTMLTextAreaElement; public element: HTMLElement; public screenElement: HTMLElement; @@ -176,7 +176,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._inputHandler.reset(); } else { // Register input handler and refire/handle events - this._inputHandler = new InputHandler(this, this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService, this._instantiationService); + this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService, this._instantiationService); this.register(this._inputHandler.onRequestBell(() => this.bell())); this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); this.register(this._inputHandler.onRequestReset(() => this.reset())); @@ -462,6 +462,7 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._viewportScrollArea ); this.viewport.onThemeChange(this._colorManager.colors); + this.register(this._inputHandler.onSyncScrollBarRequest(() => this.viewport.syncScrollArea())); this.register(this.viewport); this.register(this.onCursorMove(() => this._renderService.onCursorMove())); @@ -1316,28 +1317,6 @@ export class Terminal extends CoreTerminal implements ITerminal, IInputHandlingT this._onScroll.fire(this.buffer.ydisp); } - /** - * Emit the data event and populate the given data. - * @param data The data to populate in the event. - */ - // public handler(data: string): void { - // // Prevents all events to pty process if stdin is disabled - // if (this.options.disableStdin) { - // return; - // } - - // // Clear the selection if the selection manager is available and has an active selection - // if (this.selectionService && this.selectionService.hasSelection) { - // this.selectionService.clearSelection(); - // } - - // // Input is being sent to the terminal, the terminal should focus the prompt. - // if (this.buffer.ybase !== this.buffer.ydisp) { - // this.scrollToBottom(); - // } - // this._onData.fire(data); - // } - /** * Reset terminal. * Note: Calling this directly from JS is synchronous but does not clear diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 2027f994b..32b2633f8 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -4,7 +4,7 @@ */ import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; -import { IInputHandlingTerminal, ICompositionHelper, ITerminal, IBrowser } from './Types'; +import { ICompositionHelper, ITerminal, IBrowser } from './Types'; import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; import { Buffer } from 'common/buffer/Buffer'; @@ -196,16 +196,6 @@ export class MockTerminal implements ITerminal { public deregisterCharacterJoiner(joinerId: number): void { } } -export class MockInputHandlingTerminal implements IInputHandlingTerminal { - public viewport: IViewport; - public is(term: string): boolean { - throw new Error('Method not implemented.'); - } - public resize(x: number, y: number): void { - throw new Error('Method not implemented.'); - } -} - export class MockBuffer implements IBuffer { public markers: IMarker[]; public addMarker(y: number): IMarker { diff --git a/src/Types.d.ts b/src/Types.d.ts index 7861fc7f2..e9a2199d9 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -15,15 +15,6 @@ export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; export type LineData = CharData[]; -/** - * This interface encapsulates everything needed from the Terminal by the - * InputHandler. This cleanly separates the large amount of methods needed by - * InputHandler cleanly from the ITerminal interface. - */ -export interface IInputHandlingTerminal { - viewport: IViewport; -} - export interface ICompositionHelper { compositionstart(): void; compositionupdate(ev: CompositionEvent): void; From 81d289b266cbba584be752c010b4d1584d32ca4a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 07:03:11 -0700 Subject: [PATCH 083/130] Remove RenderService dep in InputHandler --- src/InputHandler.test.ts | 18 +++++------ src/InputHandler.ts | 65 +++++++++++++++++++--------------------- src/Terminal.ts | 28 ++++++++++++++--- src/Types.d.ts | 2 +- 4 files changed, 65 insertions(+), 48 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index fd07fcb2a..37a54e39a 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -43,7 +43,7 @@ describe('InputHandler', () => { bufferService.buffer.x = 1; bufferService.buffer.y = 2; bufferService.buffer.ybase = 0; - const inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); inputHandler.curAttrData.fg = 3; // Save cursor position inputHandler.saveCursor(); @@ -63,7 +63,7 @@ describe('InputHandler', () => { describe('setCursorStyle', () => { it('should call Terminal.setOption with correct params', () => { const optionsService = new MockOptionsService(); - const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService()); inputHandler.setCursorStyle(Params.fromArray([0])); assert.equal(optionsService.options['cursorStyle'], 'block'); @@ -103,7 +103,7 @@ describe('InputHandler', () => { describe('setMode', () => { it('should toggle bracketedPasteMode', () => { const coreService = new MockCoreService(); - const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); // Set bracketed paste mode inputHandler.setModePrivate(Params.fromArray([2004])); assert.equal(coreService.decPrivateModes.bracketedPasteMode, true); @@ -121,7 +121,7 @@ describe('InputHandler', () => { it('insertChars', function(): void { const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -158,7 +158,7 @@ describe('InputHandler', () => { }); it('deleteChars', function(): void { const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -198,7 +198,7 @@ describe('InputHandler', () => { }); it('eraseInLine', function(): void { const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); // fill 6 lines to test 3 different states inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -226,7 +226,7 @@ describe('InputHandler', () => { }); it('eraseInDisplay', function(): void { const bufferService = new MockBufferService(80, 7); - const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); // fill display with a's for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -360,7 +360,7 @@ describe('InputHandler', () => { }); describe('print', () => { it('should not cause an infinite loop (regression test)', () => { - const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); const container = new Uint32Array(10); container[0] = 0x200B; inputHandler.print(container, 0, 1); @@ -373,7 +373,7 @@ describe('InputHandler', () => { beforeEach(() => { bufferService = new MockBufferService(80, 30); - handler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); + handler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); }); it('should handle DECSET/DECRST 47 (alt screen buffer)', () => { handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST'); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index bf05d5114..61ef55463 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -18,10 +18,9 @@ import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content import { CellData } from 'common/buffer/CellData'; import { AttributeData } from 'common/buffer/AttributeData'; import { IAttributeData, IDisposable, IWindowOptions } from 'common/Types'; -import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, IInstantiationService } from 'common/services/Services'; +import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService } from 'common/services/Services'; import { OscHandler } from 'common/parser/OscParser'; import { DcsHandler } from 'common/parser/DcsParser'; -import { IRenderService } from 'browser/services/Services'; /** * Map collect to glevel. Used in `selectCharset`. @@ -94,7 +93,10 @@ function paramToWindowOption(n: number, opts: IWindowOptions): boolean { return false; } - +export enum WindowsOptionsReportType { + GET_WIN_SIZE_PIXELS = 0, + GET_CELL_SIZE_PIXELS = 1 +} /** * DCS subparser implementations @@ -224,28 +226,31 @@ export class InputHandler extends Disposable implements IInputHandler { private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone(); private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone(); + private _onRequestBell = new EventEmitter(); + public get onRequestBell(): IEvent { return this._onRequestBell.event; } private _onRequestRefreshRows = new EventEmitter(); public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; } private _onRequestReset = new EventEmitter(); public get onRequestReset(): IEvent { return this._onRequestReset.event; } - private _onRequestBell = new EventEmitter(); - public get onRequestBell(): IEvent { return this._onRequestBell.event; } + private _onRequestScroll = new EventEmitter(); + public get onRequestScroll(): IEvent { return this._onRequestScroll.event; } + private _onRequestSyncScrollBar = new EventEmitter(); + public get onRequestSyncScrollBar(): IEvent { return this._onRequestSyncScrollBar.event; } + private _onRequestWindowsOptionsReport = new EventEmitter(); + public get onRequestWindowsOptionsReport(): IEvent { return this._onRequestWindowsOptionsReport.event; } + + private _onA11yChar = new EventEmitter(); + public get onA11yChar(): IEvent { return this._onA11yChar.event; } + private _onA11yTab = new EventEmitter(); + public get onA11yTab(): IEvent { return this._onA11yTab.event; } private _onCursorMove = new EventEmitter(); public get onCursorMove(): IEvent { return this._onCursorMove.event; } private _onLineFeed = new EventEmitter(); public get onLineFeed(): IEvent { return this._onLineFeed.event; } private _onScroll = new EventEmitter(); public get onScroll(): IEvent { return this._onScroll.event; } - private _onScrollRequest = new EventEmitter(); - public get onScrollRequest(): IEvent { return this._onScrollRequest.event; } - private _onSyncScrollBarRequest = new EventEmitter(); - public get onSyncScrollBarRequest(): IEvent { return this._onSyncScrollBarRequest.event; } private _onTitleChange = new EventEmitter(); public get onTitleChange(): IEvent { return this._onTitleChange.event; } - private _onA11yChar = new EventEmitter(); - public get onA11yChar(): IEvent { return this._onA11yChar.event; } - private _onA11yTab = new EventEmitter(); - public get onA11yTab(): IEvent { return this._onA11yTab.event; } constructor( private readonly _bufferService: IBufferService, @@ -256,7 +261,6 @@ export class InputHandler extends Disposable implements IInputHandler { private readonly _optionsService: IOptionsService, private readonly _coreMouseService: ICoreMouseService, private readonly _unicodeService: IUnicodeService, - private readonly _instantiationService: IInstantiationService, private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser() ) { super(); @@ -557,7 +561,7 @@ export class InputHandler extends Disposable implements IInputHandler { buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { buffer.y--; - this._onScrollRequest.fire(this._eraseAttrData(), true); + this._onRequestScroll.fire(this._eraseAttrData(), true); } else { if (buffer.y >= this._bufferService.rows) { buffer.y = this._bufferService.rows - 1; @@ -696,7 +700,7 @@ export class InputHandler extends Disposable implements IInputHandler { buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { buffer.y--; - this._onScrollRequest.fire(this._eraseAttrData()); + this._onRequestScroll.fire(this._eraseAttrData()); } else if (buffer.y >= this._bufferService.rows) { buffer.y = this._bufferService.rows - 1; } @@ -1767,7 +1771,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 66: this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); break; case 9: // X10 Mouse // no release, no motion, no wheel, no modifiers. @@ -1813,7 +1817,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._bufferService.buffers.activateAltBuffer(this._eraseAttrData()); this._coreService.isCursorInitialized = true; this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = true; @@ -1994,7 +1998,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 66: this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); break; case 9: // X10 Mouse case 1000: // vt200 mouse @@ -2031,7 +2035,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._coreService.isCursorInitialized = true; this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = false; @@ -2370,7 +2374,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public softReset(params: IParams): void { this._coreService.isCursorHidden = false; - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); this._bufferService.buffer.scrollTop = 0; this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1; this._curAttrData = DEFAULT_ATTR_DATA.clone(); @@ -2484,21 +2488,14 @@ export class InputHandler extends Disposable implements IInputHandler { return; } const second = (params.length > 1) ? params.params[1] : 0; - const rs = this._instantiationService.getService(IRenderService); switch (params.params[0]) { case 14: // GetWinSizePixels, returns CSI 4 ; height ; width t - if (rs && second !== 2) { - const w = rs.dimensions.scaledCanvasWidth.toFixed(0); - const h = rs.dimensions.scaledCanvasHeight.toFixed(0); - this._coreService.triggerDataEvent(`${C0.ESC}[4;${h};${w}t`); + if (second !== 2) { + this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_WIN_SIZE_PIXELS); } break; case 16: // GetCellSizePixels, returns CSI 6 ; height ; width t - if (rs) { - const w = rs.dimensions.scaledCellWidth.toFixed(0); - const h = rs.dimensions.scaledCellHeight.toFixed(0); - this._coreService.triggerDataEvent(`${C0.ESC}[6;${h};${w}t`); - } + this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_CELL_SIZE_PIXELS); break; case 18: // GetWinSizeChars, returns CSI 8 ; height ; width t if (this._bufferService) { @@ -2618,7 +2615,7 @@ export class InputHandler extends Disposable implements IInputHandler { public keypadApplicationMode(): void { this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); } /** @@ -2629,7 +2626,7 @@ export class InputHandler extends Disposable implements IInputHandler { public keypadNumericMode(): void { this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; - this._onSyncScrollBarRequest.fire(); + this._onRequestSyncScrollBar.fire(); } /** @@ -2686,7 +2683,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._bufferService.buffer.y++; if (buffer.y === buffer.scrollBottom + 1) { buffer.y--; - this._onScrollRequest.fire(this._eraseAttrData()); + this._onRequestScroll.fire(this._eraseAttrData()); } else if (buffer.y >= this._bufferService.rows) { buffer.y = this._bufferService.rows - 1; } diff --git a/src/Terminal.ts b/src/Terminal.ts index 4606f1aa2..e3af555b7 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -27,7 +27,7 @@ import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard'; import { C0 } from 'common/data/EscapeSequences'; -import { InputHandler } from './InputHandler'; +import { InputHandler, WindowsOptionsReportType } from './InputHandler'; import { Renderer } from 'browser/renderer/Renderer'; import { Linkifier } from 'browser/Linkifier'; import { SelectionService } from 'browser/services/SelectionService'; @@ -176,11 +176,12 @@ export class Terminal extends CoreTerminal implements ITerminal { this._inputHandler.reset(); } else { // Register input handler and refire/handle events - this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService, this._instantiationService); + this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService); this.register(this._inputHandler.onRequestBell(() => this.bell())); this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); this.register(this._inputHandler.onRequestReset(() => this.reset())); - this.register(this._inputHandler.onScrollRequest((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined))); + this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined))); + this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); @@ -462,7 +463,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this._viewportScrollArea ); this.viewport.onThemeChange(this._colorManager.colors); - this.register(this._inputHandler.onSyncScrollBarRequest(() => this.viewport.syncScrollArea())); + this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport.syncScrollArea())); this.register(this.viewport); this.register(this.onCursorMove(() => this._renderService.onCursorMove())); @@ -1351,6 +1352,25 @@ export class Terminal extends CoreTerminal implements ITerminal { this.viewport?.syncScrollArea(); } + private _reportWindowsOptions(type: WindowsOptionsReportType): void { + if (!this._renderService) { + return; + } + + switch (type) { + case WindowsOptionsReportType.GET_WIN_SIZE_PIXELS: + const canvasWidth = this._renderService.dimensions.scaledCanvasWidth.toFixed(0); + const canvasHeight = this._renderService.dimensions.scaledCanvasHeight.toFixed(0); + this._coreService.triggerDataEvent(`${C0.ESC}[4;${canvasHeight};${canvasWidth}t`); + break; + case WindowsOptionsReportType.GET_CELL_SIZE_PIXELS: + const cellWidth = this._renderService.dimensions.scaledCellWidth.toFixed(0); + const cellHeight = this._renderService.dimensions.scaledCellHeight.toFixed(0); + this._coreService.triggerDataEvent(`${C0.ESC}[6;${cellHeight};${cellWidth}t`); + break; + } + } + // TODO: Remove cancel function and cancelEvents option public cancel(ev: Event, force?: boolean): boolean { if (!this.options.cancelEvents && !force) { diff --git a/src/Types.d.ts b/src/Types.d.ts index e9a2199d9..2f57e99c0 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -28,7 +28,7 @@ export interface ICompositionHelper { */ export interface IInputHandler { onTitleChange: IEvent; - onScrollRequest: IEvent; + onRequestScroll: IEvent; parse(data: string | Uint8Array): void; print(data: Uint32Array, start: number, end: number): void; From d756086b8edc0fc31582499012d7a50dd85f6c3f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 07:24:30 -0700 Subject: [PATCH 084/130] Move InputHandler into common Part of #2749 Part of #1507 --- src/InputHandler.test.ts | 2 +- src/Terminal.ts | 2 +- src/Types.d.ts | 85 -------------------------- src/{ => common}/InputHandler.ts | 36 +++++------ src/common/TestUtils.test.ts | 1 - src/common/Types.d.ts | 86 +++++++++++++++++++++++++++ src/common/buffer/Buffer.ts | 2 +- src/common/buffer/Types.d.ts | 2 +- src/common/data/Charsets.ts | 6 +- src/common/services/CharsetService.ts | 11 ++-- src/common/services/Services.ts | 3 +- 11 files changed, 119 insertions(+), 117 deletions(-) rename src/{ => common}/InputHandler.ts (99%) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 37a54e39a..5a3dc2b5a 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -4,7 +4,7 @@ */ import { assert, expect } from 'chai'; -import { InputHandler } from './InputHandler'; +import { InputHandler } from './common/InputHandler'; import { TestTerminal } from './TestUtils.test'; import { Terminal } from './Terminal'; import { IBufferLine, IAttributeData } from 'common/Types'; diff --git a/src/Terminal.ts b/src/Terminal.ts index e3af555b7..61c997bd0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -27,7 +27,7 @@ import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard'; import { C0 } from 'common/data/EscapeSequences'; -import { InputHandler, WindowsOptionsReportType } from './InputHandler'; +import { InputHandler, WindowsOptionsReportType } from './common/InputHandler'; import { Renderer } from 'browser/renderer/Renderer'; import { Linkifier } from 'browser/Linkifier'; import { SelectionService } from 'browser/services/SelectionService'; diff --git a/src/Types.d.ts b/src/Types.d.ts index 2f57e99c0..05c89e158 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -23,91 +23,6 @@ export interface ICompositionHelper { keydown(ev: KeyboardEvent): boolean; } -/** - * Calls the parser and handles actions generated by the parser. - */ -export interface IInputHandler { - onTitleChange: IEvent; - onRequestScroll: IEvent; - - parse(data: string | Uint8Array): void; - print(data: Uint32Array, start: number, end: number): void; - - /** C0 BEL */ bell(): void; - /** C0 LF */ lineFeed(): void; - /** C0 CR */ carriageReturn(): void; - /** C0 BS */ backspace(): void; - /** C0 HT */ tab(): void; - /** C0 SO */ shiftOut(): void; - /** C0 SI */ shiftIn(): void; - - /** CSI @ */ insertChars(params: IParams): void; - /** CSI SP @ */ scrollLeft(params: IParams): void; - /** CSI A */ cursorUp(params: IParams): void; - /** CSI SP A */ scrollRight(params: IParams): void; - /** CSI B */ cursorDown(params: IParams): void; - /** CSI C */ cursorForward(params: IParams): void; - /** CSI D */ cursorBackward(params: IParams): void; - /** CSI E */ cursorNextLine(params: IParams): void; - /** CSI F */ cursorPrecedingLine(params: IParams): void; - /** CSI G */ cursorCharAbsolute(params: IParams): void; - /** CSI H */ cursorPosition(params: IParams): void; - /** CSI I */ cursorForwardTab(params: IParams): void; - /** CSI J */ eraseInDisplay(params: IParams): void; - /** CSI K */ eraseInLine(params: IParams): void; - /** CSI L */ insertLines(params: IParams): void; - /** CSI M */ deleteLines(params: IParams): void; - /** CSI P */ deleteChars(params: IParams): void; - /** CSI S */ scrollUp(params: IParams): void; - /** CSI T */ scrollDown(params: IParams, collect?: string): void; - /** CSI X */ eraseChars(params: IParams): void; - /** CSI Z */ cursorBackwardTab(params: IParams): void; - /** CSI ` */ charPosAbsolute(params: IParams): void; - /** CSI a */ hPositionRelative(params: IParams): void; - /** CSI b */ repeatPrecedingCharacter(params: IParams): void; - /** CSI c */ sendDeviceAttributesPrimary(params: IParams): void; - /** CSI > c */ sendDeviceAttributesSecondary(params: IParams): void; - /** CSI d */ linePosAbsolute(params: IParams): void; - /** CSI e */ vPositionRelative(params: IParams): void; - /** CSI f */ hVPosition(params: IParams): void; - /** CSI g */ tabClear(params: IParams): void; - /** CSI h */ setMode(params: IParams, collect?: string): void; - /** CSI l */ resetMode(params: IParams, collect?: string): void; - /** CSI m */ charAttributes(params: IParams): void; - /** CSI n */ deviceStatus(params: IParams, collect?: string): void; - /** CSI p */ softReset(params: IParams, collect?: string): void; - /** CSI q */ setCursorStyle(params: IParams, collect?: string): void; - /** CSI r */ setScrollRegion(params: IParams, collect?: string): void; - /** CSI s */ saveCursor(params: IParams): void; - /** CSI u */ restoreCursor(params: IParams): void; - /** CSI ' } */ insertColumns(params: IParams): void; - /** CSI ' ~ */ deleteColumns(params: IParams): void; - /** OSC 0 - OSC 2 */ setTitle(data: string): void; - /** ESC E */ nextLine(): void; - /** ESC = */ keypadApplicationMode(): void; - /** ESC > */ keypadNumericMode(): void; - /** ESC % G - ESC % @ */ selectDefaultCharset(): void; - /** ESC ( C - ESC ) C - ESC * C - ESC + C - ESC - C - ESC . C - ESC / C */ selectCharset(collectAndFlag: string): void; - /** ESC D */ index(): void; - /** ESC H */ tabSet(): void; - /** ESC M */ reverseIndex(): void; - /** ESC c */ fullReset(): void; - /** ESC n - ESC o - ESC | - ESC } - ESC ~ */ setgLevel(level: number): void; - /** ESC # 8 */ screenAlignmentPattern(): void; -} - export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { screenElement: HTMLElement; browser: IBrowser; diff --git a/src/InputHandler.ts b/src/common/InputHandler.ts similarity index 99% rename from src/InputHandler.ts rename to src/common/InputHandler.ts index 61ef55463..70ec8859c 100644 --- a/src/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { IInputHandler } from './Types'; +import { IInputHandler, IAttributeData, IDisposable, IWindowOptions } from 'common/Types'; import { C0, C1 } from 'common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; @@ -17,7 +17,6 @@ import { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IFunctionId import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; import { AttributeData } from 'common/buffer/AttributeData'; -import { IAttributeData, IDisposable, IWindowOptions } from 'common/Types'; import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService } from 'common/services/Services'; import { OscHandler } from 'common/parser/OscParser'; import { DcsHandler } from 'common/parser/DcsParser'; @@ -504,7 +503,7 @@ export class InputHandler extends Disposable implements IInputHandler { const wraparoundMode = this._coreService.decPrivateModes.wraparound; const insertMode = this._coreService.modes.insertMode; const curAttr = this._curAttrData; - let bufferRow = buffer.lines.get(buffer.y + buffer.ybase); + let bufferRow = buffer.lines.get(buffer.y + buffer.ybase)!; this._dirtyRowService.markDirty(buffer.y); @@ -568,10 +567,10 @@ export class InputHandler extends Disposable implements IInputHandler { } // The line already exists (eg. the initial viewport), mark it as a // wrapped line - buffer.lines.get(buffer.y).isWrapped = true; + buffer.lines.get(buffer.y)!.isWrapped = true; } // row changed, get it again - bufferRow = buffer.lines.get(buffer.y + buffer.ybase); + bufferRow = buffer.lines.get(buffer.y + buffer.ybase)!; } else { buffer.x = cols - 1; if (chWidth === 2) { @@ -1037,7 +1036,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @param end end - 1 is last erased cell */ private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false): void { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y)!; line.replaceCells( start, end, @@ -1055,7 +1054,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @param y row index */ private _resetBufferLine(y: number): void { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y)!; line.fill(this._bufferService.buffer.getNullCell(this._eraseAttrData())); line.isWrapped = false; } @@ -1104,7 +1103,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._eraseInBufferLine(j, 0, this._bufferService.buffer.x + 1, true); if (this._bufferService.buffer.x + 1 >= this._bufferService.cols) { // Deleted entire previous line. This next line can no longer be wrapped. - this._bufferService.buffer.lines.get(j + 1).isWrapped = false; + this._bufferService.buffer.lines.get(j + 1)!.isWrapped = false; } while (j--) { this._resetBufferLine(j); @@ -1356,7 +1355,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = buffer.lines.get(buffer.ybase + y); + const line = buffer.lines.get(buffer.ybase + y)!; line.deleteCells(0, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -1389,7 +1388,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = buffer.lines.get(buffer.ybase + y); + const line = buffer.lines.get(buffer.ybase + y)!; line.insertCells(0, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -1412,7 +1411,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = this._bufferService.buffer.lines.get(buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(buffer.ybase + y)!; line.insertCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -1435,7 +1434,7 @@ export class InputHandler extends Disposable implements IInputHandler { } const param = params.params[0] || 1; for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { - const line = buffer.lines.get(buffer.ybase + y); + const line = buffer.lines.get(buffer.ybase + y)!; line.deleteCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } @@ -2064,7 +2063,7 @@ export class InputHandler extends Disposable implements IInputHandler { do { accu[advance + cSpace] = params.params[pos + advance]; if (params.hasSubParams(pos + advance)) { - const subparams = params.getSubParams(pos + advance); + const subparams = params.getSubParams(pos + advance)!; let i = 0; do { if (accu[1] === 5) { @@ -2519,12 +2518,12 @@ export class InputHandler extends Disposable implements IInputHandler { case 23: // PopTitle if (second === 0 || second === 2) { if (this._windowTitleStack.length) { - this.setTitle(this._windowTitleStack.pop()); + this.setTitle(this._windowTitleStack.pop()!); } } if (second === 0 || second === 1) { if (this._iconNameStack.length) { - this.setIconName(this._iconNameStack.pop()); + this.setIconName(this._iconNameStack.pop()!); } } break; @@ -2788,8 +2787,11 @@ export class InputHandler extends Disposable implements IInputHandler { this._setCursor(0, 0); for (let yOffset = 0; yOffset < this._bufferService.rows; ++yOffset) { const row = buffer.y + buffer.ybase + yOffset; - buffer.lines.get(row).fill(cell); - buffer.lines.get(row).isWrapped = false; + const line = buffer.lines.get(row); + if (line) { + line.fill(cell); + line.isWrapped = false; + } } this._dirtyRowService.markAllDirty(); this._setCursor(0, 0); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index eacf92fe8..55e34084b 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -49,7 +49,6 @@ export class MockCharsetService implements ICharsetService { public serviceBrand: any; public charset: ICharset | undefined; public glevel: number = 0; - public charsets: ReadonlyArray = []; public reset(): void {} public setgLevel(g: number): void {} public setgCharset(g: number, charset: ICharset): void {} diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index cc7928c30..49a723b21 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -6,6 +6,7 @@ import { ITerminalOptions as IPublicTerminalOptions } from 'xterm'; import { IEvent, IEventEmitter } from 'common/EventEmitter'; import { IDeleteEvent, IInsertEvent } from 'common/CircularList'; +import { IParams } from 'common/parser/Types'; export interface IDisposable { dispose(): void; @@ -300,3 +301,88 @@ export interface IWindowOptions { popTitle?: boolean; setWinLines?: boolean; } + +/** + * Calls the parser and handles actions generated by the parser. + */ +export interface IInputHandler { + onTitleChange: IEvent; + onRequestScroll: IEvent; + + parse(data: string | Uint8Array): void; + print(data: Uint32Array, start: number, end: number): void; + + /** C0 BEL */ bell(): void; + /** C0 LF */ lineFeed(): void; + /** C0 CR */ carriageReturn(): void; + /** C0 BS */ backspace(): void; + /** C0 HT */ tab(): void; + /** C0 SO */ shiftOut(): void; + /** C0 SI */ shiftIn(): void; + + /** CSI @ */ insertChars(params: IParams): void; + /** CSI SP @ */ scrollLeft(params: IParams): void; + /** CSI A */ cursorUp(params: IParams): void; + /** CSI SP A */ scrollRight(params: IParams): void; + /** CSI B */ cursorDown(params: IParams): void; + /** CSI C */ cursorForward(params: IParams): void; + /** CSI D */ cursorBackward(params: IParams): void; + /** CSI E */ cursorNextLine(params: IParams): void; + /** CSI F */ cursorPrecedingLine(params: IParams): void; + /** CSI G */ cursorCharAbsolute(params: IParams): void; + /** CSI H */ cursorPosition(params: IParams): void; + /** CSI I */ cursorForwardTab(params: IParams): void; + /** CSI J */ eraseInDisplay(params: IParams): void; + /** CSI K */ eraseInLine(params: IParams): void; + /** CSI L */ insertLines(params: IParams): void; + /** CSI M */ deleteLines(params: IParams): void; + /** CSI P */ deleteChars(params: IParams): void; + /** CSI S */ scrollUp(params: IParams): void; + /** CSI T */ scrollDown(params: IParams, collect?: string): void; + /** CSI X */ eraseChars(params: IParams): void; + /** CSI Z */ cursorBackwardTab(params: IParams): void; + /** CSI ` */ charPosAbsolute(params: IParams): void; + /** CSI a */ hPositionRelative(params: IParams): void; + /** CSI b */ repeatPrecedingCharacter(params: IParams): void; + /** CSI c */ sendDeviceAttributesPrimary(params: IParams): void; + /** CSI > c */ sendDeviceAttributesSecondary(params: IParams): void; + /** CSI d */ linePosAbsolute(params: IParams): void; + /** CSI e */ vPositionRelative(params: IParams): void; + /** CSI f */ hVPosition(params: IParams): void; + /** CSI g */ tabClear(params: IParams): void; + /** CSI h */ setMode(params: IParams, collect?: string): void; + /** CSI l */ resetMode(params: IParams, collect?: string): void; + /** CSI m */ charAttributes(params: IParams): void; + /** CSI n */ deviceStatus(params: IParams, collect?: string): void; + /** CSI p */ softReset(params: IParams, collect?: string): void; + /** CSI q */ setCursorStyle(params: IParams, collect?: string): void; + /** CSI r */ setScrollRegion(params: IParams, collect?: string): void; + /** CSI s */ saveCursor(params: IParams): void; + /** CSI u */ restoreCursor(params: IParams): void; + /** CSI ' } */ insertColumns(params: IParams): void; + /** CSI ' ~ */ deleteColumns(params: IParams): void; + /** OSC 0 + OSC 2 */ setTitle(data: string): void; + /** ESC E */ nextLine(): void; + /** ESC = */ keypadApplicationMode(): void; + /** ESC > */ keypadNumericMode(): void; + /** ESC % G + ESC % @ */ selectDefaultCharset(): void; + /** ESC ( C + ESC ) C + ESC * C + ESC + C + ESC - C + ESC . C + ESC / C */ selectCharset(collectAndFlag: string): void; + /** ESC D */ index(): void; + /** ESC H */ tabSet(): void; + /** ESC M */ reverseIndex(): void; + /** ESC c */ fullReset(): void; + /** ESC n + ESC o + ESC | + ESC } + ESC ~ */ setgLevel(level: number): void; + /** ESC # 8 */ screenAlignmentPattern(): void; +} diff --git a/src/common/buffer/Buffer.ts b/src/common/buffer/Buffer.ts index 152bab7a3..1de39dbd2 100644 --- a/src/common/buffer/Buffer.ts +++ b/src/common/buffer/Buffer.ts @@ -36,7 +36,7 @@ export class Buffer implements IBuffer { public savedY: number = 0; public savedX: number = 0; public savedCurAttrData = DEFAULT_ATTR_DATA.clone(); - public savedCharset: ICharset | null = DEFAULT_CHARSET; + public savedCharset: ICharset | undefined = DEFAULT_CHARSET; public markers: Marker[] = []; private _nullCell: ICellData = CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); private _whitespaceCell: ICellData = CellData.fromCharData([0, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE]); diff --git a/src/common/buffer/Types.d.ts b/src/common/buffer/Types.d.ts index e229d69c3..c271f33c7 100644 --- a/src/common/buffer/Types.d.ts +++ b/src/common/buffer/Types.d.ts @@ -31,7 +31,7 @@ export interface IBuffer { hasScrollback: boolean; savedY: number; savedX: number; - savedCharset: ICharset | null; + savedCharset: ICharset | undefined; savedCurAttrData: IAttributeData; isCursorInViewport: boolean; markers: IMarker[]; diff --git a/src/common/data/Charsets.ts b/src/common/data/Charsets.ts index 01087d8b1..c72d5a237 100644 --- a/src/common/data/Charsets.ts +++ b/src/common/data/Charsets.ts @@ -10,12 +10,12 @@ import { ICharset } from 'common/Types'; * to be represented within the terminal with only 8-bit encoding. See ISO 2022 * for a discussion on character sets. Only VT100 character sets are supported. */ -export const CHARSETS: { [key: string]: ICharset | null } = {}; +export const CHARSETS: { [key: string]: ICharset | undefined } = {}; /** * The default character set, US. */ -export const DEFAULT_CHARSET: ICharset | null = CHARSETS['B']; +export const DEFAULT_CHARSET: ICharset | undefined = CHARSETS['B']; /** * DEC Special Character and Line Drawing Set. @@ -74,7 +74,7 @@ CHARSETS['A'] = { * United States character set * ESC (B */ -CHARSETS['B'] = null; +CHARSETS['B'] = undefined; /** * Dutch character set diff --git a/src/common/services/CharsetService.ts b/src/common/services/CharsetService.ts index 47a015f6f..c5381065a 100644 --- a/src/common/services/CharsetService.ts +++ b/src/common/services/CharsetService.ts @@ -10,22 +10,23 @@ export class CharsetService implements ICharsetService { public serviceBrand: any; public charset: ICharset | undefined; - public charsets: ICharset[] = []; public glevel: number = 0; + private _charsets: (ICharset | undefined)[] = []; + public reset(): void { this.charset = undefined; - this.charsets = []; + this._charsets = []; this.glevel = 0; } public setgLevel(g: number): void { this.glevel = g; - this.charset = this.charsets[g]; + this.charset = this._charsets[g]; } - public setgCharset(g: number, charset: ICharset): void { - this.charsets[g] = charset; + public setgCharset(g: number, charset: ICharset | undefined): void { + this._charsets[g] = charset; if (this.glevel === g) { this.charset = charset; } diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 8fa3f57b3..6829d7b96 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -98,7 +98,6 @@ export interface ICharsetService { charset: ICharset | undefined; readonly glevel: number; - readonly charsets: ReadonlyArray; reset(): void; @@ -113,7 +112,7 @@ export interface ICharsetService { * @param g * @param charset */ - setgCharset(g: number, charset: ICharset): void; + setgCharset(g: number, charset: ICharset | undefined): void; } export const IDirtyRowService = createDecorator('DirtyRowService'); From 51a808c094934601042da758626e99dca9395b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 26 Apr 2020 16:34:15 +0200 Subject: [PATCH 085/130] some refactoring --- src/InputHandler.ts | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 127454051..f0962ecdc 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -728,45 +728,44 @@ export class InputHandler extends Disposable implements IInputHandler { public backspace(): void { const buffer = this._bufferService.buffer; - // by default (resverse wrap-around not set) we restrict the cursor to 0 .. rows/cols - 1 - // thus the last cell of a row cannot be accessed by BS + // reverse wrap-around is disabled if (!this._coreService.decPrivateModes.reverseWraparound) { this._restrictCursor(); - } else { - // copy of _restrictCursor(), but with x=cols as allowed max cursor position - // to make last cell accessible by BS - buffer.x = Math.min(this._bufferService.cols, Math.max(0, this._bufferService.buffer.x)); - buffer.y = this._coreService.decPrivateModes.origin - ? Math.min(buffer.scrollBottom, Math.max(buffer.scrollTop, buffer.y)) - : Math.min(this._bufferService.rows - 1, Math.max(0, buffer.y)); - this._dirtyRowService.markDirty(buffer.y); + if (buffer.x > 0) { + buffer.x--; + } + return; } + // reverse wrap-around is enabled + // other than for normal operation mode, reverse wrap-around allows the cursor + // to be at x=cols to be able to address the last cell of a row by BS + this._restrictCursor(this._bufferService.cols); + if (buffer.x > 0) { buffer.x--; } else { /** - * reverse wrap-around: + * reverse wrap-around handling: * Our implementation deviates from xterm on purpose. Details: * - only previous soft NLs can be reversed (isWrapped=true) * - only works within scrollborders (top/bottom, left/right not yet supported) * - cannot peek into scrollbuffer * - any cursor movement sequence keeps working as expected */ - if (this._coreService.decPrivateModes.reverseWraparound - && buffer.x === 0 + if (buffer.x === 0 && buffer.y > buffer.scrollTop && buffer.y <= buffer.scrollBottom - && buffer.lines.get(buffer.y + buffer.ybase).isWrapped) + && buffer.lines.get(buffer.ybase + buffer.y).isWrapped) { - buffer.lines.get(buffer.y + buffer.ybase).isWrapped = false; + buffer.lines.get(buffer.ybase + buffer.y).isWrapped = false; buffer.y--; buffer.x = this._bufferService.cols - 1; // find last taken cell - last cell can have 3 different states: // - hasContent(true) + hasWidth(1): narrow char - we are done // - hasWidth(0): second part of wide char - we are done // - hasContent(false) + hasWidth(1): empty cell due to early wrapping wide char, go one cell further back - const line = buffer.lines.get(buffer.y + buffer.ybase); + const line = buffer.lines.get(buffer.ybase + buffer.y); if (line.hasWidth(buffer.x) && !line.hasContent(buffer.x)) { buffer.x--; // We do this only once, since width=1 + hasContent=false currently happens only once before @@ -820,8 +819,8 @@ export class InputHandler extends Disposable implements IInputHandler { /** * Restrict cursor to viewport size / scroll margin (origin mode). */ - private _restrictCursor(): void { - this._bufferService.buffer.x = Math.min(this._bufferService.cols - 1, Math.max(0, this._bufferService.buffer.x)); + private _restrictCursor(maxCol: number = this._bufferService.cols - 1): void { + this._bufferService.buffer.x = Math.min(maxCol, Math.max(0, this._bufferService.buffer.x)); this._bufferService.buffer.y = this._coreService.decPrivateModes.origin ? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y)) : Math.min(this._bufferService.rows - 1, Math.max(0, this._bufferService.buffer.y)); From 31670da63398969819bccb7ae7e2244ee5debfbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 26 Apr 2020 16:53:15 +0200 Subject: [PATCH 086/130] fix sloppy coding in InputHandler --- src/InputHandler.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 3717256e8..e80887cc2 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -491,7 +491,7 @@ export class InputHandler extends Disposable implements IInputHandler { const wraparoundMode = this._coreService.decPrivateModes.wraparound; const insertMode = this._terminal.insertMode; const curAttr = this._curAttrData; - let bufferRow = buffer.lines.get(buffer.y + buffer.ybase); + let bufferRow = buffer.lines.get(buffer.ybase + buffer.y); this._dirtyRowService.markDirty(buffer.y); @@ -555,10 +555,10 @@ export class InputHandler extends Disposable implements IInputHandler { } // The line already exists (eg. the initial viewport), mark it as a // wrapped line - buffer.lines.get(buffer.y).isWrapped = true; + buffer.lines.get(buffer.ybase + buffer.y).isWrapped = true; } // row changed, get it again - bufferRow = buffer.lines.get(buffer.y + buffer.ybase); + bufferRow = buffer.lines.get(buffer.ybase + buffer.y); } else { buffer.x = cols - 1; if (chWidth === 2) { @@ -1178,7 +1178,7 @@ export class InputHandler extends Disposable implements IInputHandler { return; } - const row: number = buffer.y + buffer.ybase; + const row: number = buffer.ybase + buffer.y; const scrollBottomRowsOffset = this._bufferService.rows - 1 - buffer.scrollBottom; const scrollBottomAbsolute = this._bufferService.rows - 1 + buffer.ybase - scrollBottomRowsOffset + 1; @@ -1213,7 +1213,7 @@ export class InputHandler extends Disposable implements IInputHandler { return; } - const row: number = buffer.y + buffer.ybase; + const row: number = buffer.ybase + buffer.y; let j: number; j = this._bufferService.rows - 1 - buffer.scrollBottom; @@ -1242,7 +1242,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public insertChars(params: IParams): void { this._restrictCursor(); - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + this._bufferService.buffer.y); if (line) { line.insertCells( this._bufferService.buffer.x, @@ -1267,7 +1267,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public deleteChars(params: IParams): void { this._restrictCursor(); - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + this._bufferService.buffer.y); if (line) { line.deleteCells( this._bufferService.buffer.x, @@ -1439,7 +1439,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public eraseChars(params: IParams): void { this._restrictCursor(); - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + this._bufferService.buffer.y); if (line) { line.replaceCells( this._bufferService.buffer.x, @@ -2712,8 +2712,8 @@ export class InputHandler extends Disposable implements IInputHandler { // test: echo -ne '\e[1;1H\e[44m\eM\e[0m' // blankLine(true) is xterm/linux behavior const scrollRegionHeight = buffer.scrollBottom - buffer.scrollTop; - buffer.lines.shiftElements(buffer.y + buffer.ybase, scrollRegionHeight, 1); - buffer.lines.set(buffer.y + buffer.ybase, buffer.getBlankLine(this._eraseAttrData())); + buffer.lines.shiftElements(buffer.ybase + buffer.y, scrollRegionHeight, 1); + buffer.lines.set(buffer.ybase + buffer.y, buffer.getBlankLine(this._eraseAttrData())); this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); } else { buffer.y--; @@ -2778,7 +2778,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._setCursor(0, 0); for (let yOffset = 0; yOffset < this._bufferService.rows; ++yOffset) { - const row = buffer.y + buffer.ybase + yOffset; + const row = buffer.ybase + buffer.y + yOffset; buffer.lines.get(row).fill(cell); buffer.lines.get(row).isWrapped = false; } From c9313412594421303dd26d263478bac05e28ebb5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 08:08:49 -0700 Subject: [PATCH 087/130] Remove Terminal dep in InputHandler.test --- src/InputHandler.test.ts | 1561 +++++++++++++++++------------------- src/Terminal.test.ts | 84 ++ src/common/InputHandler.ts | 4 +- 3 files changed, 836 insertions(+), 813 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 5a3dc2b5a..455fc754c 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -5,8 +5,6 @@ import { assert, expect } from 'chai'; import { InputHandler } from './common/InputHandler'; -import { TestTerminal } from './TestUtils.test'; -import { Terminal } from './Terminal'; import { IBufferLine, IAttributeData } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; @@ -14,36 +12,52 @@ import { Attributes } from 'common/buffer/Constants'; import { AttributeData } from 'common/buffer/AttributeData'; import { Params } from 'common/parser/Params'; import { MockCoreService, MockBufferService, MockDirtyRowService, MockOptionsService, MockLogService, MockCoreMouseService, MockCharsetService, MockUnicodeService } from 'common/TestUtils.test'; -import { IBufferService } from 'common/services/Services'; +import { IBufferService, ICoreService } from 'common/services/Services'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { clone } from 'common/Clone'; +import { BufferService } from 'common/services/BufferService'; +import { CoreService } from 'common/services/CoreService'; -function getCursor(term: TestTerminal): number[] { +function getCursor(bufferService: IBufferService): number[] { return [ - term.buffer.x, - term.buffer.y + bufferService.buffer.x, + bufferService.buffer.y ]; } -function getLines(term: TestTerminal, limit: number = term.rows): string[] { +function getLines(bufferService: IBufferService, limit: number = bufferService.rows): string[] { const res: string[] = []; for (let i = 0; i < limit; ++i) { - res.push(term.buffer.lines.get(i).translateToString(true)); + res.push(bufferService.buffer.lines.get(i).translateToString(true)); } return res; } class TestInputHandler extends InputHandler { public get curAttrData(): IAttributeData { return (this as any)._curAttrData; } + public get windowTitleStack(): string[] { return this._windowTitleStack; } + public get iconNameStack(): string[] { return this._iconNameStack; } } describe('InputHandler', () => { - describe('save and restore cursor', () => { - const bufferService = new MockBufferService(80, 30); + let bufferService: IBufferService; + let coreService: ICoreService; + let optionsService: MockOptionsService; + let inputHandler: TestInputHandler; + + beforeEach(() => { + optionsService = new MockOptionsService(); + bufferService = new BufferService(optionsService); + bufferService.resize(80, 30); + coreService = new CoreService(() => {}, bufferService, new MockLogService(), optionsService); + + inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService()); + }); + + it('save and restore cursor', () => { bufferService.buffer.x = 1; bufferService.buffer.y = 2; bufferService.buffer.ybase = 0; - const inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); inputHandler.curAttrData.fg = 3; // Save cursor position inputHandler.saveCursor(); @@ -62,9 +76,6 @@ describe('InputHandler', () => { }); describe('setCursorStyle', () => { it('should call Terminal.setOption with correct params', () => { - const optionsService = new MockOptionsService(); - const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService()); - inputHandler.setCursorStyle(Params.fromArray([0])); assert.equal(optionsService.options['cursorStyle'], 'block'); assert.equal(optionsService.options['cursorBlink'], true); @@ -341,23 +352,6 @@ describe('InputHandler', () => { expect(bufferService.buffer.lines.get(2).isWrapped).false; }); }); - it('convertEol setting', function(): void { - // not converting - const termNotConverting = new Terminal({cols: 15, rows: 10}); - (termNotConverting as any)._inputHandler.parse('Hello\nWorld'); - expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World '); - expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World'); - - // converting - const termConverting = new Terminal({cols: 15, rows: 10, convertEol: true}); - (termConverting as any)._inputHandler.parse('Hello\nWorld'); - expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World '); - expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World'); - }); describe('print', () => { it('should not cause an infinite loop (regression test)', () => { const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService()); @@ -423,837 +417,772 @@ describe('InputHandler', () => { }); describe('text attributes', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal(); - }); it('bold', () => { - term.writeSync('\x1b[1m'); - assert.equal(!!term.curAttrData.isBold(), true); - term.writeSync('\x1b[22m'); - assert.equal(!!term.curAttrData.isBold(), false); + inputHandler.parse('\x1b[1m'); + assert.equal(!!inputHandler.curAttrData.isBold(), true); + inputHandler.parse('\x1b[22m'); + assert.equal(!!inputHandler.curAttrData.isBold(), false); }); it('dim', () => { - term.writeSync('\x1b[2m'); - assert.equal(!!term.curAttrData.isDim(), true); - term.writeSync('\x1b[22m'); - assert.equal(!!term.curAttrData.isDim(), false); + inputHandler.parse('\x1b[2m'); + assert.equal(!!inputHandler.curAttrData.isDim(), true); + inputHandler.parse('\x1b[22m'); + assert.equal(!!inputHandler.curAttrData.isDim(), false); }); it('italic', () => { - term.writeSync('\x1b[3m'); - assert.equal(!!term.curAttrData.isItalic(), true); - term.writeSync('\x1b[23m'); - assert.equal(!!term.curAttrData.isItalic(), false); + inputHandler.parse('\x1b[3m'); + assert.equal(!!inputHandler.curAttrData.isItalic(), true); + inputHandler.parse('\x1b[23m'); + assert.equal(!!inputHandler.curAttrData.isItalic(), false); }); it('underline', () => { - term.writeSync('\x1b[4m'); - assert.equal(!!term.curAttrData.isUnderline(), true); - term.writeSync('\x1b[24m'); - assert.equal(!!term.curAttrData.isUnderline(), false); + inputHandler.parse('\x1b[4m'); + assert.equal(!!inputHandler.curAttrData.isUnderline(), true); + inputHandler.parse('\x1b[24m'); + assert.equal(!!inputHandler.curAttrData.isUnderline(), false); }); it('blink', () => { - term.writeSync('\x1b[5m'); - assert.equal(!!term.curAttrData.isBlink(), true); - term.writeSync('\x1b[25m'); - assert.equal(!!term.curAttrData.isBlink(), false); + inputHandler.parse('\x1b[5m'); + assert.equal(!!inputHandler.curAttrData.isBlink(), true); + inputHandler.parse('\x1b[25m'); + assert.equal(!!inputHandler.curAttrData.isBlink(), false); }); it('inverse', () => { - term.writeSync('\x1b[7m'); - assert.equal(!!term.curAttrData.isInverse(), true); - term.writeSync('\x1b[27m'); - assert.equal(!!term.curAttrData.isInverse(), false); + inputHandler.parse('\x1b[7m'); + assert.equal(!!inputHandler.curAttrData.isInverse(), true); + inputHandler.parse('\x1b[27m'); + assert.equal(!!inputHandler.curAttrData.isInverse(), false); }); it('invisible', () => { - term.writeSync('\x1b[8m'); - assert.equal(!!term.curAttrData.isInvisible(), true); - term.writeSync('\x1b[28m'); - assert.equal(!!term.curAttrData.isInvisible(), false); + inputHandler.parse('\x1b[8m'); + assert.equal(!!inputHandler.curAttrData.isInvisible(), true); + inputHandler.parse('\x1b[28m'); + assert.equal(!!inputHandler.curAttrData.isInvisible(), false); }); it('colormode palette 16', () => { - assert.equal(term.curAttrData.getFgColorMode(), 0); // DEFAULT - assert.equal(term.curAttrData.getBgColorMode(), 0); // DEFAULT + assert.equal(inputHandler.curAttrData.getFgColorMode(), 0); // DEFAULT + assert.equal(inputHandler.curAttrData.getBgColorMode(), 0); // DEFAULT // lower 8 colors for (let i = 0; i < 8; ++i) { - term.writeSync(`\x1b[${i + 30};${i + 40}m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getFgColor(), i); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getBgColor(), i); + inputHandler.parse(`\x1b[${i + 30};${i + 40}m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_P16); + assert.equal(inputHandler.curAttrData.getFgColor(), i); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_P16); + assert.equal(inputHandler.curAttrData.getBgColor(), i); } // reset to DEFAULT - term.writeSync(`\x1b[39;49m`); - assert.equal(term.curAttrData.getFgColorMode(), 0); - assert.equal(term.curAttrData.getBgColorMode(), 0); + inputHandler.parse(`\x1b[39;49m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), 0); + assert.equal(inputHandler.curAttrData.getBgColorMode(), 0); }); it('colormode palette 256', () => { - assert.equal(term.curAttrData.getFgColorMode(), 0); // DEFAULT - assert.equal(term.curAttrData.getBgColorMode(), 0); // DEFAULT + assert.equal(inputHandler.curAttrData.getFgColorMode(), 0); // DEFAULT + assert.equal(inputHandler.curAttrData.getBgColorMode(), 0); // DEFAULT // lower 8 colors for (let i = 0; i < 256; ++i) { - term.writeSync(`\x1b[38;5;${i};48;5;${i}m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getFgColor(), i); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getBgColor(), i); + inputHandler.parse(`\x1b[38;5;${i};48;5;${i}m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_P256); + assert.equal(inputHandler.curAttrData.getFgColor(), i); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_P256); + assert.equal(inputHandler.curAttrData.getBgColor(), i); } // reset to DEFAULT - term.writeSync(`\x1b[39;49m`); - assert.equal(term.curAttrData.getFgColorMode(), 0); - assert.equal(term.curAttrData.getFgColor(), -1); - assert.equal(term.curAttrData.getBgColorMode(), 0); - assert.equal(term.curAttrData.getBgColor(), -1); + inputHandler.parse(`\x1b[39;49m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), 0); + assert.equal(inputHandler.curAttrData.getFgColor(), -1); + assert.equal(inputHandler.curAttrData.getBgColorMode(), 0); + assert.equal(inputHandler.curAttrData.getBgColor(), -1); }); it('colormode RGB', () => { - assert.equal(term.curAttrData.getFgColorMode(), 0); // DEFAULT - assert.equal(term.curAttrData.getBgColorMode(), 0); // DEFAULT - term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_RGB); - assert.equal(term.curAttrData.getFgColor(), 1 << 16 | 2 << 8 | 3); - assert.deepEqual(AttributeData.toColorRGB(term.curAttrData.getFgColor()), [1, 2, 3]); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_RGB); - assert.deepEqual(AttributeData.toColorRGB(term.curAttrData.getBgColor()), [4, 5, 6]); + assert.equal(inputHandler.curAttrData.getFgColorMode(), 0); // DEFAULT + assert.equal(inputHandler.curAttrData.getBgColorMode(), 0); // DEFAULT + inputHandler.parse(`\x1b[38;2;1;2;3;48;2;4;5;6m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_RGB); + assert.equal(inputHandler.curAttrData.getFgColor(), 1 << 16 | 2 << 8 | 3); + assert.deepEqual(AttributeData.toColorRGB(inputHandler.curAttrData.getFgColor()), [1, 2, 3]); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_RGB); + assert.deepEqual(AttributeData.toColorRGB(inputHandler.curAttrData.getBgColor()), [4, 5, 6]); // reset to DEFAULT - term.writeSync(`\x1b[39;49m`); - assert.equal(term.curAttrData.getFgColorMode(), 0); - assert.equal(term.curAttrData.getFgColor(), -1); - assert.equal(term.curAttrData.getBgColorMode(), 0); - assert.equal(term.curAttrData.getBgColor(), -1); + inputHandler.parse(`\x1b[39;49m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), 0); + assert.equal(inputHandler.curAttrData.getFgColor(), -1); + assert.equal(inputHandler.curAttrData.getBgColorMode(), 0); + assert.equal(inputHandler.curAttrData.getBgColor(), -1); }); it('colormode transition RGB to 256', () => { // enter RGB for FG and BG - term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`); + inputHandler.parse(`\x1b[38;2;1;2;3;48;2;4;5;6m`); // enter 256 for FG and BG - term.writeSync(`\x1b[38;5;255;48;5;255m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getFgColor(), 255); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getBgColor(), 255); + inputHandler.parse(`\x1b[38;5;255;48;5;255m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_P256); + assert.equal(inputHandler.curAttrData.getFgColor(), 255); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_P256); + assert.equal(inputHandler.curAttrData.getBgColor(), 255); }); it('colormode transition RGB to 16', () => { // enter RGB for FG and BG - term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`); + inputHandler.parse(`\x1b[38;2;1;2;3;48;2;4;5;6m`); // enter 16 for FG and BG - term.writeSync(`\x1b[37;47m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getFgColor(), 7); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getBgColor(), 7); + inputHandler.parse(`\x1b[37;47m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_P16); + assert.equal(inputHandler.curAttrData.getFgColor(), 7); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_P16); + assert.equal(inputHandler.curAttrData.getBgColor(), 7); }); it('colormode transition 16 to 256', () => { // enter 16 for FG and BG - term.writeSync(`\x1b[37;47m`); + inputHandler.parse(`\x1b[37;47m`); // enter 256 for FG and BG - term.writeSync(`\x1b[38;5;255;48;5;255m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getFgColor(), 255); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getBgColor(), 255); + inputHandler.parse(`\x1b[38;5;255;48;5;255m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_P256); + assert.equal(inputHandler.curAttrData.getFgColor(), 255); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_P256); + assert.equal(inputHandler.curAttrData.getBgColor(), 255); }); it('colormode transition 256 to 16', () => { // enter 256 for FG and BG - term.writeSync(`\x1b[38;5;255;48;5;255m`); + inputHandler.parse(`\x1b[38;5;255;48;5;255m`); // enter 16 for FG and BG - term.writeSync(`\x1b[37;47m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getFgColor(), 7); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getBgColor(), 7); + inputHandler.parse(`\x1b[37;47m`); + assert.equal(inputHandler.curAttrData.getFgColorMode(), Attributes.CM_P16); + assert.equal(inputHandler.curAttrData.getFgColor(), 7); + assert.equal(inputHandler.curAttrData.getBgColorMode(), Attributes.CM_P16); + assert.equal(inputHandler.curAttrData.getBgColor(), 7); }); it('should zero missing RGB values', () => { - term.writeSync(`\x1b[38;2;1;2;3m`); - term.writeSync(`\x1b[38;2;5m`); - assert.deepEqual(AttributeData.toColorRGB(term.curAttrData.getFgColor()), [5, 0, 0]); + inputHandler.parse(`\x1b[38;2;1;2;3m`); + inputHandler.parse(`\x1b[38;2;5m`); + assert.deepEqual(AttributeData.toColorRGB(inputHandler.curAttrData.getFgColor()), [5, 0, 0]); }); }); describe('colon notation', () => { - let termColon: TestTerminal; - let termSemicolon: TestTerminal; + let inputHandler2: TestInputHandler; beforeEach(() => { - termColon = new TestTerminal(); - termSemicolon = new TestTerminal(); + inputHandler2 = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService()); }); describe('should equal to semicolon', () => { it('CSI 38:2::50:100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38:2::50:100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;50;100;150m'); + inputHandler.parse('\x1b[38:2::50:100:150m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38:2::50:100: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;m'); - termColon.writeSync('\x1b[38:2::50:100:m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;50;100;m'); + inputHandler.parse('\x1b[38:2::50:100:m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38:2::50:: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;;m'); - termColon.writeSync('\x1b[38:2::50::m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 0 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;50;;m'); + inputHandler.parse('\x1b[38:2::50::m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 0 << 8 | 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38:2:::: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;;;m'); - termColon.writeSync('\x1b[38:2::::m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0 << 16 | 0 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;;;m'); + inputHandler.parse('\x1b[38:2::::m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 0 << 16 | 0 << 8 | 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38;2::50:100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38;2::50:100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;50;100;150m'); + inputHandler.parse('\x1b[38;2::50:100:150m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38;2;50:100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38;2;50:100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;50;100;150m'); + inputHandler.parse('\x1b[38;2;50:100:150m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38;2;50;100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38;2;50;100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2;50;100;150m'); + inputHandler.parse('\x1b[38;2;50;100:150m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38:5:50 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5;50m'); - termColon.writeSync('\x1b[38:5:50m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 50); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;5;50m'); + inputHandler.parse('\x1b[38:5:50m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFF, 50); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38:5: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5;m'); - termColon.writeSync('\x1b[38:5:m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;5;m'); + inputHandler.parse('\x1b[38:5:m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFF, 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38;5:50 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5;50m'); - termColon.writeSync('\x1b[38;5:50m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 50); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;5;50m'); + inputHandler.parse('\x1b[38;5:50m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFF, 50); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); }); describe('should fill early sequence end with default of 0', () => { it('CSI 38:2 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2m'); - termColon.writeSync('\x1b[38:2m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0 << 16 | 0 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;2m'); + inputHandler.parse('\x1b[38:2m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 0 << 16 | 0 << 8 | 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 38:5 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5m'); - termColon.writeSync('\x1b[38:5m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.curAttrData.fg = 0xFFFFFFFF; + inputHandler2.parse('\x1b[38;5m'); + inputHandler.parse('\x1b[38:5m'); + assert.equal(inputHandler2.curAttrData.fg & 0xFF, 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); }); describe('should not interfere with leading/following SGR attrs', () => { it('CSI 1 ; 38:2::50:100:150 ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;50;100;150;4m'); - termColon.writeSync('\x1b[1;38:2::50:100:150;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler2.parse('\x1b[1;38;2;50;100;150;4m'); + inputHandler.parse('\x1b[1;38:2::50:100:150;4m'); + assert.equal(!!inputHandler2.curAttrData.isBold(), true); + assert.equal(!!inputHandler2.curAttrData.isUnderline(), true); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 1 ; 38:2::50:100: ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;50;100;;4m'); - termColon.writeSync('\x1b[1;38:2::50:100:;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler2.parse('\x1b[1;38;2;50;100;;4m'); + inputHandler.parse('\x1b[1;38:2::50:100:;4m'); + assert.equal(!!inputHandler2.curAttrData.isBold(), true); + assert.equal(!!inputHandler2.curAttrData.isUnderline(), true); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 1 ; 38:2::50:100 ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;50;100;;4m'); - termColon.writeSync('\x1b[1;38:2::50:100;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler2.parse('\x1b[1;38;2;50;100;;4m'); + inputHandler.parse('\x1b[1;38:2::50:100;4m'); + assert.equal(!!inputHandler2.curAttrData.isBold(), true); + assert.equal(!!inputHandler2.curAttrData.isUnderline(), true); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 1 ; 38:2:: ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;;;;4m'); - termColon.writeSync('\x1b[1;38:2::;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler2.parse('\x1b[1;38;2;;;;4m'); + inputHandler.parse('\x1b[1;38:2::;4m'); + assert.equal(!!inputHandler2.curAttrData.isBold(), true); + assert.equal(!!inputHandler2.curAttrData.isUnderline(), true); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); it('CSI 1 ; 38;2:: ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;;;;4m'); - termColon.writeSync('\x1b[1;38;2::;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); + inputHandler2.parse('\x1b[1;38;2;;;;4m'); + inputHandler.parse('\x1b[1;38;2::;4m'); + assert.equal(!!inputHandler2.curAttrData.isBold(), true); + assert.equal(!!inputHandler2.curAttrData.isUnderline(), true); + assert.equal(inputHandler2.curAttrData.fg & 0xFFFFFF, 0); + assert.equal(inputHandler.curAttrData.fg, inputHandler2.curAttrData.fg); }); }); }); describe('cursor positioning', () => { - let term: TestTerminal; beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 10}); + bufferService.resize(10, 10); }); it('cursor forward (CUF)', () => { - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[1C'); - assert.deepEqual(getCursor(term), [2, 0]); - term.writeSync('\x1b[4C'); - assert.deepEqual(getCursor(term), [6, 0]); - term.writeSync('\x1b[100C'); - assert.deepEqual(getCursor(term), [9, 0]); + inputHandler.parse('\x1b[C'); + assert.deepEqual(getCursor(bufferService), [1, 0]); + inputHandler.parse('\x1b[1C'); + assert.deepEqual(getCursor(bufferService), [2, 0]); + inputHandler.parse('\x1b[4C'); + assert.deepEqual(getCursor(bufferService), [6, 0]); + inputHandler.parse('\x1b[100C'); + assert.deepEqual(getCursor(bufferService), [9, 0]); // should not change y - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [9, 4]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 4; + inputHandler.parse('\x1b[C'); + assert.deepEqual(getCursor(bufferService), [9, 4]); }); it('cursor backward (CUB)', () => { - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1D'); - assert.deepEqual(getCursor(term), [0, 0]); + inputHandler.parse('\x1b[D'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[1D'); + assert.deepEqual(getCursor(bufferService), [0, 0]); // place cursor at end of first line - term.writeSync('\x1b[100C'); - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [8, 0]); - term.writeSync('\x1b[1D'); - assert.deepEqual(getCursor(term), [7, 0]); - term.writeSync('\x1b[4D'); - assert.deepEqual(getCursor(term), [3, 0]); - term.writeSync('\x1b[100D'); - assert.deepEqual(getCursor(term), [0, 0]); + inputHandler.parse('\x1b[100C'); + inputHandler.parse('\x1b[D'); + assert.deepEqual(getCursor(bufferService), [8, 0]); + inputHandler.parse('\x1b[1D'); + assert.deepEqual(getCursor(bufferService), [7, 0]); + inputHandler.parse('\x1b[4D'); + assert.deepEqual(getCursor(bufferService), [3, 0]); + inputHandler.parse('\x1b[100D'); + assert.deepEqual(getCursor(bufferService), [0, 0]); // should not change y - term.buffer.x = 4; - term.buffer.y = 4; - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [3, 4]); + bufferService.buffer.x = 4; + bufferService.buffer.y = 4; + inputHandler.parse('\x1b[D'); + assert.deepEqual(getCursor(bufferService), [3, 4]); }); it('cursor down (CUD)', () => { - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[1B'); - assert.deepEqual(getCursor(term), [0, 2]); - term.writeSync('\x1b[4B'); - assert.deepEqual(getCursor(term), [0, 6]); - term.writeSync('\x1b[100B'); - assert.deepEqual(getCursor(term), [0, 9]); + inputHandler.parse('\x1b[B'); + assert.deepEqual(getCursor(bufferService), [0, 1]); + inputHandler.parse('\x1b[1B'); + assert.deepEqual(getCursor(bufferService), [0, 2]); + inputHandler.parse('\x1b[4B'); + assert.deepEqual(getCursor(bufferService), [0, 6]); + inputHandler.parse('\x1b[100B'); + assert.deepEqual(getCursor(bufferService), [0, 9]); // should not change x - term.buffer.x = 8; - term.buffer.y = 0; - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [8, 1]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 0; + inputHandler.parse('\x1b[B'); + assert.deepEqual(getCursor(bufferService), [8, 1]); }); it('cursor up (CUU)', () => { - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1A'); - assert.deepEqual(getCursor(term), [0, 0]); + inputHandler.parse('\x1b[A'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[1A'); + assert.deepEqual(getCursor(bufferService), [0, 0]); // place cursor at beginning of last row - term.writeSync('\x1b[100B'); - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [0, 8]); - term.writeSync('\x1b[1A'); - assert.deepEqual(getCursor(term), [0, 7]); - term.writeSync('\x1b[4A'); - assert.deepEqual(getCursor(term), [0, 3]); - term.writeSync('\x1b[100A'); - assert.deepEqual(getCursor(term), [0, 0]); + inputHandler.parse('\x1b[100B'); + inputHandler.parse('\x1b[A'); + assert.deepEqual(getCursor(bufferService), [0, 8]); + inputHandler.parse('\x1b[1A'); + assert.deepEqual(getCursor(bufferService), [0, 7]); + inputHandler.parse('\x1b[4A'); + assert.deepEqual(getCursor(bufferService), [0, 3]); + inputHandler.parse('\x1b[100A'); + assert.deepEqual(getCursor(bufferService), [0, 0]); // should not change x - term.buffer.x = 8; - term.buffer.y = 9; - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [8, 8]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 9; + inputHandler.parse('\x1b[A'); + assert.deepEqual(getCursor(bufferService), [8, 8]); }); it('cursor next line (CNL)', () => { - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[1E'); - assert.deepEqual(getCursor(term), [0, 2]); - term.writeSync('\x1b[4E'); - assert.deepEqual(getCursor(term), [0, 6]); - term.writeSync('\x1b[100E'); - assert.deepEqual(getCursor(term), [0, 9]); + inputHandler.parse('\x1b[E'); + assert.deepEqual(getCursor(bufferService), [0, 1]); + inputHandler.parse('\x1b[1E'); + assert.deepEqual(getCursor(bufferService), [0, 2]); + inputHandler.parse('\x1b[4E'); + assert.deepEqual(getCursor(bufferService), [0, 6]); + inputHandler.parse('\x1b[100E'); + assert.deepEqual(getCursor(bufferService), [0, 9]); // should reset x to zero - term.buffer.x = 8; - term.buffer.y = 0; - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 1]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 0; + inputHandler.parse('\x1b[E'); + assert.deepEqual(getCursor(bufferService), [0, 1]); }); it('cursor previous line (CPL)', () => { - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1F'); - assert.deepEqual(getCursor(term), [0, 0]); + inputHandler.parse('\x1b[F'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[1F'); + assert.deepEqual(getCursor(bufferService), [0, 0]); // place cursor at beginning of last row - term.writeSync('\x1b[100E'); - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 8]); - term.writeSync('\x1b[1F'); - assert.deepEqual(getCursor(term), [0, 7]); - term.writeSync('\x1b[4F'); - assert.deepEqual(getCursor(term), [0, 3]); - term.writeSync('\x1b[100F'); - assert.deepEqual(getCursor(term), [0, 0]); + inputHandler.parse('\x1b[100E'); + inputHandler.parse('\x1b[F'); + assert.deepEqual(getCursor(bufferService), [0, 8]); + inputHandler.parse('\x1b[1F'); + assert.deepEqual(getCursor(bufferService), [0, 7]); + inputHandler.parse('\x1b[4F'); + assert.deepEqual(getCursor(bufferService), [0, 3]); + inputHandler.parse('\x1b[100F'); + assert.deepEqual(getCursor(bufferService), [0, 0]); // should reset x to zero - term.buffer.x = 8; - term.buffer.y = 9; - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 8]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 9; + inputHandler.parse('\x1b[F'); + assert.deepEqual(getCursor(bufferService), [0, 8]); }); it('cursor character absolute (CHA)', () => { - term.writeSync('\x1b[G'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1G'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[2G'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[5G'); - assert.deepEqual(getCursor(term), [4, 0]); - term.writeSync('\x1b[100G'); - assert.deepEqual(getCursor(term), [9, 0]); + inputHandler.parse('\x1b[G'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[1G'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[2G'); + assert.deepEqual(getCursor(bufferService), [1, 0]); + inputHandler.parse('\x1b[5G'); + assert.deepEqual(getCursor(bufferService), [4, 0]); + inputHandler.parse('\x1b[100G'); + assert.deepEqual(getCursor(bufferService), [9, 0]); }); it('cursor position (CUP)', () => { - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[H'); - assert.deepEqual(getCursor(term), [0, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[1H'); - assert.deepEqual(getCursor(term), [0, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[1;1H'); - assert.deepEqual(getCursor(term), [0, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[8H'); - assert.deepEqual(getCursor(term), [0, 7]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[;8H'); - assert.deepEqual(getCursor(term), [7, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[100;100H'); - assert.deepEqual(getCursor(term), [9, 9]); + bufferService.buffer.x = 5; + bufferService.buffer.y = 5; + inputHandler.parse('\x1b[H'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + bufferService.buffer.x = 5; + bufferService.buffer.y = 5; + inputHandler.parse('\x1b[1H'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + bufferService.buffer.x = 5; + bufferService.buffer.y = 5; + inputHandler.parse('\x1b[1;1H'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + bufferService.buffer.x = 5; + bufferService.buffer.y = 5; + inputHandler.parse('\x1b[8H'); + assert.deepEqual(getCursor(bufferService), [0, 7]); + bufferService.buffer.x = 5; + bufferService.buffer.y = 5; + inputHandler.parse('\x1b[;8H'); + assert.deepEqual(getCursor(bufferService), [7, 0]); + bufferService.buffer.x = 5; + bufferService.buffer.y = 5; + inputHandler.parse('\x1b[100;100H'); + assert.deepEqual(getCursor(bufferService), [9, 9]); }); it('horizontal position absolute (HPA)', () => { - term.writeSync('\x1b[`'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1`'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[2`'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[5`'); - assert.deepEqual(getCursor(term), [4, 0]); - term.writeSync('\x1b[100`'); - assert.deepEqual(getCursor(term), [9, 0]); + inputHandler.parse('\x1b[`'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[1`'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[2`'); + assert.deepEqual(getCursor(bufferService), [1, 0]); + inputHandler.parse('\x1b[5`'); + assert.deepEqual(getCursor(bufferService), [4, 0]); + inputHandler.parse('\x1b[100`'); + assert.deepEqual(getCursor(bufferService), [9, 0]); }); it('horizontal position relative (HPR)', () => { - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[1a'); - assert.deepEqual(getCursor(term), [2, 0]); - term.writeSync('\x1b[4a'); - assert.deepEqual(getCursor(term), [6, 0]); - term.writeSync('\x1b[100a'); - assert.deepEqual(getCursor(term), [9, 0]); + inputHandler.parse('\x1b[a'); + assert.deepEqual(getCursor(bufferService), [1, 0]); + inputHandler.parse('\x1b[1a'); + assert.deepEqual(getCursor(bufferService), [2, 0]); + inputHandler.parse('\x1b[4a'); + assert.deepEqual(getCursor(bufferService), [6, 0]); + inputHandler.parse('\x1b[100a'); + assert.deepEqual(getCursor(bufferService), [9, 0]); // should not change y - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [9, 4]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 4; + inputHandler.parse('\x1b[a'); + assert.deepEqual(getCursor(bufferService), [9, 4]); }); it('vertical position absolute (VPA)', () => { - term.writeSync('\x1b[d'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1d'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[2d'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[5d'); - assert.deepEqual(getCursor(term), [0, 4]); - term.writeSync('\x1b[100d'); - assert.deepEqual(getCursor(term), [0, 9]); + inputHandler.parse('\x1b[d'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[1d'); + assert.deepEqual(getCursor(bufferService), [0, 0]); + inputHandler.parse('\x1b[2d'); + assert.deepEqual(getCursor(bufferService), [0, 1]); + inputHandler.parse('\x1b[5d'); + assert.deepEqual(getCursor(bufferService), [0, 4]); + inputHandler.parse('\x1b[100d'); + assert.deepEqual(getCursor(bufferService), [0, 9]); // should not change x - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[d'); - assert.deepEqual(getCursor(term), [8, 0]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 4; + inputHandler.parse('\x1b[d'); + assert.deepEqual(getCursor(bufferService), [8, 0]); }); it('vertical position relative (VPR)', () => { - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[1e'); - assert.deepEqual(getCursor(term), [0, 2]); - term.writeSync('\x1b[4e'); - assert.deepEqual(getCursor(term), [0, 6]); - term.writeSync('\x1b[100e'); - assert.deepEqual(getCursor(term), [0, 9]); + inputHandler.parse('\x1b[e'); + assert.deepEqual(getCursor(bufferService), [0, 1]); + inputHandler.parse('\x1b[1e'); + assert.deepEqual(getCursor(bufferService), [0, 2]); + inputHandler.parse('\x1b[4e'); + assert.deepEqual(getCursor(bufferService), [0, 6]); + inputHandler.parse('\x1b[100e'); + assert.deepEqual(getCursor(bufferService), [0, 9]); // should not change x - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [8, 5]); + bufferService.buffer.x = 8; + bufferService.buffer.y = 4; + inputHandler.parse('\x1b[e'); + assert.deepEqual(getCursor(bufferService), [8, 5]); }); describe('should clamp cursor into addressible range', () => { it('CUF', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [1, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[C'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[C'); + assert.deepEqual(getCursor(bufferService), [1, 0]); }); it('CUB', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [8, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[D'); + assert.deepEqual(getCursor(bufferService), [8, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[D'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); it('CUD', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [0, 1]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[B'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[B'); + assert.deepEqual(getCursor(bufferService), [0, 1]); }); it('CUU', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [9, 8]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[A'); + assert.deepEqual(getCursor(bufferService), [9, 8]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[A'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); it('CNL', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 1]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[E'); + assert.deepEqual(getCursor(bufferService), [0, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[E'); + assert.deepEqual(getCursor(bufferService), [0, 1]); }); it('CPL', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 8]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[F'); + assert.deepEqual(getCursor(bufferService), [0, 8]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[F'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); it('CHA', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5G'); - assert.deepEqual(getCursor(term), [4, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5G'); - assert.deepEqual(getCursor(term), [4, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[5G'); + assert.deepEqual(getCursor(bufferService), [4, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[5G'); + assert.deepEqual(getCursor(bufferService), [4, 0]); }); it('CUP', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5;5H'); - assert.deepEqual(getCursor(term), [4, 4]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5;5H'); - assert.deepEqual(getCursor(term), [4, 4]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[5;5H'); + assert.deepEqual(getCursor(bufferService), [4, 4]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[5;5H'); + assert.deepEqual(getCursor(bufferService), [4, 4]); }); it('HPA', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5`'); - assert.deepEqual(getCursor(term), [4, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5`'); - assert.deepEqual(getCursor(term), [4, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[5`'); + assert.deepEqual(getCursor(bufferService), [4, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[5`'); + assert.deepEqual(getCursor(bufferService), [4, 0]); }); it('HPR', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [1, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[a'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[a'); + assert.deepEqual(getCursor(bufferService), [1, 0]); }); it('VPA', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5d'); - assert.deepEqual(getCursor(term), [9, 4]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5d'); - assert.deepEqual(getCursor(term), [0, 4]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[5d'); + assert.deepEqual(getCursor(bufferService), [9, 4]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[5d'); + assert.deepEqual(getCursor(bufferService), [0, 4]); }); it('VPR', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [0, 1]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[e'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[e'); + assert.deepEqual(getCursor(bufferService), [0, 1]); }); it('DCH', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[P'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[P'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[P'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[P'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); it('DCH - should delete last cell', () => { - term.writeSync('0123456789\x1b[P'); - assert.equal(term.buffer.lines.get(0).translateToString(false), '012345678 '); + inputHandler.parse('0123456789\x1b[P'); + assert.equal(bufferService.buffer.lines.get(0).translateToString(false), '012345678 '); }); it('ECH', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[X'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[X'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[X'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[X'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); it('ECH - should delete last cell', () => { - term.writeSync('0123456789\x1b[X'); - assert.equal(term.buffer.lines.get(0).translateToString(false), '012345678 '); + inputHandler.parse('0123456789\x1b[X'); + assert.equal(bufferService.buffer.lines.get(0).translateToString(false), '012345678 '); }); it('ICH', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[@'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[@'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[@'); + assert.deepEqual(getCursor(bufferService), [9, 9]); + bufferService.buffer.x = -10000; + bufferService.buffer.y = -10000; + inputHandler.parse('\x1b[@'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); it('ICH - should delete last cell', () => { - term.writeSync('0123456789\x1b[@'); - assert.equal(term.buffer.lines.get(0).translateToString(false), '012345678 '); + inputHandler.parse('0123456789\x1b[@'); + assert.equal(bufferService.buffer.lines.get(0).translateToString(false), '012345678 '); }); }); }); describe('DECSTBM - scroll margins', () => { - let term: TestTerminal; beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 10}); + bufferService.resize(10, 10); }); it('should default to whole viewport', () => { - term.writeSync('\x1b[r'); - assert.equal(term.buffer.scrollTop, 0); - assert.equal(term.buffer.scrollBottom, 9); - term.writeSync('\x1b[3;7r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 6); - term.writeSync('\x1b[0;0r'); - assert.equal(term.buffer.scrollTop, 0); - assert.equal(term.buffer.scrollBottom, 9); + inputHandler.parse('\x1b[r'); + assert.equal(bufferService.buffer.scrollTop, 0); + assert.equal(bufferService.buffer.scrollBottom, 9); + inputHandler.parse('\x1b[3;7r'); + assert.equal(bufferService.buffer.scrollTop, 2); + assert.equal(bufferService.buffer.scrollBottom, 6); + inputHandler.parse('\x1b[0;0r'); + assert.equal(bufferService.buffer.scrollTop, 0); + assert.equal(bufferService.buffer.scrollBottom, 9); }); it('should clamp bottom', () => { - term.writeSync('\x1b[3;1000r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 9); + inputHandler.parse('\x1b[3;1000r'); + assert.equal(bufferService.buffer.scrollTop, 2); + assert.equal(bufferService.buffer.scrollBottom, 9); }); it('should only apply for top < bottom', () => { - term.writeSync('\x1b[7;2r'); - assert.equal(term.buffer.scrollTop, 0); - assert.equal(term.buffer.scrollBottom, 9); + inputHandler.parse('\x1b[7;2r'); + assert.equal(bufferService.buffer.scrollTop, 0); + assert.equal(bufferService.buffer.scrollBottom, 9); }); it('should home cursor', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[2;7r'); - assert.deepEqual(getCursor(term), [0, 0]); + bufferService.buffer.x = 10000; + bufferService.buffer.y = 10000; + inputHandler.parse('\x1b[2;7r'); + assert.deepEqual(getCursor(bufferService), [0, 0]); }); }); describe('scroll margins', () => { - let term: TestTerminal; beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 10}); + bufferService.resize(10, 10); }); it('scrollUp', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Sm'); - assert.deepEqual(getLines(term), ['m', '3', '', '', '4', '5', '6', '7', '8', '9']); + inputHandler.parse('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Sm'); + assert.deepEqual(getLines(bufferService), ['m', '3', '', '', '4', '5', '6', '7', '8', '9']); }); it('scrollDown', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Tm'); - assert.deepEqual(getLines(term), ['m', '', '', '1', '4', '5', '6', '7', '8', '9']); + inputHandler.parse('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Tm'); + assert.deepEqual(getLines(bufferService), ['m', '', '', '1', '4', '5', '6', '7', '8', '9']); }); it('insertLines - out of margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[2Lm'); - assert.deepEqual(getLines(term), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); - term.writeSync('\x1b[2H\x1b[2Ln'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); + inputHandler.parse('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(bufferService.buffer.scrollTop, 2); + assert.equal(bufferService.buffer.scrollBottom, 5); + inputHandler.parse('\x1b[2Lm'); + assert.deepEqual(getLines(bufferService), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); + inputHandler.parse('\x1b[2H\x1b[2Ln'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); // skip below scrollbottom - term.writeSync('\x1b[7H\x1b[2Lo'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); - term.writeSync('\x1b[8H\x1b[2Lp'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); - term.writeSync('\x1b[100H\x1b[2Lq'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); + inputHandler.parse('\x1b[7H\x1b[2Lo'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); + inputHandler.parse('\x1b[8H\x1b[2Lp'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); + inputHandler.parse('\x1b[100H\x1b[2Lq'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); }); it('insertLines - within margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[3H\x1b[2Lm'); - assert.deepEqual(getLines(term), ['0', '1', 'm', '', '2', '3', '6', '7', '8', '9']); - term.writeSync('\x1b[6H\x1b[2Ln'); - assert.deepEqual(getLines(term), ['0', '1', 'm', '', '2', 'n', '6', '7', '8', '9']); + inputHandler.parse('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(bufferService.buffer.scrollTop, 2); + assert.equal(bufferService.buffer.scrollBottom, 5); + inputHandler.parse('\x1b[3H\x1b[2Lm'); + assert.deepEqual(getLines(bufferService), ['0', '1', 'm', '', '2', '3', '6', '7', '8', '9']); + inputHandler.parse('\x1b[6H\x1b[2Ln'); + assert.deepEqual(getLines(bufferService), ['0', '1', 'm', '', '2', 'n', '6', '7', '8', '9']); }); it('deleteLines - out of margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[2Mm'); - assert.deepEqual(getLines(term), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); - term.writeSync('\x1b[2H\x1b[2Mn'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); + inputHandler.parse('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(bufferService.buffer.scrollTop, 2); + assert.equal(bufferService.buffer.scrollBottom, 5); + inputHandler.parse('\x1b[2Mm'); + assert.deepEqual(getLines(bufferService), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); + inputHandler.parse('\x1b[2H\x1b[2Mn'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); // skip below scrollbottom - term.writeSync('\x1b[7H\x1b[2Mo'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); - term.writeSync('\x1b[8H\x1b[2Mp'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); - term.writeSync('\x1b[100H\x1b[2Mq'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); + inputHandler.parse('\x1b[7H\x1b[2Mo'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); + inputHandler.parse('\x1b[8H\x1b[2Mp'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); + inputHandler.parse('\x1b[100H\x1b[2Mq'); + assert.deepEqual(getLines(bufferService), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); }); it('deleteLines - within margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[6H\x1b[2Mm'); - assert.deepEqual(getLines(term), ['0', '1', '2', '3', '4', 'm', '6', '7', '8', '9']); - term.writeSync('\x1b[3H\x1b[2Mn'); - assert.deepEqual(getLines(term), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']); - }); - }); - describe('SL/SR/DECIC/DECDC', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); - }); - it('SL (scrollLeft)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[ @'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '2345', '2345', '2345', '2345', '2345']); - term.writeSync('\x1b[0 @'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '345', '345', '345', '345', '345']); - term.writeSync('\x1b[2 @'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '5', '5', '5', '5', '5']); - }); - it('SR (scrollRight)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[ A'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']); - term.writeSync('\x1b[0 A'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']); - term.writeSync('\x1b[2 A'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']); - }); - it('insertColumns (DECIC)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[\'}'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[1\'}'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[2\'}'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']); - }); - it('deleteColumns (DECDC)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[\'~'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[1\'~'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[2\'~'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']); + inputHandler.parse('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); + assert.equal(bufferService.buffer.scrollTop, 2); + assert.equal(bufferService.buffer.scrollBottom, 5); + inputHandler.parse('\x1b[6H\x1b[2Mm'); + assert.deepEqual(getLines(bufferService), ['0', '1', '2', '3', '4', 'm', '6', '7', '8', '9']); + inputHandler.parse('\x1b[3H\x1b[2Mn'); + assert.deepEqual(getLines(bufferService), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']); }); }); it('should parse big chunks in smaller subchunks', () => { // max single chunk size is hardcoded as 131072 const calls: any[] = []; - const term = new TestTerminal({cols: 10, rows: 10}); - (term as any)._inputHandler._parser.parse = (data: Uint32Array, length: number) => { + bufferService.resize(10, 10); + (inputHandler as any)._parser.parse = (data: Uint32Array, length: number) => { calls.push([data.length, length]); }; - term.writeSync('12345'); - term.writeSync('a'.repeat(10000)); - term.writeSync('a'.repeat(200000)); - term.writeSync('a'.repeat(300000)); + inputHandler.parse('12345'); + inputHandler.parse('a'.repeat(10000)); + inputHandler.parse('a'.repeat(200000)); + inputHandler.parse('a'.repeat(300000)); assert.deepEqual(calls, [ [4096, 5], [10000, 10000], @@ -1263,226 +1192,236 @@ describe('InputHandler', () => { }); describe('windowOptions', () => { it('all should be disabled by default and not report', () => { - const term = new TestTerminal({cols: 10, rows: 10}); + bufferService.resize(10, 10); const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[14t'); - term.writeSync('\x1b[16t'); - term.writeSync('\x1b[18t'); - term.writeSync('\x1b[20t'); - term.writeSync('\x1b[21t'); + coreService.onData(data => stack.push(data)); + inputHandler.parse('\x1b[14t'); + inputHandler.parse('\x1b[16t'); + inputHandler.parse('\x1b[18t'); + inputHandler.parse('\x1b[20t'); + inputHandler.parse('\x1b[21t'); assert.deepEqual(stack, []); }); it('14 - GetWinSizePixels', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinSizePixels: true}}); + bufferService.resize(10, 10); + optionsService.options.windowOptions.getWinSizePixels = true; const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[14t'); + coreService.onData(data => stack.push(data)); + inputHandler.parse('\x1b[14t'); // does not report in test terminal due to missing renderer assert.deepEqual(stack, []); }); it('16 - GetCellSizePixels', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getCellSizePixels: true}}); + bufferService.resize(10, 10); + optionsService.options.windowOptions.getCellSizePixels = true; const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[16t'); + coreService.onData(data => stack.push(data)); + inputHandler.parse('\x1b[16t'); // does not report in test terminal due to missing renderer assert.deepEqual(stack, []); }); it('18 - GetWinSizeChars', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinSizeChars: true}}); + bufferService.resize(10, 10); + optionsService.options.windowOptions.getWinSizeChars = true; const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[18t'); + coreService.onData(data => stack.push(data)); + inputHandler.parse('\x1b[18t'); assert.deepEqual(stack, ['\x1b[8;10;10t']); - term.resize(50, 20); - term.writeSync('\x1b[18t'); + bufferService.resize(50, 20); + inputHandler.parse('\x1b[18t'); assert.deepEqual(stack, ['\x1b[8;10;10t', '\x1b[8;20;50t']); }); it('22/23 - PushTitle/PopTitle', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); + bufferService.resize(10, 10); + optionsService.options.windowOptions.pushTitle = true; + optionsService.options.windowOptions.popTitle = true; const stack: string[] = []; - term.onTitleChange(data => stack.push(data)); - term.writeSync('\x1b]0;1\x07'); - term.writeSync('\x1b[22t'); - term.writeSync('\x1b]0;2\x07'); - term.writeSync('\x1b[22t'); - term.writeSync('\x1b]0;3\x07'); - term.writeSync('\x1b[22t'); - assert.deepEqual((term as any)._inputHandler._windowTitleStack, ['1', '2', '3']); - assert.deepEqual((term as any)._inputHandler._iconNameStack, ['1', '2', '3']); + inputHandler.onTitleChange(data => stack.push(data)); + inputHandler.parse('\x1b]0;1\x07'); + inputHandler.parse('\x1b[22t'); + inputHandler.parse('\x1b]0;2\x07'); + inputHandler.parse('\x1b[22t'); + inputHandler.parse('\x1b]0;3\x07'); + inputHandler.parse('\x1b[22t'); + assert.deepEqual(inputHandler.windowTitleStack, ['1', '2', '3']); + assert.deepEqual(inputHandler.iconNameStack, ['1', '2', '3']); assert.deepEqual(stack, ['1', '2', '3']); - term.writeSync('\x1b[23t'); - term.writeSync('\x1b[23t'); - term.writeSync('\x1b[23t'); - term.writeSync('\x1b[23t'); // one more to test "overflow" - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); + inputHandler.parse('\x1b[23t'); + inputHandler.parse('\x1b[23t'); + inputHandler.parse('\x1b[23t'); + inputHandler.parse('\x1b[23t'); // one more to test "overflow" + assert.deepEqual(inputHandler.windowTitleStack, []); + assert.deepEqual(inputHandler.iconNameStack, []); assert.deepEqual(stack, ['1', '2', '3', '3', '2', '1']); }); it('22/23 - PushTitle/PopTitle with ;1', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); + bufferService.resize(10, 10); + optionsService.options.windowOptions.pushTitle = true; + optionsService.options.windowOptions.popTitle = true; const stack: string[] = []; - term.onTitleChange(data => stack.push(data)); - term.writeSync('\x1b]0;1\x07'); - term.writeSync('\x1b[22;1t'); - term.writeSync('\x1b]0;2\x07'); - term.writeSync('\x1b[22;1t'); - term.writeSync('\x1b]0;3\x07'); - term.writeSync('\x1b[22;1t'); - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, ['1', '2', '3']); + inputHandler.onTitleChange(data => stack.push(data)); + inputHandler.parse('\x1b]0;1\x07'); + inputHandler.parse('\x1b[22;1t'); + inputHandler.parse('\x1b]0;2\x07'); + inputHandler.parse('\x1b[22;1t'); + inputHandler.parse('\x1b]0;3\x07'); + inputHandler.parse('\x1b[22;1t'); + assert.deepEqual(inputHandler.windowTitleStack, []); + assert.deepEqual(inputHandler.iconNameStack, ['1', '2', '3']); assert.deepEqual(stack, ['1', '2', '3']); - term.writeSync('\x1b[23;1t'); - term.writeSync('\x1b[23;1t'); - term.writeSync('\x1b[23;1t'); - term.writeSync('\x1b[23;1t'); // one more to test "overflow" - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); + inputHandler.parse('\x1b[23;1t'); + inputHandler.parse('\x1b[23;1t'); + inputHandler.parse('\x1b[23;1t'); + inputHandler.parse('\x1b[23;1t'); // one more to test "overflow" + assert.deepEqual(inputHandler.windowTitleStack, []); + assert.deepEqual(inputHandler.iconNameStack, []); assert.deepEqual(stack, ['1', '2', '3']); }); it('22/23 - PushTitle/PopTitle with ;2', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); + bufferService.resize(10, 10); + optionsService.options.windowOptions.pushTitle = true; + optionsService.options.windowOptions.popTitle = true; const stack: string[] = []; - term.onTitleChange(data => stack.push(data)); - term.writeSync('\x1b]0;1\x07'); - term.writeSync('\x1b[22;2t'); - term.writeSync('\x1b]0;2\x07'); - term.writeSync('\x1b[22;2t'); - term.writeSync('\x1b]0;3\x07'); - term.writeSync('\x1b[22;2t'); - assert.deepEqual((term as any)._inputHandler._windowTitleStack, ['1', '2', '3']); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); + inputHandler.onTitleChange(data => stack.push(data)); + inputHandler.parse('\x1b]0;1\x07'); + inputHandler.parse('\x1b[22;2t'); + inputHandler.parse('\x1b]0;2\x07'); + inputHandler.parse('\x1b[22;2t'); + inputHandler.parse('\x1b]0;3\x07'); + inputHandler.parse('\x1b[22;2t'); + assert.deepEqual(inputHandler.windowTitleStack, ['1', '2', '3']); + assert.deepEqual(inputHandler.iconNameStack, []); assert.deepEqual(stack, ['1', '2', '3']); - term.writeSync('\x1b[23;2t'); - term.writeSync('\x1b[23;2t'); - term.writeSync('\x1b[23;2t'); - term.writeSync('\x1b[23;2t'); // one more to test "overflow" - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); + inputHandler.parse('\x1b[23;2t'); + inputHandler.parse('\x1b[23;2t'); + inputHandler.parse('\x1b[23;2t'); + inputHandler.parse('\x1b[23;2t'); // one more to test "overflow" + assert.deepEqual(inputHandler.windowTitleStack, []); + assert.deepEqual(inputHandler.iconNameStack, []); assert.deepEqual(stack, ['1', '2', '3', '3', '2', '1']); }); it('DECCOLM - should only work with "SetWinLines" (24) enabled', () => { // disabled - const term = new TestTerminal({cols: 10, rows: 10}); - term.writeSync('\x1b[?3l'); - assert.equal((term as any)._bufferService.cols, 10); - term.writeSync('\x1b[?3h'); - assert.equal((term as any)._bufferService.cols, 10); + bufferService.resize(10, 10); + inputHandler.parse('\x1b[?3l'); + assert.equal(bufferService.cols, 10); + inputHandler.parse('\x1b[?3h'); + assert.equal(bufferService.cols, 10); // enabled - const term2 = new TestTerminal({cols: 10, rows: 10, windowOptions: {setWinLines: true}}); - term2.writeSync('\x1b[?3l'); - assert.equal((term2 as any)._bufferService.cols, 80); - term2.writeSync('\x1b[?3h'); - assert.equal((term2 as any)._bufferService.cols, 132); + inputHandler.reset(); + optionsService.options.windowOptions.setWinLines = true; + inputHandler.parse('\x1b[?3l'); + assert.equal(bufferService.cols, 80); + inputHandler.parse('\x1b[?3h'); + assert.equal(bufferService.cols, 132); }); }); describe('should correctly reset cells taken by wide chars', () => { - let term: TestTerminal; beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 5, scrollback: 1}); - term.writeSync('¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥'); + bufferService.resize(10, 5); + optionsService.options.scrollback = 1; + inputHandler.parse('¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥'); }); it('print', () => { - term.writeSync('\x1b[H#'); - assert.deepEqual(getLines(term), ['# ¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[1;6H######'); - assert.deepEqual(getLines(term), ['# ¥ #####', '# ¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '##¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;9H#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥#', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '# ¥¥¥¥', '']); - term.writeSync('\x1b[4;10H#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '# ¥¥¥ #', '']); + inputHandler.parse('\x1b[H#'); + assert.deepEqual(getLines(bufferService), ['# ¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[1;6H######'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '# ¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('#'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '##¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('#'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[3;9H#'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥#', '¥¥¥¥¥', '']); + inputHandler.parse('#'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '¥¥¥¥¥', '']); + inputHandler.parse('#'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '# ¥¥¥¥', '']); + inputHandler.parse('\x1b[4;10H#'); + assert.deepEqual(getLines(bufferService), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '# ¥¥¥ #', '']); }); it('EL', () => { - term.writeSync('\x1b[1;6H\x1b[K#'); - assert.deepEqual(getLines(term), ['¥¥ #', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;5H\x1b[1K'); - assert.deepEqual(getLines(term), ['¥¥ #', ' ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;6H\x1b[1K'); - assert.deepEqual(getLines(term), ['¥¥ #', ' ¥¥', ' ¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[1;6H\x1b[K#'); + assert.deepEqual(getLines(bufferService), ['¥¥ #', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[2;5H\x1b[1K'); + assert.deepEqual(getLines(bufferService), ['¥¥ #', ' ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[3;6H\x1b[1K'); + assert.deepEqual(getLines(bufferService), ['¥¥ #', ' ¥¥', ' ¥¥', '¥¥¥¥¥', '']); }); it('ICH', () => { - term.writeSync('\x1b[1;6H\x1b[@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;4H\x1b[2@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;4H\x1b[3@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥ ¥¥', '¥ ¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[4;4H\x1b[4@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥ ¥¥', '¥ ¥', '¥ ¥', '']); + inputHandler.parse('\x1b[1;6H\x1b[@'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[2;4H\x1b[2@'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥', '¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[3;4H\x1b[3@'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥', '¥ ¥¥', '¥ ¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[4;4H\x1b[4@'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥', '¥ ¥¥', '¥ ¥', '¥ ¥', '']); }); it('DCH', () => { - term.writeSync('\x1b[1;6H\x1b[P'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;6H\x1b[2P'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;6H\x1b[3P'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[1;6H\x1b[P'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[2;6H\x1b[2P'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥¥', '¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[3;6H\x1b[3P'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); }); it('ECH', () => { - term.writeSync('\x1b[1;6H\x1b[X'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;6H\x1b[2X'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;6H\x1b[3X'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[1;6H\x1b[X'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[2;6H\x1b[2X'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥¥', '¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); + inputHandler.parse('\x1b[3;6H\x1b[3X'); + assert.deepEqual(getLines(bufferService), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); }); }); describe('DECSTR', () => { - let term: TestTerminal; beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 5, scrollback: 1}); - term.writeSync('01234567890123'); + bufferService.resize(10, 5); + optionsService.options.scrollback = 1; + inputHandler.parse('01234567890123'); }); it('should reset IRM', () => { - term.writeSync('\x1b[4h'); - assert.equal((term as any)._coreService.modes.insertMode, true); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._coreService.modes.insertMode, false); + inputHandler.parse('\x1b[4h'); + assert.equal(coreService.modes.insertMode, true); + inputHandler.parse('\x1b[!p'); + assert.equal(coreService.modes.insertMode, false); }); it('should reset cursor visibility', () => { - term.writeSync('\x1b[?25l'); - assert.equal((term as any)._coreService.isCursorHidden, true); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._coreService.isCursorHidden, false); + inputHandler.parse('\x1b[?25l'); + assert.equal(coreService.isCursorHidden, true); + inputHandler.parse('\x1b[!p'); + assert.equal(coreService.isCursorHidden, false); }); it('should reset scroll margins', () => { - term.writeSync('\x1b[2;4r'); - assert.equal((term as any)._bufferService.buffer.scrollTop, 1); - assert.equal((term as any)._bufferService.buffer.scrollBottom, 3); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._bufferService.buffer.scrollTop, 0); - assert.equal((term as any)._bufferService.buffer.scrollBottom, term.rows - 1); + inputHandler.parse('\x1b[2;4r'); + assert.equal(bufferService.buffer.scrollTop, 1); + assert.equal(bufferService.buffer.scrollBottom, 3); + inputHandler.parse('\x1b[!p'); + assert.equal(bufferService.buffer.scrollTop, 0); + assert.equal(bufferService.buffer.scrollBottom, bufferService.rows - 1); }); it('should reset text attributes', () => { - term.writeSync('\x1b[1;2;32;43m'); - assert.equal(!!term.curAttrData.isBold(), true); - term.writeSync('\x1b[!p'); - assert.equal(!!term.curAttrData.isBold(), false); - assert.equal(term.curAttrData.fg, 0); - assert.equal(term.curAttrData.bg, 0); + inputHandler.parse('\x1b[1;2;32;43m'); + assert.equal(!!inputHandler.curAttrData.isBold(), true); + inputHandler.parse('\x1b[!p'); + assert.equal(!!inputHandler.curAttrData.isBold(), false); + assert.equal(inputHandler.curAttrData.fg, 0); + assert.equal(inputHandler.curAttrData.bg, 0); }); it('should reset DECSC data', () => { - term.writeSync('\x1b7'); - assert.equal((term as any)._bufferService.buffer.savedX, 4); - assert.equal((term as any)._bufferService.buffer.savedY, 1); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._bufferService.buffer.savedX, 0); - assert.equal((term as any)._bufferService.buffer.savedY, 0); + inputHandler.parse('\x1b7'); + assert.equal(bufferService.buffer.savedX, 4); + assert.equal(bufferService.buffer.savedY, 1); + inputHandler.parse('\x1b[!p'); + assert.equal(bufferService.buffer.savedX, 0); + assert.equal(bufferService.buffer.savedY, 0); }); it('should reset DECOM', () => { - term.writeSync('\x1b[?6h'); - assert.equal((term as any)._coreService.decPrivateModes.origin, true); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._coreService.decPrivateModes.origin, false); + inputHandler.parse('\x1b[?6h'); + assert.equal(coreService.decPrivateModes.origin, true); + inputHandler.parse('\x1b[!p'); + assert.equal(coreService.decPrivateModes.origin, false); }); }); }); diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts index 61b40d6c3..6488aa43f 100644 --- a/src/Terminal.test.ts +++ b/src/Terminal.test.ts @@ -1401,6 +1401,90 @@ describe('Terminal', () => { assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false); }); }); + it('convertEol setting', function(): void { + // not converting + const termNotConverting = new TestTerminal({cols: 15, rows: 10}); + termNotConverting.writeSync('Hello\nWorld'); + expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); + expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World '); + expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); + expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World'); + + // converting + const termConverting = new TestTerminal({cols: 15, rows: 10, convertEol: true}); + termConverting.writeSync('Hello\nWorld'); + expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); + expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World '); + expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); + expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World'); + }); + describe('Terminal InputHandler integration', () => { + function getLines(term: TestTerminal, limit: number = term.rows): string[] { + const res: string[] = []; + for (let i = 0; i < limit; ++i) { + res.push(term.buffer.lines.get(i).translateToString(true)); + } + return res; + } + + // This suite cannot live in InputHandler unless Terminal.scroll moved into IBufferService + describe('SL/SR/DECIC/DECDC', () => { + let term: TestTerminal; + beforeEach(() => { + term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); + }); + it('SL (scrollLeft)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[ @'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '2345', '2345', '2345', '2345', '2345']); + term.writeSync('\x1b[0 @'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '345', '345', '345', '345', '345']); + term.writeSync('\x1b[2 @'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '5', '5', '5', '5', '5']); + }); + it('SR (scrollRight)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[ A'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']); + term.writeSync('\x1b[0 A'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']); + term.writeSync('\x1b[2 A'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']); + }); + it('insertColumns (DECIC)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[\'}'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[1\'}'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[2\'}'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']); + }); + it('deleteColumns (DECDC)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[\'~'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[1\'~'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[2\'~'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']); + }); + }); + }); }); class TestLinkifier extends Linkifier { diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index 70ec8859c..6a7460a48 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -219,8 +219,8 @@ export class InputHandler extends Disposable implements IInputHandler { private _workCell: CellData = new CellData(); private _windowTitle = ''; private _iconName = ''; - private _windowTitleStack: string[] = []; - private _iconNameStack: string[] = []; + protected _windowTitleStack: string[] = []; + protected _iconNameStack: string[] = []; private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone(); private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone(); From 212061be502858d21a5d2920f66713c7f418600a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 08:11:53 -0700 Subject: [PATCH 088/130] Move InputHandler.test into common, fix strict errors --- src/{ => common}/InputHandler.test.ts | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) rename src/{ => common}/InputHandler.test.ts (97%) diff --git a/src/InputHandler.test.ts b/src/common/InputHandler.test.ts similarity index 97% rename from src/InputHandler.test.ts rename to src/common/InputHandler.test.ts index 455fc754c..8f3ff9af4 100644 --- a/src/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -4,7 +4,7 @@ */ import { assert, expect } from 'chai'; -import { InputHandler } from './common/InputHandler'; +import { InputHandler } from 'common/InputHandler'; import { IBufferLine, IAttributeData } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; @@ -28,7 +28,7 @@ function getCursor(bufferService: IBufferService): number[] { function getLines(bufferService: IBufferService, limit: number = bufferService.rows): string[] { const res: string[] = []; for (let i = 0; i < limit; ++i) { - res.push(bufferService.buffer.lines.get(i).translateToString(true)); + res.push(bufferService.buffer.lines.get(i)!.translateToString(true)); } return res; } @@ -126,7 +126,7 @@ describe('InputHandler', () => { describe('regression tests', function(): void { function termContent(bufferService: IBufferService, trim: boolean): string[] { const result = []; - for (let i = 0; i < bufferService.rows; ++i) result.push(bufferService.buffer.lines.get(i).translateToString(trim)); + for (let i = 0; i < bufferService.rows; ++i) result.push(bufferService.buffer.lines.get(i)!.translateToString(trim)); return result; } @@ -139,7 +139,7 @@ describe('InputHandler', () => { inputHandler.parse('1234567890'); inputHandler.parse(Array(bufferService.cols - 9).join('a')); inputHandler.parse('1234567890'); - const line1: IBufferLine = bufferService.buffer.lines.get(0); + const line1: IBufferLine = bufferService.buffer.lines.get(0)!; expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '1234567890'); // insert one char from params = [0] @@ -176,7 +176,7 @@ describe('InputHandler', () => { inputHandler.parse('1234567890'); inputHandler.parse(Array(bufferService.cols - 9).join('a')); inputHandler.parse('1234567890'); - const line1: IBufferLine = bufferService.buffer.lines.get(0); + const line1: IBufferLine = bufferService.buffer.lines.get(0)!; expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '1234567890'); // delete one char from params = [0] @@ -220,19 +220,19 @@ describe('InputHandler', () => { bufferService.buffer.y = 0; bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([0])); - expect(bufferService.buffer.lines.get(0).translateToString(false)).equals(Array(71).join('a') + ' '); + expect(bufferService.buffer.lines.get(0)!.translateToString(false)).equals(Array(71).join('a') + ' '); // params[1] - left erase bufferService.buffer.y = 1; bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([1])); - expect(bufferService.buffer.lines.get(1).translateToString(false)).equals(Array(71).join(' ') + ' aaaaaaaaa'); + expect(bufferService.buffer.lines.get(1)!.translateToString(false)).equals(Array(71).join(' ') + ' aaaaaaaaa'); // params[1] - left erase bufferService.buffer.y = 2; bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([2])); - expect(bufferService.buffer.lines.get(2).translateToString(false)).equals(Array(bufferService.cols + 1).join(' ')); + expect(bufferService.buffer.lines.get(2)!.translateToString(false)).equals(Array(bufferService.cols + 1).join(' ')); }); it('eraseInDisplay', function(): void { @@ -330,11 +330,11 @@ describe('InputHandler', () => { // params[1] left and above with wrap // confirm precondition that line 2 is wrapped - expect(bufferService.buffer.lines.get(2).isWrapped).true; + expect(bufferService.buffer.lines.get(2)!.isWrapped).true; bufferService.buffer.y = 2; bufferService.buffer.x = 40; inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(bufferService.buffer.lines.get(2).isWrapped).false; + expect(bufferService.buffer.lines.get(2)!.isWrapped).false; // reset and add a wrapped line bufferService.buffer.y = 0; @@ -345,11 +345,11 @@ describe('InputHandler', () => { // params[1] left and above with wrap // confirm precondition that line 2 is wrapped - expect(bufferService.buffer.lines.get(2).isWrapped).true; + expect(bufferService.buffer.lines.get(2)!.isWrapped).true; bufferService.buffer.y = 1; bufferService.buffer.x = 90; // Cursor is beyond last column inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(bufferService.buffer.lines.get(2).isWrapped).false; + expect(bufferService.buffer.lines.get(2)!.isWrapped).false; }); }); describe('print', () => { @@ -374,45 +374,45 @@ describe('InputHandler', () => { expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal(''); expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal(' TEST'); // Text color of 'TEST' should be red - expect((bufferService.buffer.lines.get(1).loadCell(4, new CellData()).getFgColor())).to.equal(1); + expect((bufferService.buffer.lines.get(1)!.loadCell(4, new CellData()).getFgColor())).to.equal(1); }); it('should handle DECSET/DECRST 1047 (alt screen buffer)', () => { handler.parse('\x1b[?1047h\r\n\x1b[31mJUNK\x1b[?1047lTEST'); expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal(''); expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal(' TEST'); // Text color of 'TEST' should be red - expect((bufferService.buffer.lines.get(1).loadCell(4, new CellData()).getFgColor())).to.equal(1); + expect((bufferService.buffer.lines.get(1)!.loadCell(4, new CellData()).getFgColor())).to.equal(1); }); it('should handle DECSET/DECRST 1048 (alt screen cursor)', () => { handler.parse('\x1b[?1048h\r\n\x1b[31mJUNK\x1b[?1048lTEST'); expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal('JUNK'); // Text color of 'TEST' should be default - expect(bufferService.buffer.lines.get(0).loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); + expect(bufferService.buffer.lines.get(0)!.loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); // Text color of 'JUNK' should be red - expect((bufferService.buffer.lines.get(1).loadCell(0, new CellData()).getFgColor())).to.equal(1); + expect((bufferService.buffer.lines.get(1)!.loadCell(0, new CellData()).getFgColor())).to.equal(1); }); it('should handle DECSET/DECRST 1049 (alt screen buffer+cursor)', () => { handler.parse('\x1b[?1049h\r\n\x1b[31mJUNK\x1b[?1049lTEST'); expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal(''); // Text color of 'TEST' should be default - expect(bufferService.buffer.lines.get(0).loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); + expect(bufferService.buffer.lines.get(0)!.loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); }); it('should handle DECSET/DECRST 1049 - maintains saved cursor for alt buffer', () => { handler.parse('\x1b[?1049h\r\n\x1b[31m\x1b[s\x1b[?1049lTEST'); expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); // Text color of 'TEST' should be default - expect(bufferService.buffer.lines.get(0).loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); + expect(bufferService.buffer.lines.get(0)!.loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); handler.parse('\x1b[?1049h\x1b[uTEST'); expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal('TEST'); // Text color of 'TEST' should be red - expect((bufferService.buffer.lines.get(1).loadCell(0, new CellData()).getFgColor())).to.equal(1); + expect((bufferService.buffer.lines.get(1)!.loadCell(0, new CellData()).getFgColor())).to.equal(1); }); it('should handle DECSET/DECRST 1049 - clears alt buffer with erase attributes', () => { handler.parse('\x1b[42m\x1b[?1049h'); // Buffer should be filled with green background - expect(bufferService.buffer.lines.get(20).loadCell(10, new CellData()).getBgColor()).to.equal(2); + expect(bufferService.buffer.lines.get(20)!.loadCell(10, new CellData()).getBgColor()).to.equal(2); }); }); @@ -1045,7 +1045,7 @@ describe('InputHandler', () => { }); it('DCH - should delete last cell', () => { inputHandler.parse('0123456789\x1b[P'); - assert.equal(bufferService.buffer.lines.get(0).translateToString(false), '012345678 '); + assert.equal(bufferService.buffer.lines.get(0)!.translateToString(false), '012345678 '); }); it('ECH', () => { bufferService.buffer.x = 10000; @@ -1059,7 +1059,7 @@ describe('InputHandler', () => { }); it('ECH - should delete last cell', () => { inputHandler.parse('0123456789\x1b[X'); - assert.equal(bufferService.buffer.lines.get(0).translateToString(false), '012345678 '); + assert.equal(bufferService.buffer.lines.get(0)!.translateToString(false), '012345678 '); }); it('ICH', () => { bufferService.buffer.x = 10000; @@ -1073,7 +1073,7 @@ describe('InputHandler', () => { }); it('ICH - should delete last cell', () => { inputHandler.parse('0123456789\x1b[@'); - assert.equal(bufferService.buffer.lines.get(0).translateToString(false), '012345678 '); + assert.equal(bufferService.buffer.lines.get(0)!.translateToString(false), '012345678 '); }); }); }); From b79a0a9832a8d9a4c1c89379e4431b4002eac71f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 08:12:53 -0700 Subject: [PATCH 089/130] Remove unwanted vscode setting --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 38f4dd110..f07ca5457 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,4 @@ { "typescript.preferences.importModuleSpecifier": "non-relative", - "typescript.preferences.quoteStyle": "single", - "eslint.enable": true + "typescript.preferences.quoteStyle": "single" } From d085768e8b1f319e873e0c3478272708fbe59b20 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 08:23:38 -0700 Subject: [PATCH 090/130] Fix some lint issues --- test/api/Terminal.api.ts | 2 +- test/benchmark/EscapeSequenceParser.benchmark.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index 6829fd0aa..75e001524 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -539,7 +539,7 @@ describe('API Integration Tests', function(): void { assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'norm '); assert.equal(await page.evaluate(`window.term.buffer.normal.getLine(0).translateToString()`), 'norm '); assert.equal(await page.evaluate(`window.term.buffer.alternate.getLine(0)`), undefined); - }) + }); }); it('dispose', async () => { diff --git a/test/benchmark/EscapeSequenceParser.benchmark.ts b/test/benchmark/EscapeSequenceParser.benchmark.ts index 68247715f..e4591dde8 100644 --- a/test/benchmark/EscapeSequenceParser.benchmark.ts +++ b/test/benchmark/EscapeSequenceParser.benchmark.ts @@ -19,9 +19,9 @@ function toUtf32(s: string): Uint32Array { } class DcsHandler implements IDcsHandler { - hook(params: IParams): void {} - put(data: Uint32Array, start: number, end: number): void {} - unhook(): void {} + public hook(params: IParams): void {} + public put(data: Uint32Array, start: number, end: number): void {} + public unhook(): void {} } From b9dee59900d98fdbae18c619474186bfe6a0ddad Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 09:36:56 -0700 Subject: [PATCH 091/130] Move InputHandler init into CoreTerminal --- src/Terminal.ts | 52 +++++++++----------------------------- src/common/CoreTerminal.ts | 30 ++++++++++++++++++++-- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 61c997bd0..54863ce01 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -27,7 +27,7 @@ import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard'; import { C0 } from 'common/data/EscapeSequences'; -import { InputHandler, WindowsOptionsReportType } from './common/InputHandler'; +import { WindowsOptionsReportType } from './common/InputHandler'; import { Renderer } from 'browser/renderer/Renderer'; import { Linkifier } from 'browser/Linkifier'; import { SelectionService } from 'browser/services/SelectionService'; @@ -49,7 +49,6 @@ import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISo import { CharSizeService } from 'browser/services/CharSizeService'; import { IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; -import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { WriteBuffer } from 'common/input/WriteBuffer'; import { Linkifier2 } from 'browser/Linkifier2'; @@ -100,7 +99,6 @@ export class Terminal extends CoreTerminal implements ITerminal { */ private _keyDownHandled: boolean = false; - private _inputHandler: InputHandler; public linkifier: ILinkifier; public linkifier2: ILinkifier2; public viewport: IViewport; @@ -154,6 +152,16 @@ export class Terminal extends CoreTerminal implements ITerminal { this._setup(); + this.register(this._inputHandler.onRequestBell(() => this.bell())); + this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); + this.register(this._inputHandler.onRequestReset(() => this.reset())); + this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined))); + this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); + this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); + this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); + this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); + this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); + // Setup listeners this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)); @@ -172,24 +180,6 @@ export class Terminal extends CoreTerminal implements ITerminal { } protected _setup(): void { - if (this._inputHandler) { - this._inputHandler.reset(); - } else { - // Register input handler and refire/handle events - this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService); - this.register(this._inputHandler.onRequestBell(() => this.bell())); - this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); - this.register(this._inputHandler.onRequestReset(() => this.reset())); - this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined))); - this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); - this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); - this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); - this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); - this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); - this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); - this.register(this._inputHandler); - } - super._setup(); this._customKeyEventHandler = null; @@ -986,25 +976,6 @@ export class Terminal extends CoreTerminal implements ITerminal { this._customKeyEventHandler = customKeyEventHandler; } - /** Add handler for ESC escape sequence. See xterm.d.ts for details. */ - public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable { - return this._inputHandler.addEscHandler(id, callback); - } - - /** Add handler for DCS escape sequence. See xterm.d.ts for details. */ - public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { - return this._inputHandler.addDcsHandler(id, callback); - } - - /** Add handler for CSI escape sequence. See xterm.d.ts for details. */ - public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { - return this._inputHandler.addCsiHandler(id, callback); - } - /** Add handler for OSC escape sequence. See xterm.d.ts for details. */ - public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { - return this._inputHandler.addOscHandler(ident, callback); - } - /** * Registers a link matcher, allowing custom link patterns to be matched and * handled. @@ -1337,6 +1308,7 @@ export class Terminal extends CoreTerminal implements ITerminal { const userScrolling = this._userScrolling; this._setup(); + this._inputHandler.reset(); this._bufferService.reset(); this._charsetService.reset(); this._coreService.reset(); diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 49f3509db..8df2bd6ba 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -27,7 +27,7 @@ import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; -import { ITerminalOptions, IDisposable } from './Types'; +import { ITerminalOptions, IDisposable } from 'common/Types'; import { CoreService } from 'common/services/CoreService'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; @@ -37,6 +37,7 @@ import { CharsetService } from 'common/services/CharsetService'; import { updateWindowsModeWrappedState } from 'common/WindowsMode'; import { IFunctionIdentifier, IParams } from 'common/parser/Types'; import { IBufferSet } from 'common/buffer/Types'; +import { InputHandler } from 'common/InputHandler'; export abstract class CoreTerminal extends Disposable { protected readonly _instantiationService: IInstantiationService; @@ -50,6 +51,7 @@ export abstract class CoreTerminal extends Disposable { public readonly unicodeService: IUnicodeService; public readonly optionsService: IOptionsService; + protected _inputHandler: InputHandler; private _windowsMode: IDisposable | undefined; private _onBinary = new EventEmitter(); @@ -94,6 +96,11 @@ export abstract class CoreTerminal extends Disposable { this.register(forwardEvent(this._coreService.onData, this._onData)); this.register(forwardEvent(this._coreService.onBinary, this._onBinary)); this.register(this.optionsService.onOptionChange(key => this._updateOptions(key))); + + // Register input handler and handle/forward events + this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService); + this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); + this.register(this._inputHandler); } public dispose(): void { @@ -116,6 +123,26 @@ export abstract class CoreTerminal extends Disposable { this._bufferService.resize(x, y); } + /** Add handler for ESC escape sequence. See xterm.d.ts for details. */ + public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable { + return this._inputHandler.addEscHandler(id, callback); + } + + /** Add handler for DCS escape sequence. See xterm.d.ts for details. */ + public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { + return this._inputHandler.addDcsHandler(id, callback); + } + + /** Add handler for CSI escape sequence. See xterm.d.ts for details. */ + public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { + return this._inputHandler.addCsiHandler(id, callback); + } + + /** Add handler for OSC escape sequence. See xterm.d.ts for details. */ + public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { + return this._inputHandler.addOscHandler(ident, callback); + } + protected _setup(): void { if (this.optionsService.options.windowsMode) { this._enableWindowsMode(); @@ -156,5 +183,4 @@ export abstract class CoreTerminal extends Disposable { } public abstract scrollToBottom(): void; - public abstract addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; } From 46e7fc61cc78fdb692c454e4b54ac794a8218f83 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 09:38:34 -0700 Subject: [PATCH 092/130] Move WriteBuffer into CoreTerminal --- src/Terminal.ts | 14 -------------- src/common/CoreTerminal.ts | 21 +++++++++++++++++---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 54863ce01..2385ad19f 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -50,7 +50,6 @@ import { CharSizeService } from 'browser/services/CharSizeService'; import { IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; -import { WriteBuffer } from 'common/input/WriteBuffer'; import { Linkifier2 } from 'browser/Linkifier2'; import { CoreBrowserService } from 'browser/services/CoreBrowserService'; import { CoreTerminal } from 'common/CoreTerminal'; @@ -86,9 +85,6 @@ export class Terminal extends CoreTerminal implements ITerminal { private _selectionService: ISelectionService; private _soundService: ISoundService; - // write buffer - private _writeBuffer: WriteBuffer; - // Store if user went browsing history in scrollback private _userScrolling: boolean; @@ -164,8 +160,6 @@ export class Terminal extends CoreTerminal implements ITerminal { // Setup listeners this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)); - - this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data)); } public dispose(): void { @@ -1364,14 +1358,6 @@ export class Terminal extends CoreTerminal implements ITerminal { // return this.options.bellStyle === 'sound' || // this.options.bellStyle === 'both'; } - - public write(data: string | Uint8Array, callback?: () => void): void { - this._writeBuffer.write(data, callback); - } - - public writeSync(data: string | Uint8Array): void { - this._writeBuffer.writeSync(data); - } } /** diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 8df2bd6ba..f98ef0dc7 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -38,6 +38,7 @@ import { updateWindowsModeWrappedState } from 'common/WindowsMode'; import { IFunctionIdentifier, IParams } from 'common/parser/Types'; import { IBufferSet } from 'common/buffer/Types'; import { InputHandler } from 'common/InputHandler'; +import { WriteBuffer } from 'common/input/WriteBuffer'; export abstract class CoreTerminal extends Disposable { protected readonly _instantiationService: IInstantiationService; @@ -52,6 +53,7 @@ export abstract class CoreTerminal extends Disposable { public readonly optionsService: IOptionsService; protected _inputHandler: InputHandler; + private _writeBuffer: WriteBuffer; private _windowsMode: IDisposable | undefined; private _onBinary = new EventEmitter(); @@ -91,16 +93,19 @@ export abstract class CoreTerminal extends Disposable { this._charsetService = this._instantiationService.createInstance(CharsetService); this._instantiationService.setService(ICharsetService, this._charsetService); + // Register input handler and handle/forward events + this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService); + this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); + this.register(this._inputHandler); + // Setup listeners this.register(forwardEvent(this._bufferService.onResize, this._onResize)); this.register(forwardEvent(this._coreService.onData, this._onData)); this.register(forwardEvent(this._coreService.onBinary, this._onBinary)); this.register(this.optionsService.onOptionChange(key => this._updateOptions(key))); - // Register input handler and handle/forward events - this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService); - this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); - this.register(this._inputHandler); + // Setup WriteBuffer + this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data)); } public dispose(): void { @@ -112,6 +117,14 @@ export abstract class CoreTerminal extends Disposable { this._windowsMode = undefined; } + public write(data: string | Uint8Array, callback?: () => void): void { + this._writeBuffer.write(data, callback); + } + + public writeSync(data: string | Uint8Array): void { + this._writeBuffer.writeSync(data); + } + public resize(x: number, y: number): void { if (isNaN(x) || isNaN(y)) { return; From 21bcef5008de7ee49b2899f1549356d84c2c897c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 09:54:44 -0700 Subject: [PATCH 093/130] Move a bunch of scroll logic into CoreTerminal This change will now reset userScrolling on RIS --- src/Terminal.ts | 78 ++-------------------------- src/common/CoreTerminal.ts | 72 ++++++++++++++++++++++++- src/common/TestUtils.test.ts | 1 + src/common/services/BufferService.ts | 3 ++ src/common/services/Services.ts | 1 + 5 files changed, 80 insertions(+), 75 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 2385ad19f..9f55e2bdf 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -85,9 +85,6 @@ export class Terminal extends CoreTerminal implements ITerminal { private _selectionService: ISelectionService; private _soundService: ISoundService; - // Store if user went browsing history in scrollback - private _userScrolling: boolean; - /** * Records whether the keydown event has already been handled and triggered a data event, if so * the keypress event should not trigger a data event but should still print to the textarea so @@ -113,8 +110,6 @@ export class Terminal extends CoreTerminal implements ITerminal { public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; } private _onRender = new EventEmitter<{ start: number, end: number }>(); public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } - private _onScroll = new EventEmitter(); - public get onScroll(): IEvent { return this._onScroll.event; } private _onSelectionChange = new EventEmitter(); public get onSelectionChange(): IEvent { return this._onSelectionChange.event; } private _onTitleChange = new EventEmitter(); @@ -178,7 +173,6 @@ export class Terminal extends CoreTerminal implements ITerminal { this._customKeyEventHandler = null; - this._userScrolling = false; if (!this.linkifier) { this.linkifier = this._instantiationService.createInstance(Linkifier); } @@ -862,13 +856,13 @@ export class Terminal extends CoreTerminal implements ITerminal { if (!willBufferBeTrimmed) { this.buffer.ybase++; // Only scroll the ydisp with ybase if the user has not scrolled up - if (!this._userScrolling) { + if (!this._bufferService.isUserScrolling) { this.buffer.ydisp++; } } else { // When the buffer is full and the user has scrolled up, keep the text // stable unless ydisp is right at the top - if (this._userScrolling) { + if (this._bufferService.isUserScrolling) { this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0); } } @@ -882,7 +876,7 @@ export class Terminal extends CoreTerminal implements ITerminal { // Move the viewport to the bottom of the buffer unless the user is // scrolling. - if (!this._userScrolling) { + if (!this._bufferService.isUserScrolling) { this.buffer.ydisp = this.buffer.ybase; } @@ -892,67 +886,11 @@ export class Terminal extends CoreTerminal implements ITerminal { this._onScroll.fire(this.buffer.ydisp); } - /** - * Scroll the display of the terminal - * @param disp The number of lines to scroll down (negative scroll up). - * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used - * to avoid unwanted events being handled by the viewport when the event was triggered from the - * viewport originally. - */ public scrollLines(disp: number, suppressScrollEvent?: boolean): void { - if (disp < 0) { - if (this.buffer.ydisp === 0) { - return; - } - this._userScrolling = true; - } else if (disp + this.buffer.ydisp >= this.buffer.ybase) { - this._userScrolling = false; - } - - const oldYdisp = this.buffer.ydisp; - this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0); - - // No change occurred, don't trigger scroll/refresh - if (oldYdisp === this.buffer.ydisp) { - return; - } - - if (!suppressScrollEvent) { - this._onScroll.fire(this.buffer.ydisp); - } - + super.scrollLines(disp, suppressScrollEvent); this.refresh(0, this.rows - 1); } - /** - * Scroll the display of the terminal by a number of pages. - * @param pageCount The number of pages to scroll (negative scrolls up). - */ - public scrollPages(pageCount: number): void { - this.scrollLines(pageCount * (this.rows - 1)); - } - - /** - * Scrolls the display of the terminal to the top. - */ - public scrollToTop(): void { - this.scrollLines(-this.buffer.ydisp); - } - - /** - * Scrolls the display of the terminal to the bottom. - */ - public scrollToBottom(): void { - this.scrollLines(this.buffer.ybase - this.buffer.ydisp); - } - - public scrollToLine(line: number): void { - const scrollAmount = line - this.buffer.ydisp; - if (scrollAmount !== 0) { - this.scrollLines(scrollAmount); - } - } - public paste(data: string): void { paste(data, this.textarea, this._coreService); } @@ -1299,19 +1237,13 @@ export class Terminal extends CoreTerminal implements ITerminal { this.options.rows = this.rows; this.options.cols = this.cols; const customKeyEventHandler = this._customKeyEventHandler; - const userScrolling = this._userScrolling; this._setup(); - this._inputHandler.reset(); - this._bufferService.reset(); - this._charsetService.reset(); - this._coreService.reset(); - this._coreMouseService.reset(); + super.reset(); this._selectionService?.reset(); // reattach this._customKeyEventHandler = customKeyEventHandler; - this._userScrolling = userScrolling; // do a full screen refresh this.refresh(0, this.rows - 1); diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index f98ef0dc7..a870a7650 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -64,6 +64,8 @@ export abstract class CoreTerminal extends Disposable { public get onLineFeed(): IEvent { return this._onLineFeed.event; } private _onResize = new EventEmitter<{ cols: number, rows: number }>(); public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } + protected _onScroll = new EventEmitter(); + public get onScroll(): IEvent { return this._onScroll.event; } public get cols(): number { return this._bufferService.cols; } public get rows(): number { return this._bufferService.rows; } @@ -136,6 +138,66 @@ export abstract class CoreTerminal extends Disposable { this._bufferService.resize(x, y); } + /** + * Scroll the display of the terminal + * @param disp The number of lines to scroll down (negative scroll up). + * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used + * to avoid unwanted events being handled by the viewport when the event was triggered from the + * viewport originally. + */ + public scrollLines(disp: number, suppressScrollEvent?: boolean): void { + const buffer = this._bufferService.buffer; + if (disp < 0) { + if (buffer.ydisp === 0) { + return; + } + this._bufferService.isUserScrolling = true; + } else if (disp + buffer.ydisp >= buffer.ybase) { + this._bufferService.isUserScrolling = false; + } + + const oldYdisp = buffer.ydisp; + buffer.ydisp = Math.max(Math.min(buffer.ydisp + disp, buffer.ybase), 0); + + // No change occurred, don't trigger scroll/refresh + if (oldYdisp === buffer.ydisp) { + return; + } + + if (!suppressScrollEvent) { + this._onScroll.fire(buffer.ydisp); + } + } + + /** + * Scroll the display of the terminal by a number of pages. + * @param pageCount The number of pages to scroll (negative scrolls up). + */ + public scrollPages(pageCount: number): void { + this.scrollLines(pageCount * (this.rows - 1)); + } + + /** + * Scrolls the display of the terminal to the top. + */ + public scrollToTop(): void { + this.scrollLines(-this._bufferService.buffer.ydisp); + } + + /** + * Scrolls the display of the terminal to the bottom. + */ + public scrollToBottom(): void { + this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp); + } + + public scrollToLine(line: number): void { + const scrollAmount = line - this._bufferService.buffer.ydisp; + if (scrollAmount !== 0) { + this.scrollLines(scrollAmount); + } + } + /** Add handler for ESC escape sequence. See xterm.d.ts for details. */ public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable { return this._inputHandler.addEscHandler(id, callback); @@ -162,6 +224,14 @@ export abstract class CoreTerminal extends Disposable { } } + public reset(): void { + this._inputHandler.reset(); + this._bufferService.reset(); + this._charsetService.reset(); + this._coreService.reset(); + this._coreMouseService.reset(); + } + protected _updateOptions(key: string): void { // TODO: These listeners should be owned by individual components switch (key) { @@ -194,6 +264,4 @@ export abstract class CoreTerminal extends Disposable { }; } } - - public abstract scrollToBottom(): void; } diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 55e34084b..71faed99a 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -17,6 +17,7 @@ export class MockBufferService implements IBufferService { public get buffer(): IBuffer { return this.buffers.active; } public buffers: IBufferSet = {} as any; public onResize: IEvent<{ cols: number, rows: number }> = new EventEmitter<{ cols: number, rows: number }>().event; + public isUserScrolling: boolean = false; constructor( public cols: number, public rows: number, diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts index d62d2cb00..8de44e43c 100644 --- a/src/common/services/BufferService.ts +++ b/src/common/services/BufferService.ts @@ -17,6 +17,8 @@ export class BufferService implements IBufferService { public cols: number; public rows: number; public buffers: IBufferSet; + /** Whether the user is scrolling (locks the scroll position) */ + public isUserScrolling: boolean = false; private _onResize = new EventEmitter<{ cols: number, rows: number }>(); public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } @@ -41,5 +43,6 @@ export class BufferService implements IBufferService { public reset(): void { this.buffers = new BufferSet(this._optionsService, this); + this.isUserScrolling = false; } } diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 6829d7b96..e123bd8bd 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -16,6 +16,7 @@ export interface IBufferService { readonly rows: number; readonly buffer: IBuffer; readonly buffers: IBufferSet; + isUserScrolling: boolean; onResize: IEvent<{ cols: number, rows: number }>; From 2a9b76246b9ee56557ada869d6b6021ed6bced9a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 10:02:59 -0700 Subject: [PATCH 094/130] Move scroll into CoreTerminal --- src/Terminal.ts | 70 +------------------------------------ src/common/CoreTerminal.ts | 71 +++++++++++++++++++++++++++++++++++++- src/common/Types.d.ts | 2 +- 3 files changed, 72 insertions(+), 71 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 9f55e2bdf..b7c8ba93e 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -39,7 +39,7 @@ import { MouseZoneManager } from 'browser/MouseZoneManager'; import { AccessibilityManager } from './AccessibilityManager'; import { ITheme, IMarker, IDisposable, ISelectionPosition, ILinkProvider } from 'xterm'; import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; -import { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types'; +import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; @@ -101,9 +101,6 @@ export class Terminal extends CoreTerminal implements ITerminal { private _colorManager: ColorManager; private _theme: ITheme; - // bufferline to clone/copy from for new blank lines - private _blankLine: IBufferLine = null; - private _onCursorMove = new EventEmitter(); public get onCursorMove(): IEvent { return this._onCursorMove.event; } private _onKey = new EventEmitter<{ key: string, domEvent: KeyboardEvent }>(); @@ -821,71 +818,6 @@ export class Terminal extends CoreTerminal implements ITerminal { } } - /** - * Scroll the terminal down 1 row, creating a blank line. - * @param isWrapped Whether the new line is wrapped from the previous line. - */ - public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void { - let newLine: IBufferLine; - newLine = this._blankLine; - if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) { - newLine = this.buffer.getBlankLine(eraseAttr, isWrapped); - this._blankLine = newLine; - } - newLine.isWrapped = isWrapped; - - const topRow = this.buffer.ybase + this.buffer.scrollTop; - const bottomRow = this.buffer.ybase + this.buffer.scrollBottom; - - if (this.buffer.scrollTop === 0) { - // Determine whether the buffer is going to be trimmed after insertion. - const willBufferBeTrimmed = this.buffer.lines.isFull; - - // Insert the line using the fastest method - if (bottomRow === this.buffer.lines.length - 1) { - if (willBufferBeTrimmed) { - this.buffer.lines.recycle().copyFrom(newLine); - } else { - this.buffer.lines.push(newLine.clone()); - } - } else { - this.buffer.lines.splice(bottomRow + 1, 0, newLine.clone()); - } - - // Only adjust ybase and ydisp when the buffer is not trimmed - if (!willBufferBeTrimmed) { - this.buffer.ybase++; - // Only scroll the ydisp with ybase if the user has not scrolled up - if (!this._bufferService.isUserScrolling) { - this.buffer.ydisp++; - } - } else { - // When the buffer is full and the user has scrolled up, keep the text - // stable unless ydisp is right at the top - if (this._bufferService.isUserScrolling) { - this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0); - } - } - } else { - // scrollTop is non-zero which means no line will be going to the - // scrollback, instead we can just shift them in-place. - const scrollRegionHeight = bottomRow - topRow + 1 /* as it's zero-based */; - this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1); - this.buffer.lines.set(bottomRow, newLine.clone()); - } - - // Move the viewport to the bottom of the buffer unless the user is - // scrolling. - if (!this._bufferService.isUserScrolling) { - this.buffer.ydisp = this.buffer.ybase; - } - - // Flag rows that need updating - this._dirtyRowService.markRangeDirty(this.buffer.scrollTop, this.buffer.scrollBottom); - - this._onScroll.fire(this.buffer.ydisp); - } - public scrollLines(disp: number, suppressScrollEvent?: boolean): void { super.scrollLines(disp, suppressScrollEvent); this.refresh(0, this.rows - 1); diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index a870a7650..113132c7e 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -27,7 +27,7 @@ import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; -import { ITerminalOptions, IDisposable } from 'common/Types'; +import { ITerminalOptions, IDisposable, IBufferLine, IAttributeData } from 'common/Types'; import { CoreService } from 'common/services/CoreService'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; @@ -55,6 +55,8 @@ export abstract class CoreTerminal extends Disposable { protected _inputHandler: InputHandler; private _writeBuffer: WriteBuffer; private _windowsMode: IDisposable | undefined; + /** An IBufferline to clone/copy from for new blank lines */ + private _cachedBlankLine: IBufferLine | undefined; private _onBinary = new EventEmitter(); public get onBinary(): IEvent { return this._onBinary.event; } @@ -138,6 +140,73 @@ export abstract class CoreTerminal extends Disposable { this._bufferService.resize(x, y); } + /** + * Scroll the terminal down 1 row, creating a blank line. + * @param isWrapped Whether the new line is wrapped from the previous line. + */ + public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void { + const buffer = this._bufferService.buffer; + + let newLine: IBufferLine | undefined; + newLine = this._cachedBlankLine; + if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) { + newLine = buffer.getBlankLine(eraseAttr, isWrapped); + this._cachedBlankLine = newLine; + } + newLine.isWrapped = isWrapped; + + const topRow = buffer.ybase + buffer.scrollTop; + const bottomRow = buffer.ybase + buffer.scrollBottom; + + if (buffer.scrollTop === 0) { + // Determine whether the buffer is going to be trimmed after insertion. + const willBufferBeTrimmed = buffer.lines.isFull; + + // Insert the line using the fastest method + if (bottomRow === buffer.lines.length - 1) { + if (willBufferBeTrimmed) { + buffer.lines.recycle().copyFrom(newLine); + } else { + buffer.lines.push(newLine.clone()); + } + } else { + buffer.lines.splice(bottomRow + 1, 0, newLine.clone()); + } + + // Only adjust ybase and ydisp when the buffer is not trimmed + if (!willBufferBeTrimmed) { + buffer.ybase++; + // Only scroll the ydisp with ybase if the user has not scrolled up + if (!this._bufferService.isUserScrolling) { + buffer.ydisp++; + } + } else { + // When the buffer is full and the user has scrolled up, keep the text + // stable unless ydisp is right at the top + if (this._bufferService.isUserScrolling) { + buffer.ydisp = Math.max(buffer.ydisp - 1, 0); + } + } + } else { + // scrollTop is non-zero which means no line will be going to the + // scrollback, instead we can just shift them in-place. + const scrollRegionHeight = bottomRow - topRow + 1 /* as it's zero-based */; + buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1); + buffer.lines.set(bottomRow, newLine.clone()); + } + + // Move the viewport to the bottom of the buffer unless the user is + // scrolling. + if (!this._bufferService.isUserScrolling) { + buffer.ydisp = buffer.ybase; + } + + // Flag rows that need updating + this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); + + this._onScroll.fire(buffer.ydisp); + } + /** * Scroll the display of the terminal * @param disp The number of lines to scroll down (negative scroll up). diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 49a723b21..b9d43b746 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -51,7 +51,7 @@ export interface ICircularList { get(index: number): T | undefined; set(index: number, value: T): void; push(value: T): void; - recycle(): T | undefined; + recycle(): T; pop(): T | undefined; splice(start: number, deleteCount: number, ...items: T[]): void; trimStart(count: number): void; From 4d01929503d7b496c949f3dbf6db25fddc57d83d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 10:11:24 -0700 Subject: [PATCH 095/130] Introduce ICoreTerminal --- .../src/renderLayer/LinkRenderLayer.ts | 6 ++--- src/TestUtils.test.ts | 2 +- src/Types.d.ts | 25 ++++++------------- src/common/CoreTerminal.ts | 4 +-- src/common/Types.d.ts | 6 +++++ 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts index 10cf9c1fe..a095b4aea 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts @@ -3,18 +3,18 @@ * @license MIT */ -import { ILinkifierAccessor } from '../../../../src/Types'; import { Terminal } from 'xterm'; import { BaseRenderLayer } from './BaseRenderLayer'; import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { is256Color } from '../atlas/CharAtlasUtils'; -import { IColorSet, ILinkifierEvent } from 'browser/Types'; +import { IColorSet, ILinkifierEvent, ILinkifier, ILinkifier2 } from 'browser/Types'; import { IRenderDimensions } from 'browser/renderer/Types'; +import { ITerminal } from '../../../../src/Types'; export class LinkRenderLayer extends BaseRenderLayer { private _state: ILinkifierEvent | undefined; - constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) { + constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ITerminal) { super(container, 'link', zIndex, true, colors); terminal.linkifier.onShowLinkUnderline(e => this._onShowLinkUnderline(e)); terminal.linkifier.onHideLinkUnderline(e => this._onHideLinkUnderline(e)); diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 32b2633f8..47a90b6c8 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -171,7 +171,7 @@ export class MockTerminal implements ITerminal { public addDisposableListener(type: string, handler: XtermListener): IDisposable { throw new Error('Method not implemented.'); } - public scrollLines(disp: number, suppressScrollEvent: boolean): void { + public scrollLines(disp: number): void { throw new Error('Method not implemented.'); } public scrollToRow(absoluteRow: number): number { diff --git a/src/Types.d.ts b/src/Types.d.ts index 05c89e158..a8f7f9a86 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -4,12 +4,14 @@ */ import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; -import { IAttributeData, CharData, ITerminalOptions } from 'common/Types'; +import { IAttributeData, CharData, ITerminalOptions, ICoreTerminal } from 'common/Types'; import { IEvent } from 'common/EventEmitter'; import { ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { IOptionsService, IUnicodeService } from 'common/services/Services'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; +import { Linkifier } from 'browser/Linkifier'; +import { Linkifier2 } from 'browser/Linkifier2'; export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; @@ -23,23 +25,23 @@ export interface ICompositionHelper { keydown(ev: KeyboardEvent): boolean; } -export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { +export interface ITerminal extends IPublicTerminal, ICoreTerminal { + element: HTMLElement | undefined; screenElement: HTMLElement; browser: IBrowser; buffer: IBuffer; buffers: IBufferSet; viewport: IViewport; - optionsService: IOptionsService; // TODO: We should remove options once components adopt optionsService options: ITerminalOptions; - unicodeService: IUnicodeService; + linkifier: ILinkifier; + linkifier2: ILinkifier2; onBlur: IEvent; onFocus: IEvent; onA11yChar: IEvent; onA11yTab: IEvent; - scrollLines(disp: number, suppressScrollEvent?: boolean): void; cancel(ev: Event, force?: boolean): boolean | void; } @@ -95,19 +97,6 @@ export interface IPublicTerminal extends IDisposable { reset(): void; } -export interface IBufferAccessor { - buffer: IBuffer; -} - -export interface IElementAccessor { - readonly element: HTMLElement | undefined; -} - -export interface ILinkifierAccessor { - linkifier: ILinkifier; - linkifier2: ILinkifier2; -} - export interface IBrowser { isNode: boolean; userAgent: string; diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 113132c7e..3793ae25d 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -27,7 +27,7 @@ import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; import { OptionsService } from 'common/services/OptionsService'; -import { ITerminalOptions, IDisposable, IBufferLine, IAttributeData } from 'common/Types'; +import { ITerminalOptions, IDisposable, IBufferLine, IAttributeData, ICoreTerminal } from 'common/Types'; import { CoreService } from 'common/services/CoreService'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; @@ -40,7 +40,7 @@ import { IBufferSet } from 'common/buffer/Types'; import { InputHandler } from 'common/InputHandler'; import { WriteBuffer } from 'common/input/WriteBuffer'; -export abstract class CoreTerminal extends Disposable { +export abstract class CoreTerminal extends Disposable implements ICoreTerminal { protected readonly _instantiationService: IInstantiationService; protected readonly _bufferService: IBufferService; protected readonly _logService: ILogService; diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index b9d43b746..4fcb627bb 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -7,6 +7,12 @@ import { ITerminalOptions as IPublicTerminalOptions } from 'xterm'; import { IEvent, IEventEmitter } from 'common/EventEmitter'; import { IDeleteEvent, IInsertEvent } from 'common/CircularList'; import { IParams } from 'common/parser/Types'; +import { IOptionsService, IUnicodeService } from 'common/services/Services'; + +export interface ICoreTerminal { + optionsService: IOptionsService; + unicodeService: IUnicodeService; +} export interface IDisposable { dispose(): void; From f256206fd4435727f7123ee5c39123312c612ee4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 10:18:05 -0700 Subject: [PATCH 096/130] Move Terminal and AccessibilityManager into browser --- src/Terminal2.test.ts | 2 +- src/TestUtils.test.ts | 2 +- src/Types.d.ts | 94 --------------------- src/{ => browser}/AccessibilityManager.ts | 7 +- src/browser/RenderDebouncer.ts | 2 +- src/{ => browser}/Terminal.ts | 4 +- src/browser/Types.d.ts | 99 ++++++++++++++++++++++- src/public/Terminal.ts | 2 +- 8 files changed, 109 insertions(+), 103 deletions(-) rename src/{ => browser}/AccessibilityManager.ts (98%) rename src/{ => browser}/Terminal.ts (99%) diff --git a/src/Terminal2.test.ts b/src/Terminal2.test.ts index f7046240b..720ea6b17 100644 --- a/src/Terminal2.test.ts +++ b/src/Terminal2.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; import * as pty from 'node-pty'; -import { Terminal } from './Terminal'; +import { Terminal } from './browser/Terminal'; import { IDisposable } from 'xterm'; // all test files expect terminal in 80x25 diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 47a90b6c8..965acc880 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -10,7 +10,7 @@ import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, I import { Buffer } from 'common/buffer/Buffer'; import * as Browser from 'common/Platform'; import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm'; -import { Terminal } from './Terminal'; +import { Terminal } from './browser/Terminal'; import { AttributeData } from 'common/buffer/AttributeData'; import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2 } from 'browser/Types'; import { IOptionsService, IUnicodeService } from 'common/services/Services'; diff --git a/src/Types.d.ts b/src/Types.d.ts index a8f7f9a86..1ffb7c5ef 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -13,97 +13,3 @@ import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { Linkifier } from 'browser/Linkifier'; import { Linkifier2 } from 'browser/Linkifier2'; -export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; - -export type LineData = CharData[]; - -export interface ICompositionHelper { - compositionstart(): void; - compositionupdate(ev: CompositionEvent): void; - compositionend(): void; - updateCompositionElements(dontRecurse?: boolean): void; - keydown(ev: KeyboardEvent): boolean; -} - -export interface ITerminal extends IPublicTerminal, ICoreTerminal { - element: HTMLElement | undefined; - screenElement: HTMLElement; - browser: IBrowser; - buffer: IBuffer; - buffers: IBufferSet; - viewport: IViewport; - // TODO: We should remove options once components adopt optionsService - options: ITerminalOptions; - linkifier: ILinkifier; - linkifier2: ILinkifier2; - - onBlur: IEvent; - onFocus: IEvent; - onA11yChar: IEvent; - onA11yTab: IEvent; - - cancel(ev: Event, force?: boolean): boolean | void; -} - -// Portions of the public API that are required by the internal Terminal -export interface IPublicTerminal extends IDisposable { - textarea: HTMLTextAreaElement | undefined; - rows: number; - cols: number; - buffer: IBuffer; - markers: IMarker[]; - onCursorMove: IEvent; - onData: IEvent; - onBinary: IEvent; - onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; - onLineFeed: IEvent; - onScroll: IEvent; - onSelectionChange: IEvent; - onRender: IEvent<{ start: number, end: number }>; - onResize: IEvent<{ cols: number, rows: number }>; - onTitleChange: IEvent; - blur(): void; - focus(): void; - resize(columns: number, rows: number): void; - open(parent: HTMLElement): void; - attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void; - addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; - addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable; - addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable; - addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; - registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number; - deregisterLinkMatcher(matcherId: number): void; - registerLinkProvider(linkProvider: ILinkProvider): IDisposable; - registerCharacterJoiner(handler: (text: string) => [number, number][]): number; - deregisterCharacterJoiner(joinerId: number): void; - addMarker(cursorYOffset: number): IMarker; - hasSelection(): boolean; - getSelection(): string; - getSelectionPosition(): ISelectionPosition | undefined; - clearSelection(): void; - select(column: number, row: number, length: number): void; - selectAll(): void; - selectLines(start: number, end: number): void; - dispose(): void; - scrollLines(amount: number): void; - scrollPages(pageCount: number): void; - scrollToTop(): void; - scrollToBottom(): void; - scrollToLine(line: number): void; - clear(): void; - write(data: string | Uint8Array, callback?: () => void): void; - paste(data: string): void; - refresh(start: number, end: number): void; - reset(): void; -} - -export interface IBrowser { - isNode: boolean; - userAgent: string; - platform: string; - isFirefox: boolean; - isMac: boolean; - isIpad: boolean; - isIphone: boolean; - isWindows: boolean; -} diff --git a/src/AccessibilityManager.ts b/src/browser/AccessibilityManager.ts similarity index 98% rename from src/AccessibilityManager.ts rename to src/browser/AccessibilityManager.ts index 783915011..b613e9ba6 100644 --- a/src/AccessibilityManager.ts +++ b/src/browser/AccessibilityManager.ts @@ -3,8 +3,8 @@ * @license MIT */ -import * as Strings from './browser/LocalizableStrings'; -import { ITerminal } from './Types'; +import * as Strings from 'browser/LocalizableStrings'; +import { ITerminal } from 'browser/Types'; import { IBuffer } from 'common/buffer/Types'; import { isMac } from 'common/Platform'; import { RenderDebouncer } from 'browser/RenderDebouncer'; @@ -79,6 +79,9 @@ export class AccessibilityManager extends Disposable { this._liveRegion.setAttribute('aria-live', 'assertive'); this._accessibilityTreeRoot.appendChild(this._liveRegion); + if (!this._terminal.element) { + throw new Error('Cannot enable accessibility before Terminal.open'); + } this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityTreeRoot); this.register(this._renderRowsDebouncer); diff --git a/src/browser/RenderDebouncer.ts b/src/browser/RenderDebouncer.ts index 814afcef4..2a06fdd66 100644 --- a/src/browser/RenderDebouncer.ts +++ b/src/browser/RenderDebouncer.ts @@ -26,7 +26,7 @@ export class RenderDebouncer implements IDisposable { } } - public refresh(rowStart: number, rowEnd: number, rowCount: number): void { + public refresh(rowStart: number | undefined, rowEnd: number | undefined, rowCount: number): void { this._rowCount = rowCount; // Get the min/max row start/end for the arg values rowStart = rowStart !== undefined ? rowStart : 0; diff --git a/src/Terminal.ts b/src/browser/Terminal.ts similarity index 99% rename from src/Terminal.ts rename to src/browser/Terminal.ts index b7c8ba93e..2c22a12ca 100644 --- a/src/Terminal.ts +++ b/src/browser/Terminal.ts @@ -21,13 +21,13 @@ * http://linux.die.net/man/7/urxvt */ -import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from './Types'; +import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from '../Types'; import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard'; import { C0 } from 'common/data/EscapeSequences'; -import { WindowsOptionsReportType } from './common/InputHandler'; +import { WindowsOptionsReportType } from '../common/InputHandler'; import { Renderer } from 'browser/renderer/Renderer'; import { Linkifier } from 'browser/Linkifier'; import { SelectionService } from 'browser/services/SelectionService'; diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index f4645543f..847d64e57 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -3,9 +3,106 @@ * @license MIT */ +import { IDisposable, IMarker, ISelectionPosition } from 'xterm'; import { IEvent } from 'common/EventEmitter'; -import { IDisposable } from 'common/Types'; +import { ICoreTerminal, CharData, ITerminalOptions } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; +import { IBuffer, IBufferSet } from 'common/buffer/Types'; + +export interface ITerminal extends IPublicTerminal, ICoreTerminal { + element: HTMLElement | undefined; + screenElement: HTMLElement; + browser: IBrowser; + buffer: IBuffer; + buffers: IBufferSet; + viewport: IViewport; + // TODO: We should remove options once components adopt optionsService + options: ITerminalOptions; + linkifier: ILinkifier; + linkifier2: ILinkifier2; + + onBlur: IEvent; + onFocus: IEvent; + onA11yChar: IEvent; + onA11yTab: IEvent; + + cancel(ev: Event, force?: boolean): boolean | void; +} + +// Portions of the public API that are required by the internal Terminal +export interface IPublicTerminal extends IDisposable { + textarea: HTMLTextAreaElement | undefined; + rows: number; + cols: number; + buffer: IBuffer; + markers: IMarker[]; + onCursorMove: IEvent; + onData: IEvent; + onBinary: IEvent; + onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; + onLineFeed: IEvent; + onScroll: IEvent; + onSelectionChange: IEvent; + onRender: IEvent<{ start: number, end: number }>; + onResize: IEvent<{ cols: number, rows: number }>; + onTitleChange: IEvent; + blur(): void; + focus(): void; + resize(columns: number, rows: number): void; + open(parent: HTMLElement): void; + attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void; + // addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; + // addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable; + // addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable; + // addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; + registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number; + deregisterLinkMatcher(matcherId: number): void; + registerLinkProvider(linkProvider: ILinkProvider): IDisposable; + registerCharacterJoiner(handler: (text: string) => [number, number][]): number; + deregisterCharacterJoiner(joinerId: number): void; + addMarker(cursorYOffset: number): IMarker; + hasSelection(): boolean; + getSelection(): string; + getSelectionPosition(): ISelectionPosition | undefined; + clearSelection(): void; + select(column: number, row: number, length: number): void; + selectAll(): void; + selectLines(start: number, end: number): void; + dispose(): void; + scrollLines(amount: number): void; + scrollPages(pageCount: number): void; + scrollToTop(): void; + scrollToBottom(): void; + scrollToLine(line: number): void; + clear(): void; + write(data: string | Uint8Array, callback?: () => void): void; + paste(data: string): void; + refresh(start: number, end: number): void; + reset(): void; +} + +export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; + +export type LineData = CharData[]; + +export interface ICompositionHelper { + compositionstart(): void; + compositionupdate(ev: CompositionEvent): void; + compositionend(): void; + updateCompositionElements(dontRecurse?: boolean): void; + keydown(ev: KeyboardEvent): boolean; +} + +export interface IBrowser { + isNode: boolean; + userAgent: string; + platform: string; + isFirefox: boolean; + isMac: boolean; + isIpad: boolean; + isIphone: boolean; + isWindows: boolean; +} export interface IColorManager { colors: IColorSet; diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index 61334f08a..d9b951ef4 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -8,7 +8,7 @@ import { ITerminal } from '../Types'; import { IBufferLine, ICellData } from 'common/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { CellData } from 'common/buffer/CellData'; -import { Terminal as TerminalCore } from '../Terminal'; +import { Terminal as TerminalCore } from '../browser/Terminal'; import * as Strings from '../browser/LocalizableStrings'; import { IEvent, EventEmitter } from 'common/EventEmitter'; import { AddonManager } from './AddonManager'; From bdb438972f9b1e79f8d115b22d00b868d23e1cd1 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 10:44:44 -0700 Subject: [PATCH 097/130] Fix errors in Terminal and elsewhere This was mostly ! to compel TS, we should actually fix this down the road but that can come later. --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 19 +- .../src/renderLayer/LinkRenderLayer.ts | 3 +- src/TestUtils.test.ts | 3 +- src/browser/AccessibilityManager.ts | 2 +- src/browser/Linkifier2.ts | 2 +- src/browser/Terminal.ts | 249 +++++++++--------- src/browser/Types.d.ts | 15 +- src/browser/services/RenderService.ts | 2 +- src/public/Terminal.ts | 2 +- test/benchmark/Terminal.benchmark.ts | 2 +- typings/xterm.d.ts | 2 +- 11 files changed, 147 insertions(+), 154 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 0333fd208..ac997c960 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -3,7 +3,6 @@ * @license MIT */ -import { ITerminal } from '../../../src/Types'; import { GlyphRenderer } from './GlyphRenderer'; import { LinkRenderLayer } from './renderLayer/LinkRenderLayer'; import { CursorRenderLayer } from './renderLayer/CursorRenderLayer'; @@ -17,7 +16,7 @@ import { NULL_CELL_CODE } from 'common/buffer/Constants'; import { Terminal, IEvent } from 'xterm'; import { IRenderLayer } from './renderLayer/Types'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types'; -import { IColorSet } from 'browser/Types'; +import { ITerminal, IColorSet } from 'browser/Types'; import { EventEmitter } from 'common/EventEmitter'; import { CellData } from 'common/buffer/CellData'; @@ -52,8 +51,8 @@ export class WebglRenderer extends Disposable implements IRenderer { this._core = (this._terminal as any)._core; this._renderLayers = [ - new LinkRenderLayer(this._core.screenElement, 2, this._colors, this._core), - new CursorRenderLayer(this._core.screenElement, 3, this._colors, this._onRequestRedraw) + new LinkRenderLayer(this._core.screenElement!, 2, this._colors, this._core), + new CursorRenderLayer(this._core.screenElement!, 3, this._colors, this._onRequestRedraw) ]; this.dimensions = { scaledCharWidth: 0, @@ -83,7 +82,7 @@ export class WebglRenderer extends Disposable implements IRenderer { if (!this._gl) { throw new Error('WebGL2 not supported ' + this._gl); } - this._core.screenElement.appendChild(this._canvas); + this._core.screenElement!.appendChild(this._canvas); this._rectangleRenderer = new RectangleRenderer(this._terminal, this._colors, this._gl, this.dimensions); this._glyphRenderer = new GlyphRenderer(this._terminal, this._colors, this._gl, this.dimensions); @@ -91,12 +90,12 @@ export class WebglRenderer extends Disposable implements IRenderer { // Update dimensions and acquire char atlas this.onCharSizeChanged(); - this._isAttached = document.body.contains(this._core.screenElement); + this._isAttached = document.body.contains(this._core.screenElement!); } public dispose(): void { this._renderLayers.forEach(l => l.dispose()); - this._core.screenElement.removeChild(this._canvas); + this._core.screenElement!.removeChild(this._canvas); super.dispose(); } @@ -150,8 +149,8 @@ export class WebglRenderer extends Disposable implements IRenderer { this._canvas.style.height = `${this.dimensions.canvasHeight}px`; // Resize the screen - this._core.screenElement.style.width = `${this.dimensions.canvasWidth}px`; - this._core.screenElement.style.height = `${this.dimensions.canvasHeight}px`; + this._core.screenElement!.style.width = `${this.dimensions.canvasWidth}px`; + this._core.screenElement!.style.height = `${this.dimensions.canvasHeight}px`; this._glyphRenderer.setDimensions(this.dimensions); this._glyphRenderer.onResize(); @@ -229,7 +228,7 @@ export class WebglRenderer extends Disposable implements IRenderer { public renderRows(start: number, end: number): void { if (!this._isAttached) { - if (document.body.contains(this._core.screenElement) && (this._core as any)._charSizeService.width && (this._core as any)._charSizeService.height) { + if (document.body.contains(this._core.screenElement!) && (this._core as any)._charSizeService.width && (this._core as any)._charSizeService.height) { this._updateDimensions(); this._refreshCharAtlas(); this._isAttached = true; diff --git a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts index a095b4aea..8f6b3e6da 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts @@ -7,9 +7,8 @@ import { Terminal } from 'xterm'; import { BaseRenderLayer } from './BaseRenderLayer'; import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { is256Color } from '../atlas/CharAtlasUtils'; -import { IColorSet, ILinkifierEvent, ILinkifier, ILinkifier2 } from 'browser/Types'; +import { ITerminal, IColorSet, ILinkifierEvent } from 'browser/Types'; import { IRenderDimensions } from 'browser/renderer/Types'; -import { ITerminal } from '../../../../src/Types'; export class LinkRenderLayer extends BaseRenderLayer { private _state: ILinkifierEvent | undefined; diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 965acc880..102a53537 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -4,7 +4,6 @@ */ import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; -import { ICompositionHelper, ITerminal, IBrowser } from './Types'; import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; import { Buffer } from 'common/buffer/Buffer'; @@ -12,7 +11,7 @@ import * as Browser from 'common/Platform'; import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm'; import { Terminal } from './browser/Terminal'; import { AttributeData } from 'common/buffer/AttributeData'; -import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2 } from 'browser/Types'; +import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2, ICompositionHelper, ITerminal, IBrowser } from 'browser/Types'; import { IOptionsService, IUnicodeService } from 'common/services/Services'; import { IParams, IFunctionIdentifier } from 'common/parser/Types'; import { ISelectionService } from 'browser/services/Services'; diff --git a/src/browser/AccessibilityManager.ts b/src/browser/AccessibilityManager.ts index b613e9ba6..2a34d6a36 100644 --- a/src/browser/AccessibilityManager.ts +++ b/src/browser/AccessibilityManager.ts @@ -106,7 +106,7 @@ export class AccessibilityManager extends Disposable { public dispose(): void { super.dispose(); - this._terminal.element.removeChild(this._accessibilityTreeRoot); + this._terminal.element?.removeChild(this._accessibilityTreeRoot); this._rowElements.length = 0; } diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index 548121699..458b1bff0 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from './Types'; +import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from 'browser/Types'; import { IDisposable } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; import { IBufferService } from 'common/services/Services'; diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 2c22a12ca..7f3ead61c 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -21,7 +21,7 @@ * http://linux.die.net/man/7/urxvt */ -import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler } from '../Types'; +import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler, ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; @@ -49,41 +49,40 @@ import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISo import { CharSizeService } from 'browser/services/CharSizeService'; import { IBuffer } from 'common/buffer/Types'; import { MouseService } from 'browser/services/MouseService'; -import { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; import { Linkifier2 } from 'browser/Linkifier2'; import { CoreBrowserService } from 'browser/services/CoreBrowserService'; import { CoreTerminal } from 'common/CoreTerminal'; +import { ITerminalOptions as IInitializedTerminalOptions } from 'common/services/Services'; // Let it work inside Node.js for automated testing purposes. -const document = (typeof window !== 'undefined') ? window.document : null; - +const document: Document = (typeof window !== 'undefined') ? window.document : null as any; export class Terminal extends CoreTerminal implements ITerminal { - public textarea: HTMLTextAreaElement; - public element: HTMLElement; - public screenElement: HTMLElement; + public textarea: HTMLTextAreaElement | undefined; + public element: HTMLElement | undefined; + public screenElement: HTMLElement | undefined; - private _document: Document; - private _viewportScrollArea: HTMLElement; - private _viewportElement: HTMLElement; - private _helperContainer: HTMLElement; - private _compositionView: HTMLElement; + private _document: Document | undefined; + private _viewportScrollArea: HTMLElement | undefined; + private _viewportElement: HTMLElement | undefined; + private _helperContainer: HTMLElement | undefined; + private _compositionView: HTMLElement | undefined; - private _visualBellTimer: number; + // private _visualBellTimer: number; public browser: IBrowser = Browser; // TODO: We should remove options once components adopt optionsService - public get options(): ITerminalOptions { return this.optionsService.options; } + public get options(): IInitializedTerminalOptions { return this.optionsService.options; } - private _customKeyEventHandler: CustomKeyEventHandler; + private _customKeyEventHandler: CustomKeyEventHandler | undefined; // browser services - private _charSizeService: ICharSizeService; - private _mouseService: IMouseService; - private _renderService: IRenderService; - private _selectionService: ISelectionService; - private _soundService: ISoundService; + private _charSizeService: ICharSizeService | undefined; + private _mouseService: IMouseService | undefined; + private _renderService: IRenderService | undefined; + private _selectionService: ISelectionService | undefined; + private _soundService: ISoundService | undefined; /** * Records whether the keydown event has already been handled and triggered a data event, if so @@ -94,12 +93,12 @@ export class Terminal extends CoreTerminal implements ITerminal { public linkifier: ILinkifier; public linkifier2: ILinkifier2; - public viewport: IViewport; - private _compositionHelper: ICompositionHelper; - private _mouseZoneManager: IMouseZoneManager; - private _accessibilityManager: AccessibilityManager; - private _colorManager: ColorManager; - private _theme: ITheme; + public viewport: IViewport | undefined; + private _compositionHelper: ICompositionHelper | undefined; + private _mouseZoneManager: IMouseZoneManager | undefined; + private _accessibilityManager: AccessibilityManager | undefined; + private _colorManager: ColorManager | undefined; + private _theme: ITheme | undefined; private _onCursorMove = new EventEmitter(); public get onCursorMove(): IEvent { return this._onCursorMove.event; } @@ -140,6 +139,10 @@ export class Terminal extends CoreTerminal implements ITerminal { this._setup(); + this.linkifier = this._instantiationService.createInstance(Linkifier); + this.linkifier2 = this._instantiationService.createInstance(Linkifier2); + + // Setup InputHandler listeners this.register(this._inputHandler.onRequestBell(() => this.bell())); this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); this.register(this._inputHandler.onRequestReset(() => this.reset())); @@ -160,7 +163,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } super.dispose(); this._renderService?.dispose(); - this._customKeyEventHandler = null; + this._customKeyEventHandler = undefined; this.write = () => { }; this.element?.parentNode?.removeChild(this.element); } @@ -168,14 +171,7 @@ export class Terminal extends CoreTerminal implements ITerminal { protected _setup(): void { super._setup(); - this._customKeyEventHandler = null; - - if (!this.linkifier) { - this.linkifier = this._instantiationService.createInstance(Linkifier); - } - if (!this.linkifier2) { - this.linkifier2 = this._instantiationService.createInstance(Linkifier2); - } + this._customKeyEventHandler = undefined; } /** @@ -239,7 +235,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } } else { this._accessibilityManager?.dispose(); - this._accessibilityManager = null; + this._accessibilityManager = undefined; } break; case 'tabStopWidth': this.buffers.setupTabStops(); break; @@ -257,7 +253,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this._coreService.triggerDataEvent(C0.ESC + '[I'); } this.updateCursorStyle(ev); - this.element.classList.add('focus'); + this.element!.classList.add('focus'); this._showCursor(); this._onFocus.fire(); } @@ -267,7 +263,7 @@ export class Terminal extends CoreTerminal implements ITerminal { * textarea. */ public blur(): void { - return this.textarea.blur(); + return this.textarea?.blur(); } /** @@ -276,12 +272,12 @@ export class Terminal extends CoreTerminal implements ITerminal { private _onTextAreaBlur(): void { // Text can safely be removed on blur. Doing it earlier could interfere with // screen readers reading it out. - this.textarea.value = ''; + this.textarea!.value = ''; this.refresh(this.buffer.y, this.buffer.y); if (this._coreService.decPrivateModes.sendFocus) { this._coreService.triggerDataEvent(C0.ESC + '[O'); } - this.element.classList.remove('focus'); + this.element!.classList.remove('focus'); this._onBlur.fire(); } @@ -292,29 +288,29 @@ export class Terminal extends CoreTerminal implements ITerminal { this._bindKeys(); // Bind clipboard functionality - this.register(addDisposableDomListener(this.element, 'copy', (event: ClipboardEvent) => { + this.register(addDisposableDomListener(this.element!, 'copy', (event: ClipboardEvent) => { // If mouse events are active it means the selection manager is disabled and // copy should be handled by the host program. if (!this.hasSelection()) { return; } - copyHandler(event, this._selectionService); + copyHandler(event, this._selectionService!); })); - const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea, this._coreService); - this.register(addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper)); - this.register(addDisposableDomListener(this.element, 'paste', pasteHandlerWrapper)); + const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this._coreService); + this.register(addDisposableDomListener(this.textarea!, 'paste', pasteHandlerWrapper)); + this.register(addDisposableDomListener(this.element!, 'paste', pasteHandlerWrapper)); // Handle right click context menus if (Browser.isFirefox) { // Firefox doesn't appear to fire the contextmenu event on right click - this.register(addDisposableDomListener(this.element, 'mousedown', (event: MouseEvent) => { + this.register(addDisposableDomListener(this.element!, 'mousedown', (event: MouseEvent) => { if (event.button === 2) { - rightClickHandler(event, this.textarea, this.screenElement, this._selectionService, this.options.rightClickSelectsWord); + rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord); } })); } else { - this.register(addDisposableDomListener(this.element, 'contextmenu', (event: MouseEvent) => { - rightClickHandler(event, this.textarea, this.screenElement, this._selectionService, this.options.rightClickSelectsWord); + this.register(addDisposableDomListener(this.element!, 'contextmenu', (event: MouseEvent) => { + rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord); })); } @@ -324,9 +320,9 @@ export class Terminal extends CoreTerminal implements ITerminal { if (Browser.isLinux) { // Use auxclick event over mousedown the latter doesn't seem to work. Note // that the regular click event doesn't fire for the middle mouse button. - this.register(addDisposableDomListener(this.element, 'auxclick', (event: MouseEvent) => { + this.register(addDisposableDomListener(this.element!, 'auxclick', (event: MouseEvent) => { if (event.button === 1) { - moveTextAreaUnderMouseCursor(event, this.textarea, this.screenElement); + moveTextAreaUnderMouseCursor(event, this.textarea!, this.screenElement!); } })); } @@ -336,13 +332,13 @@ export class Terminal extends CoreTerminal implements ITerminal { * Apply key handling to the terminal */ private _bindKeys(): void { - this.register(addDisposableDomListener(this.textarea, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true)); - this.register(addDisposableDomListener(this.textarea, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true)); - this.register(addDisposableDomListener(this.textarea, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true)); - this.register(addDisposableDomListener(this.textarea, 'compositionstart', () => this._compositionHelper.compositionstart())); - this.register(addDisposableDomListener(this.textarea, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper.compositionupdate(e))); - this.register(addDisposableDomListener(this.textarea, 'compositionend', () => this._compositionHelper.compositionend())); - this.register(this.onRender(() => this._compositionHelper.updateCompositionElements())); + this.register(addDisposableDomListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true)); + this.register(addDisposableDomListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true)); + this.register(addDisposableDomListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true)); + this.register(addDisposableDomListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart())); + this.register(addDisposableDomListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e))); + this.register(addDisposableDomListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend())); + this.register(this.onRender(() => this._compositionHelper!.updateCompositionElements())); this.register(this.onRender(e => this._queueLinkification(e.start, e.end))); } @@ -360,7 +356,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this._logService.debug('Terminal.open was called on an element that was not attached to the DOM'); } - this._document = parent.ownerDocument; + this._document = parent.ownerDocument!; // Create main element container this.element = this._document.createElement('div'); @@ -416,16 +412,15 @@ export class Terminal extends CoreTerminal implements ITerminal { this.element.appendChild(fragment); this._theme = this.options.theme || this._theme; - this.options.theme = undefined; this._colorManager = new ColorManager(document, this.options.allowTransparency); - this.optionsService.onOptionChange(e => this._colorManager.onOptionsChange(e)); + this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e)); this._colorManager.setTheme(this._theme); const renderer = this._createRenderer(); this._renderService = this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement); this._instantiationService.setService(IRenderService, this._renderService); this._renderService.onRenderedBufferChange(e => this._onRender.fire(e)); - this.onResize(e => this._renderService.resize(e.cols, e.rows)); + this.onResize(e => this._renderService!.resize(e.cols, e.rows)); this._soundService = this._instantiationService.createInstance(SoundService); this._instantiationService.setService(ISoundService, this._soundService); @@ -438,14 +433,14 @@ export class Terminal extends CoreTerminal implements ITerminal { this._viewportScrollArea ); this.viewport.onThemeChange(this._colorManager.colors); - this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport.syncScrollArea())); + this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea())); this.register(this.viewport); - this.register(this.onCursorMove(() => this._renderService.onCursorMove())); - this.register(this.onResize(() => this._renderService.onResize(this.cols, this.rows))); - this.register(this.onBlur(() => this._renderService.onBlur())); - this.register(this.onFocus(() => this._renderService.onFocus())); - this.register(this._renderService.onDimensionsChange(() => this.viewport.syncScrollArea())); + this.register(this.onCursorMove(() => this._renderService!.onCursorMove())); + this.register(this.onResize(() => this._renderService!.onResize(this.cols, this.rows))); + this.register(this.onBlur(() => this._renderService!.onBlur())); + this.register(this.onFocus(() => this._renderService!.onFocus())); + this.register(this._renderService.onDimensionsChange(() => this.viewport!.syncScrollArea())); this._selectionService = this._instantiationService.createInstance(SelectionService, (amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent), @@ -453,29 +448,29 @@ export class Terminal extends CoreTerminal implements ITerminal { this.screenElement); this._instantiationService.setService(ISelectionService, this._selectionService); this.register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire())); - this.register(this._selectionService.onRedrawRequest(e => this._renderService.onSelectionChanged(e.start, e.end, e.columnSelectMode))); + this.register(this._selectionService.onRedrawRequest(e => this._renderService!.onSelectionChanged(e.start, e.end, e.columnSelectMode))); this.register(this._selectionService.onLinuxMouseSelection(text => { // If there's a new selection, put it into the textarea, focus and select it // in order to register it as a selection on the OS. This event is fired // only on Linux to enable middle click to paste selection. - this.textarea.value = text; - this.textarea.focus(); - this.textarea.select(); + this.textarea!.value = text; + this.textarea!.focus(); + this.textarea!.select(); })); this.register(this.onScroll(() => { - this.viewport.syncScrollArea(); - this._selectionService.refresh(); + this.viewport!.syncScrollArea(); + this._selectionService!.refresh(); })); - this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService.refresh())); + this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh())); this._mouseZoneManager = this._instantiationService.createInstance(MouseZoneManager, this.element, this.screenElement); this.register(this._mouseZoneManager); - this.register(this.onScroll(() => this._mouseZoneManager.clearAll())); + this.register(this.onScroll(() => this._mouseZoneManager!.clearAll())); this.linkifier.attachToDom(this.element, this._mouseZoneManager); this.linkifier2.attachToDom(this.element, this._mouseService, this._renderService); // This event listener must be registered aftre MouseZoneManager is created - this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService.onMouseDown(e))); + this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.onMouseDown(e))); // apply mouse event classes set by escape codes before terminal was attached if (this._coreMouseService.areMouseEventsActive) { @@ -507,8 +502,8 @@ export class Terminal extends CoreTerminal implements ITerminal { private _createRenderer(): IRenderer { switch (this.options.rendererType) { - case 'canvas': return this._instantiationService.createInstance(Renderer, this._colorManager.colors, this.screenElement, this.linkifier, this.linkifier2); - case 'dom': return this._instantiationService.createInstance(DomRenderer, this._colorManager.colors, this.element, this.screenElement, this._viewportElement, this.linkifier, this.linkifier2); + case 'canvas': return this._instantiationService.createInstance(Renderer, this._colorManager!.colors, this.screenElement!, this.linkifier, this.linkifier2); + case 'dom': return this._instantiationService.createInstance(DomRenderer, this._colorManager!.colors, this.element!, this.screenElement!, this._viewportElement!, this.linkifier, this.linkifier2); default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`); } } @@ -520,8 +515,8 @@ export class Terminal extends CoreTerminal implements ITerminal { private _setTheme(theme: ITheme): void { this._theme = theme; this._colorManager?.setTheme(theme); - this._renderService?.setColors(this._colorManager.colors); - this.viewport?.onThemeChange(this._colorManager.colors); + this._renderService?.setColors(this._colorManager!.colors); + this.viewport?.onThemeChange(this._colorManager!.colors); } /** @@ -541,18 +536,18 @@ export class Terminal extends CoreTerminal implements ITerminal { */ public bindMouse(): void { const self = this; - const el = this.element; + const el = this.element!; // send event to CoreMouseService function sendEvent(ev: MouseEvent | WheelEvent): boolean { // get mouse coordinates - const pos = self._mouseService.getRawByteCoords(ev, self.screenElement, self.cols, self.rows); + const pos = self._mouseService!.getRawByteCoords(ev, self.screenElement!, self.cols, self.rows); if (!pos) { return false; } let but: CoreMouseButton; - let action: CoreMouseAction; + let action: CoreMouseAction | undefined; switch ((ev).overrideType || ev.type) { case 'mousemove': action = CoreMouseAction.MOVE; @@ -621,14 +616,14 @@ export class Terminal extends CoreTerminal implements ITerminal { mousedrag: null, mousemove: null }; - const eventListeners: { [key: string]: (ev: Event) => void } = { + const eventListeners: { [key: string]: (ev: any) => void | boolean } = { mouseup: (ev: MouseEvent) => { sendEvent(ev); if (!ev.buttons) { // if no other button is held remove global handlers - this._document.removeEventListener('mouseup', requestedEvents.mouseup); + this._document!.removeEventListener('mouseup', requestedEvents.mouseup!); if (requestedEvents.mousedrag) { - this._document.removeEventListener('mousemove', requestedEvents.mousedrag); + this._document!.removeEventListener('mousemove', requestedEvents.mousedrag); } } return this.cancel(ev); @@ -657,18 +652,18 @@ export class Terminal extends CoreTerminal implements ITerminal { if (this.optionsService.options.logLevel === 'debug') { this._logService.debug('Binding to mouse events:', this._coreMouseService.explainEvents(events)); } - this.element.classList.add('enable-mouse-events'); - this._selectionService.disable(); + this.element!.classList.add('enable-mouse-events'); + this._selectionService!.disable(); } else { this._logService.debug('Unbinding from mouse events.'); - this.element.classList.remove('enable-mouse-events'); - this._selectionService.enable(); + this.element!.classList.remove('enable-mouse-events'); + this._selectionService!.enable(); } // add/remove handlers from requestedEvents if (!(events & CoreMouseEventType.MOVE)) { - el.removeEventListener('mousemove', requestedEvents.mousemove); + el.removeEventListener('mousemove', requestedEvents.mousemove!); requestedEvents.mousemove = null; } else if (!requestedEvents.mousemove) { el.addEventListener('mousemove', eventListeners.mousemove); @@ -676,7 +671,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } if (!(events & CoreMouseEventType.WHEEL)) { - el.removeEventListener('wheel', requestedEvents.wheel); + el.removeEventListener('wheel', requestedEvents.wheel!); requestedEvents.wheel = null; } else if (!requestedEvents.wheel) { el.addEventListener('wheel', eventListeners.wheel); @@ -684,14 +679,14 @@ export class Terminal extends CoreTerminal implements ITerminal { } if (!(events & CoreMouseEventType.UP)) { - this._document.removeEventListener('mouseup', requestedEvents.mouseup); + this._document!.removeEventListener('mouseup', requestedEvents.mouseup!); requestedEvents.mouseup = null; } else if (!requestedEvents.mouseup) { requestedEvents.mouseup = eventListeners.mouseup; } if (!(events & CoreMouseEventType.DRAG)) { - this._document.removeEventListener('mousemove', requestedEvents.mousedrag); + this._document!.removeEventListener('mousemove', requestedEvents.mousedrag!); requestedEvents.mousedrag = null; } else if (!requestedEvents.mousedrag) { requestedEvents.mousedrag = eventListeners.mousedrag; @@ -710,7 +705,7 @@ export class Terminal extends CoreTerminal implements ITerminal { // Don't send the mouse button to the pty if mouse events are disabled or // if the selection manager is having selection forced (ie. a modifier is // held). - if (!this._coreMouseService.areMouseEventsActive || this._selectionService.shouldForceSelection(ev)) { + if (!this._coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) { return; } @@ -721,10 +716,10 @@ export class Terminal extends CoreTerminal implements ITerminal { // Note: Other emulators also do this for 'mousedown' while a button // is held, we currently limit 'mousedown' to the terminal only. if (requestedEvents.mouseup) { - this._document.addEventListener('mouseup', requestedEvents.mouseup); + this._document!.addEventListener('mouseup', requestedEvents.mouseup); } if (requestedEvents.mousedrag) { - this._document.addEventListener('mousemove', requestedEvents.mousedrag); + this._document!.addEventListener('mousemove', requestedEvents.mousedrag); } return this.cancel(ev); @@ -735,7 +730,7 @@ export class Terminal extends CoreTerminal implements ITerminal { // Convert wheel events into up/down events when the buffer does not have scrollback, this // enables scrolling in apps hosted in the alt buffer such as vim or tmux. if (!this.buffer.hasScrollback) { - const amount = this.viewport.getLinesScrolled(ev); + const amount = this.viewport!.getLinesScrolled(ev); // Do nothing if there's no vertical scroll if (amount === 0) { @@ -758,20 +753,20 @@ export class Terminal extends CoreTerminal implements ITerminal { // the shell for example this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => { if (requestedEvents.wheel) return; - if (!this.viewport.onWheel(ev)) { + if (!this.viewport!.onWheel(ev)) { return this.cancel(ev); } })); this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => { if (this._coreMouseService.areMouseEventsActive) return; - this.viewport.onTouchStart(ev); + this.viewport!.onTouchStart(ev); return this.cancel(ev); })); this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => { if (this._coreMouseService.areMouseEventsActive) return; - if (!this.viewport.onTouchMove(ev)) { + if (!this.viewport!.onTouchMove(ev)) { return this.cancel(ev); } })); @@ -802,9 +797,9 @@ export class Terminal extends CoreTerminal implements ITerminal { */ public updateCursorStyle(ev: KeyboardEvent): void { if (this._selectionService && this._selectionService.shouldColumnSelect(ev)) { - this.element.classList.add('column-select'); + this.element!.classList.add('column-select'); } else { - this.element.classList.remove('column-select'); + this.element!.classList.remove('column-select'); } } @@ -824,7 +819,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } public paste(data: string): void { - paste(data, this.textarea, this._coreService); + paste(data, this.textarea!, this._coreService); } /** @@ -871,13 +866,13 @@ export class Terminal extends CoreTerminal implements ITerminal { } public registerCharacterJoiner(handler: CharacterJoinerHandler): number { - const joinerId = this._renderService.registerCharacterJoiner(handler); + const joinerId = this._renderService!.registerCharacterJoiner(handler); this.refresh(0, this.rows - 1); return joinerId; } public deregisterCharacterJoiner(joinerId: number): void { - if (this._renderService.deregisterCharacterJoiner(joinerId)) { + if (this._renderService!.deregisterCharacterJoiner(joinerId)) { this.refresh(0, this.rows - 1); } } @@ -886,7 +881,7 @@ export class Terminal extends CoreTerminal implements ITerminal { return this.buffer.markers; } - public addMarker(cursorYOffset: number): IMarker { + public addMarker(cursorYOffset: number): IMarker | undefined { // Disallow markers on the alt buffer if (this.buffer !== this.buffers.normal) { return; @@ -909,7 +904,7 @@ export class Terminal extends CoreTerminal implements ITerminal { * @param length The length of the selection. */ public select(column: number, row: number, length: number): void { - this._selectionService.setSelection(column, row, length); + this._selectionService!.setSelection(column, row, length); } /** @@ -921,15 +916,15 @@ export class Terminal extends CoreTerminal implements ITerminal { } public getSelectionPosition(): ISelectionPosition | undefined { - if (!this._selectionService.hasSelection) { + if (!this._selectionService || !this._selectionService.hasSelection) { return undefined; } return { - startColumn: this._selectionService.selectionStart[0], - startRow: this._selectionService.selectionStart[1], - endColumn: this._selectionService.selectionEnd[0], - endRow: this._selectionService.selectionEnd[1] + startColumn: this._selectionService.selectionStart![0], + startRow: this._selectionService.selectionStart![1], + endColumn: this._selectionService.selectionEnd![0], + endRow: this._selectionService.selectionEnd![1] }; } @@ -957,14 +952,14 @@ export class Terminal extends CoreTerminal implements ITerminal { * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent * @param ev The keydown event to be handled. */ - protected _keyDown(event: KeyboardEvent): boolean { + protected _keyDown(event: KeyboardEvent): boolean | undefined { this._keyDownHandled = false; if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) { return false; } - if (!this._compositionHelper.keydown(event)) { + if (!this._compositionHelper!.keydown(event)) { if (this.buffer.ybase !== this.buffer.ydisp) { this.scrollToBottom(); } @@ -1002,7 +997,7 @@ export class Terminal extends CoreTerminal implements ITerminal { // will announce deleted characters. This will not work 100% of the time but it should cover // most scenarios. if (result.key === C0.ETX || result.key === C0.CR) { - this.textarea.value = ''; + this.textarea!.value = ''; } this._onKey.fire({ key: result.key, domEvent: event }); @@ -1095,16 +1090,16 @@ export class Terminal extends CoreTerminal implements ITerminal { */ public bell(): void { if (this._soundBell()) { - this._soundService.playBellSound(); + this._soundService!.playBellSound(); } - if (this._visualBell()) { - this.element.classList.add('visual-bell-active'); - clearTimeout(this._visualBellTimer); - this._visualBellTimer = window.setTimeout(() => { - this.element.classList.remove('visual-bell-active'); - }, 200); - } + // if (this._visualBell()) { + // this.element.classList.add('visual-bell-active'); + // clearTimeout(this._visualBellTimer); + // this._visualBellTimer = window.setTimeout(() => { + // this.element.classList.remove('visual-bell-active'); + // }, 200); + // } } /** @@ -1141,7 +1136,7 @@ export class Terminal extends CoreTerminal implements ITerminal { // Don't clear if it's already clear return; } - this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)); + this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!); this.buffer.lines.length = 1; this.buffer.ydisp = 0; this.buffer.ybase = 0; @@ -1202,7 +1197,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } // TODO: Remove cancel function and cancelEvents option - public cancel(ev: Event, force?: boolean): boolean { + public cancel(ev: Event, force?: boolean): boolean | undefined { if (!this.options.cancelEvents && !force) { return; } diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 847d64e57..76aa0c8cf 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -8,14 +8,15 @@ import { IEvent } from 'common/EventEmitter'; import { ICoreTerminal, CharData, ITerminalOptions } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; +import { IFunctionIdentifier, IParams } from 'common/parser/Types'; export interface ITerminal extends IPublicTerminal, ICoreTerminal { element: HTMLElement | undefined; - screenElement: HTMLElement; + screenElement: HTMLElement | undefined; browser: IBrowser; buffer: IBuffer; buffers: IBufferSet; - viewport: IViewport; + viewport: IViewport | undefined; // TODO: We should remove options once components adopt optionsService options: ITerminalOptions; linkifier: ILinkifier; @@ -51,16 +52,16 @@ export interface IPublicTerminal extends IDisposable { resize(columns: number, rows: number): void; open(parent: HTMLElement): void; attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void; - // addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; - // addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable; - // addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable; - // addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; + addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; + addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable; + addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable; + addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number; deregisterLinkMatcher(matcherId: number): void; registerLinkProvider(linkProvider: ILinkProvider): IDisposable; registerCharacterJoiner(handler: (text: string) => [number, number][]): number; deregisterCharacterJoiner(joinerId: number): void; - addMarker(cursorYOffset: number): IMarker; + addMarker(cursorYOffset: number): IMarker | undefined; hasSelection(): boolean; getSelection(): string; getSelectionPosition(): ISelectionPosition | undefined; diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index a0ca25d2e..d6b305244 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -10,7 +10,7 @@ import { Disposable } from 'common/Lifecycle'; import { ScreenDprMonitor } from 'browser/ScreenDprMonitor'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { IColorSet } from 'browser/Types'; -import { IOptionsService, IBufferService, ICoreService } from 'common/services/Services'; +import { IOptionsService, IBufferService } from 'common/services/Services'; import { ICharSizeService, IRenderService } from 'browser/services/Services'; interface ISelectionState { diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index d9b951ef4..3d4838149 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -4,7 +4,7 @@ */ import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; -import { ITerminal } from '../Types'; +import { ITerminal } from 'browser/Types'; import { IBufferLine, ICellData } from 'common/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { CellData } from 'common/buffer/CellData'; diff --git a/test/benchmark/Terminal.benchmark.ts b/test/benchmark/Terminal.benchmark.ts index 71a36cc70..76139cb64 100644 --- a/test/benchmark/Terminal.benchmark.ts +++ b/test/benchmark/Terminal.benchmark.ts @@ -7,7 +7,7 @@ import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark'; import { spawn } from 'node-pty'; import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder'; -import { Terminal } from 'Terminal'; +import { Terminal } from 'browser/Terminal'; perfContext('Terminal: ls -lR /usr/lib', () => { let content = ''; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 3487c4104..35f43b1b0 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -805,7 +805,7 @@ declare module 'xterm' { /** * @deprecated use `registerMarker` instead. */ - addMarker(cursorYOffset: number): IMarker; + addMarker(cursorYOffset: number): IMarker | undefined; /** * Gets whether the terminal has an active selection. From 03bfd2c842d9947544e19a35e3622ff6771033fc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 10:59:32 -0700 Subject: [PATCH 098/130] Move Terminal*.test into browser --- bin/test.js | 1 - src/TestUtils.test.ts | 326 ---------------------------- src/{ => browser}/Terminal.test.ts | 288 ++++++++++++------------ src/{ => browser}/Terminal2.test.ts | 6 +- src/browser/TestUtils.test.ts | 324 ++++++++++++++++++++++++++- 5 files changed, 468 insertions(+), 477 deletions(-) delete mode 100644 src/TestUtils.test.ts rename src/{ => browser}/Terminal.test.ts (80%) rename src/{ => browser}/Terminal2.test.ts (96%) diff --git a/bin/test.js b/bin/test.js index 1380a5122..b9725acda 100644 --- a/bin/test.js +++ b/bin/test.js @@ -13,7 +13,6 @@ const env = { ...process.env }; env.NODE_PATH = path.resolve(__dirname, '../out'); let testFiles = [ - './out/*test.js', './out/**/*test.js', './addons/**/out/*test.js', ]; diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts deleted file mode 100644 index 102a53537..000000000 --- a/src/TestUtils.test.ts +++ /dev/null @@ -1,326 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; -import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; -import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; -import { Buffer } from 'common/buffer/Buffer'; -import * as Browser from 'common/Platform'; -import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm'; -import { Terminal } from './browser/Terminal'; -import { AttributeData } from 'common/buffer/AttributeData'; -import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2, ICompositionHelper, ITerminal, IBrowser } from 'browser/Types'; -import { IOptionsService, IUnicodeService } from 'common/services/Services'; -import { IParams, IFunctionIdentifier } from 'common/parser/Types'; -import { ISelectionService } from 'browser/services/Services'; - -export class TestTerminal extends Terminal { - public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } - public keyDown(ev: any): boolean { return this._keyDown(ev); } - public keyPress(ev: any): boolean { return this._keyPress(ev); } -} - -export class MockTerminal implements ITerminal { - public onBlur: IEvent; - public onFocus: IEvent; - public onA11yChar: IEvent; - public onA11yTab: IEvent; - public onCursorMove: IEvent; - public onLineFeed: IEvent; - public onSelectionChange: IEvent; - public onData: IEvent; - public onBinary: IEvent; - public onTitleChange: IEvent; - public onScroll: IEvent; - public onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; - public onRender: IEvent<{ start: number, end: number }>; - public onResize: IEvent<{ cols: number, rows: number }>; - public markers: IMarker[]; - public optionsService: IOptionsService; - public unicodeService: IUnicodeService; - public addMarker(cursorYOffset: number): IMarker { - throw new Error('Method not implemented.'); - } - public selectLines(start: number, end: number): void { - throw new Error('Method not implemented.'); - } - public scrollToLine(line: number): void { - throw new Error('Method not implemented.'); - } - public static string: any; - public setOption(key: any, value: any): void { - throw new Error('Method not implemented.'); - } - public blur(): void { - throw new Error('Method not implemented.'); - } - public focus(): void { - throw new Error('Method not implemented.'); - } - public resize(columns: number, rows: number): void { - throw new Error('Method not implemented.'); - } - public writeln(data: string): void { - throw new Error('Method not implemented.'); - } - public paste(data: string): void { - throw new Error('Method not implemented.'); - } - public open(parent: HTMLElement): void { - throw new Error('Method not implemented.'); - } - public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { - throw new Error('Method not implemented.'); - } - public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { - throw new Error('Method not implemented.'); - } - public deregisterLinkMatcher(matcherId: number): void { - throw new Error('Method not implemented.'); - } - public registerLinkProvider(linkProvider: ILinkProvider): IDisposable { - throw new Error('Method not implemented.'); - } - public hasSelection(): boolean { - throw new Error('Method not implemented.'); - } - public getSelection(): string { - throw new Error('Method not implemented.'); - } - public getSelectionPosition(): ISelectionPosition | undefined { - throw new Error('Method not implemented.'); - } - public clearSelection(): void { - throw new Error('Method not implemented.'); - } - public select(column: number, row: number, length: number): void { - throw new Error('Method not implemented.'); - } - public selectAll(): void { - throw new Error('Method not implemented.'); - } - public dispose(): void { - throw new Error('Method not implemented.'); - } - public scrollPages(pageCount: number): void { - throw new Error('Method not implemented.'); - } - public scrollToTop(): void { - throw new Error('Method not implemented.'); - } - public scrollToBottom(): void { - throw new Error('Method not implemented.'); - } - public clear(): void { - throw new Error('Method not implemented.'); - } - public write(data: string): void { - throw new Error('Method not implemented.'); - } - public writeUtf8(data: Uint8Array): void { - throw new Error('Method not implemented.'); - } - public bracketedPasteMode: boolean; - public renderer: IRenderer; - public linkifier: ILinkifier; - public linkifier2: ILinkifier2; - public isFocused: boolean; - public options: ITerminalOptions = {}; - public element: HTMLElement; - public screenElement: HTMLElement; - public rowContainer: HTMLElement; - public selectionContainer: HTMLElement; - public selectionService: ISelectionService; - public textarea: HTMLTextAreaElement; - public rows: number; - public cols: number; - public browser: IBrowser = Browser; - public writeBuffer: string[]; - public children: HTMLElement[]; - public cursorHidden: boolean; - public cursorState: number; - public scrollback: number; - public buffers: IBufferSet; - public buffer: IBuffer; - public viewport: IViewport; - public applicationCursor: boolean; - public handler(data: string): void { - throw new Error('Method not implemented.'); - } - public on(event: string, callback: (...args: any[]) => void): void { - throw new Error('Method not implemented.'); - } - public off(type: string, listener: XtermListener): void { - throw new Error('Method not implemented.'); - } - public addDisposableListener(type: string, handler: XtermListener): IDisposable { - throw new Error('Method not implemented.'); - } - public scrollLines(disp: number): void { - throw new Error('Method not implemented.'); - } - public scrollToRow(absoluteRow: number): number { - throw new Error('Method not implemented.'); - } - public cancel(ev: Event, force?: boolean): void { - throw new Error('Method not implemented.'); - } - public log(text: string): void { - throw new Error('Method not implemented.'); - } - public emit(event: string, data: any): void { - throw new Error('Method not implemented.'); - } - public reset(): void { - throw new Error('Method not implemented.'); - } - public refresh(start: number, end: number): void { - throw new Error('Method not implemented.'); - } - public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } - public deregisterCharacterJoiner(joinerId: number): void { } -} - -export class MockBuffer implements IBuffer { - public markers: IMarker[]; - public addMarker(y: number): IMarker { - throw new Error('Method not implemented.'); - } - public isCursorInViewport: boolean; - public lines: ICircularList; - public ydisp: number; - public ybase: number; - public hasScrollback: boolean; - public y: number; - public x: number; - public tabs: any; - public scrollBottom: number; - public scrollTop: number; - public savedY: number; - public savedX: number; - public savedCharset: ICharset | null; - public savedCurAttrData = new AttributeData(); - public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { - return Buffer.prototype.translateBufferLineToString.apply(this, arguments); - } - public getWrappedRangeForLine(y: number): { first: number, last: number } { - return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments); - } - public nextStop(x?: number): number { - throw new Error('Method not implemented.'); - } - public prevStop(x?: number): number { - throw new Error('Method not implemented.'); - } - public setLines(lines: ICircularList): void { - this.lines = lines; - } - public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine { - return Buffer.prototype.getBlankLine.apply(this, arguments); - } - public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] { - return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments); - } - public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator { - return Buffer.prototype.iterator.apply(this, arguments); - } - public getNullCell(attr?: IAttributeData): ICellData { - throw new Error('Method not implemented.'); - } - public getWhitespaceCell(attr?: IAttributeData): ICellData { - throw new Error('Method not implemented.'); - } -} - -export class MockRenderer implements IRenderer { - public onRequestRedraw: IEvent; - public onCanvasResize: IEvent<{ width: number, height: number }>; - public onRender: IEvent<{ start: number, end: number }>; - public dispose(): void { - throw new Error('Method not implemented.'); - } - public colorManager: IColorManager; - public on(type: string, listener: XtermListener): void { - throw new Error('Method not implemented.'); - } - public off(type: string, listener: XtermListener): void { - throw new Error('Method not implemented.'); - } - public emit(type: string, data?: any): void { - throw new Error('Method not implemented.'); - } - public addDisposableListener(type: string, handler: XtermListener): IDisposable { - throw new Error('Method not implemented.'); - } - public dimensions: IRenderDimensions; - public setColors(colors: IColorSet): void { - throw new Error('Method not implemented.'); - } - public onResize(cols: number, rows: number): void { } - public onCharSizeChanged(): void { } - public onBlur(): void { } - public onFocus(): void { } - public onSelectionChanged(start: [number, number], end: [number, number]): void { } - public onCursorMove(): void { } - public onOptionsChanged(): void { } - public onDevicePixelRatioChange(): void { } - public clear(): void { } - public renderRows(start: number, end: number): void { } - public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } - public deregisterCharacterJoiner(): boolean { return true; } -} - -export class MockViewport implements IViewport { - public dispose(): void { - throw new Error('Method not implemented.'); - } - public scrollBarWidth: number = 0; - public onThemeChange(colors: IColorSet): void { - throw new Error('Method not implemented.'); - } - public onWheel(ev: WheelEvent): boolean { - throw new Error('Method not implemented.'); - } - public onTouchStart(ev: TouchEvent): void { - throw new Error('Method not implemented.'); - } - public onTouchMove(ev: TouchEvent): boolean { - throw new Error('Method not implemented.'); - } - public syncScrollArea(): void { } - public getLinesScrolled(ev: WheelEvent): number { - throw new Error('Method not implemented.'); - } -} - -export class MockCompositionHelper implements ICompositionHelper { - public compositionstart(): void { - throw new Error('Method not implemented.'); - } - public compositionupdate(ev: CompositionEvent): void { - throw new Error('Method not implemented.'); - } - public compositionend(): void { - throw new Error('Method not implemented.'); - } - public updateCompositionElements(dontRecurse?: boolean): void { - throw new Error('Method not implemented.'); - } - public keydown(ev: KeyboardEvent): boolean { - return true; - } -} diff --git a/src/Terminal.test.ts b/src/browser/Terminal.test.ts similarity index 80% rename from src/Terminal.test.ts rename to src/browser/Terminal.test.ts index 6488aa43f..729c0d0f2 100644 --- a/src/Terminal.test.ts +++ b/src/browser/Terminal.test.ts @@ -4,7 +4,7 @@ */ import { assert, expect } from 'chai'; -import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from './TestUtils.test'; +import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from 'browser/TestUtils.test'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { IBufferService, IUnicodeService } from 'common/services/Services'; @@ -395,62 +395,62 @@ describe('Terminal', () => { describe('scroll() function', () => { describe('when scrollback > 0', () => { it('should create a new line and scroll', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS + 1); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(INIT_ROWS).loadCell(0, new CellData()).getChars(), ''); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(INIT_ROWS - 1)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(INIT_ROWS)!.loadCell(0, new CellData()).getChars(), ''); }); it('should properly scroll inside a scroll region (scrollTop set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c'); }); it('should properly scroll inside a scroll region (scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = 3; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS + 1); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'c'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(5).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(5)!.loadCell(0, new CellData()).getChars(), 'e'); }); it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e'); }); }); @@ -461,65 +461,65 @@ describe('Terminal', () => { }); it('should create a new line and shift everything up', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line assert.equal(term.buffer.lines.length, INIT_ROWS); term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); // 'a' gets pushed out of buffer - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), ''); - assert.equal(term.buffer.lines.get(INIT_ROWS - 2).loadCell(0, new CellData()).getChars(), 'c'); - assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), ''); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), ''); + assert.equal(term.buffer.lines.get(INIT_ROWS - 2)!.loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(INIT_ROWS - 1)!.loadCell(0, new CellData()).getChars(), ''); }); it('should properly scroll inside a scroll region (scrollTop set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c'); }); it('should properly scroll inside a scroll region (scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = 3; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e'); }); it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e'); }); }); }); @@ -722,11 +722,11 @@ describe('Terminal', () => { const cell = new CellData(); for (let i = 0xDC00; i <= 0xDCFF; ++i) { term.writeSync(high + String.fromCharCode(i)); - const tchar = term.buffer.lines.get(0).loadCell(0, cell); + const tchar = term.buffer.lines.get(0)!.loadCell(0, cell); expect(tchar.getChars()).eql(high + String.fromCharCode(i)); expect(tchar.getChars().length).eql(2); expect(tchar.getWidth()).eql(1); - expect(term.buffer.lines.get(0).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -736,9 +736,9 @@ describe('Terminal', () => { for (let i = 0xDC00; i <= 0xDCFF; ++i) { term.buffer.x = term.cols - 1; term.writeSync(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.buffer.x - 1, cell).getChars()).eql(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.buffer.x - 1, cell).getChars().length).eql(2); - expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(term.buffer.x - 1, cell).getChars()).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)!.loadCell(term.buffer.x - 1, cell).getChars().length).eql(2); + expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars()).eql(''); term.reset(); } }); @@ -749,10 +749,10 @@ describe('Terminal', () => { term.buffer.x = term.cols - 1; term.writeSync('a' + high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql('a'); - expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(1).loadCell(0, cell).getChars().length).eql(2); - expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars()).eql('a'); + expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars().length).eql(2); + expect(term.buffer.lines.get(1)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -768,9 +768,9 @@ describe('Terminal', () => { } term.writeSync('a' + high + String.fromCharCode(i)); // auto wraparound mode should cut off the rest of the line - expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars().length).eql(2); - expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars().length).eql(2); + expect(term.buffer.lines.get(1)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -780,11 +780,11 @@ describe('Terminal', () => { for (let i = 0xDC00; i <= 0xDCFF; ++i) { term.writeSync(high); term.writeSync(String.fromCharCode(i)); - const tchar = term.buffer.lines.get(0).loadCell(0, cell); + const tchar = term.buffer.lines.get(0)!.loadCell(0, cell); expect(tchar.getChars()).eql(high + String.fromCharCode(i)); expect(tchar.getChars().length).eql(2); expect(tchar.getWidth()).eql(1); - expect(term.buffer.lines.get(0).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -794,7 +794,7 @@ describe('Terminal', () => { const cell = new CellData(); it('café', () => { term.writeSync('cafe\u0301'); - term.buffer.lines.get(0).loadCell(3, cell); + term.buffer.lines.get(0)!.loadCell(3, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); @@ -802,11 +802,11 @@ describe('Terminal', () => { it('café - end of line', () => { term.buffer.x = term.cols - 1 - 3; term.writeSync('cafe\u0301'); - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(0).loadCell(1, cell); + term.buffer.lines.get(0)!.loadCell(1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); @@ -814,12 +814,12 @@ describe('Terminal', () => { it('multiple combined é', () => { term.writeSync(Array(100).join('e\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); @@ -827,12 +827,12 @@ describe('Terminal', () => { it('multiple surrogate with combined', () => { term.writeSync(Array(100).join('\uD800\uDC00\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); expect(cell.getChars()).eql('\uD800\uDC00\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(1); } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('\uD800\uDC00\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(1); @@ -855,7 +855,7 @@ describe('Terminal', () => { it('line of ¥ even', () => { term.writeSync(Array(50).join('¥')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (i % 2) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -866,7 +866,7 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥'); expect(cell.getChars().length).eql(1); expect(cell.getWidth()).eql(2); @@ -875,7 +875,7 @@ describe('Terminal', () => { term.buffer.x = 1; term.writeSync(Array(50).join('¥')); for (let i = 1; i < term.cols - 1; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (!(i % 2)) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -886,11 +886,11 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥'); expect(cell.getChars().length).eql(1); expect(cell.getWidth()).eql(2); @@ -899,7 +899,7 @@ describe('Terminal', () => { term.buffer.x = 1; term.writeSync(Array(50).join('¥\u0301')); for (let i = 1; i < term.cols - 1; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (!(i % 2)) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -910,11 +910,11 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(2); @@ -922,7 +922,7 @@ describe('Terminal', () => { it('line of ¥ with combining even', () => { term.writeSync(Array(50).join('¥\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (i % 2) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -933,7 +933,7 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(2); @@ -942,7 +942,7 @@ describe('Terminal', () => { term.buffer.x = 1; term.writeSync(Array(50).join('\ud843\ude6d\u0301')); for (let i = 1; i < term.cols - 1; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (!(i % 2)) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -953,11 +953,11 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('\ud843\ude6d\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(2); @@ -965,7 +965,7 @@ describe('Terminal', () => { it('line of surrogate fullwidth with combining even', () => { term.writeSync(Array(50).join('\ud843\ude6d\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (i % 2) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -976,7 +976,7 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('\ud843\ude6d\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(2); @@ -991,11 +991,11 @@ describe('Terminal', () => { term.buffer.y = 0; term.write('\x1b[4h'); term.writeSync('abcde'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a'); - expect(term.buffer.lines.get(0).loadCell(14, cell).getChars()).eql('e'); - expect(term.buffer.lines.get(0).loadCell(15, cell).getChars()).eql('0'); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql('4'); + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('a'); + expect(term.buffer.lines.get(0)!.loadCell(14, cell).getChars()).eql('e'); + expect(term.buffer.lines.get(0)!.loadCell(15, cell).getChars()).eql('0'); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql('4'); }); it('fullwidth - insert', () => { term.writeSync(Array(9).join('0123456789').slice(-80)); @@ -1003,12 +1003,12 @@ describe('Terminal', () => { term.buffer.y = 0; term.write('\x1b[4h'); term.writeSync('¥¥¥'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql(''); - expect(term.buffer.lines.get(0).loadCell(14, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(15, cell).getChars()).eql(''); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql('3'); + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(14, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(15, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql('3'); }); it('fullwidth - right border', () => { term.writeSync(Array(41).join('¥')); @@ -1016,15 +1016,15 @@ describe('Terminal', () => { term.buffer.y = 0; term.write('\x1b[4h'); term.writeSync('a'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a'); - expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql(''); // fullwidth char got replaced + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('a'); + expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql(''); // fullwidth char got replaced term.writeSync('b'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('b'); - expect(term.buffer.lines.get(0).loadCell(12, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql(''); // empty cell after fullwidth + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('b'); + expect(term.buffer.lines.get(0)!.loadCell(12, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql(''); // empty cell after fullwidth }); }); @@ -1269,9 +1269,9 @@ describe('Terminal', () => { terminal.writeSync(input); const s = terminal.buffer.iterator(true).next().content; assert.equal(input, s); - const stringIndex = s.match(/😃/).index; + const stringIndex = s.match(/😃/)!.index!; const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, stringIndex); - assert(terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars(), '😃'); + assert(terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars(), '😃'); }); it('multiline fullwidth chars with offset 1 (currently tests for broken behavior)', () => { @@ -1298,7 +1298,7 @@ describe('Terminal', () => { assert.equal(input, s); for (let i = 0; i < input.length; ++i) { const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, i, true); - assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars()); + assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars()); } }); @@ -1316,7 +1316,7 @@ describe('Terminal', () => { : (i % 3 === 1) ? input.substr(i, 2) : input.substr(i - 1, 2), - terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars()); + terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars()); } }); @@ -1370,15 +1370,15 @@ describe('Terminal', () => { const normalTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: false}); normalTerminal.writeSync(data.join('')); - assert.equal(normalTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(1).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(1)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(2)!.isWrapped, false); const windowsModeTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: true}); windowsModeTerminal.writeSync(data.join('')); - assert.equal(windowsModeTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(windowsModeTerminal.buffer.lines.get(1).isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); - assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(1)!.isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); + assert.equal(windowsModeTerminal.buffer.lines.get(2)!.isWrapped, false); }); it('should mark lines as wrapped when the line ends in a non-null character after a CUP', () => { @@ -1390,39 +1390,39 @@ describe('Terminal', () => { const normalTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: false}); normalTerminal.writeSync(data.join('')); - assert.equal(normalTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(1).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(1)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(2)!.isWrapped, false); const windowsModeTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: true}); windowsModeTerminal.writeSync(data.join('')); - assert.equal(windowsModeTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(windowsModeTerminal.buffer.lines.get(1).isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); - assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(1)!.isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); + assert.equal(windowsModeTerminal.buffer.lines.get(2)!.isWrapped, false); }); }); it('convertEol setting', function(): void { // not converting const termNotConverting = new TestTerminal({cols: 15, rows: 10}); termNotConverting.writeSync('Hello\nWorld'); - expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World '); - expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World'); + expect(termNotConverting.buffer.lines.get(0)!.translateToString(false)).equals('Hello '); + expect(termNotConverting.buffer.lines.get(1)!.translateToString(false)).equals(' World '); + expect(termNotConverting.buffer.lines.get(0)!.translateToString(true)).equals('Hello'); + expect(termNotConverting.buffer.lines.get(1)!.translateToString(true)).equals(' World'); // converting const termConverting = new TestTerminal({cols: 15, rows: 10, convertEol: true}); termConverting.writeSync('Hello\nWorld'); - expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World '); - expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World'); + expect(termConverting.buffer.lines.get(0)!.translateToString(false)).equals('Hello '); + expect(termConverting.buffer.lines.get(1)!.translateToString(false)).equals('World '); + expect(termConverting.buffer.lines.get(0)!.translateToString(true)).equals('Hello'); + expect(termConverting.buffer.lines.get(1)!.translateToString(true)).equals('World'); }); describe('Terminal InputHandler integration', () => { function getLines(term: TestTerminal, limit: number = term.rows): string[] { const res: string[] = []; for (let i = 0; i < limit; ++i) { - res.push(term.buffer.lines.get(i).translateToString(true)); + res.push(term.buffer.lines.get(i)!.translateToString(true)); } return res; } diff --git a/src/Terminal2.test.ts b/src/browser/Terminal2.test.ts similarity index 96% rename from src/Terminal2.test.ts rename to src/browser/Terminal2.test.ts index 720ea6b17..32a47b214 100644 --- a/src/Terminal2.test.ts +++ b/src/browser/Terminal2.test.ts @@ -8,14 +8,14 @@ import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; import * as pty from 'node-pty'; -import { Terminal } from './browser/Terminal'; +import { Terminal } from 'browser/Terminal'; import { IDisposable } from 'xterm'; // all test files expect terminal in 80x25 const COLS = 80; const ROWS = 25; -const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '..')}); +const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '../..')}); const SKIP_FILES = [ 't0084-CBT.in', 't0101-NLM.in', @@ -124,7 +124,7 @@ function terminalToString(term: Terminal): string { let result = ''; let lineText = ''; for (let line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) { - lineText = term.buffer.lines.get(line).translateToString(true); + lineText = term.buffer.lines.get(line)!.translateToString(true); // rtrim empty cells as xterm does lineText = lineText.replace(/\s+$/, ''); result += lineText; diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 1869ab874..2d6f6cbba 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -3,10 +3,328 @@ * @license MIT */ +import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; import { IEvent, EventEmitter } from 'common/EventEmitter'; -import { ICharSizeService, IMouseService, IRenderService } from 'browser/services/Services'; -import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; -import { IColorSet } from 'browser/Types'; +import { ICharSizeService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services'; +import { IRenderDimensions, IRenderer, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; +import { IColorSet, ILinkMatcherOptions, ITerminal, ILinkifier, ILinkifier2, IBrowser, IViewport, IColorManager, ICompositionHelper } from 'browser/Types'; +import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; +import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; +import { Buffer } from 'common/buffer/Buffer'; +import * as Browser from 'common/Platform'; +import { Terminal } from 'browser/Terminal'; +import { IUnicodeService, IOptionsService } from 'common/services/Services'; +import { IFunctionIdentifier, IParams } from 'common/parser/Types'; +import { AttributeData } from 'common/buffer/AttributeData'; + +export class TestTerminal extends Terminal { + public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } + public keyDown(ev: any): boolean | undefined { return this._keyDown(ev); } + public keyPress(ev: any): boolean { return this._keyPress(ev); } +} + +export class MockTerminal implements ITerminal { + public onBlur!: IEvent; + public onFocus!: IEvent; + public onA11yChar!: IEvent; + public onA11yTab!: IEvent; + public onCursorMove!: IEvent; + public onLineFeed!: IEvent; + public onSelectionChange!: IEvent; + public onData!: IEvent; + public onBinary!: IEvent; + public onTitleChange!: IEvent; + public onScroll!: IEvent; + public onKey!: IEvent<{ key: string, domEvent: KeyboardEvent }>; + public onRender!: IEvent<{ start: number, end: number }>; + public onResize!: IEvent<{ cols: number, rows: number }>; + public markers!: IMarker[]; + public optionsService!: IOptionsService; + public unicodeService!: IUnicodeService; + public addMarker(cursorYOffset: number): IMarker { + throw new Error('Method not implemented.'); + } + public selectLines(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + public scrollToLine(line: number): void { + throw new Error('Method not implemented.'); + } + public static string: any; + public setOption(key: any, value: any): void { + throw new Error('Method not implemented.'); + } + public blur(): void { + throw new Error('Method not implemented.'); + } + public focus(): void { + throw new Error('Method not implemented.'); + } + public resize(columns: number, rows: number): void { + throw new Error('Method not implemented.'); + } + public writeln(data: string): void { + throw new Error('Method not implemented.'); + } + public paste(data: string): void { + throw new Error('Method not implemented.'); + } + public open(parent: HTMLElement): void { + throw new Error('Method not implemented.'); + } + public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { + throw new Error('Method not implemented.'); + } + public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { + throw new Error('Method not implemented.'); + } + public deregisterLinkMatcher(matcherId: number): void { + throw new Error('Method not implemented.'); + } + public registerLinkProvider(linkProvider: ILinkProvider): IDisposable { + throw new Error('Method not implemented.'); + } + public hasSelection(): boolean { + throw new Error('Method not implemented.'); + } + public getSelection(): string { + throw new Error('Method not implemented.'); + } + public getSelectionPosition(): ISelectionPosition | undefined { + throw new Error('Method not implemented.'); + } + public clearSelection(): void { + throw new Error('Method not implemented.'); + } + public select(column: number, row: number, length: number): void { + throw new Error('Method not implemented.'); + } + public selectAll(): void { + throw new Error('Method not implemented.'); + } + public dispose(): void { + throw new Error('Method not implemented.'); + } + public scrollPages(pageCount: number): void { + throw new Error('Method not implemented.'); + } + public scrollToTop(): void { + throw new Error('Method not implemented.'); + } + public scrollToBottom(): void { + throw new Error('Method not implemented.'); + } + public clear(): void { + throw new Error('Method not implemented.'); + } + public write(data: string): void { + throw new Error('Method not implemented.'); + } + public writeUtf8(data: Uint8Array): void { + throw new Error('Method not implemented.'); + } + public bracketedPasteMode!: boolean; + public renderer!: IRenderer; + public linkifier!: ILinkifier; + public linkifier2!: ILinkifier2; + public isFocused!: boolean; + public options: ITerminalOptions = {}; + public element!: HTMLElement; + public screenElement!: HTMLElement; + public rowContainer!: HTMLElement; + public selectionContainer!: HTMLElement; + public selectionService!: ISelectionService; + public textarea!: HTMLTextAreaElement; + public rows!: number; + public cols!: number; + public browser: IBrowser = Browser; + public writeBuffer!: string[]; + public children!: HTMLElement[]; + public cursorHidden!: boolean; + public cursorState!: number; + public scrollback!: number; + public buffers!: IBufferSet; + public buffer!: IBuffer; + public viewport!: IViewport; + public applicationCursor!: boolean; + public handler(data: string): void { + throw new Error('Method not implemented.'); + } + public on(event: string, callback: (...args: any[]) => void): void { + throw new Error('Method not implemented.'); + } + public off(type: string, listener: XtermListener): void { + throw new Error('Method not implemented.'); + } + public addDisposableListener(type: string, handler: XtermListener): IDisposable { + throw new Error('Method not implemented.'); + } + public scrollLines(disp: number): void { + throw new Error('Method not implemented.'); + } + public scrollToRow(absoluteRow: number): number { + throw new Error('Method not implemented.'); + } + public cancel(ev: Event, force?: boolean): void { + throw new Error('Method not implemented.'); + } + public log(text: string): void { + throw new Error('Method not implemented.'); + } + public emit(event: string, data: any): void { + throw new Error('Method not implemented.'); + } + public reset(): void { + throw new Error('Method not implemented.'); + } + public refresh(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public deregisterCharacterJoiner(joinerId: number): void { } +} + +export class MockBuffer implements IBuffer { + public markers!: IMarker[]; + public addMarker(y: number): IMarker { + throw new Error('Method not implemented.'); + } + public isCursorInViewport!: boolean; + public lines!: ICircularList; + public ydisp!: number; + public ybase!: number; + public hasScrollback!: boolean; + public y!: number; + public x!: number; + public tabs: any; + public scrollBottom!: number; + public scrollTop!: number; + public savedY!: number; + public savedX!: number; + public savedCharset: ICharset | undefined; + public savedCurAttrData = new AttributeData(); + public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { + return Buffer.prototype.translateBufferLineToString.apply(this, arguments as any); + } + public getWrappedRangeForLine(y: number): { first: number, last: number } { + return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments as any); + } + public nextStop(x?: number): number { + throw new Error('Method not implemented.'); + } + public prevStop(x?: number): number { + throw new Error('Method not implemented.'); + } + public setLines(lines: ICircularList): void { + this.lines = lines; + } + public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine { + return Buffer.prototype.getBlankLine.apply(this, arguments as any); + } + public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] { + return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments as any); + } + public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator { + return Buffer.prototype.iterator.apply(this, arguments as any); + } + public getNullCell(attr?: IAttributeData): ICellData { + throw new Error('Method not implemented.'); + } + public getWhitespaceCell(attr?: IAttributeData): ICellData { + throw new Error('Method not implemented.'); + } +} + +export class MockRenderer implements IRenderer { + public onRequestRedraw!: IEvent; + public onCanvasResize!: IEvent<{ width: number, height: number }>; + public onRender!: IEvent<{ start: number, end: number }>; + public dispose(): void { + throw new Error('Method not implemented.'); + } + public colorManager!: IColorManager; + public on(type: string, listener: XtermListener): void { + throw new Error('Method not implemented.'); + } + public off(type: string, listener: XtermListener): void { + throw new Error('Method not implemented.'); + } + public emit(type: string, data?: any): void { + throw new Error('Method not implemented.'); + } + public addDisposableListener(type: string, handler: XtermListener): IDisposable { + throw new Error('Method not implemented.'); + } + public dimensions!: IRenderDimensions; + public setColors(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + public onResize(cols: number, rows: number): void { } + public onCharSizeChanged(): void { } + public onBlur(): void { } + public onFocus(): void { } + public onSelectionChanged(start: [number, number], end: [number, number]): void { } + public onCursorMove(): void { } + public onOptionsChanged(): void { } + public onDevicePixelRatioChange(): void { } + public clear(): void { } + public renderRows(start: number, end: number): void { } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public deregisterCharacterJoiner(): boolean { return true; } +} + +export class MockViewport implements IViewport { + public dispose(): void { + throw new Error('Method not implemented.'); + } + public scrollBarWidth: number = 0; + public onThemeChange(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + public onWheel(ev: WheelEvent): boolean { + throw new Error('Method not implemented.'); + } + public onTouchStart(ev: TouchEvent): void { + throw new Error('Method not implemented.'); + } + public onTouchMove(ev: TouchEvent): boolean { + throw new Error('Method not implemented.'); + } + public syncScrollArea(): void { } + public getLinesScrolled(ev: WheelEvent): number { + throw new Error('Method not implemented.'); + } +} + +export class MockCompositionHelper implements ICompositionHelper { + public compositionstart(): void { + throw new Error('Method not implemented.'); + } + public compositionupdate(ev: CompositionEvent): void { + throw new Error('Method not implemented.'); + } + public compositionend(): void { + throw new Error('Method not implemented.'); + } + public updateCompositionElements(dontRecurse?: boolean): void { + throw new Error('Method not implemented.'); + } + public keydown(ev: KeyboardEvent): boolean { + return true; + } +} export class MockCharSizeService implements ICharSizeService { public serviceBrand: undefined; From 80c5c94e7ea9a7ceba8cd0c1af37cd60e1e58dc3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 11:06:30 -0700 Subject: [PATCH 099/130] Remove src project --- .../benchmark/SerializeAddon.benchmark.ts | 2 +- .../benchmark/tsconfig.json | 2 -- demo/client.ts | 2 +- src/Types.d.ts | 15 -------- src/{ => browser}/public/AddonManager.test.ts | 6 ++-- src/{ => browser}/public/AddonManager.ts | 0 src/{ => browser}/public/Terminal.ts | 10 +++--- src/tsconfig.json | 34 ------------------- tsconfig.all.json | 2 +- typings/xterm.d.ts | 3 +- webpack.config.js | 2 +- 11 files changed, 14 insertions(+), 64 deletions(-) delete mode 100644 src/Types.d.ts rename src/{ => browser}/public/AddonManager.test.ts (90%) rename src/{ => browser}/public/AddonManager.ts (100%) rename src/{ => browser}/public/Terminal.ts (97%) delete mode 100644 src/tsconfig.json diff --git a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts b/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts index fbc16e03d..c1764d8ed 100644 --- a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts +++ b/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts @@ -7,7 +7,7 @@ import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark'; import { spawn } from 'node-pty'; import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder'; -import { Terminal } from 'public/Terminal'; +import { Terminal } from 'browser/public/Terminal'; import { SerializeAddon } from 'SerializeAddon'; class TestTerminal extends Terminal { diff --git a/addons/xterm-addon-serialize/benchmark/tsconfig.json b/addons/xterm-addon-serialize/benchmark/tsconfig.json index 4e62ed59a..42aaaa1bf 100644 --- a/addons/xterm-addon-serialize/benchmark/tsconfig.json +++ b/addons/xterm-addon-serialize/benchmark/tsconfig.json @@ -11,8 +11,6 @@ "paths": { "common/*": ["../../../src/common/*"], "browser/*": ["../../../src/browser/*"], - "public/*": ["../../../src/public/*"], - "Terminal": ["../../../src/Terminal"], "SerializeAddon": ["../src/SerializeAddon"] } }, diff --git a/demo/client.ts b/demo/client.ts index b009a534e..eaa6f8c1c 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -8,7 +8,7 @@ /// // Use tsc version (yarn watch) -import { Terminal } from '../out/public/Terminal'; +import { Terminal } from '../out/browser/public/Terminal'; import { AttachAddon } from '../addons/xterm-addon-attach/out/AttachAddon'; import { FitAddon } from '../addons/xterm-addon-fit/out/FitAddon'; import { SearchAddon, ISearchOptions } from '../addons/xterm-addon-search/out/SearchAddon'; diff --git a/src/Types.d.ts b/src/Types.d.ts deleted file mode 100644 index 1ffb7c5ef..000000000 --- a/src/Types.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; -import { IAttributeData, CharData, ITerminalOptions, ICoreTerminal } from 'common/Types'; -import { IEvent } from 'common/EventEmitter'; -import { ILinkifier, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types'; -import { IOptionsService, IUnicodeService } from 'common/services/Services'; -import { IBuffer, IBufferSet } from 'common/buffer/Types'; -import { IParams, IFunctionIdentifier } from 'common/parser/Types'; -import { Linkifier } from 'browser/Linkifier'; -import { Linkifier2 } from 'browser/Linkifier2'; - diff --git a/src/public/AddonManager.test.ts b/src/browser/public/AddonManager.test.ts similarity index 90% rename from src/public/AddonManager.test.ts rename to src/browser/public/AddonManager.test.ts index ea2290954..e947976ac 100644 --- a/src/public/AddonManager.test.ts +++ b/src/browser/public/AddonManager.test.ts @@ -42,9 +42,9 @@ describe('AddonManager', () => { public activate(): void {} public dispose(): void { called++; } } - manager.loadAddon(null, new Addon()); - manager.loadAddon(null, new Addon()); - manager.loadAddon(null, new Addon()); + manager.loadAddon(null!, new Addon()); + manager.loadAddon(null!, new Addon()); + manager.loadAddon(null!, new Addon()); assert.equal(manager.addons.length, 3); manager.dispose(); assert.equal(called, 3); diff --git a/src/public/AddonManager.ts b/src/browser/public/AddonManager.ts similarity index 100% rename from src/public/AddonManager.ts rename to src/browser/public/AddonManager.ts diff --git a/src/public/Terminal.ts b/src/browser/public/Terminal.ts similarity index 97% rename from src/public/Terminal.ts rename to src/browser/public/Terminal.ts index 3d4838149..b49fc6b8f 100644 --- a/src/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -8,8 +8,8 @@ import { ITerminal } from 'browser/Types'; import { IBufferLine, ICellData } from 'common/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { CellData } from 'common/buffer/CellData'; -import { Terminal as TerminalCore } from '../browser/Terminal'; -import * as Strings from '../browser/LocalizableStrings'; +import { Terminal as TerminalCore } from '../Terminal'; +import * as Strings from '../LocalizableStrings'; import { IEvent, EventEmitter } from 'common/EventEmitter'; import { AddonManager } from './AddonManager'; import { IParams } from 'common/parser/Types'; @@ -17,7 +17,7 @@ import { IParams } from 'common/parser/Types'; export class Terminal implements ITerminalApi { private _core: ITerminal; private _addonManager: AddonManager; - private _parser: IParser; + private _parser: IParser | undefined; constructor(options?: ITerminalOptions) { this._core = new TerminalCore(options); @@ -81,11 +81,11 @@ export class Terminal implements ITerminalApi { public deregisterCharacterJoiner(joinerId: number): void { this._core.deregisterCharacterJoiner(joinerId); } - public registerMarker(cursorYOffset: number): IMarker { + public registerMarker(cursorYOffset: number): IMarker | undefined { this._verifyIntegers(cursorYOffset); return this._core.addMarker(cursorYOffset); } - public addMarker(cursorYOffset: number): IMarker { + public addMarker(cursorYOffset: number): IMarker | undefined { return this.registerMarker(cursorYOffset); } public hasSelection(): boolean { diff --git a/src/tsconfig.json b/src/tsconfig.json deleted file mode 100644 index 975766683..000000000 --- a/src/tsconfig.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "extends": "./tsconfig-base", - "compilerOptions": { - "module": "commonjs", - "lib": [ - "dom", - "es5", - "es6", - "scripthost", - "es2015.promise" - ], - "rootDir": ".", - "outDir": "../out", - "baseUrl": ".", - "paths": { - "common/*": [ "./common/*" ], - "browser/*": [ "./browser/*" ] - }, - - "noUnusedLocals": true, - "noImplicitAny": true - }, - "include": [ - "./**/*", - "../typings/xterm.d.ts" - ], - "exclude": [ - "./addons/**/*" - ], - "references": [ - { "path": "./common" }, - { "path": "./browser" } - ] -} diff --git a/tsconfig.all.json b/tsconfig.all.json index 8143ea91b..a8febb72a 100644 --- a/tsconfig.all.json +++ b/tsconfig.all.json @@ -2,7 +2,7 @@ "files": [], "include": [], "references": [ - { "path": "./src" }, + { "path": "./src/browser" }, { "path": "./test/api" }, { "path": "./test/benchmark" }, { "path": "./addons/xterm-addon-attach/src" }, diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 35f43b1b0..dfda85831 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -799,8 +799,9 @@ declare module 'xterm' { * (EXPERIMENTAL) Adds a marker to the normal buffer and returns it. If the * alt buffer is active, undefined is returned. * @param cursorYOffset The y position offset of the marker from the cursor. + * @returns The new marker or undefined. */ - registerMarker(cursorYOffset: number): IMarker; + registerMarker(cursorYOffset: number): IMarker | undefined; /** * @deprecated use `registerMarker` instead. diff --git a/webpack.config.js b/webpack.config.js index a9a60241b..4f9087b51 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -12,7 +12,7 @@ const path = require('path'); * output by tsc (because of `baseUrl` and `paths` in `tsconfig.json`. */ module.exports = { - entry: './out/public/Terminal.js', + entry: './out/browser/public/Terminal.js', devtool: 'source-map', module: { rules: [ From 394bb38913c421ee1959a4add013b9d1df456bdc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 11:11:04 -0700 Subject: [PATCH 100/130] Remove src/tsconfig.json from eslintrc --- .eslintrc.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 41767bedf..32f8e9927 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,6 @@ "project": [ "src/browser/tsconfig.json", "src/common/tsconfig.json", - "src/tsconfig.json", "test/api/tsconfig.json", "test/benchmark/tsconfig.json", "addons/xterm-addon-attach/src/tsconfig.json", From 673138c5af7176269761b3eb5ac8158d6101cb15 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2020 08:26:57 +0000 Subject: [PATCH 101/130] Bump ws from 7.2.3 to 7.2.5 Bumps [ws](https://github.com/websockets/ws) from 7.2.3 to 7.2.5. - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/7.2.3...7.2.5) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1878a0bbf..c7f83bc3c 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "utf8": "^3.0.0", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "ws": "^7.0.0", + "ws": "^7.2.5", "xterm-benchmark": "^0.1.3" } } diff --git a/yarn.lock b/yarn.lock index c51b8b9f5..9752ced95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5955,10 +5955,10 @@ ws@^6.1.0: dependencies: async-limiter "~1.0.0" -ws@^7.0.0, ws@^7.2.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" - integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== +ws@^7.2.3, ws@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.5.tgz#abb1370d4626a5a9cd79d8de404aa18b3465d10d" + integrity sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA== xml-name-validator@^3.0.0: version "3.0.0" From e65ead3f200d861950bee07773c2013845e24037 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2020 13:01:17 +0000 Subject: [PATCH 102/130] Bump mocha from 7.1.1 to 7.1.2 Bumps [mocha](https://github.com/mochajs/mocha) from 7.1.1 to 7.1.2. - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v7.1.1...v7.1.2) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index c7f83bc3c..f08004daa 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "express-ws": "^4.0.0", "glob": "^7.0.5", "jsdom": "^16.2.2", - "mocha": "^7.1.1", + "mocha": "^7.1.2", "mustache": "^4.0.1", "node-pty": "^0.9.0", "nyc": "^15.0.1", diff --git a/yarn.lock b/yarn.lock index 9752ced95..cff2b4c4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3739,20 +3739,20 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c" - integrity sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg== - dependencies: - minimist "^1.2.5" - -mkdirp@0.5.4, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4: +mkdirp@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== dependencies: minimist "^1.2.5" +mkdirp@0.5.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + mocha@^6.1.4: version "6.2.3" resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.3.tgz#e648432181d8b99393410212664450a4c1e31912" @@ -3782,10 +3782,10 @@ mocha@^6.1.4: yargs-parser "13.1.2" yargs-unparser "1.6.0" -mocha@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.1.tgz#89fbb30d09429845b1bb893a830bf5771049a441" - integrity sha512-3qQsu3ijNS3GkWcccT5Zw0hf/rWvu1fTN9sPvEd81hlwsr30GX2GcDSSoBxo24IR8FelmrAydGC6/1J5QQP4WA== +mocha@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6" + integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -3800,7 +3800,7 @@ mocha@^7.1.1: js-yaml "3.13.1" log-symbols "3.0.0" minimatch "3.0.4" - mkdirp "0.5.3" + mkdirp "0.5.5" ms "2.1.1" node-environment-flags "1.0.6" object.assign "4.1.0" From 0d0f04de5cab57e8ac460352df71171d0eff4fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Mon, 27 Apr 2020 16:16:31 +0200 Subject: [PATCH 103/130] resolve master conflicts --- src/InputHandler.test.ts | 1621 -------------------------------------- 1 file changed, 1621 deletions(-) delete mode 100644 src/InputHandler.test.ts diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts deleted file mode 100644 index 53ce80aa6..000000000 --- a/src/InputHandler.test.ts +++ /dev/null @@ -1,1621 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { assert, expect } from 'chai'; -import { InputHandler } from './InputHandler'; -import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test'; -import { Terminal } from './Terminal'; -import { IBufferLine, IAttributeData } from 'common/Types'; -import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; -import { CellData } from 'common/buffer/CellData'; -import { Attributes } from 'common/buffer/Constants'; -import { AttributeData } from 'common/buffer/AttributeData'; -import { Params } from 'common/parser/Params'; -import { MockCoreService, MockBufferService, MockDirtyRowService, MockOptionsService, MockLogService, MockCoreMouseService, MockCharsetService, MockUnicodeService } from 'common/TestUtils.test'; -import { IBufferService } from 'common/services/Services'; -import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; -import { clone } from 'common/Clone'; - -function getCursor(term: TestTerminal): number[] { - return [ - term.buffer.x, - term.buffer.y - ]; -} - -function getLines(term: TestTerminal, limit: number = term.rows): string[] { - const res: string[] = []; - for (let i = 0; i < limit; ++i) { - res.push(term.buffer.lines.get(i).translateToString(true)); - } - return res; -} - -class TestInputHandler extends InputHandler { - public get curAttrData(): IAttributeData { return (this as any)._curAttrData; } -} - -describe('InputHandler', () => { - describe('save and restore cursor', () => { - const terminal = new MockInputHandlingTerminal(); - const bufferService = new MockBufferService(80, 30); - bufferService.buffer.x = 1; - bufferService.buffer.y = 2; - bufferService.buffer.ybase = 0; - const inputHandler = new TestInputHandler(terminal, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - inputHandler.curAttrData.fg = 3; - // Save cursor position - inputHandler.saveCursor(); - assert.equal(bufferService.buffer.x, 1); - assert.equal(bufferService.buffer.y, 2); - assert.equal(inputHandler.curAttrData.fg, 3); - // Change cursor position - bufferService.buffer.x = 10; - bufferService.buffer.y = 20; - inputHandler.curAttrData.fg = 30; - // Restore cursor position - inputHandler.restoreCursor(); - assert.equal(bufferService.buffer.x, 1); - assert.equal(bufferService.buffer.y, 2); - assert.equal(inputHandler.curAttrData.fg, 3); - }); - describe('setCursorStyle', () => { - it('should call Terminal.setOption with correct params', () => { - const optionsService = new MockOptionsService(); - const inputHandler = new InputHandler(new MockInputHandlingTerminal(), new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService(), {} as any); - - inputHandler.setCursorStyle(Params.fromArray([0])); - assert.equal(optionsService.options['cursorStyle'], 'block'); - assert.equal(optionsService.options['cursorBlink'], true); - - optionsService.options = clone(DEFAULT_OPTIONS); - inputHandler.setCursorStyle(Params.fromArray([1])); - assert.equal(optionsService.options['cursorStyle'], 'block'); - assert.equal(optionsService.options['cursorBlink'], true); - - optionsService.options = clone(DEFAULT_OPTIONS); - inputHandler.setCursorStyle(Params.fromArray([2])); - assert.equal(optionsService.options['cursorStyle'], 'block'); - assert.equal(optionsService.options['cursorBlink'], false); - - optionsService.options = clone(DEFAULT_OPTIONS); - inputHandler.setCursorStyle(Params.fromArray([3])); - assert.equal(optionsService.options['cursorStyle'], 'underline'); - assert.equal(optionsService.options['cursorBlink'], true); - - optionsService.options = clone(DEFAULT_OPTIONS); - inputHandler.setCursorStyle(Params.fromArray([4])); - assert.equal(optionsService.options['cursorStyle'], 'underline'); - assert.equal(optionsService.options['cursorBlink'], false); - - optionsService.options = clone(DEFAULT_OPTIONS); - inputHandler.setCursorStyle(Params.fromArray([5])); - assert.equal(optionsService.options['cursorStyle'], 'bar'); - assert.equal(optionsService.options['cursorBlink'], true); - - optionsService.options = clone(DEFAULT_OPTIONS); - inputHandler.setCursorStyle(Params.fromArray([6])); - assert.equal(optionsService.options['cursorStyle'], 'bar'); - assert.equal(optionsService.options['cursorBlink'], false); - }); - }); - describe('setMode', () => { - it('should toggle Terminal.bracketedPasteMode', () => { - const terminal = new MockInputHandlingTerminal(); - terminal.bracketedPasteMode = false; - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - // Set bracketed paste mode - inputHandler.setModePrivate(Params.fromArray([2004])); - assert.equal(terminal.bracketedPasteMode, true); - // Reset bracketed paste mode - inputHandler.resetModePrivate(Params.fromArray([2004])); - assert.equal(terminal.bracketedPasteMode, false); - }); - }); - describe('regression tests', function(): void { - function termContent(bufferService: IBufferService, trim: boolean): string[] { - const result = []; - for (let i = 0; i < bufferService.rows; ++i) result.push(bufferService.buffer.lines.get(i).translateToString(trim)); - return result; - } - - it('insertChars', function(): void { - const term = new Terminal(); - const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - - // insert some data in first and second line - inputHandler.parse(Array(bufferService.cols - 9).join('a')); - inputHandler.parse('1234567890'); - inputHandler.parse(Array(bufferService.cols - 9).join('a')); - inputHandler.parse('1234567890'); - const line1: IBufferLine = bufferService.buffer.lines.get(0); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '1234567890'); - - // insert one char from params = [0] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.insertChars(Params.fromArray([0])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + ' 123456789'); - - // insert one char from params = [1] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.insertChars(Params.fromArray([1])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + ' 12345678'); - - // insert two chars from params = [2] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.insertChars(Params.fromArray([2])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + ' 123456'); - - // insert 10 chars from params = [10] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.insertChars(Params.fromArray([10])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + ' '); - expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a')); - }); - it('deleteChars', function(): void { - const term = new Terminal(); - const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - - // insert some data in first and second line - inputHandler.parse(Array(bufferService.cols - 9).join('a')); - inputHandler.parse('1234567890'); - inputHandler.parse(Array(bufferService.cols - 9).join('a')); - inputHandler.parse('1234567890'); - const line1: IBufferLine = bufferService.buffer.lines.get(0); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '1234567890'); - - // delete one char from params = [0] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.deleteChars(Params.fromArray([0])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '234567890 '); - expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a') + '234567890'); - - // insert one char from params = [1] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.deleteChars(Params.fromArray([1])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '34567890 '); - expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a') + '34567890'); - - // insert two chars from params = [2] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.deleteChars(Params.fromArray([2])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + '567890 '); - expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a') + '567890'); - - // insert 10 chars from params = [10] - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.deleteChars(Params.fromArray([10])); - expect(line1.translateToString(false)).equals(Array(bufferService.cols - 9).join('a') + ' '); - expect(line1.translateToString(true)).equals(Array(bufferService.cols - 9).join('a')); - }); - it('eraseInLine', function(): void { - const term = new Terminal(); - const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - - // fill 6 lines to test 3 different states - inputHandler.parse(Array(bufferService.cols + 1).join('a')); - inputHandler.parse(Array(bufferService.cols + 1).join('a')); - inputHandler.parse(Array(bufferService.cols + 1).join('a')); - - // params[0] - right erase - bufferService.buffer.y = 0; - bufferService.buffer.x = 70; - inputHandler.eraseInLine(Params.fromArray([0])); - expect(bufferService.buffer.lines.get(0).translateToString(false)).equals(Array(71).join('a') + ' '); - - // params[1] - left erase - bufferService.buffer.y = 1; - bufferService.buffer.x = 70; - inputHandler.eraseInLine(Params.fromArray([1])); - expect(bufferService.buffer.lines.get(1).translateToString(false)).equals(Array(71).join(' ') + ' aaaaaaaaa'); - - // params[1] - left erase - bufferService.buffer.y = 2; - bufferService.buffer.x = 70; - inputHandler.eraseInLine(Params.fromArray([2])); - expect(bufferService.buffer.lines.get(2).translateToString(false)).equals(Array(bufferService.cols + 1).join(' ')); - - }); - it('eraseInDisplay', function(): void { - const term = new Terminal({cols: 80, rows: 7}); - const bufferService = new MockBufferService(80, 7); - const inputHandler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - - // fill display with a's - for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); - - // params [0] - right and below erase - bufferService.buffer.y = 5; - bufferService.buffer.x = 40; - inputHandler.eraseInDisplay(Params.fromArray([0])); - expect(termContent(bufferService, false)).eql([ - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(40 + 1).join('a') + Array(bufferService.cols - 40 + 1).join(' '), - Array(bufferService.cols + 1).join(' ') - ]); - expect(termContent(bufferService, true)).eql([ - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(bufferService.cols + 1).join('a'), - Array(40 + 1).join('a'), - '' - ]); - - // reset - bufferService.buffer.y = 0; - bufferService.buffer.x = 0; - for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); - - // params [1] - left and above - bufferService.buffer.y = 5; - bufferService.buffer.x = 40; - inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(termContent(bufferService, false)).eql([ - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(41 + 1).join(' ') + Array(bufferService.cols - 41 + 1).join('a'), - Array(bufferService.cols + 1).join('a') - ]); - expect(termContent(bufferService, true)).eql([ - '', - '', - '', - '', - '', - Array(41 + 1).join(' ') + Array(bufferService.cols - 41 + 1).join('a'), - Array(bufferService.cols + 1).join('a') - ]); - - // reset - bufferService.buffer.y = 0; - bufferService.buffer.x = 0; - for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); - - // params [2] - whole screen - bufferService.buffer.y = 5; - bufferService.buffer.x = 40; - inputHandler.eraseInDisplay(Params.fromArray([2])); - expect(termContent(bufferService, false)).eql([ - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' '), - Array(bufferService.cols + 1).join(' ') - ]); - expect(termContent(bufferService, true)).eql([ - '', - '', - '', - '', - '', - '', - '' - ]); - - // reset and add a wrapped line - bufferService.buffer.y = 0; - bufferService.buffer.x = 0; - inputHandler.parse(Array(bufferService.cols + 1).join('a')); // line 0 - inputHandler.parse(Array(bufferService.cols + 10).join('a')); // line 1 and 2 - for (let i = 3; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); - - // params[1] left and above with wrap - // confirm precondition that line 2 is wrapped - expect(bufferService.buffer.lines.get(2).isWrapped).true; - bufferService.buffer.y = 2; - bufferService.buffer.x = 40; - inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(bufferService.buffer.lines.get(2).isWrapped).false; - - // reset and add a wrapped line - bufferService.buffer.y = 0; - bufferService.buffer.x = 0; - inputHandler.parse(Array(bufferService.cols + 1).join('a')); // line 0 - inputHandler.parse(Array(bufferService.cols + 10).join('a')); // line 1 and 2 - for (let i = 3; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); - - // params[1] left and above with wrap - // confirm precondition that line 2 is wrapped - expect(bufferService.buffer.lines.get(2).isWrapped).true; - bufferService.buffer.y = 1; - bufferService.buffer.x = 90; // Cursor is beyond last column - inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(bufferService.buffer.lines.get(2).isWrapped).false; - }); - }); - it('convertEol setting', function(): void { - // not converting - const termNotConverting = new Terminal({cols: 15, rows: 10}); - (termNotConverting as any)._inputHandler.parse('Hello\nWorld'); - expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World '); - expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World'); - - // converting - const termConverting = new Terminal({cols: 15, rows: 10, convertEol: true}); - (termConverting as any)._inputHandler.parse('Hello\nWorld'); - expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World '); - expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World'); - }); - describe('print', () => { - it('should not cause an infinite loop (regression test)', () => { - const term = new Terminal(); - const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - const container = new Uint32Array(10); - container[0] = 0x200B; - inputHandler.print(container, 0, 1); - }); - it('should clear cells to the right on early wrap-around', () => { - const term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); - term.writeSync('12345'); - term.buffer.x = 0; - term.writeSync('¥¥¥'); - assert.deepEqual(getLines(term, 2), ['¥¥', '¥']); - }); - }); - - describe('alt screen', () => { - let term: Terminal; - let bufferService: IBufferService; - let handler: InputHandler; - - beforeEach(() => { - term = new Terminal(); - bufferService = new MockBufferService(80, 30); - handler = new InputHandler(term, bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any); - }); - it('should handle DECSET/DECRST 47 (alt screen buffer)', () => { - handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST'); - expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal(''); - expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal(' TEST'); - // Text color of 'TEST' should be red - expect((bufferService.buffer.lines.get(1).loadCell(4, new CellData()).getFgColor())).to.equal(1); - }); - it('should handle DECSET/DECRST 1047 (alt screen buffer)', () => { - handler.parse('\x1b[?1047h\r\n\x1b[31mJUNK\x1b[?1047lTEST'); - expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal(''); - expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal(' TEST'); - // Text color of 'TEST' should be red - expect((bufferService.buffer.lines.get(1).loadCell(4, new CellData()).getFgColor())).to.equal(1); - }); - it('should handle DECSET/DECRST 1048 (alt screen cursor)', () => { - handler.parse('\x1b[?1048h\r\n\x1b[31mJUNK\x1b[?1048lTEST'); - expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); - expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal('JUNK'); - // Text color of 'TEST' should be default - expect(bufferService.buffer.lines.get(0).loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); - // Text color of 'JUNK' should be red - expect((bufferService.buffer.lines.get(1).loadCell(0, new CellData()).getFgColor())).to.equal(1); - }); - it('should handle DECSET/DECRST 1049 (alt screen buffer+cursor)', () => { - handler.parse('\x1b[?1049h\r\n\x1b[31mJUNK\x1b[?1049lTEST'); - expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); - expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal(''); - // Text color of 'TEST' should be default - expect(bufferService.buffer.lines.get(0).loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); - }); - it('should handle DECSET/DECRST 1049 - maintains saved cursor for alt buffer', () => { - handler.parse('\x1b[?1049h\r\n\x1b[31m\x1b[s\x1b[?1049lTEST'); - expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); - // Text color of 'TEST' should be default - expect(bufferService.buffer.lines.get(0).loadCell(0, new CellData()).fg).to.equal(DEFAULT_ATTR_DATA.fg); - handler.parse('\x1b[?1049h\x1b[uTEST'); - expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal('TEST'); - // Text color of 'TEST' should be red - expect((bufferService.buffer.lines.get(1).loadCell(0, new CellData()).getFgColor())).to.equal(1); - }); - it('should handle DECSET/DECRST 1049 - clears alt buffer with erase attributes', () => { - handler.parse('\x1b[42m\x1b[?1049h'); - // Buffer should be filled with green background - expect(bufferService.buffer.lines.get(20).loadCell(10, new CellData()).getBgColor()).to.equal(2); - }); - }); - - describe('text attributes', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal(); - }); - it('bold', () => { - term.writeSync('\x1b[1m'); - assert.equal(!!term.curAttrData.isBold(), true); - term.writeSync('\x1b[22m'); - assert.equal(!!term.curAttrData.isBold(), false); - }); - it('dim', () => { - term.writeSync('\x1b[2m'); - assert.equal(!!term.curAttrData.isDim(), true); - term.writeSync('\x1b[22m'); - assert.equal(!!term.curAttrData.isDim(), false); - }); - it('italic', () => { - term.writeSync('\x1b[3m'); - assert.equal(!!term.curAttrData.isItalic(), true); - term.writeSync('\x1b[23m'); - assert.equal(!!term.curAttrData.isItalic(), false); - }); - it('underline', () => { - term.writeSync('\x1b[4m'); - assert.equal(!!term.curAttrData.isUnderline(), true); - term.writeSync('\x1b[24m'); - assert.equal(!!term.curAttrData.isUnderline(), false); - }); - it('blink', () => { - term.writeSync('\x1b[5m'); - assert.equal(!!term.curAttrData.isBlink(), true); - term.writeSync('\x1b[25m'); - assert.equal(!!term.curAttrData.isBlink(), false); - }); - it('inverse', () => { - term.writeSync('\x1b[7m'); - assert.equal(!!term.curAttrData.isInverse(), true); - term.writeSync('\x1b[27m'); - assert.equal(!!term.curAttrData.isInverse(), false); - }); - it('invisible', () => { - term.writeSync('\x1b[8m'); - assert.equal(!!term.curAttrData.isInvisible(), true); - term.writeSync('\x1b[28m'); - assert.equal(!!term.curAttrData.isInvisible(), false); - }); - it('colormode palette 16', () => { - assert.equal(term.curAttrData.getFgColorMode(), 0); // DEFAULT - assert.equal(term.curAttrData.getBgColorMode(), 0); // DEFAULT - // lower 8 colors - for (let i = 0; i < 8; ++i) { - term.writeSync(`\x1b[${i + 30};${i + 40}m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getFgColor(), i); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getBgColor(), i); - } - // reset to DEFAULT - term.writeSync(`\x1b[39;49m`); - assert.equal(term.curAttrData.getFgColorMode(), 0); - assert.equal(term.curAttrData.getBgColorMode(), 0); - }); - it('colormode palette 256', () => { - assert.equal(term.curAttrData.getFgColorMode(), 0); // DEFAULT - assert.equal(term.curAttrData.getBgColorMode(), 0); // DEFAULT - // lower 8 colors - for (let i = 0; i < 256; ++i) { - term.writeSync(`\x1b[38;5;${i};48;5;${i}m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getFgColor(), i); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getBgColor(), i); - } - // reset to DEFAULT - term.writeSync(`\x1b[39;49m`); - assert.equal(term.curAttrData.getFgColorMode(), 0); - assert.equal(term.curAttrData.getFgColor(), -1); - assert.equal(term.curAttrData.getBgColorMode(), 0); - assert.equal(term.curAttrData.getBgColor(), -1); - }); - it('colormode RGB', () => { - assert.equal(term.curAttrData.getFgColorMode(), 0); // DEFAULT - assert.equal(term.curAttrData.getBgColorMode(), 0); // DEFAULT - term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_RGB); - assert.equal(term.curAttrData.getFgColor(), 1 << 16 | 2 << 8 | 3); - assert.deepEqual(AttributeData.toColorRGB(term.curAttrData.getFgColor()), [1, 2, 3]); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_RGB); - assert.deepEqual(AttributeData.toColorRGB(term.curAttrData.getBgColor()), [4, 5, 6]); - // reset to DEFAULT - term.writeSync(`\x1b[39;49m`); - assert.equal(term.curAttrData.getFgColorMode(), 0); - assert.equal(term.curAttrData.getFgColor(), -1); - assert.equal(term.curAttrData.getBgColorMode(), 0); - assert.equal(term.curAttrData.getBgColor(), -1); - }); - it('colormode transition RGB to 256', () => { - // enter RGB for FG and BG - term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`); - // enter 256 for FG and BG - term.writeSync(`\x1b[38;5;255;48;5;255m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getFgColor(), 255); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getBgColor(), 255); - }); - it('colormode transition RGB to 16', () => { - // enter RGB for FG and BG - term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`); - // enter 16 for FG and BG - term.writeSync(`\x1b[37;47m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getFgColor(), 7); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getBgColor(), 7); - }); - it('colormode transition 16 to 256', () => { - // enter 16 for FG and BG - term.writeSync(`\x1b[37;47m`); - // enter 256 for FG and BG - term.writeSync(`\x1b[38;5;255;48;5;255m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getFgColor(), 255); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256); - assert.equal(term.curAttrData.getBgColor(), 255); - }); - it('colormode transition 256 to 16', () => { - // enter 256 for FG and BG - term.writeSync(`\x1b[38;5;255;48;5;255m`); - // enter 16 for FG and BG - term.writeSync(`\x1b[37;47m`); - assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getFgColor(), 7); - assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16); - assert.equal(term.curAttrData.getBgColor(), 7); - }); - it('should zero missing RGB values', () => { - term.writeSync(`\x1b[38;2;1;2;3m`); - term.writeSync(`\x1b[38;2;5m`); - assert.deepEqual(AttributeData.toColorRGB(term.curAttrData.getFgColor()), [5, 0, 0]); - }); - }); - describe('colon notation', () => { - let termColon: TestTerminal; - let termSemicolon: TestTerminal; - beforeEach(() => { - termColon = new TestTerminal(); - termSemicolon = new TestTerminal(); - }); - describe('should equal to semicolon', () => { - it('CSI 38:2::50:100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38:2::50:100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38:2::50:100: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;m'); - termColon.writeSync('\x1b[38:2::50:100:m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38:2::50:: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;;m'); - termColon.writeSync('\x1b[38:2::50::m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 0 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38:2:::: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;;;m'); - termColon.writeSync('\x1b[38:2::::m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0 << 16 | 0 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38;2::50:100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38;2::50:100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38;2;50:100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38;2;50:100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38;2;50;100:150 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2;50;100;150m'); - termColon.writeSync('\x1b[38;2;50;100:150m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38:5:50 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5;50m'); - termColon.writeSync('\x1b[38:5:50m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 50); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38:5: m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5;m'); - termColon.writeSync('\x1b[38:5:m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38;5:50 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5;50m'); - termColon.writeSync('\x1b[38;5:50m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 50); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - }); - describe('should fill early sequence end with default of 0', () => { - it('CSI 38:2 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;2m'); - termColon.writeSync('\x1b[38:2m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0 << 16 | 0 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 38:5 m', () => { - termColon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.curAttrData.fg = 0xFFFFFFFF; - termSemicolon.writeSync('\x1b[38;5m'); - termColon.writeSync('\x1b[38:5m'); - assert.equal(termSemicolon.curAttrData.fg & 0xFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - }); - describe('should not interfere with leading/following SGR attrs', () => { - it('CSI 1 ; 38:2::50:100:150 ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;50;100;150;4m'); - termColon.writeSync('\x1b[1;38:2::50:100:150;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 150); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 1 ; 38:2::50:100: ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;50;100;;4m'); - termColon.writeSync('\x1b[1;38:2::50:100:;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 1 ; 38:2::50:100 ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;50;100;;4m'); - termColon.writeSync('\x1b[1;38:2::50:100;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 50 << 16 | 100 << 8 | 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 1 ; 38:2:: ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;;;;4m'); - termColon.writeSync('\x1b[1;38:2::;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - it('CSI 1 ; 38;2:: ; 4 m', () => { - termSemicolon.writeSync('\x1b[1;38;2;;;;4m'); - termColon.writeSync('\x1b[1;38;2::;4m'); - assert.equal(!!termSemicolon.curAttrData.isBold(), true); - assert.equal(!!termSemicolon.curAttrData.isUnderline(), true); - assert.equal(termSemicolon.curAttrData.fg & 0xFFFFFF, 0); - assert.equal(termColon.curAttrData.fg, termSemicolon.curAttrData.fg); - }); - }); - }); - describe('cursor positioning', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 10}); - }); - it('cursor forward (CUF)', () => { - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[1C'); - assert.deepEqual(getCursor(term), [2, 0]); - term.writeSync('\x1b[4C'); - assert.deepEqual(getCursor(term), [6, 0]); - term.writeSync('\x1b[100C'); - assert.deepEqual(getCursor(term), [9, 0]); - // should not change y - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [9, 4]); - }); - it('cursor backward (CUB)', () => { - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1D'); - assert.deepEqual(getCursor(term), [0, 0]); - // place cursor at end of first line - term.writeSync('\x1b[100C'); - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [8, 0]); - term.writeSync('\x1b[1D'); - assert.deepEqual(getCursor(term), [7, 0]); - term.writeSync('\x1b[4D'); - assert.deepEqual(getCursor(term), [3, 0]); - term.writeSync('\x1b[100D'); - assert.deepEqual(getCursor(term), [0, 0]); - // should not change y - term.buffer.x = 4; - term.buffer.y = 4; - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [3, 4]); - }); - it('cursor down (CUD)', () => { - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[1B'); - assert.deepEqual(getCursor(term), [0, 2]); - term.writeSync('\x1b[4B'); - assert.deepEqual(getCursor(term), [0, 6]); - term.writeSync('\x1b[100B'); - assert.deepEqual(getCursor(term), [0, 9]); - // should not change x - term.buffer.x = 8; - term.buffer.y = 0; - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [8, 1]); - }); - it('cursor up (CUU)', () => { - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1A'); - assert.deepEqual(getCursor(term), [0, 0]); - // place cursor at beginning of last row - term.writeSync('\x1b[100B'); - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [0, 8]); - term.writeSync('\x1b[1A'); - assert.deepEqual(getCursor(term), [0, 7]); - term.writeSync('\x1b[4A'); - assert.deepEqual(getCursor(term), [0, 3]); - term.writeSync('\x1b[100A'); - assert.deepEqual(getCursor(term), [0, 0]); - // should not change x - term.buffer.x = 8; - term.buffer.y = 9; - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [8, 8]); - }); - it('cursor next line (CNL)', () => { - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[1E'); - assert.deepEqual(getCursor(term), [0, 2]); - term.writeSync('\x1b[4E'); - assert.deepEqual(getCursor(term), [0, 6]); - term.writeSync('\x1b[100E'); - assert.deepEqual(getCursor(term), [0, 9]); - // should reset x to zero - term.buffer.x = 8; - term.buffer.y = 0; - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 1]); - }); - it('cursor previous line (CPL)', () => { - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1F'); - assert.deepEqual(getCursor(term), [0, 0]); - // place cursor at beginning of last row - term.writeSync('\x1b[100E'); - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 8]); - term.writeSync('\x1b[1F'); - assert.deepEqual(getCursor(term), [0, 7]); - term.writeSync('\x1b[4F'); - assert.deepEqual(getCursor(term), [0, 3]); - term.writeSync('\x1b[100F'); - assert.deepEqual(getCursor(term), [0, 0]); - // should reset x to zero - term.buffer.x = 8; - term.buffer.y = 9; - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 8]); - }); - it('cursor character absolute (CHA)', () => { - term.writeSync('\x1b[G'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1G'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[2G'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[5G'); - assert.deepEqual(getCursor(term), [4, 0]); - term.writeSync('\x1b[100G'); - assert.deepEqual(getCursor(term), [9, 0]); - }); - it('cursor position (CUP)', () => { - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[H'); - assert.deepEqual(getCursor(term), [0, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[1H'); - assert.deepEqual(getCursor(term), [0, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[1;1H'); - assert.deepEqual(getCursor(term), [0, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[8H'); - assert.deepEqual(getCursor(term), [0, 7]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[;8H'); - assert.deepEqual(getCursor(term), [7, 0]); - term.buffer.x = 5; - term.buffer.y = 5; - term.writeSync('\x1b[100;100H'); - assert.deepEqual(getCursor(term), [9, 9]); - }); - it('horizontal position absolute (HPA)', () => { - term.writeSync('\x1b[`'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1`'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[2`'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[5`'); - assert.deepEqual(getCursor(term), [4, 0]); - term.writeSync('\x1b[100`'); - assert.deepEqual(getCursor(term), [9, 0]); - }); - it('horizontal position relative (HPR)', () => { - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [1, 0]); - term.writeSync('\x1b[1a'); - assert.deepEqual(getCursor(term), [2, 0]); - term.writeSync('\x1b[4a'); - assert.deepEqual(getCursor(term), [6, 0]); - term.writeSync('\x1b[100a'); - assert.deepEqual(getCursor(term), [9, 0]); - // should not change y - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [9, 4]); - }); - it('vertical position absolute (VPA)', () => { - term.writeSync('\x1b[d'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[1d'); - assert.deepEqual(getCursor(term), [0, 0]); - term.writeSync('\x1b[2d'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[5d'); - assert.deepEqual(getCursor(term), [0, 4]); - term.writeSync('\x1b[100d'); - assert.deepEqual(getCursor(term), [0, 9]); - // should not change x - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[d'); - assert.deepEqual(getCursor(term), [8, 0]); - }); - it('vertical position relative (VPR)', () => { - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [0, 1]); - term.writeSync('\x1b[1e'); - assert.deepEqual(getCursor(term), [0, 2]); - term.writeSync('\x1b[4e'); - assert.deepEqual(getCursor(term), [0, 6]); - term.writeSync('\x1b[100e'); - assert.deepEqual(getCursor(term), [0, 9]); - // should not change x - term.buffer.x = 8; - term.buffer.y = 4; - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [8, 5]); - }); - describe('should clamp cursor into addressible range', () => { - it('CUF', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[C'); - assert.deepEqual(getCursor(term), [1, 0]); - }); - it('CUB', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [8, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[D'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - it('CUD', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[B'); - assert.deepEqual(getCursor(term), [0, 1]); - }); - it('CUU', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [9, 8]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[A'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - it('CNL', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[E'); - assert.deepEqual(getCursor(term), [0, 1]); - }); - it('CPL', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 8]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[F'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - it('CHA', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5G'); - assert.deepEqual(getCursor(term), [4, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5G'); - assert.deepEqual(getCursor(term), [4, 0]); - }); - it('CUP', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5;5H'); - assert.deepEqual(getCursor(term), [4, 4]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5;5H'); - assert.deepEqual(getCursor(term), [4, 4]); - }); - it('HPA', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5`'); - assert.deepEqual(getCursor(term), [4, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5`'); - assert.deepEqual(getCursor(term), [4, 0]); - }); - it('HPR', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[a'); - assert.deepEqual(getCursor(term), [1, 0]); - }); - it('VPA', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[5d'); - assert.deepEqual(getCursor(term), [9, 4]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[5d'); - assert.deepEqual(getCursor(term), [0, 4]); - }); - it('VPR', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[e'); - assert.deepEqual(getCursor(term), [0, 1]); - }); - it('DCH', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[P'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[P'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - it('DCH - should delete last cell', () => { - term.writeSync('0123456789\x1b[P'); - assert.equal(term.buffer.lines.get(0).translateToString(false), '012345678 '); - }); - it('ECH', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[X'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[X'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - it('ECH - should delete last cell', () => { - term.writeSync('0123456789\x1b[X'); - assert.equal(term.buffer.lines.get(0).translateToString(false), '012345678 '); - }); - it('ICH', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[@'); - assert.deepEqual(getCursor(term), [9, 9]); - term.buffer.x = -10000; - term.buffer.y = -10000; - term.writeSync('\x1b[@'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - it('ICH - should delete last cell', () => { - term.writeSync('0123456789\x1b[@'); - assert.equal(term.buffer.lines.get(0).translateToString(false), '012345678 '); - }); - }); - }); - describe('DECSTBM - scroll margins', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 10}); - }); - it('should default to whole viewport', () => { - term.writeSync('\x1b[r'); - assert.equal(term.buffer.scrollTop, 0); - assert.equal(term.buffer.scrollBottom, 9); - term.writeSync('\x1b[3;7r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 6); - term.writeSync('\x1b[0;0r'); - assert.equal(term.buffer.scrollTop, 0); - assert.equal(term.buffer.scrollBottom, 9); - }); - it('should clamp bottom', () => { - term.writeSync('\x1b[3;1000r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 9); - }); - it('should only apply for top < bottom', () => { - term.writeSync('\x1b[7;2r'); - assert.equal(term.buffer.scrollTop, 0); - assert.equal(term.buffer.scrollBottom, 9); - }); - it('should home cursor', () => { - term.buffer.x = 10000; - term.buffer.y = 10000; - term.writeSync('\x1b[2;7r'); - assert.deepEqual(getCursor(term), [0, 0]); - }); - }); - describe('scroll margins', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 10}); - }); - it('scrollUp', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Sm'); - assert.deepEqual(getLines(term), ['m', '3', '', '', '4', '5', '6', '7', '8', '9']); - }); - it('scrollDown', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Tm'); - assert.deepEqual(getLines(term), ['m', '', '', '1', '4', '5', '6', '7', '8', '9']); - }); - it('insertLines - out of margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[2Lm'); - assert.deepEqual(getLines(term), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); - term.writeSync('\x1b[2H\x1b[2Ln'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); - // skip below scrollbottom - term.writeSync('\x1b[7H\x1b[2Lo'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); - term.writeSync('\x1b[8H\x1b[2Lp'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); - term.writeSync('\x1b[100H\x1b[2Lq'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); - }); - it('insertLines - within margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[3H\x1b[2Lm'); - assert.deepEqual(getLines(term), ['0', '1', 'm', '', '2', '3', '6', '7', '8', '9']); - term.writeSync('\x1b[6H\x1b[2Ln'); - assert.deepEqual(getLines(term), ['0', '1', 'm', '', '2', 'n', '6', '7', '8', '9']); - }); - it('deleteLines - out of margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[2Mm'); - assert.deepEqual(getLines(term), ['m', '1', '2', '3', '4', '5', '6', '7', '8', '9']); - term.writeSync('\x1b[2H\x1b[2Mn'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', '6', '7', '8', '9']); - // skip below scrollbottom - term.writeSync('\x1b[7H\x1b[2Mo'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', '7', '8', '9']); - term.writeSync('\x1b[8H\x1b[2Mp'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', '9']); - term.writeSync('\x1b[100H\x1b[2Mq'); - assert.deepEqual(getLines(term), ['m', 'n', '2', '3', '4', '5', 'o', 'p', '8', 'q']); - }); - it('deleteLines - within margins', () => { - term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[3;6r'); - assert.equal(term.buffer.scrollTop, 2); - assert.equal(term.buffer.scrollBottom, 5); - term.writeSync('\x1b[6H\x1b[2Mm'); - assert.deepEqual(getLines(term), ['0', '1', '2', '3', '4', 'm', '6', '7', '8', '9']); - term.writeSync('\x1b[3H\x1b[2Mn'); - assert.deepEqual(getLines(term), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']); - }); - }); - describe('SL/SR/DECIC/DECDC', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); - }); - it('SL (scrollLeft)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[ @'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '2345', '2345', '2345', '2345', '2345']); - term.writeSync('\x1b[0 @'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '345', '345', '345', '345', '345']); - term.writeSync('\x1b[2 @'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '5', '5', '5', '5', '5']); - }); - it('SR (scrollRight)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[ A'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']); - term.writeSync('\x1b[0 A'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']); - term.writeSync('\x1b[2 A'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']); - }); - it('insertColumns (DECIC)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[\'}'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[1\'}'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[2\'}'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']); - }); - it('deleteColumns (DECDC)', () => { - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[\'~'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[1\'~'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); - term.reset(); - term.writeSync('12345'.repeat(6)); - term.writeSync('\x1b[3;3H'); - term.writeSync('\x1b[2\'~'); - assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']); - }); - }); - it('should parse big chunks in smaller subchunks', () => { - // max single chunk size is hardcoded as 131072 - const calls: any[] = []; - const term = new TestTerminal({cols: 10, rows: 10}); - (term as any)._inputHandler._parser.parse = (data: Uint32Array, length: number) => { - calls.push([data.length, length]); - }; - term.writeSync('12345'); - term.writeSync('a'.repeat(10000)); - term.writeSync('a'.repeat(200000)); - term.writeSync('a'.repeat(300000)); - assert.deepEqual(calls, [ - [4096, 5], - [10000, 10000], - [131072, 131072], [131072, 200000 - 131072], - [131072, 131072], [131072, 131072], [131072, 300000 - 131072 - 131072] - ]); - }); - describe('windowOptions', () => { - it('all should be disabled by default and not report', () => { - const term = new TestTerminal({cols: 10, rows: 10}); - const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[14t'); - term.writeSync('\x1b[16t'); - term.writeSync('\x1b[18t'); - term.writeSync('\x1b[20t'); - term.writeSync('\x1b[21t'); - assert.deepEqual(stack, []); - }); - it('14 - GetWinSizePixels', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinSizePixels: true}}); - const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[14t'); - // does not report in test terminal due to missing renderer - assert.deepEqual(stack, []); - }); - it('16 - GetCellSizePixels', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getCellSizePixels: true}}); - const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[16t'); - // does not report in test terminal due to missing renderer - assert.deepEqual(stack, []); - }); - it('18 - GetWinSizeChars', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinSizeChars: true}}); - const stack: string[] = []; - term.onData(data => stack.push(data)); - term.writeSync('\x1b[18t'); - assert.deepEqual(stack, ['\x1b[8;10;10t']); - term.resize(50, 20); - term.writeSync('\x1b[18t'); - assert.deepEqual(stack, ['\x1b[8;10;10t', '\x1b[8;20;50t']); - }); - it('22/23 - PushTitle/PopTitle', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); - const stack: string[] = []; - term.onTitleChange(data => stack.push(data)); - term.writeSync('\x1b]0;1\x07'); - term.writeSync('\x1b[22t'); - term.writeSync('\x1b]0;2\x07'); - term.writeSync('\x1b[22t'); - term.writeSync('\x1b]0;3\x07'); - term.writeSync('\x1b[22t'); - assert.deepEqual((term as any)._inputHandler._windowTitleStack, ['1', '2', '3']); - assert.deepEqual((term as any)._inputHandler._iconNameStack, ['1', '2', '3']); - assert.deepEqual(stack, ['1', '2', '3']); - term.writeSync('\x1b[23t'); - term.writeSync('\x1b[23t'); - term.writeSync('\x1b[23t'); - term.writeSync('\x1b[23t'); // one more to test "overflow" - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); - assert.deepEqual(stack, ['1', '2', '3', '3', '2', '1']); - }); - it('22/23 - PushTitle/PopTitle with ;1', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); - const stack: string[] = []; - term.onTitleChange(data => stack.push(data)); - term.writeSync('\x1b]0;1\x07'); - term.writeSync('\x1b[22;1t'); - term.writeSync('\x1b]0;2\x07'); - term.writeSync('\x1b[22;1t'); - term.writeSync('\x1b]0;3\x07'); - term.writeSync('\x1b[22;1t'); - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, ['1', '2', '3']); - assert.deepEqual(stack, ['1', '2', '3']); - term.writeSync('\x1b[23;1t'); - term.writeSync('\x1b[23;1t'); - term.writeSync('\x1b[23;1t'); - term.writeSync('\x1b[23;1t'); // one more to test "overflow" - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); - assert.deepEqual(stack, ['1', '2', '3']); - }); - it('22/23 - PushTitle/PopTitle with ;2', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); - const stack: string[] = []; - term.onTitleChange(data => stack.push(data)); - term.writeSync('\x1b]0;1\x07'); - term.writeSync('\x1b[22;2t'); - term.writeSync('\x1b]0;2\x07'); - term.writeSync('\x1b[22;2t'); - term.writeSync('\x1b]0;3\x07'); - term.writeSync('\x1b[22;2t'); - assert.deepEqual((term as any)._inputHandler._windowTitleStack, ['1', '2', '3']); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); - assert.deepEqual(stack, ['1', '2', '3']); - term.writeSync('\x1b[23;2t'); - term.writeSync('\x1b[23;2t'); - term.writeSync('\x1b[23;2t'); - term.writeSync('\x1b[23;2t'); // one more to test "overflow" - assert.deepEqual((term as any)._inputHandler._windowTitleStack, []); - assert.deepEqual((term as any)._inputHandler._iconNameStack, []); - assert.deepEqual(stack, ['1', '2', '3', '3', '2', '1']); - }); - it('DECCOLM - should only work with "SetWinLines" (24) enabled', () => { - // disabled - const term = new TestTerminal({cols: 10, rows: 10}); - term.writeSync('\x1b[?3l'); - assert.equal((term as any)._bufferService.cols, 10); - term.writeSync('\x1b[?3h'); - assert.equal((term as any)._bufferService.cols, 10); - // enabled - const term2 = new TestTerminal({cols: 10, rows: 10, windowOptions: {setWinLines: true}}); - term2.writeSync('\x1b[?3l'); - assert.equal((term2 as any)._bufferService.cols, 80); - term2.writeSync('\x1b[?3h'); - assert.equal((term2 as any)._bufferService.cols, 132); - }); - }); - describe('should correctly reset cells taken by wide chars', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 5, scrollback: 1}); - term.writeSync('¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥'); - }); - it('print', () => { - term.writeSync('\x1b[H#'); - assert.deepEqual(getLines(term), ['# ¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[1;6H######'); - assert.deepEqual(getLines(term), ['# ¥ #####', '# ¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '##¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;9H#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥#', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '¥¥¥¥¥', '']); - term.writeSync('#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '# ¥¥¥¥', '']); - term.writeSync('\x1b[4;10H#'); - assert.deepEqual(getLines(term), ['# ¥ #####', '### ¥¥¥', '¥¥¥¥##', '# ¥¥¥ #', '']); - }); - it('EL', () => { - term.writeSync('\x1b[1;6H\x1b[K#'); - assert.deepEqual(getLines(term), ['¥¥ #', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;5H\x1b[1K'); - assert.deepEqual(getLines(term), ['¥¥ #', ' ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;6H\x1b[1K'); - assert.deepEqual(getLines(term), ['¥¥ #', ' ¥¥', ' ¥¥', '¥¥¥¥¥', '']); - }); - it('ICH', () => { - term.writeSync('\x1b[1;6H\x1b[@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;4H\x1b[2@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;4H\x1b[3@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥ ¥¥', '¥ ¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[4;4H\x1b[4@'); - assert.deepEqual(getLines(term), ['¥¥ ¥', '¥ ¥¥', '¥ ¥', '¥ ¥', '']); - }); - it('DCH', () => { - term.writeSync('\x1b[1;6H\x1b[P'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;6H\x1b[2P'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;6H\x1b[3P'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); - }); - it('ECH', () => { - term.writeSync('\x1b[1;6H\x1b[X'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[2;6H\x1b[2X'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥¥¥¥', '¥¥¥¥¥', '']); - term.writeSync('\x1b[3;6H\x1b[3X'); - assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); - }); - }); - describe('BS with reverseWraparound set/unset', () => { - const ttyBS = '\x08 \x08'; // tty ICANON sends on pressing BS - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); - }); - describe('reverseWraparound unset (default)', () => { - it('cannot delete last cell', () => { - term.writeSync('12345'); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 1), ['123 5']); - term.writeSync(ttyBS.repeat(10)); - assert.deepEqual(getLines(term, 1), [' 5']); - }); - it('cannot access prev line', () => { - term.writeSync('12345'.repeat(2)); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), ['12345', '123 5']); - term.writeSync(ttyBS.repeat(10)); - assert.deepEqual(getLines(term, 2), ['12345', ' 5']); - }); - }); - describe('reverseWraparound set', () => { - it('can delete last cell', () => { - term.writeSync('\x1b[?45h'); - term.writeSync('12345'); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 1), ['1234 ']); - term.writeSync(ttyBS.repeat(7)); - assert.deepEqual(getLines(term, 1), [' ']); - }); - it('can access prev line if wrapped', () => { - term.writeSync('\x1b[?45h'); - term.writeSync('12345'.repeat(2)); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), ['12345', '1234 ']); - term.writeSync(ttyBS.repeat(7)); - assert.deepEqual(getLines(term, 2), ['12 ', ' ']); - }); - it('should lift isWrapped', () => { - term.writeSync('\x1b[?45h'); - term.writeSync('12345'.repeat(2)); - assert.equal(term.buffer.lines.get(1).isWrapped, true); - term.writeSync(ttyBS.repeat(7)); - assert.equal(term.buffer.lines.get(1).isWrapped, false); - }); - it('stops at hard NLs', () => { - term.writeSync('\x1b[?45h'); - term.writeSync('12345\r\n'); - term.writeSync('12345'.repeat(2)); - term.writeSync(ttyBS.repeat(50)); - assert.deepEqual(getLines(term, 3), ['12345', ' ', ' ']); - assert.equal(term.buffer.x, 0); - assert.equal(term.buffer.y, 1); - }); - it('handles wide chars correctly', () => { - term.writeSync('\x1b[?45h'); - term.writeSync('¥¥¥'); - assert.deepEqual(getLines(term, 2), ['¥¥', '¥']); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), ['¥¥', ' ']); - assert.equal(term.buffer.x, 1); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), ['¥¥', ' ']); - assert.equal(term.buffer.x, 0); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), ['¥ ', ' ']); - assert.equal(term.buffer.x, 3); // x=4 skipped due to early wrap-around - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), ['¥ ', ' ']); - assert.equal(term.buffer.x, 2); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), [' ', ' ']); - assert.equal(term.buffer.x, 1); - term.writeSync(ttyBS); - assert.deepEqual(getLines(term, 2), [' ', ' ']); - assert.equal(term.buffer.x, 0); - }); - it('should not reverse outside of scroll margins', () => { - // prepare buffer content - term.writeSync('#####abcdefghijklmnopqrstuvwxy'); - assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']); - assert.equal(term.buffer.ydisp, 1); - assert.equal(term.buffer.x, 5); - assert.equal(term.buffer.y, 4); - term.writeSync(ttyBS.repeat(100)); - assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']); - - term.writeSync('\x1b[?45h'); - term.writeSync('uvwxy'); - - // set top/bottom to 1/3 (0-based) - term.writeSync('\x1b[2;4r'); - // place cursor below scroll bottom - term.buffer.x = 5; - term.buffer.y = 4; - term.writeSync(ttyBS.repeat(100)); - assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']); - - term.writeSync('uvwxy'); - // place cursor within scroll margins - term.buffer.x = 5; - term.buffer.y = 3; - term.writeSync(ttyBS.repeat(100)); - assert.deepEqual(getLines(term, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']); - assert.equal(term.buffer.x, 0); - assert.equal(term.buffer.y, term.buffer.scrollTop); // stops at 0, scrollTop - - term.writeSync('fghijklmnopqrst'); - // place cursor above scroll top - term.buffer.x = 5; - term.buffer.y = 0; - term.writeSync(ttyBS.repeat(100)); - assert.deepEqual(getLines(term, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']); - }); - }); - }); - describe('DECSTR', () => { - let term: TestTerminal; - beforeEach(() => { - term = new TestTerminal({cols: 10, rows: 5, scrollback: 1}); - term.writeSync('01234567890123'); - }); - it('should reset IRM', () => { - term.writeSync('\x1b[4h'); - assert.equal(term.insertMode, true); - term.writeSync('\x1b[!p'); - assert.equal(term.insertMode, false); - }); - it('should reset cursor visibility', () => { - term.writeSync('\x1b[?25l'); - assert.equal((term as any)._coreService.isCursorHidden, true); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._coreService.isCursorHidden, false); - }); - it('should reset scroll margins', () => { - term.writeSync('\x1b[2;4r'); - assert.equal((term as any)._bufferService.buffer.scrollTop, 1); - assert.equal((term as any)._bufferService.buffer.scrollBottom, 3); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._bufferService.buffer.scrollTop, 0); - assert.equal((term as any)._bufferService.buffer.scrollBottom, term.rows - 1); - }); - it('should reset text attributes', () => { - term.writeSync('\x1b[1;2;32;43m'); - assert.equal(!!term.curAttrData.isBold(), true); - term.writeSync('\x1b[!p'); - assert.equal(!!term.curAttrData.isBold(), false); - assert.equal(term.curAttrData.fg, 0); - assert.equal(term.curAttrData.bg, 0); - }); - it('should reset DECSC data', () => { - term.writeSync('\x1b7'); - assert.equal((term as any)._bufferService.buffer.savedX, 4); - assert.equal((term as any)._bufferService.buffer.savedY, 1); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._bufferService.buffer.savedX, 0); - assert.equal((term as any)._bufferService.buffer.savedY, 0); - }); - it('should reset DECOM', () => { - term.writeSync('\x1b[?6h'); - assert.equal((term as any)._coreService.decPrivateModes.origin, true); - term.writeSync('\x1b[!p'); - assert.equal((term as any)._coreService.decPrivateModes.origin, false); - }); - }); -}); From 74ac45730f5c69af0305790cb675790ed95b5f33 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2020 08:06:37 +0000 Subject: [PATCH 104/130] Bump @typescript-eslint/parser from 2.29.0 to 2.30.0 Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.29.0 to 2.30.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.30.0/packages/parser) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 35 +++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index f08004daa..42da3e704 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/webpack": "^4.41.12", "@types/ws": "^7.2.4", "@typescript-eslint/eslint-plugin": "^2.29.0", - "@typescript-eslint/parser": "^2.29.0", + "@typescript-eslint/parser": "^2.30.0", "chai": "^4.2.0", "deep-equal": "^2.0.3", "eslint": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index cff2b4c4b..b8326686d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -391,14 +391,24 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.29.0": - version "2.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.29.0.tgz#6e3c4e21ed6393dc05b9d8b47f0b7e731ef21c9c" - integrity sha512-H78M+jcu5Tf6m/5N8iiFblUUv+HJDguMSdFfzwa6vSg9lKR8Mk9BsgeSjO8l2EshKnJKcbv0e8IDDOvSNjl0EA== +"@typescript-eslint/experimental-utils@2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.30.0.tgz#9845e868c01f3aed66472c561d4b6bac44809dd0" + integrity sha512-L3/tS9t+hAHksy8xuorhOzhdefN0ERPDWmR9CclsIGOUqGKy6tqc/P+SoXeJRye5gazkuPO0cK9MQRnolykzkA== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.30.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.30.0.tgz#7681c305a6f4341ae2579f5e3a75846c29eee9ce" + integrity sha512-9kDOxzp0K85UnpmPJqUzdWaCNorYYgk1yZmf4IKzpeTlSAclnFsrLjfwD9mQExctLoLoGAUXq1co+fbr+3HeFw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.29.0" - "@typescript-eslint/typescript-estree" "2.29.0" + "@typescript-eslint/experimental-utils" "2.30.0" + "@typescript-eslint/typescript-estree" "2.30.0" eslint-visitor-keys "^1.1.0" "@typescript-eslint/typescript-estree@2.29.0": @@ -414,6 +424,19 @@ semver "^6.3.0" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.30.0.tgz#1b8e848b55144270255ffbfe4c63291f8f766615" + integrity sha512-nI5WOechrA0qAhnr+DzqwmqHsx7Ulr/+0H7bWCcClDhhWkSyZR5BmTvnBEyONwJCTWHfc5PAQExX24VD26IAVw== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" From a6a5c010fea998ccf9a832f5a506942cd8473c3c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2020 12:46:07 +0000 Subject: [PATCH 105/130] Bump @typescript-eslint/eslint-plugin from 2.29.0 to 2.30.0 Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.29.0 to 2.30.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.30.0/packages/eslint-plugin) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 33 +++++---------------------------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 42da3e704..5a3ff63c3 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@types/utf8": "^2.1.6", "@types/webpack": "^4.41.12", "@types/ws": "^7.2.4", - "@typescript-eslint/eslint-plugin": "^2.29.0", + "@typescript-eslint/eslint-plugin": "^2.30.0", "@typescript-eslint/parser": "^2.30.0", "chai": "^4.2.0", "deep-equal": "^2.0.3", diff --git a/yarn.lock b/yarn.lock index b8326686d..850d5bc4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -371,26 +371,16 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^2.29.0": - version "2.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.29.0.tgz#c9efab7624e3dd6d144a0e4577a541d1bd42c2ac" - integrity sha512-X/YAY7azKirENm4QRpT7OVmzok02cSkqeIcLmdz6gXUQG4Hk0Fi9oBAynSAyNXeGdMRuZvjBa0c1Lu0dn/u6VA== +"@typescript-eslint/eslint-plugin@^2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.30.0.tgz#312a37e80542a764d96e8ad88a105316cdcd7b05" + integrity sha512-PGejii0qIZ9Q40RB2jIHyUpRWs1GJuHP1pkoCiaeicfwO9z7Fx03NQzupuyzAmv+q9/gFNHu7lo1ByMXe8PNyg== dependencies: - "@typescript-eslint/experimental-utils" "2.29.0" + "@typescript-eslint/experimental-utils" "2.30.0" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.29.0": - version "2.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.29.0.tgz#3cb8060de9265ba131625a96bbfec31ba6d4a0fe" - integrity sha512-H/6VJr6eWYstyqjWXBP2Nn1hQJyvJoFdDtsHxGiD+lEP7piGnGpb/ZQd+z1ZSB1F7dN+WsxUDh8+S4LwI+f3jw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.29.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/experimental-utils@2.30.0": version "2.30.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.30.0.tgz#9845e868c01f3aed66472c561d4b6bac44809dd0" @@ -411,19 +401,6 @@ "@typescript-eslint/typescript-estree" "2.30.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.29.0": - version "2.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.29.0.tgz#1be6612bb02fc37ac9f466521c1459a4744e8d3a" - integrity sha512-3YGbtnWy4az16Egy5Fj5CckkVlpIh0MADtAQza+jiMADRSKkjdpzZp/5WuvwK/Qib3Z0HtzrDFeWanS99dNhnA== - dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^6.3.0" - tsutils "^3.17.1" - "@typescript-eslint/typescript-estree@2.30.0": version "2.30.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.30.0.tgz#1b8e848b55144270255ffbfe4c63291f8f766615" From 9567ae4bfee5690b173cdde23031ae69f4728500 Mon Sep 17 00:00:00 2001 From: lunaroyster Date: Thu, 30 Apr 2020 04:35:34 +0000 Subject: [PATCH 106/130] Added @ as a character to pathCharacterSet for xterm-addons-web-links Co-authored-by: lunaroyster Co-authored-by: EricWangUTM --- addons/xterm-addon-web-links/src/WebLinksAddon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-web-links/src/WebLinksAddon.ts b/addons/xterm-addon-web-links/src/WebLinksAddon.ts index 4e700b574..dce405a54 100644 --- a/addons/xterm-addon-web-links/src/WebLinksAddon.ts +++ b/addons/xterm-addon-web-links/src/WebLinksAddon.ts @@ -15,7 +15,7 @@ const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})'; const localHostClause = '(localhost)'; const portClause = '(:\\d{1,5})'; const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; -const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+]*)*([^:"\'\\s])'; +const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+@]*)*([^:"\'\\s])'; const pathClause = '(' + pathCharacterSet + ')?'; const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; From 1c73fd545487b3ccce59237427a4642121ed5dd7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2020 08:01:12 +0000 Subject: [PATCH 107/130] Bump ts-loader from 7.0.1 to 7.0.2 Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/TypeStrong/ts-loader/releases) - [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/TypeStrong/ts-loader/compare/v7.0.1...v7.0.2) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5a3ff63c3..db3aea78d 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "nyc": "^15.0.1", "playwright-core": "^0.11.1", "source-map-loader": "^0.2.4", - "ts-loader": "^7.0.1", + "ts-loader": "^7.0.2", "typescript": "3.8", "utf8": "^3.0.0", "webpack": "^4.43.0", diff --git a/yarn.lock b/yarn.lock index 850d5bc4a..1394e171a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5444,10 +5444,10 @@ triple-beam@^1.2.0, triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-loader@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.1.tgz#ac9ae9eb8f5ebd0aa7b78b44db20691b6e31251b" - integrity sha512-wdGs9xO8UnwASwbluehzXciBtc9HfGlYA8Aiv856etLmdv8mJfAxCkt3YpS4g7G1IsGxaCVKQ102Qh0zycpeZQ== +ts-loader@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.2.tgz#465bc904aea4c331e9550e7c7d75dd17a0b7c24c" + integrity sha512-DwpZFB67RoILQHx42dMjSgv2STpacsQu5X+GD/H9ocd8IhU0m8p3b/ZrIln2KmcucC6xep2PdEMEblpWT71euA== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" From 15df03ba09a3e6779442a388416148790ba5a3ca Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:24:37 +0530 Subject: [PATCH 108/130] clone ligatures addon repo --- addons/xterm-addon-ligatures/.editorconfig | 14 + .../.github/ISSUE_TEMPLATE/bug_report.md | 18 + .../.github/ISSUE_TEMPLATE/feature_request.md | 7 + .../.github/ISSUE_TEMPLATE/question.md | 8 + addons/xterm-addon-ligatures/.gitignore | 13 + addons/xterm-addon-ligatures/.npmignore | 36 + addons/xterm-addon-ligatures/AUTHORS | 1 + .../xterm-addon-ligatures/CODE_OF_CONDUCT.md | 73 + addons/xterm-addon-ligatures/CONTRIBUTING.md | 51 + addons/xterm-addon-ligatures/LICENSE | 21 + addons/xterm-addon-ligatures/README.md | 98 + .../xterm-addon-ligatures/azure-pipelines.yml | 76 + .../bin/download-fonts.js | 70 + addons/xterm-addon-ligatures/package.json | 79 + .../src/LigaturesAddon.ts | 23 + addons/xterm-addon-ligatures/src/font.ts | 48 + .../xterm-addon-ligatures/src/index.test.ts | 220 ++ addons/xterm-addon-ligatures/src/index.ts | 92 + .../xterm-addon-ligatures/src/parse.test.ts | 70 + addons/xterm-addon-ligatures/src/parse.ts | 174 ++ addons/xterm-addon-ligatures/tsconfig.json | 15 + addons/xterm-addon-ligatures/tslint.json | 114 + .../typings/xterm-addon-ligatures.d.ts | 33 + addons/xterm-addon-ligatures/yarn.lock | 2130 +++++++++++++++++ 24 files changed, 3484 insertions(+) create mode 100644 addons/xterm-addon-ligatures/.editorconfig create mode 100644 addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md create mode 100644 addons/xterm-addon-ligatures/.gitignore create mode 100644 addons/xterm-addon-ligatures/.npmignore create mode 100644 addons/xterm-addon-ligatures/AUTHORS create mode 100644 addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md create mode 100644 addons/xterm-addon-ligatures/CONTRIBUTING.md create mode 100644 addons/xterm-addon-ligatures/LICENSE create mode 100644 addons/xterm-addon-ligatures/README.md create mode 100644 addons/xterm-addon-ligatures/azure-pipelines.yml create mode 100644 addons/xterm-addon-ligatures/bin/download-fonts.js create mode 100644 addons/xterm-addon-ligatures/package.json create mode 100644 addons/xterm-addon-ligatures/src/LigaturesAddon.ts create mode 100644 addons/xterm-addon-ligatures/src/font.ts create mode 100644 addons/xterm-addon-ligatures/src/index.test.ts create mode 100644 addons/xterm-addon-ligatures/src/index.ts create mode 100644 addons/xterm-addon-ligatures/src/parse.test.ts create mode 100644 addons/xterm-addon-ligatures/src/parse.ts create mode 100644 addons/xterm-addon-ligatures/tsconfig.json create mode 100644 addons/xterm-addon-ligatures/tslint.json create mode 100644 addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts create mode 100644 addons/xterm-addon-ligatures/yarn.lock diff --git a/addons/xterm-addon-ligatures/.editorconfig b/addons/xterm-addon-ligatures/.editorconfig new file mode 100644 index 000000000..3c486688d --- /dev/null +++ b/addons/xterm-addon-ligatures/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf + +[*.{j,t}s] +max_line_length = 100 + +[*.md] +trim_trailing_whitespace = false diff --git a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..5e82715fb --- /dev/null +++ b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,18 @@ +--- +name: Bug report +about: Create a bug report +--- + + + + +## Details +- Browser and browser and/or electron version: +- OS version: +- xterm.js version: +- xterm-addon-ligatures version: + +### Steps to reproduce + +1. +2. diff --git a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..979f35aa7 --- /dev/null +++ b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,7 @@ +--- +name: Feature request +about: Suggest a feature or enhancement +--- + + + diff --git a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 000000000..10eee3d96 --- /dev/null +++ b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,8 @@ +--- +name: Question +about: The issue tracker is not for questions. Please ask questions on https://stackoverflow.com/questions/tagged/xtermjs or https://gitter.im/sourcelair/xterm.js. +--- + +🛑 The issue tracker is not for questions 🛑 + +If you have a question, please ask it on https://stackoverflow.com/questions/tagged/xtermjs or https://gitter.im/sourcelair/xterm.js. diff --git a/addons/xterm-addon-ligatures/.gitignore b/addons/xterm-addon-ligatures/.gitignore new file mode 100644 index 000000000..2cb99040a --- /dev/null +++ b/addons/xterm-addon-ligatures/.gitignore @@ -0,0 +1,13 @@ +node_modules/ +.nyc_output/ +coverage/ + +lib/ +fonts/ + +.env +.vscode/ +*.swp +*.tgz +npm-debug.log* +yarn-error.log* diff --git a/addons/xterm-addon-ligatures/.npmignore b/addons/xterm-addon-ligatures/.npmignore new file mode 100644 index 000000000..620e71984 --- /dev/null +++ b/addons/xterm-addon-ligatures/.npmignore @@ -0,0 +1,36 @@ +# Blacklist - exclude everything except npm defaults such as LICENSE, etc +* +!*/ + +# Whitelist - entries to be included must be negated with "!" +!*.js +!*.json + +# Whitelist - lib/ +!lib/**/*.d.ts + +!lib/**/*.js +!lib/**/*.js.map + +# Whitelist - src/ +!src/**/*.ts +!src/**/*.d.ts + +!src/**/*.js +!src/**/*.js.map + +# Whitelist - typings/ +!typings/**/*.d.ts + +# Blacklist - (normal behavior) these will override any whitelist +*.test.ts +*.test.d.ts +*.test.js +*.test.js.map + +docs/ +/.idea/ +.vscode/ +coverage/ +.nyc_output/ +fonts/ diff --git a/addons/xterm-addon-ligatures/AUTHORS b/addons/xterm-addon-ligatures/AUTHORS new file mode 100644 index 000000000..c4038fa49 --- /dev/null +++ b/addons/xterm-addon-ligatures/AUTHORS @@ -0,0 +1 @@ +Jeff Principe diff --git a/addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md b/addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..e8ba414b8 --- /dev/null +++ b/addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting [@Tyriar](https://twitter.com/Tyriar) or [@pariskasid](https://twitter.com/pariskasid) on Twitter. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/addons/xterm-addon-ligatures/CONTRIBUTING.md b/addons/xterm-addon-ligatures/CONTRIBUTING.md new file mode 100644 index 000000000..260bb255b --- /dev/null +++ b/addons/xterm-addon-ligatures/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# How to contribute to xterm-addon-ligatures + +- [Opening issues for bug reports or feature requests](#opening-issues) +- [Contributing code](#contributing-code) + +## Opening issues + +The preferred way to report bugs or request features is to use +[GitHub issues](http://github.com/xtermjs/xterm-addon-ligatures/issues). Before +opening an issue, read these pointers. + +### Opening issues effectively + +- Include information about **the browser in which the problem occurred**. Even + if you tested several browsers, and the problem occurred in all of them, + mention this fact in the bug report. Also include browser version numbers and + the operating system that you're on. + +- Mention which release of xterm.js and xterm-addon-ligatures you're using. + Preferably, try also with the current HEAD of the master branch, to ensure the + problem has not already been fixed. + +- Mention precisely what went wrong. What did you expect to happen? What + happened instead? Describe the exact steps a maintainer has to take to make + the problem occur. + +- Be polite. Issues with an indignant or belligerent tone tend to be moved to + the bottom of the pile. + +## Contributing code + +- Make sure you have a [GitHub account](https://github.com/join) +- Fork [xterm-addon-ligatures](https://github.com/xtermjs/xterm-addon-ligatures/) + ([how to fork a repo](https://help.github.com/articles/fork-a-repo)) +- Make your changes +- If your changes are easy to test or likely to regress, add tests. Tests go into corresponding `.test.ts` files. +- Follow the general code style of the rest of the project (see below). +- Submit a pull request +([how to create a pull request](https://help.github.com/articles/fork-a-repo)). + Don't put more than one feature/fix in a single pull request. + +By contributing code to xterm-addon-ligatures you + + - agree to license the contributed code under xterm-addon-ligatures's [MIT + license](LICENSE). + + - confirm that you have the right to contribute and license the code + in question. (Either you hold all rights on the code, or the rights + holder has explicitly granted the right to use it like this, + through a compatible open source license or through a direct + agreement with you.) diff --git a/addons/xterm-addon-ligatures/LICENSE b/addons/xterm-addon-ligatures/LICENSE new file mode 100644 index 000000000..b442934b7 --- /dev/null +++ b/addons/xterm-addon-ligatures/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/xterm-addon-ligatures/README.md b/addons/xterm-addon-ligatures/README.md new file mode 100644 index 000000000..fdf3c9a48 --- /dev/null +++ b/addons/xterm-addon-ligatures/README.md @@ -0,0 +1,98 @@ +# xterm-addon-ligatures + +[![Build Status](https://dev.azure.com/xtermjs/xterm-addon-ligatures/_apis/build/status/xtermjs.xterm-addon-ligatures)](https://dev.azure.com/xtermjs/xterm-addon-ligatures/_build/latest?definitionId=4) +[![Coverage Status](https://coveralls.io/repos/github/xtermjs/xterm-addon-ligatures/badge.svg?branch=refs%2Fheads%2Fmaster)](https://coveralls.io/github/xtermjs/xterm-addon-ligatures?branch=refs%2Fheads%2Fmaster) + +Add support for programming ligatures to [xterm.js][] when running in +environments with access to [Node.js][] APIs (such as [Electron][]). + +## Requirements + + * [Node.js][] 8.x or higher (present in [Electron][] 1.8.3 or higher) + * [xterm.js][] 4.0.0 or higher using the default canvas renderer + +## Usage + +Install in your project by running: + +``` +npm install xterm-addon-ligatures +``` + +Then, modify the location where you initialize the terminal to enable ligature +support after opening. If you enable ligatures prior to opening the terminal, +they will not function properly. + +Your code should look something like this: + +```js +import { Terminal } from 'xterm'; +import * as ligatures from 'xterm-addon-ligatures'; + +Terminal.applyAddon(ligatures); + +const terminal = new Terminal(); +terminal.open(document.getElementById('terminal-mount')); +terminal.enableLigatures(); +``` + +### Importing in TypeScript + +If you use TypeScript, you will need to cast the terminal variable as `any` when +you enable ligatures because TypeScript does not know that the addon is +available on the terminal object. It will look like this: + +```ts +(terminal as any).enableLigatures() +``` + +Alternatively, you can import the addon directly as a function and pass the +terminal as an argument: + +```js +import { Terminal } from 'xterm'; +import { enableLigatures } from 'xterm-addon-ligatures'; + +const terminal = new Terminal(); +terminal.open(document.getElementById('terminal-mount')); +enableLigatures(terminal); +``` + +## How It Works + +In a browser environment, font ligature information is read directly by the web +browser and used to render text correctly without any intervention from the +developer. As of version 3, xterm.js uses the canvas to render characters +individually, resulting in a significant performance boost. However, this means +that it can no longer lean on the browser to determine when to draw font +ligatures. + +This package locates the font file on disk for the font currently in use by the +terminal and parses the ligature information out of it (via the +[font-ligatures][] package). As text is rendered in xterm.js, this package +annotates it with the locations of ligatures, allowing xterm.js to render it +correctly. + +Since this package depends on being able to find and resolve a system font from +disk, it has to have system access that isn't available in the web browser. As a +result, this package is mainly useful in environments that combine browser and +Node.js runtimes (such as [Electron][]). + +## Fonts + +This package makes use of the following fonts for testing: + + * [Fira Code][] - [Licensed under the OFL][Fira Code License] by Nikita + Prokopov, Mozilla Foundation with reserved names Fira Code, Fira Mono, and + Fira Sans + * [Iosevka][] - [Licensed under the OFL][Iosevka License] by Belleve Invis with + reserved name Iosevka + +[xterm.js]: https://github.com/xtermjs/xterm.js +[Electron]: https://electronjs.org/ +[Node.js]: https://nodejs.org/ +[font-ligatures]: https://github.com/princjef/font-ligatures +[Fira Code]: https://github.com/tonsky/FiraCode +[Fira Code License]: https://github.com/tonsky/FiraCode/blob/master/LICENSE +[Iosevka]: https://github.com/be5invis/Iosevka +[Iosevka License]: https://github.com/be5invis/Iosevka/blob/master/LICENSE.md diff --git a/addons/xterm-addon-ligatures/azure-pipelines.yml b/addons/xterm-addon-ligatures/azure-pipelines.yml new file mode 100644 index 000000000..68b6ba2f1 --- /dev/null +++ b/addons/xterm-addon-ligatures/azure-pipelines.yml @@ -0,0 +1,76 @@ +# Node.js +# Build a general Node.js application with npm. +# Add steps that analyze code, save build artifacts, deploy, and more: +# https://docs.microsoft.com/vsts/pipelines/languages/javascript + +jobs: +- job: Linux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: NodeTool@0 + inputs: + versionSpec: '8.x' + displayName: 'Install Node.js' + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.9.4" + displayName: 'Install Yarn' + - script: | + yarn + displayName: 'Install dependencies' + - script: | + yarn build + displayName: 'Build' + - script: | + yarn test + displayName: 'Test' + - script: | + yarn lint + displayName: 'Lint' + - script: | + export COVERALLS_GIT_BRANCH=$BUILD_SOURCEBRANCH + yarn coveralls + displayName: 'Publish coverage' + +- job: macOS + pool: + vmImage: 'xcode9-macos10.13' + steps: + - task: NodeTool@0 + inputs: + versionSpec: '8.x' + displayName: 'Install Node.js' + - script: | + yarn + displayName: 'Install dependencies' + - script: | + yarn build + displayName: 'Build' + - script: | + yarn test + displayName: 'Test' + - script: | + yarn lint + displayName: 'Lint' + +- job: Windows + pool: + vmImage: 'vs2017-win2016' + steps: + - task: NodeTool@0 + inputs: + versionSpec: '8.x' + displayName: 'Install Node.js' + - script: | + yarn + displayName: 'Install dependencies' + - script: | + yarn build + displayName: 'Build' + - script: | + yarn test + displayName: 'Test' + - script: | + yarn lint + displayName: 'Lint' diff --git a/addons/xterm-addon-ligatures/bin/download-fonts.js b/addons/xterm-addon-ligatures/bin/download-fonts.js new file mode 100644 index 000000000..0342f8488 --- /dev/null +++ b/addons/xterm-addon-ligatures/bin/download-fonts.js @@ -0,0 +1,70 @@ +const fs = require('fs'); +const path = require('path'); +const util = require('util'); + +const axios = require('axios').default; +const mkdirp = require('mkdirp'); +const yauzl = require('yauzl'); + +const urls = { + fira: 'https://github.com/tonsky/FiraCode/raw/master/distr/otf/FiraCode-Regular.otf', + iosevka: 'https://github.com/be5invis/Iosevka/releases/download/v1.14.3/01-iosevka-1.14.3.zip' +}; + +const writeFile = util.promisify(fs.writeFile); +const fontsFolder = path.join(__dirname, '../fonts'); + +async function download() { + await mkdirp(fontsFolder); + + await downloadFiraCode(); + await downloadIosevka(); + + console.log('Loaded all fonts for testing') +} + +async function downloadFiraCode() { + const file = path.join(fontsFolder, 'firaCode.otf'); + if (await util.promisify(fs.exists)(file)) { + console.log('Fira Code already loaded'); + } else { + console.log('Downloading Fira Code...'); + await writeFile( + file, + (await axios.get(urls.fira, { responseType: 'arraybuffer' })).data + ); + } +} + +async function downloadIosevka() { + const file = path.join(fontsFolder, 'iosevka.ttf'); + if (await util.promisify(fs.exists)(file)) { + console.log('Iosevka already loaded'); + } else { + console.log('Downloading Iosevka...'); + const iosevkaContents = (await axios.get(urls.iosevka, { responseType: 'arraybuffer' })).data; + const iosevkaZipfile = await util.promisify(yauzl.fromBuffer)(iosevkaContents); + await new Promise((resolve, reject) => { + iosevkaZipfile.on('entry', entry => { + if (entry.fileName === 'ttf/iosevka-regular.ttf') { + iosevkaZipfile.openReadStream(entry, (err, stream) => { + if (err) { + return reject(err); + } + + const writeStream = fs.createWriteStream(file); + stream.pipe(writeStream); + writeStream.on('close', () => resolve()); + }); + } + }); + }); + } +} + +download(); + +process.on('unhandledRejection', e => { + console.error(e); + process.exit(1); +}); diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json new file mode 100644 index 000000000..393ad0770 --- /dev/null +++ b/addons/xterm-addon-ligatures/package.json @@ -0,0 +1,79 @@ +{ + "name": "xterm-addon-ligatures", + "version": "0.2.1", + "description": "Add support for programming ligatures to xterm.js", + "homepage": "https://github.com/xtermjs/xterm-addon-ligatures#readme", + "repository": { + "type": "git", + "url": "https://github.com/xtermjs/xterm-addon-ligatures.git" + }, + "bugs": { + "url": "https://github.com/xtermjs/xterm-addon-ligatures/issues" + }, + "engines": { + "node": ">8.0.0" + }, + "main": "lib/LigaturesAddon.js", + "types": "typings/xterm-addon-ligatures.d.ts", + "scripts": { + "prepare": "node bin/download-fonts.js", + "lint": "tslint --project tsconfig.json --fix", + "prebuild": "npm run lint", + "build": "tsc", + "watch": "tsc -w", + "pretest": "npm run build", + "test": "nyc mocha lib/**/*.test.js", + "coveralls": "nyc report --reporter=text-lcov | coveralls", + "prepublish": "npm run build" + }, + "keywords": [ + "font", + "ligature", + "xterm", + "xterm.js", + "terminal" + ], + "license": "MIT", + "dependencies": { + "font-finder": "^1.0.4", + "font-ligatures": "^1.3.2" + }, + "devDependencies": { + "@types/chai": "^4.1.3", + "@types/mocha": "^5.2.0", + "@types/node": "^8.10.10", + "@types/sinon": "^5.0.1", + "axios": "^0.18.0", + "chai": "^4.1.2", + "coveralls": "^3.0.2", + "mkdirp": "^0.5.1", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.1.3", + "tslint": "^5.9.1", + "tslint-consistent-codestyle": "^1.13.0", + "typescript": "^2.8.3", + "xterm": "^3.6.0", + "yauzl": "^2.10.0" + }, + "peerDependencies": { + "xterm": "^4.0.0" + }, + "nyc": { + "sourceMap": true, + "reporter": [ + "text", + "html", + "json" + ], + "include": [ + "lib/**/*.js" + ], + "exclude": [ + "lib/**/*.test.*", + "lib/**/*.integration.*", + "lib/**/*.d.ts", + "lib/**/*.map*" + ] + } +} diff --git a/addons/xterm-addon-ligatures/src/LigaturesAddon.ts b/addons/xterm-addon-ligatures/src/LigaturesAddon.ts new file mode 100644 index 000000000..c19bf2f81 --- /dev/null +++ b/addons/xterm-addon-ligatures/src/LigaturesAddon.ts @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { Terminal } from 'xterm'; +import { enableLigatures } from '.'; + +export interface ITerminalAddon { + activate(terminal: Terminal): void; + dispose(): void; +} + +export class LigaturesAddon implements ITerminalAddon { + constructor() {} + + public activate(terminal: Terminal): void { + enableLigatures(terminal); + } + + public dispose(): void {} +} + diff --git a/addons/xterm-addon-ligatures/src/font.ts b/addons/xterm-addon-ligatures/src/font.ts new file mode 100644 index 000000000..00b0a157b --- /dev/null +++ b/addons/xterm-addon-ligatures/src/font.ts @@ -0,0 +1,48 @@ +import * as fontFinder from 'font-finder'; +import * as fontLigatures from 'font-ligatures'; + +import parse from './parse'; + +let fontsPromise: Promise | undefined = undefined; + +/** + * Loads the font ligature wrapper for the specified font family if it could be + * resolved, throwing if it is unable to find a suitable match. + * @param fontFamily The CSS font family definition to resolve + * @param cacheSize The size of the ligature cache to maintain if the font is resolved + */ +export default async function load(fontFamily: string, cacheSize: number): Promise { + if (!fontsPromise) { + fontsPromise = fontFinder.list(); + } + + const fonts = await fontsPromise; + for (const family of parse(fontFamily)) { + // If we reach one of the generic font families, the font resolution + // will end for the browser and we can't determine the specific font + // used. Throw. + if (genericFontFamilies.includes(family)) { + return undefined; + } + + if (fonts.hasOwnProperty(family) && fonts[family].length > 0) { + return await fontLigatures.loadFile(fonts[family][0].path, { cacheSize }); + } + } + + // If none of the fonts could resolve, throw an error + return undefined; +} + +// https://drafts.csswg.org/css-fonts-4/#generic-font-families +const genericFontFamilies = [ + 'serif', + 'sans-serif', + 'cursive', + 'fantasy', + 'monospace', + 'system-ui', + 'emoji', + 'math', + 'fangsong' +]; diff --git a/addons/xterm-addon-ligatures/src/index.test.ts b/addons/xterm-addon-ligatures/src/index.test.ts new file mode 100644 index 000000000..fba564ce2 --- /dev/null +++ b/addons/xterm-addon-ligatures/src/index.test.ts @@ -0,0 +1,220 @@ +import * as path from 'path'; +import * as sinon from 'sinon'; +import { assert } from 'chai'; +import * as fontFinder from 'font-finder'; +import * as fontLigatures from 'font-ligatures'; + +import * as ligatureSupport from '.'; + +describe('xterm-addon-ligatures', () => { + let onRefresh: sinon.SinonStub; + let term: MockTerminal; + + // -> forms a ligature in Fira Code and Iosevka, but www only forms a ligature + // in Fira Code + const input = 'a -> b www c'; + + before(() => { + sinon.stub(fontFinder, 'list').returns(Promise.resolve({ + 'Fira Code': [{ + path: path.join(__dirname, '../fonts/firaCode.otf'), + style: fontFinder.Style.Regular, + type: fontFinder.Type.Monospace, + weight: 400 + }], + 'Iosevka': [{ + path: path.join(__dirname, '../fonts/iosevka.ttf'), + style: fontFinder.Style.Regular, + type: fontFinder.Type.Monospace, + weight: 400 + }], + 'Nonexistant Font': [{ + path: path.join(__dirname, '../fonts/nonexistant.ttf'), + style: fontFinder.Style.Regular, + type: fontFinder.Type.Monospace, + weight: 400 + }] + } as fontFinder.FontList)); + }); + + beforeEach(() => { + MockTerminal.applyAddon(ligatureSupport); + onRefresh = sinon.stub(); + term = new MockTerminal(onRefresh); + (term as any).enableLigatures(); + }); + + it('registers itself correctly', () => { + MockTerminal.applyAddon(ligatureSupport); + const term = new MockTerminal(sinon.spy()); + assert.isUndefined(term.joiner); + (term as any).enableLigatures(); + assert.isFunction(term.joiner); + }); + + it('registers itself correctly when called directly', () => { + const term = new MockTerminal(sinon.spy()); + assert.isUndefined(term.joiner); + ligatureSupport.enableLigatures(term as any); + assert.isFunction(term.joiner); + }); + + it('returns an empty set of ranges on the first call while the font is loading', () => { + assert.deepEqual(term.joiner!(input), []); + }); + + it('returns the correct set of ranges once the font has loaded', done => { + assert.deepEqual(term.joiner!(input), []); + onRefresh.callsFake(() => { + assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); + done(); + }); + }); + + it('handles quoted font names', done => { + term.setOption('fontFamily', '"Fira Code", monospace'); + assert.deepEqual(term.joiner!(input), []); + onRefresh.callsFake(() => { + assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); + done(); + }); + }); + + it('falls back to later fonts if earlier ones are not present', done => { + term.setOption('fontFamily', 'notinstalled, Fira Code, monospace'); + assert.deepEqual(term.joiner!(input), []); + onRefresh.callsFake(() => { + assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); + done(); + }); + }); + + it('uses the current font value', done => { + // The first three calls are all synchronous so that we don't allow time for + // any fonts to load while we're switching things around + term.setOption('fontFamily', 'Fira Code'); + assert.deepEqual(term.joiner!(input), []); + term.setOption('fontFamily', 'notinstalled'); + assert.deepEqual(term.joiner!(input), []); + term.setOption('fontFamily', 'Iosevka'); + assert.deepEqual(term.joiner!(input), []); + onRefresh.callsFake(() => { + assert.deepEqual(term.joiner!(input), [[2, 4]]); + + // And switch it back to Fira Code for good measure + term.setOption('fontFamily', 'Fira Code'); + + // At this point, we haven't loaded the new font, so the result reverts + // back to empty until that happens + assert.deepEqual(term.joiner!(input), []); + + onRefresh.callsFake(() => { + assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); + done(); + }); + }); + }); + + it('allows multiple terminal instances that use different fonts', done => { + const onRefresh2 = sinon.stub(); + const term2 = new MockTerminal(onRefresh2); + term2.setOption('fontFamily', 'Iosevka'); + (term2 as any).enableLigatures(); + + assert.deepEqual(term.joiner!(input), []); + onRefresh.callsFake(() => { + assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); + assert.deepEqual(term2.joiner!(input), []); + onRefresh2.callsFake(() => { + assert.deepEqual(term2.joiner!(input), [[2, 4]]); + assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); + done(); + }); + }); + }); + + it('fails if it finds but cannot load the font', async () => { + term.setOption('fontFamily', 'Nonexistant Font, monospace'); + assert.deepEqual(term.joiner!(input), []); + await delay(500); + assert.isTrue(onRefresh.notCalled); + assert.throws(() => term.joiner!(input)); + }); + + it('returns nothing if the font is not present on the system', async () => { + term.setOption('fontFamily', 'notinstalled'); + assert.deepEqual(term.joiner!(input), []); + await delay(500); + assert.isTrue(onRefresh.notCalled); + assert.deepEqual(term.joiner!(input), []); + }); + + it('returns nothing if no specific font is specified', async () => { + term.setOption('fontFamily', 'monospace'); + assert.deepEqual(term.joiner!(input), []); + await delay(500); + assert.isTrue(onRefresh.notCalled); + assert.deepEqual(term.joiner!(input), []); + }); + + it('returns nothing if no fonts are provided', async () => { + term.setOption('fontFamily', ''); + assert.deepEqual(term.joiner!(input), []); + await delay(500); + assert.isTrue(onRefresh.notCalled); + assert.deepEqual(term.joiner!(input), []); + }); + + it('fails when given malformed inputs', async () => { + term.setOption('fontFamily', {} as any); + assert.deepEqual(term.joiner!(input), []); + await delay(500); + assert.isTrue(onRefresh.notCalled); + assert.throws(() => term.joiner!(input)); + }); + + it('ensures no empty errors are thrown', async () => { + sinon.stub(fontLigatures, 'loadFile').callsFake(async () => { throw undefined; }); + term.setOption('fontFamily', 'Iosevka'); + assert.deepEqual(term.joiner!(input), []); + await delay(500); + assert.isTrue(onRefresh.notCalled); + assert.throws(() => term.joiner!(input), 'Failure while loading font'); + (fontLigatures.loadFile as sinon.SinonStub).restore(); + }); +}); + +class MockTerminal { + static applyAddon(addon: any): void { + addon.apply(MockTerminal); + } + + private _options: { [name: string]: string | number; } = { + fontFamily: 'Fira Code, monospace', + rows: 50 + }; + joiner?: (text: string) => [number, number][]; + refresh: (start: number, end: number) => void; + + constructor(onRefresh: (start: number, end: number) => void) { + this.refresh = onRefresh; + } + + registerCharacterJoiner(handler: (text: string) => [number, number][]): number { + this.joiner = handler; + return 1; + } + deregisterCharacterJoiner(id: number): void { + this.joiner = undefined; + } + setOption(name: string, value: string | number): void { + this._options[name] = value; + } + getOption(name: string): string | number { + return this._options[name]; + } +} + +function delay(delayMs: number): Promise { + return new Promise(resolve => setTimeout(resolve, delayMs)); +} diff --git a/addons/xterm-addon-ligatures/src/index.ts b/addons/xterm-addon-ligatures/src/index.ts new file mode 100644 index 000000000..c828abcba --- /dev/null +++ b/addons/xterm-addon-ligatures/src/index.ts @@ -0,0 +1,92 @@ +import { Terminal } from 'xterm'; +import { Font } from 'font-ligatures'; + +import load from './font'; + +const enum LoadingState { + UNLOADED, + LOADING, + LOADED, + FAILED +} + +// Caches 100K characters worth of ligatures. In practice this works out to +// about 650 KB worth of cache, when a moderate number of ligatures are present. +const CACHE_SIZE = 100000; + +/** + * Enable ligature support for the provided Terminal instance. To function + * properly, this must be called after `open()` is called on the therminal. If + * the font currently in use supports ligatures, the terminal will automatically + * start to render them. + * @param term Terminal instance from xterm.js + */ +export function enableLigatures(term: Terminal): void { + let currentFontName: string | undefined = undefined; + let font: Font | undefined = undefined; + let loadingState: LoadingState = LoadingState.UNLOADED; + let loadError: any | undefined = undefined; + + term.registerCharacterJoiner((text: string): [number, number][] => { + // If the font hasn't been loaded yet, load it and return an empty result + const termFont = term.getOption('fontFamily'); + if ( + termFont && + (loadingState === LoadingState.UNLOADED || currentFontName !== termFont) + ) { + font = undefined; + loadingState = LoadingState.LOADING; + currentFontName = termFont; + const currentCallFontName = currentFontName; + + load(currentCallFontName, CACHE_SIZE) + .then(f => { + // Another request may have come in while we were waiting, so make + // sure our font is still vaild. + if (currentCallFontName === term.getOption('fontFamily')) { + loadingState = LoadingState.LOADED; + font = f; + + // Only refresh things if we actually found a font + if (f) { + term.refresh(0, term.getOption('rows') - 1); + } + } + }) + .catch(e => { + // Another request may have come in while we were waiting, so make + // sure our font is still vaild. + if (currentCallFontName === term.getOption('fontFamily')) { + loadingState = LoadingState.FAILED; + font = undefined; + loadError = e; + } + }); + } + + if (font && loadingState === LoadingState.LOADED) { + // We clone the entries to avoid the internal cache of the ligature finder + // getting messed up. + return font.findLigatureRanges(text).map<[number, number]>( + range => [range[0], range[1]] + ); + } else if (loadingState === LoadingState.FAILED) { + throw loadError || new Error('Failure while loading font'); + } + + return []; + }); +} + +/** + * Add capabilities to the provided terminal class for enabling ligature + * support. After calling this function, an `enableLigatures()` method is + * available on the terminal class, which will enable ligature support when + * called. + * @param terminalConstructor Terminal class from xterm.js + */ +export function apply(terminalConstructor: typeof Terminal): void { + (terminalConstructor.prototype).enableLigatures = function (): void { + enableLigatures(this); + }; +} diff --git a/addons/xterm-addon-ligatures/src/parse.test.ts b/addons/xterm-addon-ligatures/src/parse.test.ts new file mode 100644 index 000000000..bdaf096db --- /dev/null +++ b/addons/xterm-addon-ligatures/src/parse.test.ts @@ -0,0 +1,70 @@ +import { assert } from 'chai'; + +import parse from './parse'; + +// TODO: integrate tests from http://test.csswg.org/suites/css-fonts-4_dev/nightly-unstable/ +describe('parse', () => { + it('parses individual families', () => { + assert.deepEqual(parse('monospace'), ['monospace']); + }); + + it('parses multiple families', () => { + assert.deepEqual(parse('Arial, Verdana, serif'), ['Arial', 'Verdana', 'serif']); + }); + + it('parses quoted families', () => { + assert.deepEqual(parse('"Times New Roman", serif'), ['Times New Roman', 'serif']); + }); + + it('parses single quoted families', () => { + assert.deepEqual(parse('\'Times New Roman\', serif'), ['Times New Roman', 'serif']); + }); + + it('parses families with spaces in their names', () => { + assert.deepEqual(parse('Times New Roman, serif'), ['Times New Roman', 'serif']); + }); + + it('collapses multiple spaces together in identifiers', () => { + assert.deepEqual(parse('Times New Roman, serif'), ['Times New Roman', 'serif']); + }); + + it('does not collapse multiple spaces together in quoted strings', () => { + assert.deepEqual(parse('"Times New Roman", serif'), ['Times New Roman', 'serif']); + }); + + it('handles escaped characters in strings', () => { + assert.deepEqual(parse('"quote \\" slash \\\\ slashquote \\\\\\"", serif'), ['quote " slash \\ slashquote \\"', 'serif']); + }); + + it('fails if a family has an unterminated string', () => { + assert.throws(() => parse('"Unterminated, serif')); + }); + + it('handles unicode escape sequences', () => { + assert.deepEqual(parse('"space\\20 between", serif'), ['space between', 'serif']); + }); + + it('swallows only the first space after a unicode escape', () => { + assert.deepEqual(parse('"two-space\\20 between", serif'), ['two-space between', 'serif']); + }); + + it('automatically ends the unicode escape after six digits', () => { + assert.deepEqual(parse('space\\000020between, serif'), ['space between', 'serif']); + }); + + it('handles unicode escapes at the end of the family', () => { + assert.deepEqual(parse('endswithbrace \\7b, serif'), ['endswithbrace {', 'serif']); + }); + + it('handles unicode escapes at the end of the input', () => { + assert.deepEqual(parse('endswithbrace \\7b'), ['endswithbrace {']); + }); + + it('handles other escaped characters in identifiers', () => { + assert.deepEqual(parse('has\\,comma'), ['has,comma']); + }); + + it('swallows escaped newlines in strings', () => { + assert.deepEqual(parse('"multi \\\nline", serif'), ['multi line', 'serif']); + }); +}); diff --git a/addons/xterm-addon-ligatures/src/parse.ts b/addons/xterm-addon-ligatures/src/parse.ts new file mode 100644 index 000000000..c6ec05347 --- /dev/null +++ b/addons/xterm-addon-ligatures/src/parse.ts @@ -0,0 +1,174 @@ +interface IParseContext { + input: string; + offset: number; +} + +/** + * Parses a CSS font family value, returning the component font families + * contained within. + * + * @param family The CSS font family input string to parse + */ +export default function parse(family: string): string[] { + if (typeof family !== 'string') { + throw new Error('Font family must be a string'); + } + + const context: IParseContext = { + input: family, + offset: 0 + }; + + const families = []; + let currentFamily = ''; + + // Work through the input character by character until there are none left. + // This lexing and parsing in one pass. + while (context.offset < context.input.length) { + const char = context.input[context.offset++]; + switch (char) { + // String + case '\'': + case '"': + currentFamily += parseString(context, char); + break; + // End of family + case ',': + families.push(currentFamily); + currentFamily = ''; + break; + default: + // Identifiers (whitespace between families is swallowed) + if (!/\s/.test(char)) { + context.offset--; + currentFamily += parseIdentifier(context); + families.push(currentFamily); + currentFamily = ''; + } + } + } + + return families; +} + +/** + * Parse a CSS string. + * + * @param context Parsing input and offset + * @param quoteChar The quote character for the string (' or ") + */ +function parseString(context: IParseContext, quoteChar: '\'' | '"'): string { + let str = ''; + let escaped = false; + while (context.offset < context.input.length) { + const char = context.input[context.offset++]; + if (escaped) { + if (/[0-9a-fA-F]/.test(char)) { + // Unicode escape + context.offset--; + str += parseUnicode(context); + } else if (char !== '\n') { + // Newlines are ignored if escaped. Other characters are used as is. + str += char; + } + escaped = false; + } else { + switch (char) { + // Terminated quote + case quoteChar: + return str; + // Begin escape + case '\\': + escaped = true; + break; + // Add character to string + default: + str += char; + } + } + } + + throw new Error('Unterminated string'); +} + +/** + * Parse a CSS custom identifier. + * + * @param context Parsing input and offset + */ +function parseIdentifier(context: IParseContext): string { + let str = ''; + let escaped = false; + while (context.offset < context.input.length) { + const char = context.input[context.offset++]; + if (escaped) { + if (/[0-9a-fA-F]/.test(char)) { + // Unicode escape + context.offset--; + str += parseUnicode(context); + } else { + // Everything else is used as is + str += char; + } + escaped = false; + } else { + switch (char) { + // Begin escape + case '\\': + escaped = true; + break; + // Terminate identifier + case ',': + return str; + default: + if (/\s/.test(char)) { + // Whitespace is collapsed into a single space within an identifier + if (!str.endsWith(' ')) { + str += ' '; + } + } else { + // Add other characters directly + str += char; + } + } + } + } + + return str; +} + +/** + * Parse a CSS unicode escape. + * + * @param context Parsing input and offset + */ +function parseUnicode(context: IParseContext): string { + let str = ''; + while (context.offset < context.input.length) { + const char = context.input[context.offset++]; + if (/\s/.test(char)) { + // The first whitespace character after a unicode escape indicates the end + // of the escape and is swallowed. + return unicodeToString(str); + } else if (str.length >= 6 || !/[0-9a-fA-F]/.test(char)) { + // If the next character is not a valid hex digit or we have reached the + // maximum of 6 digits in the escape, terminate the escape. + context.offset--; + return unicodeToString(str); + } + + // Otherwise, just add it to the escape + str += char; + } + + return unicodeToString(str); +} + +/** + * Convert a unicode code point from a hex string to a utf8 string. + * + * @param codePoint Unicode code point represented as a hex string + */ +function unicodeToString(codePoint: string): string { + return String.fromCodePoint(parseInt(codePoint, 16)); +} diff --git a/addons/xterm-addon-ligatures/tsconfig.json b/addons/xterm-addon-ligatures/tsconfig.json new file mode 100644 index 000000000..a549d790e --- /dev/null +++ b/addons/xterm-addon-ligatures/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs", + "sourceMap": true, + "outDir": "lib", + "rootDir": "src", + "strict": true, + "noUnusedLocals": true, + "preserveWatchOutput": true + }, + "include": [ + "src" + ] +} diff --git a/addons/xterm-addon-ligatures/tslint.json b/addons/xterm-addon-ligatures/tslint.json new file mode 100644 index 000000000..7fc3311d9 --- /dev/null +++ b/addons/xterm-addon-ligatures/tslint.json @@ -0,0 +1,114 @@ +{ + "rulesDirectory": [ + "tslint-consistent-codestyle" + ], + "rules": { + "array-type": [ + true, + "array" + ], + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": [ + true, + "ignore-same-line" + ], + "indent": [ + true, + "spaces" + ], + "interface-name": [ + true, + "always-prefix" + ], + "interface-over-type-literal": true, + "typedef": [ + true, + "call-signature", + "parameter" + ], + "eofline": true, + "new-parens": true, + "no-duplicate-imports": true, + "no-eval": true, + "no-internal-module": true, + "no-trailing-whitespace": true, + "one-variable-per-declaration": true, + "no-unsafe-finally": true, + "no-var-keyword": true, + "quotemark": [ + true, + "single" + ], + "semicolon": [ + true, + "always" + ], + "trailing-comma": [ + true, + { + "multiline": { + "objects": "never", + "arrays": "never", + "functions": "never", + "typeLiterals": "ignore" + }, + "esSpecCompliant": true + } + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": [ + true, + "ban-keywords", + "check-format", + "allow-leading-underscore" + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-module", + "check-operator", + "check-rest-spread", + "check-separator", + "check-type", + "check-type-operator", + "check-preblock" + ], + + "naming-convention": [ + true, + {"type": "default", "format": "camelCase", "leadingUnderscore": "forbid"}, + {"type": "type", "format": "PascalCase"}, + {"type": "class", "format": "PascalCase"}, + {"type": "property", "modifiers": ["const"], "format": "UPPER_CASE"}, + {"type": "member", "modifiers": ["protected"], "format": "camelCase", "leadingUnderscore": "require"}, + {"type": "member", "modifiers": ["private"], "format": "camelCase", "leadingUnderscore": "require"}, + {"type": "variable", "modifiers": ["const"], "format": ["camelCase", "UPPER_CASE"]}, + {"type": "interface", "prefix": "I"} + ], + "no-else-after-return": { + "options": "allow-else-if" + }, + "prefer-const-enum": [ + true + ], + "prefer-const": true + } +} diff --git a/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts b/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts new file mode 100644 index 000000000..7d66fb03c --- /dev/null +++ b/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts @@ -0,0 +1,33 @@ +/** + * @license MIT + * + * This contains the type declarations for the xterm-addon-ligatures library. + * Note that some interfaces may differ between this file and the actual + * implementation in src/, that's because this file declares the *public* API + * which is intended to be stable and consumed by external programs. + */ + +import { Terminal, ILinkMatcherOptions, ITerminalAddon } from 'xterm'; + +declare module 'xterm-addon-ligatures' { + /** + * An xterm.js addon that enables web links. + */ + export class LigaturesAddon implements ITerminalAddon { + /** + * Creates a new ligatures addon. + */ + constructor(); + + /** + * Activates the addon + * @param terminal The terminal the addon is being loaded in. + */ + public activate(terminal: Terminal): void; + + /** + * Disposes the addon. + */ + public dispose(): void; + } +} diff --git a/addons/xterm-addon-ligatures/yarn.lock b/addons/xterm-addon-ligatures/yarn.lock new file mode 100644 index 000000000..7af4956e8 --- /dev/null +++ b/addons/xterm-addon-ligatures/yarn.lock @@ -0,0 +1,2130 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz#bd71d9b192af978df915829d39d4094456439a0c" + dependencies: + "@babel/highlight" "7.0.0-beta.51" + +"@babel/generator@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.51.tgz#6c7575ffde761d07485e04baedc0392c6d9e30f6" + dependencies: + "@babel/types" "7.0.0-beta.51" + jsesc "^2.5.1" + lodash "^4.17.5" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@babel/helper-function-name@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.51.tgz#21b4874a227cf99ecafcc30a90302da5a2640561" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.51" + "@babel/template" "7.0.0-beta.51" + "@babel/types" "7.0.0-beta.51" + +"@babel/helper-get-function-arity@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.51.tgz#3281b2d045af95c172ce91b20825d85ea4676411" + dependencies: + "@babel/types" "7.0.0-beta.51" + +"@babel/helper-split-export-declaration@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.51.tgz#8a6c3f66c4d265352fc077484f9f6e80a51ab978" + dependencies: + "@babel/types" "7.0.0-beta.51" + +"@babel/highlight@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.51.tgz#e8844ae25a1595ccfd42b89623b4376ca06d225d" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/parser@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.51.tgz#27cec2df409df60af58270ed8f6aa55409ea86f6" + +"@babel/template@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.51.tgz#9602a40aebcf357ae9677e2532ef5fc810f5fbff" + dependencies: + "@babel/code-frame" "7.0.0-beta.51" + "@babel/parser" "7.0.0-beta.51" + "@babel/types" "7.0.0-beta.51" + lodash "^4.17.5" + +"@babel/traverse@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.51.tgz#981daf2cec347a6231d3aa1d9e1803b03aaaa4a8" + dependencies: + "@babel/code-frame" "7.0.0-beta.51" + "@babel/generator" "7.0.0-beta.51" + "@babel/helper-function-name" "7.0.0-beta.51" + "@babel/helper-split-export-declaration" "7.0.0-beta.51" + "@babel/parser" "7.0.0-beta.51" + "@babel/types" "7.0.0-beta.51" + debug "^3.1.0" + globals "^11.1.0" + invariant "^2.2.0" + lodash "^4.17.5" + +"@babel/types@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.51.tgz#d802b7b543b5836c778aa691797abf00f3d97ea9" + dependencies: + esutils "^2.0.2" + lodash "^4.17.5" + to-fast-properties "^2.0.0" + +"@fimbul/bifrost@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.11.0.tgz#83cacc21464198b12e3cc1c2204ae6c6d7afd158" + dependencies: + "@fimbul/ymir" "^0.11.0" + get-caller-file "^1.0.2" + tslib "^1.8.1" + tsutils "^2.24.0" + +"@fimbul/ymir@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@fimbul/ymir/-/ymir-0.11.0.tgz#892a01997f1f80c7e4e437cf5ca51c95994c136f" + dependencies: + inversify "^4.10.0" + reflect-metadata "^0.1.12" + tslib "^1.8.1" + +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + +"@sinonjs/samsam@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.0.0.tgz#9163742ac35c12d3602dece74317643b35db6a80" + +"@types/chai@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.4.tgz#5ca073b330d90b4066d6ce18f60d57f2084ce8ca" + +"@types/mocha@^5.2.0": + version "5.2.4" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.4.tgz#2f8fbdf95c69ebf82150a7864864010f186745bf" + +"@types/node@^8.10.10": + version "8.10.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.21.tgz#12b3f2359b27aa05a45d886c8ba1eb8d1a77e285" + +"@types/sinon@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.1.tgz#a15b36ec42f1f53166617491feabd1734cb03e21" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +append-transform@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" + dependencies: + default-require-extensions "^1.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assertion-error@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + +axios@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +caching-transform@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" + dependencies: + md5-hex "^1.2.0" + mkdirp "^0.5.1" + write-file-atomic "^1.1.4" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chai@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" + dependencies: + assertion-error "^1.0.1" + check-error "^1.0.1" + deep-eql "^3.0.0" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +check-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +combined-stream@1.0.6, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + +commander@^2.12.1: + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" + +commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +coveralls@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" + dependencies: + growl "~> 1.10.0" + js-yaml "^3.11.0" + lcov-parse "^0.0.10" + log-driver "^1.2.7" + minimist "^1.2.0" + request "^2.85.0" + +cross-spawn@^4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug-log@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" + +debug@3.1.0, debug@=3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +deep-eql@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + dependencies: + type-detect "^4.0.0" + +default-require-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" + dependencies: + strip-bom "^2.0.0" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +diff@3.5.0, diff@^3.2.0, diff@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + dependencies: + pend "~1.2.0" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + dependencies: + debug "=3.1.0" + +font-finder@^1.0.3, font-finder@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/font-finder/-/font-finder-1.0.4.tgz#2ca944954dd8d0e1b5bdc4c596cc08607761d89b" + dependencies: + get-system-fonts "^2.0.0" + promise-stream-reader "^1.0.1" + +font-ligatures@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/font-ligatures/-/font-ligatures-1.3.2.tgz#227eb5fc38fef34b5373aa19b555320b82842a71" + dependencies: + font-finder "^1.0.3" + lru-cache "^4.1.3" + opentype.js "^0.8.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +foreground-child@^1.5.3, foreground-child@^1.5.6: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +get-caller-file@^1.0.1, get-caller-file@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +get-system-fonts@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-system-fonts/-/get-system-fonts-2.0.0.tgz#a43b9a33f05c0715a60176d2aad5ce6e98f0a3c6" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob@7.1.2, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.7.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growl@1.10.5, "growl@~> 1.10.0": + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + +handlebars@^4.0.11: + version "4.5.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + +hosted-git-info@^2.1.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +invariant@^2.2.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + dependencies: + loose-envify "^1.0.0" + +inversify@^4.10.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.13.0.tgz#0ab40570bfa4474b04d5b919bbab3a4f682a72f5" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-buffer@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" + +istanbul-lib-coverage@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda" + +istanbul-lib-hook@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b" + dependencies: + append-transform "^0.4.0" + +istanbul-lib-instrument@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-2.3.1.tgz#406406730a395acb2e50f0d98137ace16bd4a970" + dependencies: + "@babel/generator" "7.0.0-beta.51" + "@babel/parser" "7.0.0-beta.51" + "@babel/template" "7.0.0-beta.51" + "@babel/traverse" "7.0.0-beta.51" + "@babel/types" "7.0.0-beta.51" + istanbul-lib-coverage "^2.0.1" + semver "^5.5.0" + +istanbul-lib-report@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz#2df12188c0fa77990c0d2176d2d0ba3394188259" + dependencies: + istanbul-lib-coverage "^1.1.2" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1" + dependencies: + debug "^3.1.0" + istanbul-lib-coverage "^1.2.0" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + +istanbul-reports@^1.4.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.0.tgz#c6c2867fa65f59eb7dcedb7f845dfc76aaee70f9" + dependencies: + handlebars "^4.0.11" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + +js-yaml@^3.11.0, js-yaml@^3.7.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +just-extend@^1.1.27: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +lcov-parse@^0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + +lodash@^4.17.5: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + +lolex@^2.3.2, lolex@^2.4.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.1.tgz#e40a8c4d1f14b536aa03e42a537c7adbaf0c20be" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^4.0.1, lru-cache@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + +md5-hex@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" + dependencies: + md5-o-matic "^0.1.1" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + dependencies: + source-map "^0.6.1" + +micromatch@^3.1.10, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-types@^2.1.12, mime-types@~2.1.17: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + dependencies: + mime-db "~1.35.0" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +neo-async@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + +nise@^1.3.3: + version "1.4.2" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.2.tgz#a9a3800e3994994af9e452333d549d60f72b8e8c" + dependencies: + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +nyc@^12.0.2: + version "12.0.2" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-12.0.2.tgz#8a4a4ed690966c11ec587ff87eea0c12c974ba99" + dependencies: + archy "^1.0.0" + arrify "^1.0.1" + caching-transform "^1.0.0" + convert-source-map "^1.5.1" + debug-log "^1.0.1" + default-require-extensions "^1.0.0" + find-cache-dir "^0.1.1" + find-up "^2.1.0" + foreground-child "^1.5.3" + glob "^7.0.6" + istanbul-lib-coverage "^1.2.0" + istanbul-lib-hook "^1.1.0" + istanbul-lib-instrument "^2.1.0" + istanbul-lib-report "^1.1.3" + istanbul-lib-source-maps "^1.2.5" + istanbul-reports "^1.4.1" + md5-hex "^1.2.0" + merge-source-map "^1.1.0" + micromatch "^3.1.10" + mkdirp "^0.5.0" + resolve-from "^2.0.0" + rimraf "^2.6.2" + signal-exit "^3.0.1" + spawn-wrap "^1.4.2" + test-exclude "^4.2.0" + yargs "11.1.0" + yargs-parser "^8.0.0" + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +opentype.js@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/opentype.js/-/opentype.js-0.8.0.tgz#acabcfa1642fbe894a3e4d759e43ba694e02bd35" + dependencies: + tiny-inflate "^1.0.2" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +promise-stream-reader@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-stream-reader/-/promise-stream-reader-1.0.1.tgz#4e793a79c9d49a73ccd947c6da9c127f12923649" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +reflect-metadata@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +request@^2.85.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +resolve@^1.3.2: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + dependencies: + path-parse "^1.0.5" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + +rimraf@^2.6.1, rimraf@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +samsam@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +sinon@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-6.1.3.tgz#98e7d716b7b11f7f1200e9c997e74f50ae094660" + dependencies: + "@sinonjs/formatio" "^2.0.0" + "@sinonjs/samsam" "^2.0.0" + diff "^3.5.0" + lodash.get "^4.4.2" + lolex "^2.4.2" + nise "^1.3.3" + supports-color "^5.4.0" + type-detect "^4.0.8" + +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +spawn-wrap@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" + dependencies: + foreground-child "^1.5.6" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.6.2" + signal-exit "^3.0.2" + which "^1.3.0" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +supports-color@5.4.0, supports-color@^5.3.0, supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +test-exclude@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" + dependencies: + arrify "^1.0.1" + micromatch "^3.1.8" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + +tiny-inflate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.2.tgz#93d9decffc8805bd57eae4310f0b745e9b6fb3a7" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + +tslint-consistent-codestyle@^1.13.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.13.2.tgz#c60662f08a83d62797e47e5d74737470b5e17714" + dependencies: + "@fimbul/bifrost" "^0.11.0" + tslib "^1.7.1" + tsutils "^2.27.0" + +tslint@^5.9.1: + version "5.10.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" + dependencies: + babel-code-frame "^6.22.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^3.2.0" + glob "^7.1.1" + js-yaml "^3.7.0" + minimatch "^3.0.4" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.12.1" + +tsutils@^2.12.1, tsutils@^2.24.0, tsutils@^2.27.0: + version "2.27.2" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.2.tgz#60ba88a23d6f785ec4b89c6e8179cac9b431f1c7" + dependencies: + tslib "^1.8.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-detect@^4.0.0, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + +typescript@^2.8.3: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + +uglify-js@^3.1.4: + version "3.7.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" + dependencies: + commander "~2.20.3" + source-map "~0.6.1" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" + dependencies: + kind-of "^6.0.2" + +uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@^1.2.9, which@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + dependencies: + isexe "^2.0.0" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^1.1.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +xterm@^3.6.0: + version "3.8.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.8.1.tgz#0beabaccdc23bd3ab2397c5129ed9b06b0abb167" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + dependencies: + camelcase "^4.1.0" + +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + dependencies: + camelcase "^4.1.0" + +yargs@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" From dcca79baef36948d76db600ef7cd0f8f7d1c5ca5 Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:24:47 +0530 Subject: [PATCH 109/130] delete non-required files --- addons/xterm-addon-ligatures/.editorconfig | 14 --- .../.github/ISSUE_TEMPLATE/bug_report.md | 18 --- .../.github/ISSUE_TEMPLATE/feature_request.md | 7 -- .../.github/ISSUE_TEMPLATE/question.md | 8 -- addons/xterm-addon-ligatures/AUTHORS | 1 - .../xterm-addon-ligatures/CODE_OF_CONDUCT.md | 73 ----------- addons/xterm-addon-ligatures/CONTRIBUTING.md | 51 -------- addons/xterm-addon-ligatures/tslint.json | 114 ------------------ 8 files changed, 286 deletions(-) delete mode 100644 addons/xterm-addon-ligatures/.editorconfig delete mode 100644 addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md delete mode 100644 addons/xterm-addon-ligatures/AUTHORS delete mode 100644 addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md delete mode 100644 addons/xterm-addon-ligatures/CONTRIBUTING.md delete mode 100644 addons/xterm-addon-ligatures/tslint.json diff --git a/addons/xterm-addon-ligatures/.editorconfig b/addons/xterm-addon-ligatures/.editorconfig deleted file mode 100644 index 3c486688d..000000000 --- a/addons/xterm-addon-ligatures/.editorconfig +++ /dev/null @@ -1,14 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true -end_of_line = lf - -[*.{j,t}s] -max_line_length = 100 - -[*.md] -trim_trailing_whitespace = false diff --git a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 5e82715fb..000000000 --- a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: Bug report -about: Create a bug report ---- - - - - -## Details -- Browser and browser and/or electron version: -- OS version: -- xterm.js version: -- xterm-addon-ligatures version: - -### Steps to reproduce - -1. -2. diff --git a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 979f35aa7..000000000 --- a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: Feature request -about: Suggest a feature or enhancement ---- - - - diff --git a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md b/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 10eee3d96..000000000 --- a/addons/xterm-addon-ligatures/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: Question -about: The issue tracker is not for questions. Please ask questions on https://stackoverflow.com/questions/tagged/xtermjs or https://gitter.im/sourcelair/xterm.js. ---- - -🛑 The issue tracker is not for questions 🛑 - -If you have a question, please ask it on https://stackoverflow.com/questions/tagged/xtermjs or https://gitter.im/sourcelair/xterm.js. diff --git a/addons/xterm-addon-ligatures/AUTHORS b/addons/xterm-addon-ligatures/AUTHORS deleted file mode 100644 index c4038fa49..000000000 --- a/addons/xterm-addon-ligatures/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Jeff Principe diff --git a/addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md b/addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md deleted file mode 100644 index e8ba414b8..000000000 --- a/addons/xterm-addon-ligatures/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,73 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, race, -religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting [@Tyriar](https://twitter.com/Tyriar) or [@pariskasid](https://twitter.com/pariskasid) on Twitter. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org diff --git a/addons/xterm-addon-ligatures/CONTRIBUTING.md b/addons/xterm-addon-ligatures/CONTRIBUTING.md deleted file mode 100644 index 260bb255b..000000000 --- a/addons/xterm-addon-ligatures/CONTRIBUTING.md +++ /dev/null @@ -1,51 +0,0 @@ -# How to contribute to xterm-addon-ligatures - -- [Opening issues for bug reports or feature requests](#opening-issues) -- [Contributing code](#contributing-code) - -## Opening issues - -The preferred way to report bugs or request features is to use -[GitHub issues](http://github.com/xtermjs/xterm-addon-ligatures/issues). Before -opening an issue, read these pointers. - -### Opening issues effectively - -- Include information about **the browser in which the problem occurred**. Even - if you tested several browsers, and the problem occurred in all of them, - mention this fact in the bug report. Also include browser version numbers and - the operating system that you're on. - -- Mention which release of xterm.js and xterm-addon-ligatures you're using. - Preferably, try also with the current HEAD of the master branch, to ensure the - problem has not already been fixed. - -- Mention precisely what went wrong. What did you expect to happen? What - happened instead? Describe the exact steps a maintainer has to take to make - the problem occur. - -- Be polite. Issues with an indignant or belligerent tone tend to be moved to - the bottom of the pile. - -## Contributing code - -- Make sure you have a [GitHub account](https://github.com/join) -- Fork [xterm-addon-ligatures](https://github.com/xtermjs/xterm-addon-ligatures/) - ([how to fork a repo](https://help.github.com/articles/fork-a-repo)) -- Make your changes -- If your changes are easy to test or likely to regress, add tests. Tests go into corresponding `.test.ts` files. -- Follow the general code style of the rest of the project (see below). -- Submit a pull request -([how to create a pull request](https://help.github.com/articles/fork-a-repo)). - Don't put more than one feature/fix in a single pull request. - -By contributing code to xterm-addon-ligatures you - - - agree to license the contributed code under xterm-addon-ligatures's [MIT - license](LICENSE). - - - confirm that you have the right to contribute and license the code - in question. (Either you hold all rights on the code, or the rights - holder has explicitly granted the right to use it like this, - through a compatible open source license or through a direct - agreement with you.) diff --git a/addons/xterm-addon-ligatures/tslint.json b/addons/xterm-addon-ligatures/tslint.json deleted file mode 100644 index 7fc3311d9..000000000 --- a/addons/xterm-addon-ligatures/tslint.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "rulesDirectory": [ - "tslint-consistent-codestyle" - ], - "rules": { - "array-type": [ - true, - "array" - ], - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "curly": [ - true, - "ignore-same-line" - ], - "indent": [ - true, - "spaces" - ], - "interface-name": [ - true, - "always-prefix" - ], - "interface-over-type-literal": true, - "typedef": [ - true, - "call-signature", - "parameter" - ], - "eofline": true, - "new-parens": true, - "no-duplicate-imports": true, - "no-eval": true, - "no-internal-module": true, - "no-trailing-whitespace": true, - "one-variable-per-declaration": true, - "no-unsafe-finally": true, - "no-var-keyword": true, - "quotemark": [ - true, - "single" - ], - "semicolon": [ - true, - "always" - ], - "trailing-comma": [ - true, - { - "multiline": { - "objects": "never", - "arrays": "never", - "functions": "never", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true - } - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "variable-name": [ - true, - "ban-keywords", - "check-format", - "allow-leading-underscore" - ], - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-module", - "check-operator", - "check-rest-spread", - "check-separator", - "check-type", - "check-type-operator", - "check-preblock" - ], - - "naming-convention": [ - true, - {"type": "default", "format": "camelCase", "leadingUnderscore": "forbid"}, - {"type": "type", "format": "PascalCase"}, - {"type": "class", "format": "PascalCase"}, - {"type": "property", "modifiers": ["const"], "format": "UPPER_CASE"}, - {"type": "member", "modifiers": ["protected"], "format": "camelCase", "leadingUnderscore": "require"}, - {"type": "member", "modifiers": ["private"], "format": "camelCase", "leadingUnderscore": "require"}, - {"type": "variable", "modifiers": ["const"], "format": ["camelCase", "UPPER_CASE"]}, - {"type": "interface", "prefix": "I"} - ], - "no-else-after-return": { - "options": "allow-else-if" - }, - "prefer-const-enum": [ - true - ], - "prefer-const": true - } -} From fb65cea1153ec4a185712bfa73cd89d4dc5ba802 Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:24:57 +0530 Subject: [PATCH 110/130] set up similar to other addons --- addons/xterm-addon-ligatures/.npmignore | 8 ++++---- addons/xterm-addon-ligatures/package.json | 20 +++++++++---------- .../{ => src}/tsconfig.json | 7 ++++--- 3 files changed, 17 insertions(+), 18 deletions(-) rename addons/xterm-addon-ligatures/{ => src}/tsconfig.json (68%) diff --git a/addons/xterm-addon-ligatures/.npmignore b/addons/xterm-addon-ligatures/.npmignore index 620e71984..298e0b7b0 100644 --- a/addons/xterm-addon-ligatures/.npmignore +++ b/addons/xterm-addon-ligatures/.npmignore @@ -6,11 +6,11 @@ !*.js !*.json -# Whitelist - lib/ -!lib/**/*.d.ts +# Whitelist - out/ +!out/**/*.d.ts -!lib/**/*.js -!lib/**/*.js.map +!out/**/*.js +!out/**/*.js.map # Whitelist - src/ !src/**/*.ts diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index 393ad0770..474dd2fc9 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -13,16 +13,14 @@ "engines": { "node": ">8.0.0" }, - "main": "lib/LigaturesAddon.js", + "main": "out/LigaturesAddon.js", "types": "typings/xterm-addon-ligatures.d.ts", "scripts": { "prepare": "node bin/download-fonts.js", - "lint": "tslint --project tsconfig.json --fix", - "prebuild": "npm run lint", - "build": "tsc", - "watch": "tsc -w", + "build": "tsc -p src", + "watch": "tsc -w -p src", "pretest": "npm run build", - "test": "nyc mocha lib/**/*.test.js", + "test": "nyc mocha out/**/*.test.js", "coveralls": "nyc report --reporter=text-lcov | coveralls", "prepublish": "npm run build" }, @@ -67,13 +65,13 @@ "json" ], "include": [ - "lib/**/*.js" + "out/**/*.js" ], "exclude": [ - "lib/**/*.test.*", - "lib/**/*.integration.*", - "lib/**/*.d.ts", - "lib/**/*.map*" + "out/**/*.test.*", + "out/**/*.integration.*", + "out/**/*.d.ts", + "out/**/*.map*" ] } } diff --git a/addons/xterm-addon-ligatures/tsconfig.json b/addons/xterm-addon-ligatures/src/tsconfig.json similarity index 68% rename from addons/xterm-addon-ligatures/tsconfig.json rename to addons/xterm-addon-ligatures/src/tsconfig.json index a549d790e..fc6ab2085 100644 --- a/addons/xterm-addon-ligatures/tsconfig.json +++ b/addons/xterm-addon-ligatures/src/tsconfig.json @@ -3,13 +3,14 @@ "target": "es2017", "module": "commonjs", "sourceMap": true, - "outDir": "lib", - "rootDir": "src", + "outDir": "../out", + "rootDir": ".", "strict": true, "noUnusedLocals": true, "preserveWatchOutput": true }, "include": [ - "src" + "./**/*", + "../../../typings/xterm.d.ts" ] } From ef4ecf7c8e0d6a693f0413488755dc6b92f2a24b Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:25:07 +0530 Subject: [PATCH 111/130] clean up dev dependencies --- addons/xterm-addon-ligatures/package.json | 10 - addons/xterm-addon-ligatures/yarn.lock | 1640 +-------------------- 2 files changed, 8 insertions(+), 1642 deletions(-) diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index 474dd2fc9..fe99f6cc2 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -37,21 +37,11 @@ "font-ligatures": "^1.3.2" }, "devDependencies": { - "@types/chai": "^4.1.3", - "@types/mocha": "^5.2.0", - "@types/node": "^8.10.10", "@types/sinon": "^5.0.1", "axios": "^0.18.0", - "chai": "^4.1.2", "coveralls": "^3.0.2", "mkdirp": "^0.5.1", - "mocha": "^5.2.0", - "nyc": "^12.0.2", "sinon": "^6.1.3", - "tslint": "^5.9.1", - "tslint-consistent-codestyle": "^1.13.0", - "typescript": "^2.8.3", - "xterm": "^3.6.0", "yauzl": "^2.10.0" }, "peerDependencies": { diff --git a/addons/xterm-addon-ligatures/yarn.lock b/addons/xterm-addon-ligatures/yarn.lock index 7af4956e8..ec68a6aa6 100644 --- a/addons/xterm-addon-ligatures/yarn.lock +++ b/addons/xterm-addon-ligatures/yarn.lock @@ -2,103 +2,6 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz#bd71d9b192af978df915829d39d4094456439a0c" - dependencies: - "@babel/highlight" "7.0.0-beta.51" - -"@babel/generator@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.51.tgz#6c7575ffde761d07485e04baedc0392c6d9e30f6" - dependencies: - "@babel/types" "7.0.0-beta.51" - jsesc "^2.5.1" - lodash "^4.17.5" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/helper-function-name@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.51.tgz#21b4874a227cf99ecafcc30a90302da5a2640561" - dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.51" - "@babel/template" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - -"@babel/helper-get-function-arity@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.51.tgz#3281b2d045af95c172ce91b20825d85ea4676411" - dependencies: - "@babel/types" "7.0.0-beta.51" - -"@babel/helper-split-export-declaration@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.51.tgz#8a6c3f66c4d265352fc077484f9f6e80a51ab978" - dependencies: - "@babel/types" "7.0.0-beta.51" - -"@babel/highlight@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.51.tgz#e8844ae25a1595ccfd42b89623b4376ca06d225d" - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" - -"@babel/parser@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.51.tgz#27cec2df409df60af58270ed8f6aa55409ea86f6" - -"@babel/template@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.51.tgz#9602a40aebcf357ae9677e2532ef5fc810f5fbff" - dependencies: - "@babel/code-frame" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - lodash "^4.17.5" - -"@babel/traverse@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.51.tgz#981daf2cec347a6231d3aa1d9e1803b03aaaa4a8" - dependencies: - "@babel/code-frame" "7.0.0-beta.51" - "@babel/generator" "7.0.0-beta.51" - "@babel/helper-function-name" "7.0.0-beta.51" - "@babel/helper-split-export-declaration" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - debug "^3.1.0" - globals "^11.1.0" - invariant "^2.2.0" - lodash "^4.17.5" - -"@babel/types@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.51.tgz#d802b7b543b5836c778aa691797abf00f3d97ea9" - dependencies: - esutils "^2.0.2" - lodash "^4.17.5" - to-fast-properties "^2.0.0" - -"@fimbul/bifrost@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.11.0.tgz#83cacc21464198b12e3cc1c2204ae6c6d7afd158" - dependencies: - "@fimbul/ymir" "^0.11.0" - get-caller-file "^1.0.2" - tslib "^1.8.1" - tsutils "^2.24.0" - -"@fimbul/ymir@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@fimbul/ymir/-/ymir-0.11.0.tgz#892a01997f1f80c7e4e437cf5ca51c95994c136f" - dependencies: - inversify "^4.10.0" - reflect-metadata "^0.1.12" - tslib "^1.8.1" - "@sinonjs/formatio@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" @@ -109,18 +12,6 @@ version "2.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.0.0.tgz#9163742ac35c12d3602dece74317643b35db6a80" -"@types/chai@^4.1.3": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.4.tgz#5ca073b330d90b4066d6ce18f60d57f2084ce8ca" - -"@types/mocha@^5.2.0": - version "5.2.4" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.4.tgz#2f8fbdf95c69ebf82150a7864864010f186745bf" - -"@types/node@^8.10.10": - version "8.10.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.21.tgz#12b3f2359b27aa05a45d886c8ba1eb8d1a77e285" - "@types/sinon@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.1.tgz#a15b36ec42f1f53166617491feabd1734cb03e21" @@ -134,60 +25,12 @@ ajv@^5.1.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" - -append-transform@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - dependencies: - default-require-extensions "^1.0.0" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -198,22 +41,10 @@ assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" -assertion-error@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -atob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -229,213 +60,30 @@ axios@^0.18.0: follow-redirects "1.5.10" is-buffer "^2.0.2" -babel-code-frame@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" dependencies: tweetnacl "^0.14.3" -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" -builtin-modules@^1.0.0, builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -caching-transform@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" - dependencies: - md5-hex "^1.2.0" - mkdirp "^0.5.1" - write-file-atomic "^1.1.4" - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" -chai@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" - dependencies: - assertion-error "^1.0.1" - check-error "^1.0.1" - deep-eql "^3.0.0" - get-func-name "^2.0.0" - pathval "^1.0.0" - type-detect "^4.0.0" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -check-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" - dependencies: - color-name "1.1.1" - -color-name@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" - combined-stream@1.0.6, combined-stream@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - -commander@^2.12.1: - version "2.16.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" - -commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - -component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -convert-source-map@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -451,87 +99,23 @@ coveralls@^3.0.2: minimist "^1.2.0" request "^2.85.0" -cross-spawn@^4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" -debug-log@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" - -debug@3.1.0, debug@=3.1.0, debug@^3.1.0: +debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" -debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" - -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - -deep-eql@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - dependencies: - type-detect "^4.0.0" - -default-require-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - dependencies: - strip-bom "^2.0.0" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" -diff@3.5.0, diff@^3.2.0, diff@^3.5.0: +diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -542,78 +126,14 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - dependencies: - is-arrayish "^0.2.1" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@~3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -636,36 +156,6 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - follow-redirects@1.5.10: version "1.5.10" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" @@ -687,17 +177,6 @@ font-ligatures@^1.3.2: lru-cache "^4.1.3" opentype.js "^0.8.0" -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -foreground-child@^1.5.3, foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -710,75 +189,20 @@ form-data@~2.3.1: combined-stream "1.0.6" mime-types "^2.1.12" -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - dependencies: - map-cache "^0.2.2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -get-caller-file@^1.0.1, get-caller-file@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - get-system-fonts@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-system-fonts/-/get-system-fonts-2.0.0.tgz#a43b9a33f05c0715a60176d2aad5ce6e98f0a3c6" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" dependencies: assert-plus "^1.0.0" -glob@7.1.2, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.7.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -growl@1.10.5, "growl@~> 1.10.0": +"growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" -handlebars@^4.0.11: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -790,55 +214,10 @@ har-validator@~5.0.3: ajv "^5.1.0" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - -hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -847,227 +226,23 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -invariant@^2.2.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - dependencies: - loose-envify "^1.0.0" - -inversify@^4.10.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.13.0.tgz#0ab40570bfa4474b04d5b919bbab3a4f682a72f5" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - is-buffer@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - dependencies: - is-plain-object "^2.0.4" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - dependencies: - isobject "^3.0.1" - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" - -istanbul-lib-coverage@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda" - -istanbul-lib-hook@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b" - dependencies: - append-transform "^0.4.0" - -istanbul-lib-instrument@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-2.3.1.tgz#406406730a395acb2e50f0d98137ace16bd4a970" - dependencies: - "@babel/generator" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/template" "7.0.0-beta.51" - "@babel/traverse" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - istanbul-lib-coverage "^2.0.1" - semver "^5.5.0" - -istanbul-lib-report@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz#2df12188c0fa77990c0d2176d2d0ba3394188259" - dependencies: - istanbul-lib-coverage "^1.1.2" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" - -istanbul-lib-source-maps@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1" - dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^1.2.0" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" - -istanbul-reports@^1.4.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.0.tgz#c6c2867fa65f59eb7dcedb7f845dfc76aaee70f9" - dependencies: - handlebars "^4.0.11" - -js-tokens@^3.0.0, js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - -js-yaml@^3.11.0, js-yaml@^3.7.0: +js-yaml@^3.11.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" dependencies: @@ -1078,10 +253,6 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" -jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" @@ -1107,61 +278,14 @@ just-extend@^1.1.27: version "1.1.27" resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" -lodash@^4.17.5: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" @@ -1170,69 +294,13 @@ lolex@^2.3.2, lolex@^2.4.2: version "2.7.1" resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.1.tgz#e40a8c4d1f14b536aa03e42a537c7adbaf0c20be" -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^4.0.1, lru-cache@^4.1.3: +lru-cache@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" dependencies: pseudomap "^1.0.2" yallist "^2.1.2" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - dependencies: - object-visit "^1.0.0" - -md5-hex@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" - dependencies: - md5-o-matic "^0.1.1" - -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - dependencies: - mimic-fn "^1.0.0" - -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - dependencies: - source-map "^0.6.1" - -micromatch@^3.1.10, micromatch@^3.1.8: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - mime-db@~1.35.0: version "1.35.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" @@ -1243,16 +311,6 @@ mime-types@^2.1.12, mime-types@~2.1.17: dependencies: mime-db "~1.35.0" -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -1261,63 +319,16 @@ minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - nise@^1.3.3: version "1.4.2" resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.2.tgz#a9a3800e3994994af9e452333d549d60f72b8e8c" @@ -1328,186 +339,22 @@ nise@^1.3.3: path-to-regexp "^1.7.0" text-encoding "^0.6.4" -normalize-package-data@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - dependencies: - path-key "^2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -nyc@^12.0.2: - version "12.0.2" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-12.0.2.tgz#8a4a4ed690966c11ec587ff87eea0c12c974ba99" - dependencies: - archy "^1.0.0" - arrify "^1.0.1" - caching-transform "^1.0.0" - convert-source-map "^1.5.1" - debug-log "^1.0.1" - default-require-extensions "^1.0.0" - find-cache-dir "^0.1.1" - find-up "^2.1.0" - foreground-child "^1.5.3" - glob "^7.0.6" - istanbul-lib-coverage "^1.2.0" - istanbul-lib-hook "^1.1.0" - istanbul-lib-instrument "^2.1.0" - istanbul-lib-report "^1.1.3" - istanbul-lib-source-maps "^1.2.5" - istanbul-reports "^1.4.1" - md5-hex "^1.2.0" - merge-source-map "^1.1.0" - micromatch "^3.1.10" - mkdirp "^0.5.0" - resolve-from "^2.0.0" - rimraf "^2.6.2" - signal-exit "^3.0.1" - spawn-wrap "^1.4.2" - test-exclude "^4.2.0" - yargs "11.1.0" - yargs-parser "^8.0.0" - oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - dependencies: - isobject "^3.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - dependencies: - isobject "^3.0.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - opentype.js@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/opentype.js/-/opentype.js-0.8.0.tgz#acabcfa1642fbe894a3e4d759e43ba694e02bd35" dependencies: tiny-inflate "^1.0.2" -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - dependencies: - p-try "^1.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - path-to-regexp@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" dependencies: isarray "0.0.1" -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pathval@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -1516,30 +363,6 @@ performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - promise-stream-reader@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-stream-reader/-/promise-stream-reader-1.0.1.tgz#4e793a79c9d49a73ccd947c6da9c127f12923649" @@ -1556,40 +379,6 @@ qs@~6.5.1: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -reflect-metadata@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - request@^2.85.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" @@ -1615,48 +404,10 @@ request@^2.85.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - -resolve@^1.3.2: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - dependencies: - path-parse "^1.0.5" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - -rimraf@^2.6.1, rimraf@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - dependencies: - glob "^7.0.5" - safe-buffer@^5.0.1, safe-buffer@^5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - dependencies: - ret "~0.1.10" - safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -1665,46 +416,6 @@ samsam@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - -signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - sinon@^6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/sinon/-/sinon-6.1.3.tgz#98e7d716b7b11f7f1200e9c997e74f50ae094660" @@ -1718,98 +429,6 @@ sinon@^6.1.3: supports-color "^5.4.0" type-detect "^4.0.8" -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - -spawn-wrap@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" - dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.6.2" - signal-exit "^3.0.2" - which "^1.3.0" - -spdx-correct@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -1829,76 +448,12 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - -supports-color@5.4.0, supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" dependencies: has-flag "^3.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.1.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - dependencies: - has-flag "^1.0.0" - -test-exclude@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" - dependencies: - arrify "^1.0.1" - micromatch "^3.1.8" - object-assign "^4.1.0" - read-pkg-up "^1.0.1" - require-main-filename "^1.0.1" - text-encoding@^0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" @@ -1907,77 +462,12 @@ tiny-inflate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.2.tgz#93d9decffc8805bd57eae4310f0b745e9b6fb3a7" -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - tough-cookie@~2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1" -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - -tslint-consistent-codestyle@^1.13.0: - version "1.13.2" - resolved "https://registry.yarnpkg.com/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.13.2.tgz#c60662f08a83d62797e47e5d74737470b5e17714" - dependencies: - "@fimbul/bifrost" "^0.11.0" - tslib "^1.7.1" - tsutils "^2.27.0" - -tslint@^5.9.1: - version "5.10.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" - dependencies: - babel-code-frame "^6.22.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^3.2.0" - glob "^7.1.1" - js-yaml "^3.7.0" - minimatch "^3.0.4" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.8.0" - tsutils "^2.12.1" - -tsutils@^2.12.1, tsutils@^2.24.0, tsutils@^2.27.0: - version "2.27.2" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.2.tgz#60ba88a23d6f785ec4b89c6e8179cac9b431f1c7" - dependencies: - tslib "^1.8.1" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -1988,58 +478,14 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -type-detect@^4.0.0, type-detect@^4.0.8: +type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" -typescript@^2.8.3: - version "2.9.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" - -uglify-js@^3.1.4: - version "3.7.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" - dependencies: - commander "~2.20.3" - source-map "~0.6.1" - -union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - -use@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" - dependencies: - kind-of "^6.0.2" - uuid@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" -validate-npm-package-license@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -2048,80 +494,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - -which@^1.2.9, which@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - dependencies: - isexe "^2.0.0" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write-file-atomic@^1.1.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -xterm@^3.6.0: - version "3.8.1" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.8.1.tgz#0beabaccdc23bd3ab2397c5129ed9b06b0abb167" - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" -yargs-parser@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - dependencies: - camelcase "^4.1.0" - -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - dependencies: - camelcase "^4.1.0" - -yargs@11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From c818381ef1bf6b5030eb47ac69939e770df34edf Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:25:17 +0530 Subject: [PATCH 112/130] add ligatures addon config --- .eslintrc.json | 6 ++++-- bin/publish.js | 1 + tsconfig.all.json | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 32f8e9927..64d997697 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -18,12 +18,14 @@ "addons/xterm-addon-web-links/src/tsconfig.json", "addons/xterm-addon-webgl/src/tsconfig.json", "addons/xterm-addon-serialize/src/tsconfig.json", - "addons/xterm-addon-serialize/benchmark/tsconfig.json" + "addons/xterm-addon-serialize/benchmark/tsconfig.json", + "addons/xterm-addon-ligatures/src/tsconfig.json" ], "sourceType": "module" }, "ignorePatterns": [ - "**/typings/*.d.ts" + "**/typings/*.d.ts", + "**/node_modules" ], "plugins": [ "@typescript-eslint" diff --git a/bin/publish.js b/bin/publish.js index 88e4d0c0b..fd0015d64 100644 --- a/bin/publish.js +++ b/bin/publish.js @@ -28,6 +28,7 @@ if (changedFiles.some(e => e.search(/^addons\//) === -1)) { const addonPackageDirs = [ path.resolve(__dirname, '../addons/xterm-addon-attach'), path.resolve(__dirname, '../addons/xterm-addon-fit'), + path.resolve(__dirname, '../addons/xterm-addon-ligatures'), path.resolve(__dirname, '../addons/xterm-addon-search'), path.resolve(__dirname, '../addons/xterm-addon-serialize'), path.resolve(__dirname, '../addons/xterm-addon-unicode11'), diff --git a/tsconfig.all.json b/tsconfig.all.json index a8febb72a..98b4e97ba 100644 --- a/tsconfig.all.json +++ b/tsconfig.all.json @@ -12,6 +12,7 @@ { "path": "./addons/xterm-addon-web-links/src" }, { "path": "./addons/xterm-addon-webgl/src" }, { "path": "./addons/xterm-addon-serialize/src" }, - { "path": "./addons/xterm-addon-serialize/benchmark" } + { "path": "./addons/xterm-addon-serialize/benchmark" }, + { "path": "./addons/xterm-addon-ligatures/src" } ] } From 4702a0af9d5cd5ad1d15fc6ad55fe2ea08e1f00f Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:25:27 +0530 Subject: [PATCH 113/130] lint --- .../xterm-addon-ligatures/src/index.test.ts | 19 +++++++++++-------- addons/xterm-addon-ligatures/src/index.ts | 3 ++- addons/xterm-addon-ligatures/src/parse.ts | 3 ++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/addons/xterm-addon-ligatures/src/index.test.ts b/addons/xterm-addon-ligatures/src/index.test.ts index fba564ce2..2763ddb94 100644 --- a/addons/xterm-addon-ligatures/src/index.test.ts +++ b/addons/xterm-addon-ligatures/src/index.test.ts @@ -16,18 +16,21 @@ describe('xterm-addon-ligatures', () => { before(() => { sinon.stub(fontFinder, 'list').returns(Promise.resolve({ + // eslint-disable-next-line @typescript-eslint/naming-convention 'Fira Code': [{ path: path.join(__dirname, '../fonts/firaCode.otf'), style: fontFinder.Style.Regular, type: fontFinder.Type.Monospace, weight: 400 }], + // eslint-disable-next-line @typescript-eslint/naming-convention 'Iosevka': [{ path: path.join(__dirname, '../fonts/iosevka.ttf'), style: fontFinder.Style.Regular, type: fontFinder.Type.Monospace, weight: 400 }], + // eslint-disable-next-line @typescript-eslint/naming-convention 'Nonexistant Font': [{ path: path.join(__dirname, '../fonts/nonexistant.ttf'), style: fontFinder.Style.Regular, @@ -185,32 +188,32 @@ describe('xterm-addon-ligatures', () => { }); class MockTerminal { - static applyAddon(addon: any): void { + public static applyAddon(addon: any): void { addon.apply(MockTerminal); } - private _options: { [name: string]: string | number; } = { + private _options: { [name: string]: string | number } = { fontFamily: 'Fira Code, monospace', rows: 50 }; - joiner?: (text: string) => [number, number][]; - refresh: (start: number, end: number) => void; + public joiner?: (text: string) => [number, number][]; + public refresh: (start: number, end: number) => void; constructor(onRefresh: (start: number, end: number) => void) { this.refresh = onRefresh; } - registerCharacterJoiner(handler: (text: string) => [number, number][]): number { + public registerCharacterJoiner(handler: (text: string) => [number, number][]): number { this.joiner = handler; return 1; } - deregisterCharacterJoiner(id: number): void { + public deregisterCharacterJoiner(id: number): void { this.joiner = undefined; } - setOption(name: string, value: string | number): void { + public setOption(name: string, value: string | number): void { this._options[name] = value; } - getOption(name: string): string | number { + public getOption(name: string): string | number { return this._options[name]; } } diff --git a/addons/xterm-addon-ligatures/src/index.ts b/addons/xterm-addon-ligatures/src/index.ts index c828abcba..88b71d99e 100644 --- a/addons/xterm-addon-ligatures/src/index.ts +++ b/addons/xterm-addon-ligatures/src/index.ts @@ -70,7 +70,8 @@ export function enableLigatures(term: Terminal): void { return font.findLigatureRanges(text).map<[number, number]>( range => [range[0], range[1]] ); - } else if (loadingState === LoadingState.FAILED) { + } + if (loadingState === LoadingState.FAILED) { throw loadError || new Error('Failure while loading font'); } diff --git a/addons/xterm-addon-ligatures/src/parse.ts b/addons/xterm-addon-ligatures/src/parse.ts index c6ec05347..e26abfd97 100644 --- a/addons/xterm-addon-ligatures/src/parse.ts +++ b/addons/xterm-addon-ligatures/src/parse.ts @@ -150,7 +150,8 @@ function parseUnicode(context: IParseContext): string { // The first whitespace character after a unicode escape indicates the end // of the escape and is swallowed. return unicodeToString(str); - } else if (str.length >= 6 || !/[0-9a-fA-F]/.test(char)) { + } + if (str.length >= 6 || !/[0-9a-fA-F]/.test(char)) { // If the next character is not a valid hex digit or we have reached the // maximum of 6 digits in the escape, terminate the escape. context.offset--; From 7bde7039bb5305c8dcd630cd1a7cd76920e3b058 Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:25:38 +0530 Subject: [PATCH 114/130] add webpack config --- addons/xterm-addon-ligatures/.npmignore | 12 +++++++ addons/xterm-addon-ligatures/package.json | 10 +++--- .../xterm-addon-ligatures/webpack.config.js | 32 +++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 addons/xterm-addon-ligatures/webpack.config.js diff --git a/addons/xterm-addon-ligatures/.npmignore b/addons/xterm-addon-ligatures/.npmignore index 298e0b7b0..9f4fec9a1 100644 --- a/addons/xterm-addon-ligatures/.npmignore +++ b/addons/xterm-addon-ligatures/.npmignore @@ -6,6 +6,12 @@ !*.js !*.json +# Whitelist - lib/ +!lib/**/*.d.ts + +!lib/**/*.js +!lib/**/*.js.map + # Whitelist - out/ !out/**/*.d.ts @@ -34,3 +40,9 @@ docs/ coverage/ .nyc_output/ fonts/ + +**/*.api.js +**/*.api.ts +tsconfig.json +.yarnrc +webpack.config.js diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index fe99f6cc2..1e34d1a35 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -13,16 +13,18 @@ "engines": { "node": ">8.0.0" }, - "main": "out/LigaturesAddon.js", + "main": "lib/xterm-addon-ligatures.js", "types": "typings/xterm-addon-ligatures.d.ts", "scripts": { "prepare": "node bin/download-fonts.js", - "build": "tsc -p src", - "watch": "tsc -w -p src", + "build": "../../node_modules/.bin/tsc -p src", + "watch": "../../node_modules/.bin/tsc -w -p src", + "prepackage": "npm run build", + "package": "../../node_modules/.bin/webpack", "pretest": "npm run build", "test": "nyc mocha out/**/*.test.js", "coveralls": "nyc report --reporter=text-lcov | coveralls", - "prepublish": "npm run build" + "prepublish": "npm run package" }, "keywords": [ "font", diff --git a/addons/xterm-addon-ligatures/webpack.config.js b/addons/xterm-addon-ligatures/webpack.config.js new file mode 100644 index 000000000..819256fb5 --- /dev/null +++ b/addons/xterm-addon-ligatures/webpack.config.js @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +const path = require('path'); + +const addonName = 'LigaturesAddon'; +const mainFile = 'xterm-addon-ligatures.js'; + +module.exports = { + entry: `./out/${addonName}.js`, + devtool: 'source-map', + target: 'electron-renderer', + module: { + rules: [ + { + test: /\.js$/, + use: ["source-map-loader"], + enforce: "pre", + exclude: /node_modules/ + } + ] + }, + output: { + filename: mainFile, + path: path.resolve('./lib'), + library: addonName, + libraryTarget: 'umd' + }, + mode: 'production' +}; From 42b88f34f4f115bd402fc92c1be179faf6f5c2f5 Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:25:48 +0530 Subject: [PATCH 115/130] remove azure devops config --- .../xterm-addon-ligatures/azure-pipelines.yml | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 addons/xterm-addon-ligatures/azure-pipelines.yml diff --git a/addons/xterm-addon-ligatures/azure-pipelines.yml b/addons/xterm-addon-ligatures/azure-pipelines.yml deleted file mode 100644 index 68b6ba2f1..000000000 --- a/addons/xterm-addon-ligatures/azure-pipelines.yml +++ /dev/null @@ -1,76 +0,0 @@ -# Node.js -# Build a general Node.js application with npm. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/vsts/pipelines/languages/javascript - -jobs: -- job: Linux - pool: - vmImage: 'ubuntu-16.04' - steps: - - task: NodeTool@0 - inputs: - versionSpec: '8.x' - displayName: 'Install Node.js' - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.9.4" - displayName: 'Install Yarn' - - script: | - yarn - displayName: 'Install dependencies' - - script: | - yarn build - displayName: 'Build' - - script: | - yarn test - displayName: 'Test' - - script: | - yarn lint - displayName: 'Lint' - - script: | - export COVERALLS_GIT_BRANCH=$BUILD_SOURCEBRANCH - yarn coveralls - displayName: 'Publish coverage' - -- job: macOS - pool: - vmImage: 'xcode9-macos10.13' - steps: - - task: NodeTool@0 - inputs: - versionSpec: '8.x' - displayName: 'Install Node.js' - - script: | - yarn - displayName: 'Install dependencies' - - script: | - yarn build - displayName: 'Build' - - script: | - yarn test - displayName: 'Test' - - script: | - yarn lint - displayName: 'Lint' - -- job: Windows - pool: - vmImage: 'vs2017-win2016' - steps: - - task: NodeTool@0 - inputs: - versionSpec: '8.x' - displayName: 'Install Node.js' - - script: | - yarn - displayName: 'Install dependencies' - - script: | - yarn build - displayName: 'Build' - - script: | - yarn test - displayName: 'Test' - - script: | - yarn lint - displayName: 'Lint' From 195bce0485080673160b5af7e005be3c9e8bd008 Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:25:58 +0530 Subject: [PATCH 116/130] add dependencies as externals in webpack --- addons/xterm-addon-ligatures/webpack.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/xterm-addon-ligatures/webpack.config.js b/addons/xterm-addon-ligatures/webpack.config.js index 819256fb5..253e12076 100644 --- a/addons/xterm-addon-ligatures/webpack.config.js +++ b/addons/xterm-addon-ligatures/webpack.config.js @@ -28,5 +28,9 @@ module.exports = { library: addonName, libraryTarget: 'umd' }, - mode: 'production' + mode: 'production', + externals: { + 'font-finder':'font-finder', + 'font-ligatures':'font-ligatures' + } }; From ad9aabbb7e9031866d5e52274a4321515b623a82 Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 27 Apr 2020 11:26:08 +0530 Subject: [PATCH 117/130] fix ci errors --- addons/xterm-addon-ligatures/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index 1e34d1a35..60c7e574c 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -17,10 +17,10 @@ "types": "typings/xterm-addon-ligatures.d.ts", "scripts": { "prepare": "node bin/download-fonts.js", - "build": "../../node_modules/.bin/tsc -p src", - "watch": "../../node_modules/.bin/tsc -w -p src", + "build": "tsc -p src", + "watch": "tsc -w -p src", "prepackage": "npm run build", - "package": "../../node_modules/.bin/webpack", + "package": "webpack", "pretest": "npm run build", "test": "nyc mocha out/**/*.test.js", "coveralls": "nyc report --reporter=text-lcov | coveralls", From 40a09d74125535ae380f319d019d2074526bda51 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sat, 2 May 2020 16:20:46 +0200 Subject: [PATCH 118/130] fixed ScreenDprListener never being fired --- src/browser/ScreenDprMonitor.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/browser/ScreenDprMonitor.ts b/src/browser/ScreenDprMonitor.ts index ec8c6d8a5..6bd4857eb 100644 --- a/src/browser/ScreenDprMonitor.ts +++ b/src/browser/ScreenDprMonitor.ts @@ -44,12 +44,14 @@ export class ScreenDprMonitor extends Disposable { } private _updateDpr(): void { - if (!this._resolutionMediaMatchList || !this._outerListener) { + if (!this._outerListener) { return; } // Clear listeners for old DPR - this._resolutionMediaMatchList.removeListener(this._outerListener); + if (this._resolutionMediaMatchList) { + this._resolutionMediaMatchList.removeListener(this._outerListener); + } // Add listeners for new DPR this._currentDevicePixelRatio = window.devicePixelRatio; From 930de9aeb7fa25537a7b7ff1106fd95659c4e4b7 Mon Sep 17 00:00:00 2001 From: Eugene Date: Sat, 2 May 2020 22:48:30 +0200 Subject: [PATCH 119/130] Update src/browser/ScreenDprMonitor.ts Co-authored-by: Daniel Imms --- src/browser/ScreenDprMonitor.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/browser/ScreenDprMonitor.ts b/src/browser/ScreenDprMonitor.ts index 6bd4857eb..27ae231f0 100644 --- a/src/browser/ScreenDprMonitor.ts +++ b/src/browser/ScreenDprMonitor.ts @@ -49,9 +49,7 @@ export class ScreenDprMonitor extends Disposable { } // Clear listeners for old DPR - if (this._resolutionMediaMatchList) { - this._resolutionMediaMatchList.removeListener(this._outerListener); - } + this._resolutionMediaMatchList?.removeListener(this._outerListener); // Add listeners for new DPR this._currentDevicePixelRatio = window.devicePixelRatio; From b84831f14818729811754d6995d8830d5db80e49 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:05:06 -0700 Subject: [PATCH 120/130] Make all eslint rules warnings eslint warnings normally don't exit with non-zero when warnings fail unless '--max-warnings 0' is used. This commit adds that and changes all rules to be warnings in order to improve feedback in the editor. After this commit all warning diagnostics (yellow) are stylistic/lint-related ones that will still fail lint, which error diagnostics (red) are actual errors that will fail compilation (from tsc). Fixes #2886 --- .eslintrc.json | 60 +++++++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 32f8e9927..1d4c4895c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -30,22 +30,22 @@ ], "rules": { "@typescript-eslint/array-type": [ - "error", + "warn", { "default": "array-simple", "readonly": "generic" } ], - "@typescript-eslint/class-name-casing": "error", - "@typescript-eslint/consistent-type-definitions": "error", + "@typescript-eslint/class-name-casing": "warn", + "@typescript-eslint/consistent-type-definitions": "warn", "@typescript-eslint/explicit-function-return-type": [ - "error", + "warn", { "allowExpressions": true } ], "@typescript-eslint/explicit-member-accessibility": [ - "error", + "warn", { "accessibility": "explicit", "overrides": { @@ -54,15 +54,15 @@ } ], "@typescript-eslint/indent": [ - "error", + "warn", 2 ], "@typescript-eslint/interface-name-prefix": [ - "error", + "warn", "always" ], "@typescript-eslint/member-delimiter-style": [ - "error", + "warn", { "multiline": { "delimiter": "semi", @@ -75,7 +75,7 @@ } ], "@typescript-eslint/naming-convention": [ - "error", + "warn", { "selector": "default", "format": ["camelCase"] }, // variableLike { "selector": "variable", "format": ["camelCase", "UPPER_CASE"] }, @@ -91,19 +91,19 @@ { "selector": "typeLike", "format": ["PascalCase"] }, { "selector": "interface", "format": ["PascalCase"], "prefix": ["I"] } ], - "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/type-annotation-spacing": "error", + "@typescript-eslint/prefer-namespace-keyword": "warn", + "@typescript-eslint/type-annotation-spacing": "warn", "@typescript-eslint/quotes": [ - "error", + "warn", "single", { "allowTemplateLiterals": true } ], "@typescript-eslint/semi": [ - "error", + "warn", "always" ], "comma-dangle": [ - "error", + "warn", { "objects": "never", "arrays": "never", @@ -111,43 +111,43 @@ } ], "curly": [ - "error", + "warn", "multi-line" ], - "eol-last": "error", + "eol-last": "warn", "eqeqeq": [ - "error", + "warn", "always" ], - "keyword-spacing": "error", - "new-parens": "error", - "no-duplicate-imports": "error", + "keyword-spacing": "warn", + "new-parens": "warn", + "no-duplicate-imports": "warn", "no-else-return": [ - "error", + "warn", { "allowElseIf": false } ], - "no-eval": "error", - "no-irregular-whitespace": "error", + "no-eval": "warn", + "no-irregular-whitespace": "warn", "no-restricted-imports": [ - "error", + "warn", { "patterns": [ ".*\\/out\\/.*" ] } ], - "no-trailing-spaces": "error", - "no-unsafe-finally": "error", - "no-var": "error", + "no-trailing-spaces": "warn", + "no-unsafe-finally": "warn", + "no-var": "warn", "one-var": [ - "error", + "warn", "never" ], - "prefer-const": "error", + "prefer-const": "warn", "spaced-comment": [ - "error", + "warn", "always", { "markers": ["/"], diff --git a/package.json b/package.json index f08004daa..3ac35d2ae 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "prepackage": "npm run build", "package": "webpack", "start": "node demo/start", - "lint": "eslint -c .eslintrc.json --ext .ts src/ addons/", + "lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/", "test": "npm run test-unit", "posttest": "npm run lint", "test-api": "npm run test-api-chromium", From 5b90b8a3ad74b00818b6d0093aa15e6feb4c6f4e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:26:23 -0700 Subject: [PATCH 121/130] Clean up ligatures readme --- addons/xterm-addon-ligatures/README.md | 43 +++++++------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/addons/xterm-addon-ligatures/README.md b/addons/xterm-addon-ligatures/README.md index fdf3c9a48..892c3ce9b 100644 --- a/addons/xterm-addon-ligatures/README.md +++ b/addons/xterm-addon-ligatures/README.md @@ -1,15 +1,11 @@ # xterm-addon-ligatures -[![Build Status](https://dev.azure.com/xtermjs/xterm-addon-ligatures/_apis/build/status/xtermjs.xterm-addon-ligatures)](https://dev.azure.com/xtermjs/xterm-addon-ligatures/_build/latest?definitionId=4) -[![Coverage Status](https://coveralls.io/repos/github/xtermjs/xterm-addon-ligatures/badge.svg?branch=refs%2Fheads%2Fmaster)](https://coveralls.io/github/xtermjs/xterm-addon-ligatures?branch=refs%2Fheads%2Fmaster) - -Add support for programming ligatures to [xterm.js][] when running in -environments with access to [Node.js][] APIs (such as [Electron][]). +Add support for programming ligatures to [xterm.js] when running in environments with access to [Node.js] APIs (such as [Electron]). ## Requirements - * [Node.js][] 8.x or higher (present in [Electron][] 1.8.3 or higher) - * [xterm.js][] 4.0.0 or higher using the default canvas renderer + * [Node.js] 8.x or higher (present in [Electron] 1.8.3 or higher) + * [xterm.js] 4.0.0 or higher using the default canvas renderer ## Usage @@ -19,9 +15,7 @@ Install in your project by running: npm install xterm-addon-ligatures ``` -Then, modify the location where you initialize the terminal to enable ligature -support after opening. If you enable ligatures prior to opening the terminal, -they will not function properly. +Then, modify the location where you initialize the terminal to enable ligature support after opening. If you enable ligatures prior to opening the terminal, they will not function properly. Your code should look something like this: @@ -38,16 +32,13 @@ terminal.enableLigatures(); ### Importing in TypeScript -If you use TypeScript, you will need to cast the terminal variable as `any` when -you enable ligatures because TypeScript does not know that the addon is -available on the terminal object. It will look like this: +If you use TypeScript, you will need to cast the terminal variable as `any` when you enable ligatures because TypeScript does not know that the addon is available on the terminal object. It will look like this: ```ts (terminal as any).enableLigatures() ``` -Alternatively, you can import the addon directly as a function and pass the -terminal as an argument: +Alternatively, you can import the addon directly as a function and pass the terminal as an argument: ```js import { Terminal } from 'xterm'; @@ -60,32 +51,20 @@ enableLigatures(terminal); ## How It Works -In a browser environment, font ligature information is read directly by the web -browser and used to render text correctly without any intervention from the -developer. As of version 3, xterm.js uses the canvas to render characters -individually, resulting in a significant performance boost. However, this means -that it can no longer lean on the browser to determine when to draw font -ligatures. +In a browser environment, font ligature information is read directly by the web browser and used to render text correctly without any intervention from the developer. As of version 3, xterm.js uses the canvas to render characters individually, resulting in a significant performance boost. However, this means that it can no longer lean on the browser to determine when to draw font ligatures. -This package locates the font file on disk for the font currently in use by the -terminal and parses the ligature information out of it (via the -[font-ligatures][] package). As text is rendered in xterm.js, this package -annotates it with the locations of ligatures, allowing xterm.js to render it -correctly. +This package locates the font file on disk for the font currently in use by the terminal and parses the ligature information out of it (via the [font-ligatures] package). As text is rendered in xterm.js, this package annotates it with the locations of ligatures, allowing xterm.js to render it correctly. -Since this package depends on being able to find and resolve a system font from -disk, it has to have system access that isn't available in the web browser. As a -result, this package is mainly useful in environments that combine browser and -Node.js runtimes (such as [Electron][]). +Since this package depends on being able to find and resolve a system font from disk, it has to have system access that isn't available in the web browser. As a result, this package is mainly useful in environments that combine browser and Node.js runtimes (such as [Electron]). ## Fonts This package makes use of the following fonts for testing: - * [Fira Code][] - [Licensed under the OFL][Fira Code License] by Nikita + * [Fira Code][Fira Code] - [Licensed under the OFL][Fira Code License] by Nikita Prokopov, Mozilla Foundation with reserved names Fira Code, Fira Mono, and Fira Sans - * [Iosevka][] - [Licensed under the OFL][Iosevka License] by Belleve Invis with + * [Iosevka] - [Licensed under the OFL][Iosevka License] by Belleve Invis with reserved name Iosevka [xterm.js]: https://github.com/xtermjs/xterm.js From d98fcf8d1f0bad6b59e24ad70966ce602223d2ea Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:29:02 -0700 Subject: [PATCH 122/130] Update copyright --- addons/xterm-addon-ligatures/src/font.ts | 5 +++++ addons/xterm-addon-ligatures/src/index.test.ts | 5 +++++ addons/xterm-addon-ligatures/src/index.ts | 5 +++++ addons/xterm-addon-ligatures/src/parse.test.ts | 5 +++++ addons/xterm-addon-ligatures/src/parse.ts | 5 +++++ .../xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts | 3 ++- 6 files changed, 27 insertions(+), 1 deletion(-) diff --git a/addons/xterm-addon-ligatures/src/font.ts b/addons/xterm-addon-ligatures/src/font.ts index 00b0a157b..825fc7978 100644 --- a/addons/xterm-addon-ligatures/src/font.ts +++ b/addons/xterm-addon-ligatures/src/font.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + import * as fontFinder from 'font-finder'; import * as fontLigatures from 'font-ligatures'; diff --git a/addons/xterm-addon-ligatures/src/index.test.ts b/addons/xterm-addon-ligatures/src/index.test.ts index 2763ddb94..b2fb53831 100644 --- a/addons/xterm-addon-ligatures/src/index.test.ts +++ b/addons/xterm-addon-ligatures/src/index.test.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + import * as path from 'path'; import * as sinon from 'sinon'; import { assert } from 'chai'; diff --git a/addons/xterm-addon-ligatures/src/index.ts b/addons/xterm-addon-ligatures/src/index.ts index 88b71d99e..5a2480c89 100644 --- a/addons/xterm-addon-ligatures/src/index.ts +++ b/addons/xterm-addon-ligatures/src/index.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + import { Terminal } from 'xterm'; import { Font } from 'font-ligatures'; diff --git a/addons/xterm-addon-ligatures/src/parse.test.ts b/addons/xterm-addon-ligatures/src/parse.test.ts index bdaf096db..99dec083c 100644 --- a/addons/xterm-addon-ligatures/src/parse.test.ts +++ b/addons/xterm-addon-ligatures/src/parse.test.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + import { assert } from 'chai'; import parse from './parse'; diff --git a/addons/xterm-addon-ligatures/src/parse.ts b/addons/xterm-addon-ligatures/src/parse.ts index e26abfd97..5ad7747f0 100644 --- a/addons/xterm-addon-ligatures/src/parse.ts +++ b/addons/xterm-addon-ligatures/src/parse.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + interface IParseContext { input: string; offset: number; diff --git a/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts b/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts index 7d66fb03c..7c3edb037 100644 --- a/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts +++ b/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts @@ -1,4 +1,5 @@ /** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. * @license MIT * * This contains the type declarations for the xterm-addon-ligatures library. @@ -7,7 +8,7 @@ * which is intended to be stable and consumed by external programs. */ -import { Terminal, ILinkMatcherOptions, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from 'xterm'; declare module 'xterm-addon-ligatures' { /** From b450470142a2c66baecca392afa3f3ad3c62b3a4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:32:32 -0700 Subject: [PATCH 123/130] Remove old addon api 'apply' call --- addons/xterm-addon-ligatures/src/index.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/addons/xterm-addon-ligatures/src/index.ts b/addons/xterm-addon-ligatures/src/index.ts index 5a2480c89..c867369d8 100644 --- a/addons/xterm-addon-ligatures/src/index.ts +++ b/addons/xterm-addon-ligatures/src/index.ts @@ -83,16 +83,3 @@ export function enableLigatures(term: Terminal): void { return []; }); } - -/** - * Add capabilities to the provided terminal class for enabling ligature - * support. After calling this function, an `enableLigatures()` method is - * available on the terminal class, which will enable ligature support when - * called. - * @param terminalConstructor Terminal class from xterm.js - */ -export function apply(terminalConstructor: typeof Terminal): void { - (terminalConstructor.prototype).enableLigatures = function (): void { - enableLigatures(this); - }; -} From 6c6900ede8edc4983a6cee8444ccca8bfcb37ce3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:35:36 -0700 Subject: [PATCH 124/130] Bring ligatures readme install/usage up to date --- addons/xterm-addon-ligatures/README.md | 48 +++++++------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/addons/xterm-addon-ligatures/README.md b/addons/xterm-addon-ligatures/README.md index 892c3ce9b..6336bf83d 100644 --- a/addons/xterm-addon-ligatures/README.md +++ b/addons/xterm-addon-ligatures/README.md @@ -1,55 +1,31 @@ -# xterm-addon-ligatures +## xterm-addon-ligatures Add support for programming ligatures to [xterm.js] when running in environments with access to [Node.js] APIs (such as [Electron]). -## Requirements +### Requirements * [Node.js] 8.x or higher (present in [Electron] 1.8.3 or higher) * [xterm.js] 4.0.0 or higher using the default canvas renderer -## Usage +### Install -Install in your project by running: - -``` -npm install xterm-addon-ligatures +```bash +npm install --save xterm-addon-ligatures ``` -Then, modify the location where you initialize the terminal to enable ligature support after opening. If you enable ligatures prior to opening the terminal, they will not function properly. - -Your code should look something like this: - -```js -import { Terminal } from 'xterm'; -import * as ligatures from 'xterm-addon-ligatures'; - -Terminal.applyAddon(ligatures); - -const terminal = new Terminal(); -terminal.open(document.getElementById('terminal-mount')); -terminal.enableLigatures(); -``` - -### Importing in TypeScript - -If you use TypeScript, you will need to cast the terminal variable as `any` when you enable ligatures because TypeScript does not know that the addon is available on the terminal object. It will look like this: +### Usage ```ts -(terminal as any).enableLigatures() -``` - -Alternatively, you can import the addon directly as a function and pass the terminal as an argument: - -```js import { Terminal } from 'xterm'; -import { enableLigatures } from 'xterm-addon-ligatures'; +import { LigaturesAddon } from 'xterm-addon-ligatures'; const terminal = new Terminal(); -terminal.open(document.getElementById('terminal-mount')); -enableLigatures(terminal); +const ligaturesAddon = new LigaturesAddon(); +terminal.open(containerElement); +terminal.loadAddon(ligaturesAddon); ``` -## How It Works +### How It Works In a browser environment, font ligature information is read directly by the web browser and used to render text correctly without any intervention from the developer. As of version 3, xterm.js uses the canvas to render characters individually, resulting in a significant performance boost. However, this means that it can no longer lean on the browser to determine when to draw font ligatures. @@ -57,7 +33,7 @@ This package locates the font file on disk for the font currently in use by the Since this package depends on being able to find and resolve a system font from disk, it has to have system access that isn't available in the web browser. As a result, this package is mainly useful in environments that combine browser and Node.js runtimes (such as [Electron]). -## Fonts +### Fonts This package makes use of the following fonts for testing: From 41670dc181c78c43a08192ac90bc37826f6f6a38 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:44:17 -0700 Subject: [PATCH 125/130] Remove test dependence on applyAddon --- addons/xterm-addon-ligatures/src/index.test.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/addons/xterm-addon-ligatures/src/index.test.ts b/addons/xterm-addon-ligatures/src/index.test.ts index b2fb53831..838955c01 100644 --- a/addons/xterm-addon-ligatures/src/index.test.ts +++ b/addons/xterm-addon-ligatures/src/index.test.ts @@ -46,17 +46,15 @@ describe('xterm-addon-ligatures', () => { }); beforeEach(() => { - MockTerminal.applyAddon(ligatureSupport); onRefresh = sinon.stub(); term = new MockTerminal(onRefresh); - (term as any).enableLigatures(); + ligatureSupport.enableLigatures(term as any); }); it('registers itself correctly', () => { - MockTerminal.applyAddon(ligatureSupport); const term = new MockTerminal(sinon.spy()); assert.isUndefined(term.joiner); - (term as any).enableLigatures(); + ligatureSupport.enableLigatures(term as any); assert.isFunction(term.joiner); }); @@ -127,7 +125,7 @@ describe('xterm-addon-ligatures', () => { const onRefresh2 = sinon.stub(); const term2 = new MockTerminal(onRefresh2); term2.setOption('fontFamily', 'Iosevka'); - (term2 as any).enableLigatures(); + ligatureSupport.enableLigatures(term2 as any); assert.deepEqual(term.joiner!(input), []); onRefresh.callsFake(() => { @@ -193,10 +191,6 @@ describe('xterm-addon-ligatures', () => { }); class MockTerminal { - public static applyAddon(addon: any): void { - addon.apply(MockTerminal); - } - private _options: { [name: string]: string | number } = { fontFamily: 'Fira Code, monospace', rows: 50 From 001e16e08148ec78f8e967c317ceefc214b3ec20 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:45:12 -0700 Subject: [PATCH 126/130] Copyright --- addons/xterm-addon-ligatures/bin/download-fonts.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/xterm-addon-ligatures/bin/download-fonts.js b/addons/xterm-addon-ligatures/bin/download-fonts.js index 0342f8488..12790fb5a 100644 --- a/addons/xterm-addon-ligatures/bin/download-fonts.js +++ b/addons/xterm-addon-ligatures/bin/download-fonts.js @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + const fs = require('fs'); const path = require('path'); const util = require('util'); From ed7bab7f0202fba0fa72967d8bf88d9f084c28ef Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:46:38 -0700 Subject: [PATCH 127/130] Correct package.json repo links --- addons/xterm-addon-ligatures/package.json | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index 60c7e574c..6d58daf21 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -2,19 +2,16 @@ "name": "xterm-addon-ligatures", "version": "0.2.1", "description": "Add support for programming ligatures to xterm.js", - "homepage": "https://github.com/xtermjs/xterm-addon-ligatures#readme", - "repository": { - "type": "git", - "url": "https://github.com/xtermjs/xterm-addon-ligatures.git" - }, - "bugs": { - "url": "https://github.com/xtermjs/xterm-addon-ligatures/issues" - }, - "engines": { - "node": ">8.0.0" + "author": { + "name": "The xterm.js authors", + "url": "https://xtermjs.org/" }, "main": "lib/xterm-addon-ligatures.js", "types": "typings/xterm-addon-ligatures.d.ts", + "repository": "https://github.com/xtermjs/xterm.js", + "engines": { + "node": ">8.0.0" + }, "scripts": { "prepare": "node bin/download-fonts.js", "build": "tsc -p src", From c5b0068c9bbab326360c34b00c3006e37872458f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:48:00 -0700 Subject: [PATCH 128/130] Remove coveralls --- addons/xterm-addon-ligatures/package.json | 19 -- addons/xterm-addon-ligatures/yarn.lock | 312 ---------------------- 2 files changed, 331 deletions(-) diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index 6d58daf21..31a869cdc 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -20,7 +20,6 @@ "package": "webpack", "pretest": "npm run build", "test": "nyc mocha out/**/*.test.js", - "coveralls": "nyc report --reporter=text-lcov | coveralls", "prepublish": "npm run package" }, "keywords": [ @@ -38,29 +37,11 @@ "devDependencies": { "@types/sinon": "^5.0.1", "axios": "^0.18.0", - "coveralls": "^3.0.2", "mkdirp": "^0.5.1", "sinon": "^6.1.3", "yauzl": "^2.10.0" }, "peerDependencies": { "xterm": "^4.0.0" - }, - "nyc": { - "sourceMap": true, - "reporter": [ - "text", - "html", - "json" - ], - "include": [ - "out/**/*.js" - ], - "exclude": [ - "out/**/*.test.*", - "out/**/*.integration.*", - "out/**/*.d.ts", - "out/**/*.map*" - ] } } diff --git a/addons/xterm-addon-ligatures/yarn.lock b/addons/xterm-addon-ligatures/yarn.lock index ec68a6aa6..e235ab229 100644 --- a/addons/xterm-addon-ligatures/yarn.lock +++ b/addons/xterm-addon-ligatures/yarn.lock @@ -16,43 +16,6 @@ version "5.0.1" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.1.tgz#a15b36ec42f1f53166617491feabd1734cb03e21" -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - dependencies: - sprintf-js "~1.0.2" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - -aws4@^1.6.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - axios@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" @@ -60,96 +23,20 @@ axios@^0.18.0: follow-redirects "1.5.10" is-buffer "^2.0.2" -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - dependencies: - tweetnacl "^0.14.3" - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -combined-stream@1.0.6, combined-stream@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -coveralls@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" - dependencies: - growl "~> 1.10.0" - js-yaml "^3.11.0" - lcov-parse "^0.0.10" - log-driver "^1.2.7" - minimist "^1.2.0" - request "^2.85.0" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - -extend@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -177,119 +64,30 @@ font-ligatures@^1.3.2: lru-cache "^4.1.3" opentype.js "^0.8.0" -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - get-system-fonts@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-system-fonts/-/get-system-fonts-2.0.0.tgz#a43b9a33f05c0715a60176d2aad5ce6e98f0a3c6" -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -"growl@~> 1.10.0": - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - is-buffer@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -js-yaml@^3.11.0: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - just-extend@^1.1.27: version "1.1.27" resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" -lcov-parse@^0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" -log-driver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" - lolex@^2.3.2, lolex@^2.4.2: version "2.7.1" resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.1.tgz#e40a8c4d1f14b536aa03e42a537c7adbaf0c20be" @@ -301,24 +99,10 @@ lru-cache@^4.1.3: pseudomap "^1.0.2" yallist "^2.1.2" -mime-db@~1.35.0: - version "1.35.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" - -mime-types@^2.1.12, mime-types@~2.1.17: - version "2.1.19" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" - dependencies: - mime-db "~1.35.0" - minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -339,10 +123,6 @@ nise@^1.3.3: path-to-regexp "^1.7.0" text-encoding "^0.6.4" -oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - opentype.js@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/opentype.js/-/opentype.js-0.8.0.tgz#acabcfa1642fbe894a3e4d759e43ba694e02bd35" @@ -359,10 +139,6 @@ pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - promise-stream-reader@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-stream-reader/-/promise-stream-reader-1.0.1.tgz#4e793a79c9d49a73ccd947c6da9c127f12923649" @@ -371,47 +147,6 @@ pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - -request@^2.85.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - samsam@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" @@ -429,25 +164,6 @@ sinon@^6.1.3: supports-color "^5.4.0" type-detect "^4.0.8" -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - supports-color@^5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" @@ -462,38 +178,10 @@ tiny-inflate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.2.tgz#93d9decffc8805bd57eae4310f0b745e9b6fb3a7" -tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - dependencies: - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" -uuid@^3.1.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" From 36e241cd8d0b31a239d5ab6722dc6febbc89357e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 06:49:05 -0700 Subject: [PATCH 129/130] Alphabetize tsconfig addons --- tsconfig.all.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tsconfig.all.json b/tsconfig.all.json index 98b4e97ba..a4286deba 100644 --- a/tsconfig.all.json +++ b/tsconfig.all.json @@ -7,12 +7,12 @@ { "path": "./test/benchmark" }, { "path": "./addons/xterm-addon-attach/src" }, { "path": "./addons/xterm-addon-fit/src" }, + { "path": "./addons/xterm-addon-ligatures/src" }, { "path": "./addons/xterm-addon-search/src" }, - { "path": "./addons/xterm-addon-unicode11/src" }, - { "path": "./addons/xterm-addon-web-links/src" }, - { "path": "./addons/xterm-addon-webgl/src" }, { "path": "./addons/xterm-addon-serialize/src" }, { "path": "./addons/xterm-addon-serialize/benchmark" }, - { "path": "./addons/xterm-addon-ligatures/src" } + { "path": "./addons/xterm-addon-unicode11/src" }, + { "path": "./addons/xterm-addon-web-links/src" }, + { "path": "./addons/xterm-addon-webgl/src" } ] } From 210fa7f655b96f81f0e5eed158dc1cf039ce2e8d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 3 May 2020 07:04:01 -0700 Subject: [PATCH 130/130] Move commented test into Terminal.test --- src/browser/Terminal.test.ts | 48 +++++++++++++++++++++++++++++++++ src/common/InputHandler.test.ts | 39 --------------------------- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/browser/Terminal.test.ts b/src/browser/Terminal.test.ts index 729c0d0f2..f192b0313 100644 --- a/src/browser/Terminal.test.ts +++ b/src/browser/Terminal.test.ts @@ -1484,6 +1484,54 @@ describe('Terminal', () => { assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']); }); }); + + describe('BS with reverseWraparound set/unset', () => { + const ttyBS = '\x08 \x08'; // tty ICANON sends on pressing BS + + beforeEach(() => { + term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); + }); + + describe('reverseWraparound set', () => { + it('should not reverse outside of scroll margins', () => { + // prepare buffer content + term.writeSync('#####abcdefghijklmnopqrstuvwxy'); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']); + assert.equal(term.buffer.ydisp, 1); + assert.equal(term.buffer.x, 5); + assert.equal(term.buffer.y, 4); + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']); + + term.writeSync('\x1b[?45h'); + term.writeSync('uvwxy'); + + // set top/bottom to 1/3 (0-based) + term.writeSync('\x1b[2;4r'); + // place cursor below scroll bottom + term.buffer.x = 5; + term.buffer.y = 4; + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']); + + term.writeSync('uvwxy'); + // place cursor within scroll margins + term.buffer.x = 5; + term.buffer.y = 3; + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']); + assert.equal(term.buffer.x, 0); + assert.equal(term.buffer.y, term.buffer.scrollTop); // stops at 0, scrollTop + + term.writeSync('fghijklmnopqrst'); + // place cursor above scroll top + term.buffer.x = 5; + term.buffer.y = 0; + term.writeSync(ttyBS.repeat(100)); + assert.deepEqual(getLines(term, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']); + }); + }); + }); }); }); diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index d94b9d86a..611885904 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -1465,45 +1465,6 @@ describe('InputHandler', () => { assert.deepEqual(getLines(bufferService, 2), [' ', ' ']); assert.equal(bufferService.buffer.x, 0); }); - /* - it.only('should not reverse outside of scroll margins', () => { - // prepare buffer content - inputHandler.parse('#####abcdefghijklmnopqrstuvwxy'); - assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']); - assert.equal(bufferService.buffer.ydisp, 1); - assert.equal(bufferService.buffer.x, 5); - assert.equal(bufferService.buffer.y, 4); - inputHandler.parse(ttyBS.repeat(100)); - assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']); - - inputHandler.parse('\x1b[?45h'); - inputHandler.parse('uvwxy'); - - // set top/bottom to 1/3 (0-based) - inputHandler.parse('\x1b[2;4r'); - // place cursor below scroll bottom - bufferService.buffer.x = 5; - bufferService.buffer.y = 4; - inputHandler.parse(ttyBS.repeat(100)); - assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']); - - inputHandler.parse('uvwxy'); - // place cursor within scroll margins - bufferService.buffer.x = 5; - bufferService.buffer.y = 3; - inputHandler.parse(ttyBS.repeat(100)); - assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']); - assert.equal(bufferService.buffer.x, 0); - assert.equal(bufferService.buffer.y, bufferService.buffer.scrollTop); // stops at 0, scrollTop - - inputHandler.parse('fghijklmnopqrst'); - // place cursor above scroll top - bufferService.buffer.x = 5; - bufferService.buffer.y = 0; - inputHandler.parse(ttyBS.repeat(100)); - assert.deepEqual(getLines(bufferService, 6), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']); - }); - */ }); });