From ba40fe4ff4a16e794190e8876fb3707cc086e13c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 06:46:37 -0700 Subject: [PATCH] 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;