From ee3668eb03bba671ab219c4abd07a1368a591137 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 24 Jul 2018 08:40:51 -0700 Subject: [PATCH 1/3] Report device status directly via emit Fixes #1579 --- src/InputHandler.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 3fda521f..bea5da2c 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1712,15 +1712,13 @@ export class InputHandler extends Disposable implements IInputHandler { switch (params[0]) { case 5: // status report - this._terminal.send(C0.ESC + '[0n'); + this._terminal.emit('data', `${C0.ESC}[0n`); break; case 6: // cursor position - this._terminal.send(C0.ESC + '[' - + (this._terminal.buffer.y + 1) - + ';' - + (this._terminal.buffer.x + 1) - + 'R'); + const y = this._terminal.buffer.y + 1; + const x = this._terminal.buffer.x + 1; + this._terminal.emit('data', `${C0.ESC}[${y};${x}R`); break; } } else if (collect === '?') { @@ -1729,11 +1727,9 @@ export class InputHandler extends Disposable implements IInputHandler { switch (params[0]) { case 6: // cursor position - this._terminal.send(C0.ESC + '[?' - + (this._terminal.buffer.y + 1) - + ';' - + (this._terminal.buffer.x + 1) - + 'R'); + const y = this._terminal.buffer.y + 1; + const x = this._terminal.buffer.x + 1; + this._terminal.emit('data', `${C0.ESC}[?${y};${x}R`); break; case 15: // no printer From fec66c7dac42e292dcdf6110c63e0a751b08d4c3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 27 Jul 2018 11:32:11 -0700 Subject: [PATCH 2/3] Remove Terminal.send --- src/InputHandler.ts | 34 +++++++++++++++--------------- src/Terminal.ts | 37 +++++++++------------------------ src/Types.ts | 2 -- src/handlers/AltClickHandler.ts | 2 +- src/utils/TestUtils.test.ts | 6 ------ 5 files changed, 28 insertions(+), 53 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index bea5da2c..4ae45b8b 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -40,7 +40,7 @@ class RequestTerminfo implements IDcsHandler { } unhook(): void { // invalid: DCS 0 + r Pt ST - this._terminal.send(`${C0.ESC}P0+r${this._data}${C0.ESC}\\`); + this._terminal.handler(`${C0.ESC}P0+r${this._data}${C0.ESC}\\`); } } @@ -68,25 +68,25 @@ class DECRQSS implements IDcsHandler { switch (this._data) { // valid: DCS 1 $ r Pt ST (xterm) case '"q': // DECSCA - return this._terminal.send(`${C0.ESC}P1$r0"q${C0.ESC}\\`); + return this._terminal.handler(`${C0.ESC}P1$r0"q${C0.ESC}\\`); case '"p': // DECSCL - return this._terminal.send(`${C0.ESC}P1$r61"p${C0.ESC}\\`); + return this._terminal.handler(`${C0.ESC}P1$r61"p${C0.ESC}\\`); case 'r': // DECSTBM const pt = '' + (this._terminal.buffer.scrollTop + 1) + ';' + (this._terminal.buffer.scrollBottom + 1) + 'r'; - return this._terminal.send(`${C0.ESC}P1$r${pt}${C0.ESC}\\`); + return this._terminal.handler(`${C0.ESC}P1$r${pt}${C0.ESC}\\`); case 'm': // SGR // TODO: report real settings instead of 0m - return this._terminal.send(`${C0.ESC}P1$r0m${C0.ESC}\\`); + return this._terminal.handler(`${C0.ESC}P1$r0m${C0.ESC}\\`); case ' q': // DECSCUSR const STYLES: {[key: string]: number} = {'block': 2, 'underline': 4, 'bar': 6}; let style = STYLES[this._terminal.getOption('cursorStyle')]; style -= this._terminal.getOption('cursorBlink'); - return this._terminal.send(`${C0.ESC}P1$r${style} q${C0.ESC}\\`); + return this._terminal.handler(`${C0.ESC}P1$r${style} q${C0.ESC}\\`); default: // invalid: DCS 0 $ r Pt ST (xterm) this._terminal.error('Unknown DCS $q %s', this._data); - this._terminal.send(`${C0.ESC}P0$r${this._data}${C0.ESC}\\`); + this._terminal.handler(`${C0.ESC}P0$r${this._data}${C0.ESC}\\`); } } } @@ -1032,24 +1032,24 @@ export class InputHandler extends Disposable implements IInputHandler { if (!collect) { if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) { - this._terminal.send(C0.ESC + '[?1;2c'); + this._terminal.handler(C0.ESC + '[?1;2c'); } else if (this._terminal.is('linux')) { - this._terminal.send(C0.ESC + '[?6c'); + this._terminal.handler(C0.ESC + '[?6c'); } } else if (collect === '>') { // xterm and urxvt // seem to spit this // out around ~370 times (?). if (this._terminal.is('xterm')) { - this._terminal.send(C0.ESC + '[>0;276;0c'); + this._terminal.handler(C0.ESC + '[>0;276;0c'); } else if (this._terminal.is('rxvt-unicode')) { - this._terminal.send(C0.ESC + '[>85;95;0c'); + this._terminal.handler(C0.ESC + '[>85;95;0c'); } else if (this._terminal.is('linux')) { // not supported by linux console. // linux console echoes parameters. - this._terminal.send(params[0] + 'c'); + this._terminal.handler(params[0] + 'c'); } else if (this._terminal.is('screen')) { - this._terminal.send(C0.ESC + '[>83;40003;0c'); + this._terminal.handler(C0.ESC + '[>83;40003;0c'); } } } @@ -1733,19 +1733,19 @@ export class InputHandler extends Disposable implements IInputHandler { break; case 15: // no printer - // this.send(C0.ESC + '[?11n'); + // this.handler(C0.ESC + '[?11n'); break; case 25: // dont support user defined keys - // this.send(C0.ESC + '[?21n'); + // this.handler(C0.ESC + '[?21n'); break; case 26: // north american keyboard - // this.send(C0.ESC + '[?27;1;0;0n'); + // this.handler(C0.ESC + '[?27;1;0;0n'); break; case 53: // no dec locator/mouse - // this.send(C0.ESC + '[?50n'); + // this.handler(C0.ESC + '[?50n'); break; } } diff --git a/src/Terminal.ts b/src/Terminal.ts index e8366290..8bd9870c 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -135,7 +135,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II public cursorHidden: boolean; public convertEol: boolean; - private _sendDataQueue: string; private _customKeyEventHandler: CustomKeyEventHandler; // modes @@ -270,7 +269,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.cursorState = 0; this.cursorHidden = false; - this._sendDataQueue = ''; this._customKeyEventHandler = null; // modes @@ -486,7 +484,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II */ private _onTextAreaFocus(): void { if (this.sendFocus) { - this.send(C0.ESC + '[I'); + this.handler(C0.ESC + '[I'); } this.element.classList.add('focus'); this.showCursor(); @@ -510,7 +508,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.textarea.value = ''; this.refresh(this.buffer.y, this.buffer.y); if (this.sendFocus) { - this.send(C0.ESC + '[O'); + this.handler(C0.ESC + '[O'); } this.element.classList.remove('focus'); this.emit('blur'); @@ -860,7 +858,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II else if (button === 3) return; else data += '0'; data += '~[' + pos.x + ',' + pos.y + ']\r'; - self.send(data); + self.handler(data); return; } @@ -873,7 +871,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II else if (button === 1) button = 4; else if (button === 2) button = 6; else if (button === 3) button = 3; - self.send(C0.ESC + '[' + self.handler(C0.ESC + '[' + button + ';' + (button === 3 ? 4 : 0) @@ -893,14 +891,14 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II pos.y -= 32; pos.x++; pos.y++; - self.send(C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M'); + self.handler(C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M'); return; } if (self.sgrMouse) { pos.x -= 32; pos.y -= 32; - self.send(C0.ESC + '[<' + self.handler(C0.ESC + '[<' + (((button & 3) === 3 ? button & ~3 : button) - 32) + ';' + pos.x @@ -916,7 +914,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II encode(data, pos.x); encode(data, pos.y); - self.send(C0.ESC + '[M' + String.fromCharCode.apply(String, data)); + self.handler(C0.ESC + '[M' + String.fromCharCode.apply(String, data)); } function getButton(ev: MouseEvent): number { @@ -1065,7 +1063,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II for (let i = 0; i < Math.abs(amount); i++) { data += sequence; } - this.send(data); + this.handler(data); } return; } @@ -1279,7 +1277,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II if (this.options.useFlowControl && !this._xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) { // XOFF - stop pty pipe // XON will be triggered by emulator before processing data chunk - this.send(C0.DC3); + this.handler(C0.DC3); this._xoffSentToCatchUp = true; } @@ -1301,7 +1299,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // If XOFF was sent in order to catch up with the pty process, resume it if // the writeBuffer is empty to allow more data to come in. if (this._xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) { - this.send(C0.DC1); + this.handler(C0.DC1); this._xoffSentToCatchUp = false; } @@ -1576,21 +1574,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II return true; } - /** - * Send data for handling to the terminal - * @param {string} data - */ - public send(data: string): void { - if (!this._sendDataQueue) { - setTimeout(() => { - this.handler(this._sendDataQueue); - this._sendDataQueue = ''; - }, 1); - } - - this._sendDataQueue += data; - } - /** * Ring the bell. * Note: We could do sweet things with webaudio here diff --git a/src/Types.ts b/src/Types.ts index 26a8a861..5a7d1476 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -75,7 +75,6 @@ export interface IInputHandlingTerminal extends IEventEmitter { eraseLeft(x: number, y: number): void; blankLine(cur?: boolean, isWrapped?: boolean): LineData; is(term: string): boolean; - send(data: string): void; setgCharset(g: number, charset: ICharset): void; resize(x: number, y: number): void; log(text: string, data?: any): void; @@ -225,7 +224,6 @@ export interface ITerminal extends PublicTerminal, IElementAccessor, IBufferAcce * @param data The data to populate in the event. */ handler(data: string): void; - send(data: string): void; scrollLines(disp: number, suppressScrollEvent?: boolean): void; cancel(ev: Event, force?: boolean): boolean | void; log(text: string): void; diff --git a/src/handlers/AltClickHandler.ts b/src/handlers/AltClickHandler.ts index 344a5543..7ac084db 100644 --- a/src/handlers/AltClickHandler.ts +++ b/src/handlers/AltClickHandler.ts @@ -50,7 +50,7 @@ export class AltClickHandler { */ public move(): void { if (this._mouseEvent.altKey && this._endCol !== undefined && this._endRow !== undefined) { - this._terminal.send(this._arrowSequences()); + this._terminal.handler(this._arrowSequences()); } } diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 78a1942b..7a3e7701 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -84,9 +84,6 @@ export class MockTerminal implements ITerminal { write(data: string): void { throw new Error('Method not implemented.'); } - send(data: string): void { - throw new Error('Method not implemented.'); - } bracketedPasteMode: boolean; mouseHelper: IMouseHelper; renderer: IRenderer; @@ -240,9 +237,6 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { is(term: string): boolean { throw new Error('Method not implemented.'); } - send(data: string): void { - throw new Error('Method not implemented.'); - } setgCharset(g: number, charset: { [key: string]: string; }): void { throw new Error('Method not implemented.'); } From 1c4cb8c62055ddd82d9847379869e648695ac59a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 27 Jul 2018 11:45:52 -0700 Subject: [PATCH 3/3] Reinstate IInputHandlingTerminal Fixes #1587 --- src/InputHandler.ts | 16 +++++++++------- src/Types.ts | 5 +++++ src/utils/TestUtils.test.ts | 12 ++++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 4ae45b8b..4f6e58f8 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { CharData, IInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer } from './Types'; +import { CharData, IInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer, IInputHandlingTerminal } from './Types'; import { C0, C1 } from './common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets'; import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, DEFAULT_ATTR } from './Buffer'; @@ -116,7 +116,7 @@ export class InputHandler extends Disposable implements IInputHandler { private _surrogateHigh: string; constructor( - private _terminal: any, // TODO: reestablish IInputHandlingTerminal here + private _terminal: IInputHandlingTerminal, private _parser: IEscapeSequenceParser = new EscapeSequenceParser()) { super(); @@ -129,16 +129,16 @@ export class InputHandler extends Disposable implements IInputHandler { * custom fallback handlers */ this._parser.setCsiHandlerFallback((collect: string, params: number[], flag: number) => { - this._terminal.error('Unknown CSI code: ', collect, params, String.fromCharCode(flag)); + this._terminal.error('Unknown CSI code: ', { collect, params, flag: String.fromCharCode(flag) }); }); this._parser.setEscHandlerFallback((collect: string, flag: number) => { - this._terminal.error('Unknown ESC code: ', collect, String.fromCharCode(flag)); + this._terminal.error('Unknown ESC code: ', { collect, flag: String.fromCharCode(flag) }); }); this._parser.setExecuteHandlerFallback((code: number) => { - this._terminal.error('Unknown EXECUTE code: ', code); + this._terminal.error('Unknown EXECUTE code: ', { code }); }); this._parser.setOscHandlerFallback((identifier: number, data: string) => { - this._terminal.error('Unknown OSC code: ', identifier, data); + this._terminal.error('Unknown OSC code: ', { identifier, data }); }); /** @@ -299,7 +299,9 @@ export class InputHandler extends Disposable implements IInputHandler { let buffer = this._terminal.buffer; const cursorStartX = buffer.x; const cursorStartY = buffer.y; - if (this._terminal.debug) { + + // TODO: Consolidate debug/logging #1560 + if ((this._terminal).debug) { this._terminal.log('data: ' + data); } diff --git a/src/Types.ts b/src/Types.ts index 5a7d1476..ba1a7990 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -47,6 +47,7 @@ export interface IInputHandlingTerminal extends IEventEmitter { wraparoundMode: boolean; bracketedPasteMode: boolean; curAttr: number; + savedCurAttr: number; savedCols: number; x10Mouse: boolean; vt200Mouse: boolean; @@ -85,6 +86,10 @@ export interface IInputHandlingTerminal extends IEventEmitter { error(text: string, data?: any): void; setOption(key: string, value: any): void; tabSet(): void; + handler(data: string): void; + handleTitle(title: string): void; + index(): void; + reverseIndex(): void; } export interface IViewport extends IDisposable { diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 7a3e7701..769eb341 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -279,6 +279,18 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal { tabSet(): void { throw new Error('Method not implemented.'); } + handler(data: string): void { + throw new Error('Method not implemented.'); + } + handleTitle(title: string): void { + throw new Error('Method not implemented.'); + } + index(): void { + throw new Error('Method not implemented.'); + } + reverseIndex(): void { + throw new Error('Method not implemented.'); + } } export class MockBuffer implements IBuffer {