From dd239b98110d8a0437edda141d6b85357e5e9e5e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 00:52:54 -0700 Subject: [PATCH 1/9] Use IBufferService for buffer access in InputHandler --- src/InputHandler.test.ts | 270 ++++++++++++++++++++------------------- src/InputHandler.ts | 208 +++++++++++++++--------------- src/Terminal.ts | 2 +- 3 files changed, 246 insertions(+), 234 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index d5f0ecd6ce..ff477b9cc9 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -13,7 +13,8 @@ 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 } from 'common/TestUtils.test'; +import { MockCoreService, MockBufferService } from 'common/TestUtils.test'; +import { IBufferService } from 'common/services/Services'; function getCursor(term: TestTerminal): number[] { return [ @@ -27,30 +28,31 @@ describe('InputHandler', () => { const terminal = new MockInputHandlingTerminal(); terminal.cols = 80; terminal.rows = 30; - terminal.buffer.x = 1; - terminal.buffer.y = 2; - terminal.buffer.ybase = 0; terminal.curAttrData.fg = 3; - const inputHandler = new InputHandler(terminal, new MockCoreService()); + const bufferService = new MockBufferService(80, 30); + bufferService.buffer.x = 1; + bufferService.buffer.y = 2; + bufferService.buffer.ybase = 0; + const inputHandler = new InputHandler(terminal, bufferService, new MockCoreService()); // Save cursor position inputHandler.saveCursor(); - assert.equal(terminal.buffer.x, 1); - assert.equal(terminal.buffer.y, 2); + assert.equal(bufferService.buffer.x, 1); + assert.equal(bufferService.buffer.y, 2); assert.equal(terminal.curAttrData.fg, 3); // Change cursor position - terminal.buffer.x = 10; - terminal.buffer.y = 20; + bufferService.buffer.x = 10; + bufferService.buffer.y = 20; terminal.curAttrData.fg = 30; // Restore cursor position inputHandler.restoreCursor(); - assert.equal(terminal.buffer.x, 1); - assert.equal(terminal.buffer.y, 2); + assert.equal(bufferService.buffer.x, 1); + assert.equal(bufferService.buffer.y, 2); assert.equal(terminal.curAttrData.fg, 3); }); describe('setCursorStyle', () => { it('should call Terminal.setOption with correct params', () => { const terminal = new MockInputHandlingTerminal(); - const inputHandler = new InputHandler(terminal, new MockCoreService()); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService()); const collect = ' '; inputHandler.setCursorStyle(Params.fromArray([0]), collect); @@ -93,7 +95,7 @@ describe('InputHandler', () => { const terminal = new MockInputHandlingTerminal(); const collect = '?'; terminal.bracketedPasteMode = false; - const inputHandler = new InputHandler(terminal, new MockCoreService()); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService()); // Set bracketed paste mode inputHandler.setMode(Params.fromArray([2004]), collect); assert.equal(terminal.bracketedPasteMode, true); @@ -103,92 +105,95 @@ describe('InputHandler', () => { }); }); describe('regression tests', function(): void { - function termContent(term: Terminal, trim: boolean): string[] { + function termContent(bufferService: IBufferService, trim: boolean): string[] { const result = []; - for (let i = 0; i < term.rows; ++i) result.push(term.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; } it('insertChars', function(): void { const term = new Terminal(); - const inputHandler = new InputHandler(term, new MockCoreService()); + const bufferService = new MockBufferService(80, 30); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // insert some data in first and second line inputHandler.parse(Array(term.cols - 9).join('a')); inputHandler.parse('1234567890'); inputHandler.parse(Array(term.cols - 9).join('a')); inputHandler.parse('1234567890'); - const line1: IBufferLine = term.buffer.lines.get(0); + const line1: IBufferLine = bufferService.buffer.lines.get(0); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + '1234567890'); // insert one char from params = [0] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.insertChars(Params.fromArray([0])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + ' 123456789'); // insert one char from params = [1] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.insertChars(Params.fromArray([1])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + ' 12345678'); // insert two chars from params = [2] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.insertChars(Params.fromArray([2])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + ' 123456'); // insert 10 chars from params = [10] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.insertChars(Params.fromArray([10])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + ' '); expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a')); }); it('deleteChars', function(): void { const term = new Terminal(); - const inputHandler = new InputHandler(term, new MockCoreService()); + const bufferService = new MockBufferService(80, 30); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // insert some data in first and second line inputHandler.parse(Array(term.cols - 9).join('a')); inputHandler.parse('1234567890'); inputHandler.parse(Array(term.cols - 9).join('a')); inputHandler.parse('1234567890'); - const line1: IBufferLine = term.buffer.lines.get(0); + const line1: IBufferLine = bufferService.buffer.lines.get(0); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + '1234567890'); // delete one char from params = [0] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.deleteChars(Params.fromArray([0])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + '234567890 '); expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a') + '234567890'); // insert one char from params = [1] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.deleteChars(Params.fromArray([1])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + '34567890 '); expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a') + '34567890'); // insert two chars from params = [2] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.deleteChars(Params.fromArray([2])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + '567890 '); expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a') + '567890'); // insert 10 chars from params = [10] - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.deleteChars(Params.fromArray([10])); expect(line1.translateToString(false)).equals(Array(term.cols - 9).join('a') + ' '); expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a')); }); it('eraseInLine', function(): void { const term = new Terminal(); - const inputHandler = new InputHandler(term, new MockCoreService()); + const bufferService = new MockBufferService(80, 30); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // fill 6 lines to test 3 different states inputHandler.parse(Array(term.cols + 1).join('a')); @@ -196,101 +201,102 @@ describe('InputHandler', () => { inputHandler.parse(Array(term.cols + 1).join('a')); // params[0] - right erase - term.buffer.y = 0; - term.buffer.x = 70; + bufferService.buffer.y = 0; + bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([0])); - expect(term.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 - term.buffer.y = 1; - term.buffer.x = 70; + bufferService.buffer.y = 1; + bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([1])); - expect(term.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 - term.buffer.y = 2; - term.buffer.x = 70; + bufferService.buffer.y = 2; + bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([2])); - expect(term.buffer.lines.get(2).translateToString(false)).equals(Array(term.cols + 1).join(' ')); + expect(bufferService.buffer.lines.get(2).translateToString(false)).equals(Array(term.cols + 1).join(' ')); }); it('eraseInDisplay', function(): void { const term = new Terminal({cols: 80, rows: 7}); - const inputHandler = new InputHandler(term, new MockCoreService()); + const bufferService = new MockBufferService(80, 7); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // fill display with a's - for (let i = 0; i < term.rows; ++i) inputHandler.parse(Array(term.cols + 1).join('a')); + for (let i = 0; i < term.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); // params [0] - right and below erase - term.buffer.y = 5; - term.buffer.x = 40; + bufferService.buffer.y = 5; + bufferService.buffer.x = 40; inputHandler.eraseInDisplay(Params.fromArray([0])); - expect(termContent(term, false)).eql([ - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(40 + 1).join('a') + Array(term.cols - 40 + 1).join(' '), - Array(term.cols + 1).join(' ') + 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(term, true)).eql([ - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), - Array(term.cols + 1).join('a'), + 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 - term.buffer.y = 0; - term.buffer.x = 0; - for (let i = 0; i < term.rows; ++i) inputHandler.parse(Array(term.cols + 1).join('a')); + 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 - term.buffer.y = 5; - term.buffer.x = 40; + bufferService.buffer.y = 5; + bufferService.buffer.x = 40; inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(termContent(term, false)).eql([ - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(41 + 1).join(' ') + Array(term.cols - 41 + 1).join('a'), - Array(term.cols + 1).join('a') + 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(term, true)).eql([ + expect(termContent(bufferService, true)).eql([ '', '', '', '', '', - Array(41 + 1).join(' ') + Array(term.cols - 41 + 1).join('a'), - Array(term.cols + 1).join('a') + Array(41 + 1).join(' ') + Array(bufferService.cols - 41 + 1).join('a'), + Array(bufferService.cols + 1).join('a') ]); // reset - term.buffer.y = 0; - term.buffer.x = 0; - for (let i = 0; i < term.rows; ++i) inputHandler.parse(Array(term.cols + 1).join('a')); + 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 - term.buffer.y = 5; - term.buffer.x = 40; + bufferService.buffer.y = 5; + bufferService.buffer.x = 40; inputHandler.eraseInDisplay(Params.fromArray([2])); - expect(termContent(term, false)).eql([ - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' '), - Array(term.cols + 1).join(' ') + 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(term, true)).eql([ + expect(termContent(bufferService, true)).eql([ '', '', '', @@ -301,34 +307,34 @@ describe('InputHandler', () => { ]); // reset and add a wrapped line - term.buffer.y = 0; - term.buffer.x = 0; - inputHandler.parse(Array(term.cols + 1).join('a')); // line 0 - inputHandler.parse(Array(term.cols + 10).join('a')); // line 1 and 2 - for (let i = 3; i < term.rows; ++i) inputHandler.parse(Array(term.cols + 1).join('a')); + 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(term.buffer.lines.get(2).isWrapped).true; - term.buffer.y = 2; - term.buffer.x = 40; + expect(bufferService.buffer.lines.get(2).isWrapped).true; + bufferService.buffer.y = 2; + bufferService.buffer.x = 40; inputHandler.eraseInDisplay(Params.fromArray([1])); - expect(term.buffer.lines.get(2).isWrapped).false; + expect(bufferService.buffer.lines.get(2).isWrapped).false; // reset and add a wrapped line - term.buffer.y = 0; - term.buffer.x = 0; - inputHandler.parse(Array(term.cols + 1).join('a')); // line 0 - inputHandler.parse(Array(term.cols + 10).join('a')); // line 1 and 2 - for (let i = 3; i < term.rows; ++i) inputHandler.parse(Array(term.cols + 1).join('a')); + 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(term.buffer.lines.get(2).isWrapped).true; - term.buffer.y = 1; - term.buffer.x = 90; // Cursor is beyond last column + 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(term.buffer.lines.get(2).isWrapped).false; + expect(bufferService.buffer.lines.get(2).isWrapped).false; }); }); it('convertEol setting', function(): void { @@ -351,7 +357,7 @@ describe('InputHandler', () => { describe('print', () => { it('should not cause an infinite loop (regression test)', () => { const term = new Terminal(); - const inputHandler = new InputHandler(term, new MockCoreService()); + const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCoreService()); const container = new Uint32Array(10); container[0] = 0x200B; inputHandler.print(container, 0, 1); @@ -360,56 +366,58 @@ describe('InputHandler', () => { describe('alt screen', () => { let term: Terminal; + let bufferService: IBufferService; let handler: InputHandler; beforeEach(() => { term = new Terminal(); - handler = new InputHandler(term, new MockCoreService()); + bufferService = new MockBufferService(80, 30); + handler = new InputHandler(term, bufferService, new MockCoreService()); }); it('should handle DECSET/DECRST 47 (alt screen buffer)', () => { handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST'); - expect(term.buffer.translateBufferLineToString(0, true)).to.equal(''); - expect(term.buffer.translateBufferLineToString(1, true)).to.equal(' TEST'); + 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((term.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(term.buffer.translateBufferLineToString(0, true)).to.equal(''); - expect(term.buffer.translateBufferLineToString(1, true)).to.equal(' TEST'); + 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((term.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(term.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); - expect(term.buffer.translateBufferLineToString(1, true)).to.equal('JUNK'); + 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(term.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((term.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(term.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); - expect(term.buffer.translateBufferLineToString(1, true)).to.equal(''); + 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(term.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(term.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); + expect(bufferService.buffer.translateBufferLineToString(0, true)).to.equal('TEST'); // Text color of 'TEST' should be default - expect(term.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(term.buffer.translateBufferLineToString(1, true)).to.equal('TEST'); + expect(bufferService.buffer.translateBufferLineToString(1, true)).to.equal('TEST'); // Text color of 'TEST' should be red - expect((term.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(term.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); }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 150ed8bbab..115653548c 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -19,7 +19,7 @@ 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 } from 'common/Types'; -import { ICoreService } from 'common/services/Services'; +import { ICoreService, IBufferService } from 'common/services/Services'; import { ISelectionService } from 'browser/services/Services'; /** @@ -41,7 +41,10 @@ const GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1, class DECRQSS implements IDcsHandler { private _data: Uint32Array = new Uint32Array(0); - constructor(private _terminal: any) { } + constructor( + private _terminal: any, + private _bufferService: IBufferService + ) { } hook(collect: string, params: IParams, flag: number): void { this._data = new Uint32Array(0); @@ -61,8 +64,8 @@ class DECRQSS implements IDcsHandler { case '"p': // DECSCL 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'; + const pt = '' + (this._bufferService.buffer.scrollTop + 1) + + ';' + (this._bufferService.buffer.scrollBottom + 1) + 'r'; return this._terminal.handler(`${C0.ESC}P1$r${pt}${C0.ESC}\\`); case 'm': // SGR // TODO: report real settings instead of 0m @@ -124,6 +127,7 @@ export class InputHandler extends Disposable implements IInputHandler { constructor( protected _terminal: IInputHandlingTerminal, + private _bufferService: IBufferService, private _coreService: ICoreService, private _parser: IEscapeSequenceParser = new EscapeSequenceParser()) { @@ -293,7 +297,7 @@ export class InputHandler extends Disposable implements IInputHandler { /** * DCS handler */ - this._parser.setDcsHandler('$q', new DECRQSS(this._terminal)); + this._parser.setDcsHandler('$q', new DECRQSS(this._terminal, this._bufferService)); } public dispose(): void { @@ -312,7 +316,7 @@ export class InputHandler extends Disposable implements IInputHandler { return; } - let buffer = this._terminal.buffer; + let buffer = this._bufferService.buffer; const cursorStartX = buffer.x; const cursorStartY = buffer.y; @@ -326,7 +330,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._parser.parse(this._parseBuffer, this._stringDecoder.decode(data, this._parseBuffer)); - buffer = this._terminal.buffer; + buffer = this._bufferService.buffer; if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) { this._onCursorMove.fire(); } @@ -338,7 +342,7 @@ export class InputHandler extends Disposable implements IInputHandler { return; } - let buffer = this._terminal.buffer; + let buffer = this._bufferService.buffer; const cursorStartX = buffer.x; const cursorStartY = buffer.y; @@ -352,7 +356,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._parser.parse(this._parseBuffer, this._utf8Decoder.decode(data, this._parseBuffer)); - buffer = this._terminal.buffer; + buffer = this._bufferService.buffer; if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) { this._onCursorMove.fire(); } @@ -361,7 +365,7 @@ export class InputHandler extends Disposable implements IInputHandler { public print(data: Uint32Array, start: number, end: number): void { let code: number; let chWidth: number; - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; const charset = this._terminal.charset; const screenReaderMode = this._terminal.options.screenReaderMode; const cols = this._terminal.cols; @@ -510,7 +514,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public lineFeed(): void { // make buffer local for faster access - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; if (this._terminal.options.convertEol) { buffer.x = 0; @@ -533,7 +537,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Carriage Return (Ctrl-M). */ public carriageReturn(): void { - this._terminal.buffer.x = 0; + this._bufferService.buffer.x = 0; } /** @@ -542,8 +546,8 @@ export class InputHandler extends Disposable implements IInputHandler { */ public backspace(): void { this._restrictCursor(); - if (this._terminal.buffer.x > 0) { - this._terminal.buffer.x--; + if (this._bufferService.buffer.x > 0) { + this._bufferService.buffer.x--; } } @@ -552,13 +556,13 @@ export class InputHandler extends Disposable implements IInputHandler { * Horizontal Tab (HT) (Ctrl-I). */ public tab(): void { - if (this._terminal.buffer.x >= this._terminal.cols) { + if (this._bufferService.buffer.x >= this._terminal.cols) { return; } - const originalX = this._terminal.buffer.x; - this._terminal.buffer.x = this._terminal.buffer.nextStop(); + const originalX = this._bufferService.buffer.x; + this._bufferService.buffer.x = this._bufferService.buffer.nextStop(); if (this._terminal.options.screenReaderMode) { - this._terminal.onA11yTabEmitter.fire(this._terminal.buffer.x - originalX); + this._terminal.onA11yTabEmitter.fire(this._bufferService.buffer.x - originalX); } } @@ -584,10 +588,10 @@ export class InputHandler extends Disposable implements IInputHandler { * Restrict cursor to viewport size / scroll margin (origin mode). */ private _restrictCursor(): void { - this._terminal.buffer.x = Math.min(this._terminal.cols - 1, Math.max(0, this._terminal.buffer.x)); - this._terminal.buffer.y = this._terminal.originMode - ? Math.min(this._terminal.buffer.scrollBottom, Math.max(this._terminal.buffer.scrollTop, this._terminal.buffer.y)) - : Math.min(this._terminal.rows - 1, Math.max(0, this._terminal.buffer.y)); + this._bufferService.buffer.x = Math.min(this._terminal.cols - 1, Math.max(0, this._bufferService.buffer.x)); + this._bufferService.buffer.y = this._terminal.originMode + ? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y)) + : Math.min(this._terminal.rows - 1, Math.max(0, this._bufferService.buffer.y)); } /** @@ -595,11 +599,11 @@ export class InputHandler extends Disposable implements IInputHandler { */ private _setCursor(x: number, y: number): void { if (this._terminal.originMode) { - this._terminal.buffer.x = x; - this._terminal.buffer.y = this._terminal.buffer.scrollTop + y; + this._bufferService.buffer.x = x; + this._bufferService.buffer.y = this._bufferService.buffer.scrollTop + y; } else { - this._terminal.buffer.x = x; - this._terminal.buffer.y = y; + this._bufferService.buffer.x = x; + this._bufferService.buffer.y = y; } this._restrictCursor(); } @@ -611,7 +615,7 @@ export class InputHandler extends Disposable implements IInputHandler { // for relative changes we have to make sure we are within 0 .. cols/rows - 1 // before calculating the new position this._restrictCursor(); - this._setCursor(this._terminal.buffer.x + x, this._terminal.buffer.y + y); + this._setCursor(this._bufferService.buffer.x + x, this._bufferService.buffer.y + y); } /** @@ -653,7 +657,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public cursorNextLine(params: IParams): void { this._moveCursor(0, params.params[0] || 1); - this._terminal.buffer.x = 0; + this._bufferService.buffer.x = 0; } /** @@ -663,7 +667,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public cursorPrecedingLine(params: IParams): void { this._moveCursor(0, -(params.params[0] || 1)); - this._terminal.buffer.x = 0; + this._bufferService.buffer.x = 0; } /** @@ -671,7 +675,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Cursor Character Absolute [column] (default = [row,1]) (CHA). */ public cursorCharAbsolute(params: IParams): void { - this._setCursor((params.params[0] || 1) - 1, this._terminal.buffer.y); + this._setCursor((params.params[0] || 1) - 1, this._bufferService.buffer.y); } /** @@ -692,7 +696,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Currently same functionality as CHA. */ public charPosAbsolute(params: IParams): void { - this._setCursor((params.params[0] || 1) - 1, this._terminal.buffer.y); + this._setCursor((params.params[0] || 1) - 1, this._bufferService.buffer.y); } /** @@ -709,7 +713,7 @@ export class InputHandler extends Disposable implements IInputHandler { * [row] (default = [1,column]) */ public linePosAbsolute(params: IParams): void { - this._setCursor(this._terminal.buffer.x, (params.params[0] || 1) - 1); + this._setCursor(this._bufferService.buffer.x, (params.params[0] || 1) - 1); } /** @@ -742,9 +746,9 @@ export class InputHandler extends Disposable implements IInputHandler { public tabClear(params: IParams): void { const param = params.params[0]; if (param === 0) { - delete this._terminal.buffer.tabs[this._terminal.buffer.x]; + delete this._bufferService.buffer.tabs[this._bufferService.buffer.x]; } else if (param === 3) { - this._terminal.buffer.tabs = {}; + this._bufferService.buffer.tabs = {}; } } @@ -753,12 +757,12 @@ export class InputHandler extends Disposable implements IInputHandler { * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT). */ public cursorForwardTab(params: IParams): void { - if (this._terminal.buffer.x >= this._terminal.cols) { + if (this._bufferService.buffer.x >= this._terminal.cols) { return; } let param = params.params[0] || 1; while (param--) { - this._terminal.buffer.x = this._terminal.buffer.nextStop(); + this._bufferService.buffer.x = this._bufferService.buffer.nextStop(); } } @@ -766,13 +770,13 @@ export class InputHandler extends Disposable implements IInputHandler { * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT). */ public cursorBackwardTab(params: IParams): void { - if (this._terminal.buffer.x >= this._terminal.cols) { + if (this._bufferService.buffer.x >= this._terminal.cols) { return; } let param = params.params[0] || 1; // make buffer local for faster access - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; while (param--) { buffer.x = buffer.prevStop(); @@ -788,11 +792,11 @@ 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._terminal.buffer.lines.get(this._terminal.buffer.ybase + y); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); line.replaceCells( start, end, - this._terminal.buffer.getNullCell(this._terminal.eraseAttrData()) + this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData()) ); if (clearWrap) { line.isWrapped = false; @@ -805,8 +809,8 @@ export class InputHandler extends Disposable implements IInputHandler { * @param y row index */ private _resetBufferLine(y: number): void { - const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y); - line.fill(this._terminal.buffer.getNullCell(this._terminal.eraseAttrData())); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + line.fill(this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } @@ -827,22 +831,22 @@ export class InputHandler extends Disposable implements IInputHandler { let j; switch (params.params[0]) { case 0: - j = this._terminal.buffer.y; + j = this._bufferService.buffer.y; this._terminal.updateRange(j); - this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols, this._terminal.buffer.x === 0); + this._eraseInBufferLine(j++, this._bufferService.buffer.x, this._terminal.cols, this._bufferService.buffer.x === 0); for (; j < this._terminal.rows; j++) { this._resetBufferLine(j); } this._terminal.updateRange(j); break; case 1: - j = this._terminal.buffer.y; + j = this._bufferService.buffer.y; this._terminal.updateRange(j); // Deleted front part of line and everything before. This line will no longer be wrapped. - this._eraseInBufferLine(j, 0, this._terminal.buffer.x + 1, true); - if (this._terminal.buffer.x + 1 >= this._terminal.cols) { + this._eraseInBufferLine(j, 0, this._bufferService.buffer.x + 1, true); + if (this._bufferService.buffer.x + 1 >= this._terminal.cols) { // Deleted entire previous line. This next line can no longer be wrapped. - this._terminal.buffer.lines.get(j + 1).isWrapped = false; + this._bufferService.buffer.lines.get(j + 1).isWrapped = false; } while (j--) { this._resetBufferLine(j); @@ -859,11 +863,11 @@ export class InputHandler extends Disposable implements IInputHandler { break; case 3: // Clear scrollback (everything not in viewport) - const scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows; + const scrollBackSize = this._bufferService.buffer.lines.length - this._terminal.rows; if (scrollBackSize > 0) { - this._terminal.buffer.lines.trimStart(scrollBackSize); - this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0); - this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0); + this._bufferService.buffer.lines.trimStart(scrollBackSize); + this._bufferService.buffer.ybase = Math.max(this._bufferService.buffer.ybase - scrollBackSize, 0); + this._bufferService.buffer.ydisp = Math.max(this._bufferService.buffer.ydisp - scrollBackSize, 0); // Force a scroll event to refresh viewport this._onScroll.fire(0); } @@ -886,16 +890,16 @@ export class InputHandler extends Disposable implements IInputHandler { this._restrictCursor(); switch (params.params[0]) { case 0: - this._eraseInBufferLine(this._terminal.buffer.y, this._terminal.buffer.x, this._terminal.cols); + this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._terminal.cols); break; case 1: - this._eraseInBufferLine(this._terminal.buffer.y, 0, this._terminal.buffer.x + 1); + this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._bufferService.buffer.x + 1); break; case 2: - this._eraseInBufferLine(this._terminal.buffer.y, 0, this._terminal.cols); + this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._terminal.cols); break; } - this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._bufferService.buffer.y); } /** @@ -907,7 +911,7 @@ export class InputHandler extends Disposable implements IInputHandler { let param = params.params[0] || 1; // make buffer local for faster access - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { return; @@ -939,7 +943,7 @@ export class InputHandler extends Disposable implements IInputHandler { let param = params.params[0] || 1; // make buffer local for faster access - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { return; @@ -969,14 +973,14 @@ export class InputHandler extends Disposable implements IInputHandler { */ public insertChars(params: IParams): void { this._restrictCursor(); - const line = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase); if (line) { line.insertCells( - this._terminal.buffer.x, + this._bufferService.buffer.x, params.params[0] || 1, - this._terminal.buffer.getNullCell(this._terminal.eraseAttrData()) + this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData()) ); - this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._bufferService.buffer.y); } } @@ -986,14 +990,14 @@ export class InputHandler extends Disposable implements IInputHandler { */ public deleteChars(params: IParams): void { this._restrictCursor(); - const line = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase); if (line) { line.deleteCells( - this._terminal.buffer.x, + this._bufferService.buffer.x, params.params[0] || 1, - this._terminal.buffer.getNullCell(this._terminal.eraseAttrData()) + this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData()) ); - this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._bufferService.buffer.y); } } @@ -1004,7 +1008,7 @@ export class InputHandler extends Disposable implements IInputHandler { let param = params.params[0] || 1; // make buffer local for faster access - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; while (param--) { buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1); @@ -1023,7 +1027,7 @@ export class InputHandler extends Disposable implements IInputHandler { let param = params.params[0] || 1; // make buffer local for faster access - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; while (param--) { buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1); @@ -1041,14 +1045,14 @@ export class InputHandler extends Disposable implements IInputHandler { */ public eraseChars(params: IParams): void { this._restrictCursor(); - const line = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase); + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase); if (line) { line.replaceCells( - this._terminal.buffer.x, - this._terminal.buffer.x + (params.params[0] || 1), - this._terminal.buffer.getNullCell(this._terminal.eraseAttrData()) + this._bufferService.buffer.x, + this._bufferService.buffer.x + (params.params[0] || 1), + this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData()) ); - this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._bufferService.buffer.y); } } @@ -1349,7 +1353,7 @@ export class InputHandler extends Disposable implements IInputHandler { // FALL-THROUGH case 47: // alt screen buffer case 1047: // alt screen buffer - this._terminal.buffers.activateAltBuffer(this._terminal.eraseAttrData()); + this._bufferService.buffers.activateAltBuffer(this._terminal.eraseAttrData()); this._terminal.refresh(0, this._terminal.rows - 1); if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); @@ -1531,7 +1535,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 47: // normal screen buffer case 1047: // normal screen buffer - clearing it first // Ensure the selection manager has the correct buffer - this._terminal.buffers.activateNormalBuffer(); + this._bufferService.buffers.activateNormalBuffer(); if (param === 1049) { this.restoreCursor(); } @@ -1815,8 +1819,8 @@ export class InputHandler extends Disposable implements IInputHandler { break; case 6: // cursor position - const y = this._terminal.buffer.y + 1; - const x = this._terminal.buffer.x + 1; + const y = this._bufferService.buffer.y + 1; + const x = this._bufferService.buffer.x + 1; this._coreService.triggerDataEvent(`${C0.ESC}[${y};${x}R`); break; } @@ -1826,8 +1830,8 @@ export class InputHandler extends Disposable implements IInputHandler { switch (params.params[0]) { case 6: // cursor position - const y = this._terminal.buffer.y + 1; - const x = this._terminal.buffer.x + 1; + const y = this._bufferService.buffer.y + 1; + const x = this._bufferService.buffer.x + 1; this._coreService.triggerDataEvent(`${C0.ESC}[?${y};${x}R`); break; case 15: @@ -1865,10 +1869,10 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.viewport.syncScrollArea(); } this._coreService.decPrivateModes.applicationCursorKeys = false; - this._terminal.buffer.scrollTop = 0; - this._terminal.buffer.scrollBottom = this._terminal.rows - 1; + this._bufferService.buffer.scrollTop = 0; + this._bufferService.buffer.scrollBottom = this._terminal.rows - 1; this._terminal.curAttrData = DEFAULT_ATTR_DATA.clone(); - this._terminal.buffer.x = this._terminal.buffer.y = 0; // ? + this._bufferService.buffer.x = this._bufferService.buffer.y = 0; // ? this._terminal.charset = null; this._terminal.glevel = 0; // ?? this._terminal.charsets = [null]; // ?? @@ -1927,8 +1931,8 @@ export class InputHandler extends Disposable implements IInputHandler { } if (bottom > top) { - this._terminal.buffer.scrollTop = top - 1; - this._terminal.buffer.scrollBottom = bottom - 1; + this._bufferService.buffer.scrollTop = top - 1; + this._bufferService.buffer.scrollBottom = bottom - 1; this._setCursor(0, 0); } } @@ -1940,11 +1944,11 @@ export class InputHandler extends Disposable implements IInputHandler { * Save cursor (ANSI.SYS). */ public saveCursor(params?: IParams): void { - this._terminal.buffer.savedX = this._terminal.buffer.x; - this._terminal.buffer.savedY = this._terminal.buffer.ybase + this._terminal.buffer.y; - this._terminal.buffer.savedCurAttrData.fg = this._terminal.curAttrData.fg; - this._terminal.buffer.savedCurAttrData.bg = this._terminal.curAttrData.bg; - this._terminal.buffer.savedCharset = this._terminal.charset; + this._bufferService.buffer.savedX = this._bufferService.buffer.x; + this._bufferService.buffer.savedY = this._bufferService.buffer.ybase + this._bufferService.buffer.y; + this._bufferService.buffer.savedCurAttrData.fg = this._terminal.curAttrData.fg; + this._bufferService.buffer.savedCurAttrData.bg = this._terminal.curAttrData.bg; + this._bufferService.buffer.savedCharset = this._terminal.charset; } @@ -1954,13 +1958,13 @@ export class InputHandler extends Disposable implements IInputHandler { * Restore cursor (ANSI.SYS). */ public restoreCursor(params?: IParams): void { - this._terminal.buffer.x = this._terminal.buffer.savedX || 0; - this._terminal.buffer.y = Math.max(this._terminal.buffer.savedY - this._terminal.buffer.ybase, 0); - this._terminal.curAttrData.fg = this._terminal.buffer.savedCurAttrData.fg; - this._terminal.curAttrData.bg = this._terminal.buffer.savedCurAttrData.bg; + this._bufferService.buffer.x = this._bufferService.buffer.savedX || 0; + this._bufferService.buffer.y = Math.max(this._bufferService.buffer.savedY - this._bufferService.buffer.ybase, 0); + this._terminal.curAttrData.fg = this._bufferService.buffer.savedCurAttrData.fg; + this._terminal.curAttrData.bg = this._bufferService.buffer.savedCurAttrData.bg; this._terminal.charset = (this as any)._savedCharset; - if (this._terminal.buffer.savedCharset) { - this._terminal.charset = this._terminal.buffer.savedCharset; + if (this._bufferService.buffer.savedCharset) { + this._terminal.charset = this._bufferService.buffer.savedCharset; } this._restrictCursor(); } @@ -1982,7 +1986,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Moves cursor to first position on next line. */ public nextLine(): void { - this._terminal.buffer.x = 0; + this._bufferService.buffer.x = 0; this.index(); } @@ -2059,9 +2063,9 @@ export class InputHandler extends Disposable implements IInputHandler { */ public index(): void { this._restrictCursor(); - this._terminal.buffer.y++; - if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { - this._terminal.buffer.y--; + this._bufferService.buffer.y++; + if (this._bufferService.buffer.y > this._bufferService.buffer.scrollBottom) { + this._bufferService.buffer.y--; this._terminal.scroll(); } this._restrictCursor(); @@ -2075,7 +2079,7 @@ export class InputHandler extends Disposable implements IInputHandler { * the value of the active column when the terminal receives an HTS. */ public tabSet(): void { - this._terminal.buffer.tabs[this._terminal.buffer.x] = true; + this._bufferService.buffer.tabs[this._bufferService.buffer.x] = true; } /** @@ -2087,7 +2091,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public reverseIndex(): void { this._restrictCursor(); - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; if (buffer.y === buffer.scrollTop) { // possibly move the code below to term.reverseScroll(); // test: echo -ne '\e[1;1H\e[44m\eM\e[0m' @@ -2142,7 +2146,7 @@ export class InputHandler extends Disposable implements IInputHandler { cell.fg = this._terminal.curAttrData.fg; cell.bg = this._terminal.curAttrData.bg; - const buffer = this._terminal.buffer; + const buffer = this._bufferService.buffer; this._setCursor(0, 0); for (let yOffset = 0; yOffset < this._terminal.rows; ++yOffset) { diff --git a/src/Terminal.ts b/src/Terminal.ts index f519ae58c6..8c5c2bd8ec 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -297,7 +297,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this._userScrolling = false; // Register input handler and refire/handle events - this._inputHandler = new InputHandler(this, this._coreService); + this._inputHandler = new InputHandler(this, this._bufferService, this._coreService); this._inputHandler.onCursorMove(() => this._onCursorMove.fire()); this._inputHandler.onLineFeed(() => this._onLineFeed.fire()); this.register(this._inputHandler); From 49fa86d6bbf129e0daba53e92998df49309fb2e2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 01:38:02 -0700 Subject: [PATCH 2/9] Get rows/cols in input hander from buffer service --- src/InputHandler.test.ts | 50 +++++++++++++++++----------------- src/InputHandler.ts | 58 ++++++++++++++++++++-------------------- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index ff477b9cc9..352eec7794 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -26,8 +26,6 @@ function getCursor(term: TestTerminal): number[] { describe('InputHandler', () => { describe('save and restore cursor', () => { const terminal = new MockInputHandlingTerminal(); - terminal.cols = 80; - terminal.rows = 30; terminal.curAttrData.fg = 3; const bufferService = new MockBufferService(80, 30); bufferService.buffer.x = 1; @@ -117,37 +115,37 @@ describe('InputHandler', () => { const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // insert some data in first and second line - inputHandler.parse(Array(term.cols - 9).join('a')); + inputHandler.parse(Array(bufferService.cols - 9).join('a')); inputHandler.parse('1234567890'); - inputHandler.parse(Array(term.cols - 9).join('a')); + 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(term.cols - 9).join('a') + '1234567890'); + 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(term.cols - 9).join('a') + ' 123456789'); + 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(term.cols - 9).join('a') + ' 12345678'); + 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(term.cols - 9).join('a') + ' 123456'); + 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(term.cols - 9).join('a') + ' '); - expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a')); + 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(); @@ -155,40 +153,40 @@ describe('InputHandler', () => { const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // insert some data in first and second line - inputHandler.parse(Array(term.cols - 9).join('a')); + inputHandler.parse(Array(bufferService.cols - 9).join('a')); inputHandler.parse('1234567890'); - inputHandler.parse(Array(term.cols - 9).join('a')); + 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(term.cols - 9).join('a') + '1234567890'); + 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(term.cols - 9).join('a') + '234567890 '); - expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a') + '234567890'); + 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(term.cols - 9).join('a') + '34567890 '); - expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a') + '34567890'); + 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(term.cols - 9).join('a') + '567890 '); - expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a') + '567890'); + 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(term.cols - 9).join('a') + ' '); - expect(line1.translateToString(true)).equals(Array(term.cols - 9).join('a')); + 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(); @@ -196,9 +194,9 @@ describe('InputHandler', () => { const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // fill 6 lines to test 3 different states - inputHandler.parse(Array(term.cols + 1).join('a')); - inputHandler.parse(Array(term.cols + 1).join('a')); - inputHandler.parse(Array(term.cols + 1).join('a')); + 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; @@ -216,7 +214,7 @@ describe('InputHandler', () => { bufferService.buffer.y = 2; bufferService.buffer.x = 70; inputHandler.eraseInLine(Params.fromArray([2])); - expect(bufferService.buffer.lines.get(2).translateToString(false)).equals(Array(term.cols + 1).join(' ')); + expect(bufferService.buffer.lines.get(2).translateToString(false)).equals(Array(bufferService.cols + 1).join(' ')); }); it('eraseInDisplay', function(): void { @@ -225,7 +223,7 @@ describe('InputHandler', () => { const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); // fill display with a's - for (let i = 0; i < term.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); + 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; diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 115653548c..507c7d85bb 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -368,7 +368,7 @@ export class InputHandler extends Disposable implements IInputHandler { const buffer = this._bufferService.buffer; const charset = this._terminal.charset; const screenReaderMode = this._terminal.options.screenReaderMode; - const cols = this._terminal.cols; + const cols = this._bufferService.cols; const wraparoundMode = this._terminal.wraparoundMode; const insertMode = this._terminal.insertMode; const curAttr = this._terminal.curAttrData; @@ -525,7 +525,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.scroll(); } // If the end of the line is hit, prevent this action from wrapping around to the next line. - if (buffer.x >= this._terminal.cols) { + if (buffer.x >= this._bufferService.cols) { buffer.x--; } @@ -556,7 +556,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Horizontal Tab (HT) (Ctrl-I). */ public tab(): void { - if (this._bufferService.buffer.x >= this._terminal.cols) { + if (this._bufferService.buffer.x >= this._bufferService.cols) { return; } const originalX = this._bufferService.buffer.x; @@ -588,10 +588,10 @@ 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._terminal.cols - 1, Math.max(0, this._bufferService.buffer.x)); + this._bufferService.buffer.x = Math.min(this._bufferService.cols - 1, Math.max(0, this._bufferService.buffer.x)); this._bufferService.buffer.y = this._terminal.originMode ? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y)) - : Math.min(this._terminal.rows - 1, Math.max(0, this._bufferService.buffer.y)); + : Math.min(this._bufferService.rows - 1, Math.max(0, this._bufferService.buffer.y)); } /** @@ -757,7 +757,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT). */ public cursorForwardTab(params: IParams): void { - if (this._bufferService.buffer.x >= this._terminal.cols) { + if (this._bufferService.buffer.x >= this._bufferService.cols) { return; } let param = params.params[0] || 1; @@ -770,7 +770,7 @@ export class InputHandler extends Disposable implements IInputHandler { * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT). */ public cursorBackwardTab(params: IParams): void { - if (this._bufferService.buffer.x >= this._terminal.cols) { + if (this._bufferService.buffer.x >= this._bufferService.cols) { return; } let param = params.params[0] || 1; @@ -833,8 +833,8 @@ export class InputHandler extends Disposable implements IInputHandler { case 0: j = this._bufferService.buffer.y; this._terminal.updateRange(j); - this._eraseInBufferLine(j++, this._bufferService.buffer.x, this._terminal.cols, this._bufferService.buffer.x === 0); - for (; j < this._terminal.rows; j++) { + this._eraseInBufferLine(j++, this._bufferService.buffer.x, this._bufferService.cols, this._bufferService.buffer.x === 0); + for (; j < this._bufferService.rows; j++) { this._resetBufferLine(j); } this._terminal.updateRange(j); @@ -844,7 +844,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.updateRange(j); // Deleted front part of line and everything before. This line will no longer be wrapped. this._eraseInBufferLine(j, 0, this._bufferService.buffer.x + 1, true); - if (this._bufferService.buffer.x + 1 >= this._terminal.cols) { + 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; } @@ -854,7 +854,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.updateRange(0); break; case 2: - j = this._terminal.rows; + j = this._bufferService.rows; this._terminal.updateRange(j - 1); while (j--) { this._resetBufferLine(j); @@ -863,7 +863,7 @@ export class InputHandler extends Disposable implements IInputHandler { break; case 3: // Clear scrollback (everything not in viewport) - const scrollBackSize = this._bufferService.buffer.lines.length - this._terminal.rows; + const scrollBackSize = this._bufferService.buffer.lines.length - this._bufferService.rows; if (scrollBackSize > 0) { this._bufferService.buffer.lines.trimStart(scrollBackSize); this._bufferService.buffer.ybase = Math.max(this._bufferService.buffer.ybase - scrollBackSize, 0); @@ -890,13 +890,13 @@ export class InputHandler extends Disposable implements IInputHandler { this._restrictCursor(); switch (params.params[0]) { case 0: - this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._terminal.cols); + this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._bufferService.cols); break; case 1: this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._bufferService.buffer.x + 1); break; case 2: - this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._terminal.cols); + this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._bufferService.cols); break; } this._terminal.updateRange(this._bufferService.buffer.y); @@ -919,8 +919,8 @@ export class InputHandler extends Disposable implements IInputHandler { const row: number = buffer.y + buffer.ybase; - const scrollBottomRowsOffset = this._terminal.rows - 1 - buffer.scrollBottom; - const scrollBottomAbsolute = this._terminal.rows - 1 + buffer.ybase - scrollBottomRowsOffset + 1; + const scrollBottomRowsOffset = this._bufferService.rows - 1 - buffer.scrollBottom; + const scrollBottomAbsolute = this._bufferService.rows - 1 + buffer.ybase - scrollBottomRowsOffset + 1; while (param--) { // test: echo -e '\e[44m\e[1L\e[0m' // blankLine(true) - xterm/linux behavior @@ -952,8 +952,8 @@ export class InputHandler extends Disposable implements IInputHandler { const row: number = buffer.y + buffer.ybase; let j: number; - j = this._terminal.rows - 1 - buffer.scrollBottom; - j = this._terminal.rows - 1 + buffer.ybase - j; + j = this._bufferService.rows - 1 - buffer.scrollBottom; + j = this._bufferService.rows - 1 + buffer.ybase - j; while (param--) { // test: echo -e '\e[44m\e[1M\e[0m' // blankLine(true) - xterm/linux behavior @@ -1273,8 +1273,8 @@ export class InputHandler extends Disposable implements IInputHandler { break; case 3: // 132 col mode // TODO: move DECCOLM into compat addon - this._terminal.savedCols = this._terminal.cols; - this._terminal.resize(132, this._terminal.rows); + this._terminal.savedCols = this._bufferService.cols; + this._terminal.resize(132, this._bufferService.rows); this._terminal.reset(); break; case 6: @@ -1354,7 +1354,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 47: // alt screen buffer case 1047: // alt screen buffer this._bufferService.buffers.activateAltBuffer(this._terminal.eraseAttrData()); - this._terminal.refresh(0, this._terminal.rows - 1); + this._terminal.refresh(0, this._bufferService.rows - 1); if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); } @@ -1474,8 +1474,8 @@ export class InputHandler extends Disposable implements IInputHandler { // TODO: move DECCOLM into compat addon // Note: This impl currently does not enforce col 80, instead reverts // to previous terminal width before entering DECCOLM 132 - if (this._terminal.cols === 132 && this._terminal.savedCols) { - this._terminal.resize(this._terminal.savedCols, this._terminal.rows); + if (this._bufferService.cols === 132 && this._terminal.savedCols) { + this._terminal.resize(this._terminal.savedCols, this._bufferService.rows); } delete this._terminal.savedCols; this._terminal.reset(); @@ -1539,7 +1539,7 @@ export class InputHandler extends Disposable implements IInputHandler { if (param === 1049) { this.restoreCursor(); } - this._terminal.refresh(0, this._terminal.rows - 1); + this._terminal.refresh(0, this._bufferService.rows - 1); if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); } @@ -1870,7 +1870,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._coreService.decPrivateModes.applicationCursorKeys = false; this._bufferService.buffer.scrollTop = 0; - this._bufferService.buffer.scrollBottom = this._terminal.rows - 1; + this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1; this._terminal.curAttrData = DEFAULT_ATTR_DATA.clone(); this._bufferService.buffer.x = this._bufferService.buffer.y = 0; // ? this._terminal.charset = null; @@ -1926,8 +1926,8 @@ export class InputHandler extends Disposable implements IInputHandler { const top = params.params[0] || 1; let bottom: number; - if (params.length < 2 || (bottom = params.params[1]) > this._terminal.rows || bottom === 0) { - bottom = this._terminal.rows; + if (params.length < 2 || (bottom = params.params[1]) > this._bufferService.rows || bottom === 0) { + bottom = this._bufferService.rows; } if (bottom > top) { @@ -2149,13 +2149,13 @@ export class InputHandler extends Disposable implements IInputHandler { const buffer = this._bufferService.buffer; this._setCursor(0, 0); - for (let yOffset = 0; yOffset < this._terminal.rows; ++yOffset) { + 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; } this._terminal.updateRange(0); - this._terminal.updateRange(this._terminal.rows); + this._terminal.updateRange(this._bufferService.rows); this._setCursor(0, 0); } } From af9c050e93bc347868c8dcf689411f1fd5ca9ae9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 01:46:01 -0700 Subject: [PATCH 3/9] Remove ITerminal usage in DECRQSS --- src/InputHandler.test.ts | 20 ++++++++++---------- src/InputHandler.ts | 29 ++++++++++++++++------------- src/Terminal.ts | 2 +- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 352eec7794..2b274811fb 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -13,7 +13,7 @@ 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 } from 'common/TestUtils.test'; +import { MockCoreService, MockBufferService, MockOptionsService } from 'common/TestUtils.test'; import { IBufferService } from 'common/services/Services'; function getCursor(term: TestTerminal): number[] { @@ -31,7 +31,7 @@ describe('InputHandler', () => { bufferService.buffer.x = 1; bufferService.buffer.y = 2; bufferService.buffer.ybase = 0; - const inputHandler = new InputHandler(terminal, bufferService, new MockCoreService()); + const inputHandler = new InputHandler(terminal, bufferService, new MockCoreService(), new MockOptionsService()); // Save cursor position inputHandler.saveCursor(); assert.equal(bufferService.buffer.x, 1); @@ -50,7 +50,7 @@ describe('InputHandler', () => { describe('setCursorStyle', () => { it('should call Terminal.setOption with correct params', () => { const terminal = new MockInputHandlingTerminal(); - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService()); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockOptionsService()); const collect = ' '; inputHandler.setCursorStyle(Params.fromArray([0]), collect); @@ -93,7 +93,7 @@ describe('InputHandler', () => { const terminal = new MockInputHandlingTerminal(); const collect = '?'; terminal.bracketedPasteMode = false; - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService()); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockOptionsService()); // Set bracketed paste mode inputHandler.setMode(Params.fromArray([2004]), collect); assert.equal(terminal.bracketedPasteMode, true); @@ -112,7 +112,7 @@ describe('InputHandler', () => { it('insertChars', function(): void { const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -150,7 +150,7 @@ describe('InputHandler', () => { it('deleteChars', function(): void { const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -191,7 +191,7 @@ describe('InputHandler', () => { it('eraseInLine', function(): void { const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCoreService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); // fill 6 lines to test 3 different states inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -220,7 +220,7 @@ 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 MockCoreService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); // fill display with a's for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -355,7 +355,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 MockCoreService()); + const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCoreService(), new MockOptionsService()); const container = new Uint32Array(10); container[0] = 0x200B; inputHandler.print(container, 0, 1); @@ -370,7 +370,7 @@ describe('InputHandler', () => { beforeEach(() => { term = new Terminal(); bufferService = new MockBufferService(80, 30); - handler = new InputHandler(term, bufferService, new MockCoreService()); + handler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); }); 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 507c7d85bb..9b09ad8347 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -19,7 +19,7 @@ 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 } from 'common/Types'; -import { ICoreService, IBufferService } from 'common/services/Services'; +import { ICoreService, IBufferService, IOptionsService } from 'common/services/Services'; import { ISelectionService } from 'browser/services/Services'; /** @@ -42,8 +42,9 @@ class DECRQSS implements IDcsHandler { private _data: Uint32Array = new Uint32Array(0); constructor( - private _terminal: any, - private _bufferService: IBufferService + private _bufferService: IBufferService, + private _coreService: ICoreService, + private _optionsService: IOptionsService ) { } hook(collect: string, params: IParams, flag: number): void { @@ -60,25 +61,26 @@ class DECRQSS implements IDcsHandler { switch (data) { // valid: DCS 1 $ r Pt ST (xterm) case '"q': // DECSCA - return this._terminal.handler(`${C0.ESC}P1$r0"q${C0.ESC}\\`); + return this._coreService.triggerDataEvent(`${C0.ESC}P1$r0"q${C0.ESC}\\`); case '"p': // DECSCL - return this._terminal.handler(`${C0.ESC}P1$r61"p${C0.ESC}\\`); + return this._coreService.triggerDataEvent(`${C0.ESC}P1$r61"p${C0.ESC}\\`); case 'r': // DECSTBM const pt = '' + (this._bufferService.buffer.scrollTop + 1) + ';' + (this._bufferService.buffer.scrollBottom + 1) + 'r'; - return this._terminal.handler(`${C0.ESC}P1$r${pt}${C0.ESC}\\`); + return this._coreService.triggerDataEvent(`${C0.ESC}P1$r${pt}${C0.ESC}\\`); case 'm': // SGR // TODO: report real settings instead of 0m - return this._terminal.handler(`${C0.ESC}P1$r0m${C0.ESC}\\`); + return this._coreService.triggerDataEvent(`${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.handler(`${C0.ESC}P1$r${style} q${C0.ESC}\\`); + let style = STYLES[this._optionsService.options.cursorStyle]; + style -= this._optionsService.options.cursorBlink ? 1 : 0; + return this._coreService.triggerDataEvent(`${C0.ESC}P1$r${style} q${C0.ESC}\\`); default: // invalid: DCS 0 $ r Pt ST (xterm) - this._terminal.error('Unknown DCS $q %s', data); - this._terminal.handler(`${C0.ESC}P0$r${C0.ESC}\\`); + // TODO: Move this into a log service + console.error('Unknown DCS $q %s', data); + this._coreService.triggerDataEvent(`${C0.ESC}P0$r${C0.ESC}\\`); } } } @@ -129,6 +131,7 @@ export class InputHandler extends Disposable implements IInputHandler { protected _terminal: IInputHandlingTerminal, private _bufferService: IBufferService, private _coreService: ICoreService, + private _optionsService: IOptionsService, private _parser: IEscapeSequenceParser = new EscapeSequenceParser()) { super(); @@ -297,7 +300,7 @@ export class InputHandler extends Disposable implements IInputHandler { /** * DCS handler */ - this._parser.setDcsHandler('$q', new DECRQSS(this._terminal, this._bufferService)); + this._parser.setDcsHandler('$q', new DECRQSS(this._bufferService, this._coreService, this._optionsService)); } public dispose(): void { diff --git a/src/Terminal.ts b/src/Terminal.ts index 8c5c2bd8ec..c79d871ab3 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -297,7 +297,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this._userScrolling = false; // Register input handler and refire/handle events - this._inputHandler = new InputHandler(this, this._bufferService, this._coreService); + this._inputHandler = new InputHandler(this, this._bufferService, this._coreService, this.optionsService); this._inputHandler.onCursorMove(() => this._onCursorMove.fire()); this._inputHandler.onLineFeed(() => this._onLineFeed.fire()); this.register(this._inputHandler); From 94199ae124870bd2cd94379c33015f6bc6f1e66c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 09:36:21 -0700 Subject: [PATCH 4/9] Introduce logLevel option Part of #1560 --- src/InputHandler.test.ts | 20 +++---- src/InputHandler.ts | 40 +++++++------- src/Terminal.ts | 7 ++- src/common/TestUtils.test.ts | 9 +++- src/common/services/LogService.ts | 78 +++++++++++++++++++++++++++ src/common/services/OptionsService.ts | 1 + src/common/services/Services.d.ts | 13 ++++- typings/xterm.d.ts | 17 ++++++ 8 files changed, 148 insertions(+), 37 deletions(-) create mode 100644 src/common/services/LogService.ts diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 2b274811fb..53d0bc4966 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -13,7 +13,7 @@ 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, MockOptionsService } from 'common/TestUtils.test'; +import { MockCoreService, MockBufferService, MockOptionsService, MockLogService } from 'common/TestUtils.test'; import { IBufferService } from 'common/services/Services'; function getCursor(term: TestTerminal): number[] { @@ -31,7 +31,7 @@ describe('InputHandler', () => { bufferService.buffer.x = 1; bufferService.buffer.y = 2; bufferService.buffer.ybase = 0; - const inputHandler = new InputHandler(terminal, bufferService, new MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(terminal, bufferService, new MockCoreService(), new MockLogService(), new MockOptionsService()); // Save cursor position inputHandler.saveCursor(); assert.equal(bufferService.buffer.x, 1); @@ -50,7 +50,7 @@ describe('InputHandler', () => { describe('setCursorStyle', () => { it('should call Terminal.setOption with correct params', () => { const terminal = new MockInputHandlingTerminal(); - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockLogService(), new MockOptionsService()); const collect = ' '; inputHandler.setCursorStyle(Params.fromArray([0]), collect); @@ -93,7 +93,7 @@ describe('InputHandler', () => { const terminal = new MockInputHandlingTerminal(); const collect = '?'; terminal.bracketedPasteMode = false; - const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(terminal, new MockBufferService(80, 30), new MockCoreService(), new MockLogService(), new MockOptionsService()); // Set bracketed paste mode inputHandler.setMode(Params.fromArray([2004]), collect); assert.equal(terminal.bracketedPasteMode, true); @@ -112,7 +112,7 @@ describe('InputHandler', () => { it('insertChars', function(): void { const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockLogService(), new MockOptionsService()); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -150,7 +150,7 @@ describe('InputHandler', () => { it('deleteChars', function(): void { const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockLogService(), new MockOptionsService()); // insert some data in first and second line inputHandler.parse(Array(bufferService.cols - 9).join('a')); @@ -191,7 +191,7 @@ describe('InputHandler', () => { it('eraseInLine', function(): void { const term = new Terminal(); const bufferService = new MockBufferService(80, 30); - const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockLogService(), new MockOptionsService()); // fill 6 lines to test 3 different states inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -220,7 +220,7 @@ 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 MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(term, bufferService, new MockCoreService(), new MockLogService(), new MockOptionsService()); // fill display with a's for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a')); @@ -355,7 +355,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 MockCoreService(), new MockOptionsService()); + const inputHandler = new InputHandler(term, new MockBufferService(80, 30), new MockCoreService(), new MockLogService(), new MockOptionsService()); const container = new Uint32Array(10); container[0] = 0x200B; inputHandler.print(container, 0, 1); @@ -370,7 +370,7 @@ describe('InputHandler', () => { beforeEach(() => { term = new Terminal(); bufferService = new MockBufferService(80, 30); - handler = new InputHandler(term, bufferService, new MockCoreService(), new MockOptionsService()); + handler = new InputHandler(term, bufferService, new MockCoreService(), new MockLogService(), new MockOptionsService()); }); 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 9b09ad8347..da94209d49 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -19,7 +19,7 @@ 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 } from 'common/Types'; -import { ICoreService, IBufferService, IOptionsService } from 'common/services/Services'; +import { ICoreService, IBufferService, IOptionsService, ILogService } from 'common/services/Services'; import { ISelectionService } from 'browser/services/Services'; /** @@ -44,6 +44,7 @@ class DECRQSS implements IDcsHandler { constructor( private _bufferService: IBufferService, private _coreService: ICoreService, + private _logService: ILogService, private _optionsService: IOptionsService ) { } @@ -78,8 +79,7 @@ class DECRQSS implements IDcsHandler { return this._coreService.triggerDataEvent(`${C0.ESC}P1$r${style} q${C0.ESC}\\`); default: // invalid: DCS 0 $ r Pt ST (xterm) - // TODO: Move this into a log service - console.error('Unknown DCS $q %s', data); + this._logService.error('Unknown DCS $q %s', data); this._coreService.triggerDataEvent(`${C0.ESC}P0$r${C0.ESC}\\`); } } @@ -131,6 +131,7 @@ export class InputHandler extends Disposable implements IInputHandler { protected _terminal: IInputHandlingTerminal, private _bufferService: IBufferService, private _coreService: ICoreService, + private _logService: ILogService, private _optionsService: IOptionsService, private _parser: IEscapeSequenceParser = new EscapeSequenceParser()) { @@ -142,16 +143,16 @@ export class InputHandler extends Disposable implements IInputHandler { * custom fallback handlers */ this._parser.setCsiHandlerFallback((collect: string, params: IParams, flag: number) => { - this._terminal.error('Unknown CSI code: ', { collect, params: params.toArray(), flag: String.fromCharCode(flag) }); + this._logService.error('Unknown CSI code: ', { collect, params: params.toArray(), flag: String.fromCharCode(flag) }); }); this._parser.setEscHandlerFallback((collect: string, flag: number) => { - this._terminal.error('Unknown ESC code: ', { collect, flag: String.fromCharCode(flag) }); + this._logService.error('Unknown ESC code: ', { collect, flag: String.fromCharCode(flag) }); }); this._parser.setExecuteHandlerFallback((code: number) => { - this._terminal.error('Unknown EXECUTE code: ', { code }); + this._logService.error('Unknown EXECUTE code: ', { code }); }); this._parser.setOscHandlerFallback((identifier: number, data: string) => { - this._terminal.error('Unknown OSC code: ', { identifier, data }); + this._logService.error('Unknown OSC code: ', { identifier, data }); }); /** @@ -293,14 +294,14 @@ export class InputHandler extends Disposable implements IInputHandler { * error handler */ this._parser.setErrorHandler((state: IParsingState) => { - this._terminal.error('Parsing error: ', state); + this._logService.error('Parsing error: ', state); return state; }); /** * DCS handler */ - this._parser.setDcsHandler('$q', new DECRQSS(this._bufferService, this._coreService, this._optionsService)); + this._parser.setDcsHandler('$q', new DECRQSS(this._bufferService, this._coreService, this._logService, this._optionsService)); } public dispose(): void { @@ -323,10 +324,7 @@ export class InputHandler extends Disposable implements IInputHandler { const cursorStartX = buffer.x; const cursorStartY = buffer.y; - // TODO: Consolidate debug/logging #1560 - if ((this._terminal).debug) { - this._terminal.log('data: ' + data); - } + this._logService.debug('data: ' + data); if (this._parseBuffer.length < data.length) { this._parseBuffer = new Uint32Array(data.length); @@ -350,9 +348,7 @@ export class InputHandler extends Disposable implements IInputHandler { const cursorStartY = buffer.y; // TODO: Consolidate debug/logging #1560 - if ((this._terminal).debug) { - this._terminal.log('data: ' + data); - } + this._logService.debug('data: ' + data); if (this._parseBuffer.length < data.length) { this._parseBuffer = new Uint32Array(data.length); @@ -1291,7 +1287,7 @@ export class InputHandler extends Disposable implements IInputHandler { // this.cursorBlink = true; break; case 66: - this._terminal.log('Serial port requested application keypad.'); + this._logService.info('Serial port requested application keypad.'); this._terminal.applicationKeypad = true; if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); @@ -1319,7 +1315,7 @@ export class InputHandler extends Disposable implements IInputHandler { if (this._selectionService) { this._selectionService.disable(); } - this._terminal.log('Binding to mouse events.'); + this._logService.info('Binding to mouse events.'); break; case 1004: // send focusin/focusout events // focusin: ^[[I @@ -1494,7 +1490,7 @@ export class InputHandler extends Disposable implements IInputHandler { // this.cursorBlink = false; break; case 66: - this._terminal.log('Switching back to normal keypad.'); + this._logService.info('Switching back to normal keypad.'); this._terminal.applicationKeypad = false; if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); @@ -1785,7 +1781,7 @@ export class InputHandler extends Disposable implements IInputHandler { attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK); attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK); } else { - this._terminal.error('Unknown SGR attribute: %d.', p); + this._logService.error('Unknown SGR attribute: %d.', p); } } } @@ -1999,7 +1995,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Enables the numeric keypad to send application sequences to the host. */ public keypadApplicationMode(): void { - this._terminal.log('Serial port requested application keypad.'); + this._logService.info('Serial port requested application keypad.'); this._terminal.applicationKeypad = true; if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); @@ -2012,7 +2008,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Enables the keypad to send numeric characters to the host. */ public keypadNumericMode(): void { - this._terminal.log('Switching back to normal keypad.'); + this._logService.info('Switching back to normal keypad.'); this._terminal.applicationKeypad = false; if (this._terminal.viewport) { this._terminal.viewport.syncScrollArea(); diff --git a/src/Terminal.ts b/src/Terminal.ts index c79d871ab3..8fc41263b1 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -47,7 +47,7 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { applyWindowsMode } from './WindowsMode'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; -import { IOptionsService, IBufferService, ICoreService } from 'common/services/Services'; +import { IOptionsService, IBufferService, ICoreService, ILogService } from 'common/services/Services'; import { OptionsService } from 'common/services/OptionsService'; import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService } from 'browser/services/Services'; import { CharSizeService } from 'browser/services/CharSizeService'; @@ -58,6 +58,7 @@ import { Attributes } from 'common/buffer/Constants'; import { MouseService } from 'browser/services/MouseService'; import { IParams } from 'common/parser/Types'; import { CoreService } from 'common/services/CoreService'; +import { LogService } from 'common/services/LogService'; // Let it work inside Node.js for automated testing purposes. const document = (typeof window !== 'undefined') ? window.document : null; @@ -110,6 +111,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp // common services private _bufferService: IBufferService; private _coreService: ICoreService; + private _logService: ILogService; public optionsService: IOptionsService; // browser services @@ -241,6 +243,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this._bufferService = new BufferService(this.optionsService); this._coreService = new CoreService(() => this.scrollToBottom(), this._bufferService, this.optionsService); this._coreService.onData(e => this._onData.fire(e)); + this._logService = new LogService(this.optionsService); this._setupOptionsListeners(); this._setup(); @@ -297,7 +300,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this._userScrolling = false; // Register input handler and refire/handle events - this._inputHandler = new InputHandler(this, this._bufferService, this._coreService, this.optionsService); + this._inputHandler = new InputHandler(this, this._bufferService, this._coreService, this._logService, this.optionsService); this._inputHandler.onCursorMove(() => this._onCursorMove.fire()); this._inputHandler.onLineFeed(() => this._onLineFeed.fire()); this.register(this._inputHandler); diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index e3a6c9b9ab..c786a06d60 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IBufferService, ICoreService, IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services'; +import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services'; import { IEvent, EventEmitter } from 'common/EventEmitter'; import { clone } from 'common/Clone'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; @@ -36,6 +36,13 @@ export class MockCoreService implements ICoreService { triggerDataEvent(data: string, wasUserInput?: boolean): void {} } +export class MockLogService implements ILogService { + debug(message: any, ...optionalParams: any[]): void {} + info(message: any, ...optionalParams: any[]): void {} + warn(message: any, ...optionalParams: any[]): void {} + error(message: any, ...optionalParams: any[]): void {} +} + export class MockOptionsService implements IOptionsService { options: ITerminalOptions = clone(DEFAULT_OPTIONS); onOptionChange: IEvent = new EventEmitter().event; diff --git a/src/common/services/LogService.ts b/src/common/services/LogService.ts new file mode 100644 index 0000000000..78e59e1c77 --- /dev/null +++ b/src/common/services/LogService.ts @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ILogService, IOptionsService } from 'common/services/Services'; + +interface IConsole { + log(message?: any, ...optionalParams: any[]): void; + error(message?: any, ...optionalParams: any[]): void; + info(message?: any, ...optionalParams: any[]): void; + trace(message?: any, ...optionalParams: any[]): void; + warn(message?: any, ...optionalParams: any[]): void; +} + +// console is available on both node.js and browser contexts but the common +// module doesn't depend on them so we need to explicitly declare it. +declare const console: IConsole; + + +export enum LogLevel { + Debug = 0, + Info = 1, + Warn = 2, + Error = 3, + Off = 4 +} + +const optionsKeyToLogLevel: { [key: string]: LogLevel } = { + debug: LogLevel.Debug, + info: LogLevel.Info, + warn: LogLevel.Warn, + error: LogLevel.Error, + off: LogLevel.Off +}; + +export class LogService implements ILogService { + private _logLevel!: LogLevel; + + constructor( + private readonly _optionsService: IOptionsService + ) { + this._updateLogLevel(); + this._optionsService.onOptionChange(key => { + if (key === 'logLevel') { + this._updateLogLevel(); + } + }) + } + + private _updateLogLevel(): void { + this._logLevel = optionsKeyToLogLevel[this._optionsService.options.logLevel]; + } + + debug(message: any, ...optionalParams: any[]): void { + if (this._logLevel <= LogLevel.Debug) { + console.log.call(console, message, optionalParams); + } + } + + info(message: any, ...optionalParams: any[]): void { + if (this._logLevel <= LogLevel.Info) { + console.info.call(console, message, optionalParams); + } + } + + warn(message: any, ...optionalParams: any[]): void { + if (this._logLevel <= LogLevel.Warn) { + console.warn.call(console, message, optionalParams); + } + } + + error(message: any, ...optionalParams: any[]): void { + if (this._logLevel <= LogLevel.Error) { + console.error.call(console, message, optionalParams); + } + } +} diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index ab04148822..8b58de8db7 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -29,6 +29,7 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ fontWeightBold: 'bold', lineHeight: 1.0, letterSpacing: 0, + logLevel: 'info', scrollback: 1000, screenReaderMode: false, macOptionIsMeta: false, diff --git a/src/common/services/Services.d.ts b/src/common/services/Services.d.ts index f46f3d76f3..9ef5defc30 100644 --- a/src/common/services/Services.d.ts +++ b/src/common/services/Services.d.ts @@ -38,6 +38,13 @@ export interface ICoreService { triggerDataEvent(data: string, wasUserInput?: boolean): void; } +export interface ILogService { + debug(message: any, ...optionalParams: any[]): void; + info(message: any, ...optionalParams: any[]): void; + warn(message: any, ...optionalParams: any[]): void; + error(message: any, ...optionalParams: any[]): void; +} + export interface IOptionsService { readonly options: ITerminalOptions; @@ -48,7 +55,7 @@ export interface IOptionsService { } export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; - +export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off'; export type RendererType = 'dom' | 'canvas'; export interface IPartialTerminalOptions { @@ -66,6 +73,7 @@ export interface IPartialTerminalOptions { fontWeightBold?: FontWeight; letterSpacing?: number; lineHeight?: number; + logLevel?: LogLevel; macOptionIsMeta?: boolean; macOptionClickForcesSelection?: boolean; rendererType?: RendererType; @@ -86,6 +94,7 @@ export interface ITerminalOptions { cols: number; cursorBlink: boolean; cursorStyle: 'block' | 'underline' | 'bar'; + debug: boolean; disableStdin: boolean; drawBoldTextInBrightColors: boolean; fontSize: number; @@ -94,6 +103,7 @@ export interface ITerminalOptions { fontWeightBold: FontWeight; letterSpacing: number; lineHeight: number; + logLevel: LogLevel; macOptionIsMeta: boolean; macOptionClickForcesSelection: boolean; rendererType: RendererType; @@ -109,7 +119,6 @@ export interface ITerminalOptions { [key: string]: any; cancelEvents: boolean; convertEol: boolean; - debug: boolean; screenKeys: boolean; termName: string; useFlowControl: boolean; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index c915a4ba71..c4062db85b 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -15,6 +15,11 @@ declare module 'xterm' { */ export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + /** + * A string representing log level. + */ + export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off'; + /** * A string representing a renderer type. */ @@ -107,6 +112,18 @@ declare module 'xterm' { */ lineHeight?: number; + /** + * What log level to use, this will log for all levels below and including + * what is set: + * + * 1. debug + * 2. info (default) + * 3. warn + * 4. error + * 5. off + */ + logLevel?: LogLevel; + /** * Whether to treat option as the meta key. */ From 2977a53cc1340982d31276e898f4ad5d4280567f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 09:44:12 -0700 Subject: [PATCH 5/9] Use log service everywhere, fix log printing Fixes #1560 --- addons/xterm-addon-webgl/src/WebglUtils.ts | 4 ++-- demo/client.ts | 1 + src/InputHandler.ts | 4 ++-- src/Linkifier.test.ts | 3 ++- src/Linkifier.ts | 6 +++-- src/Terminal.ts | 23 +------------------ src/Types.d.ts | 3 --- src/browser/services/SelectionService.test.ts | 3 --- src/common/services/LogService.ts | 8 +++---- 9 files changed, 16 insertions(+), 39 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglUtils.ts b/addons/xterm-addon-webgl/src/WebglUtils.ts index ff62388e54..841ad067bb 100644 --- a/addons/xterm-addon-webgl/src/WebglUtils.ts +++ b/addons/xterm-addon-webgl/src/WebglUtils.ts @@ -24,7 +24,7 @@ export function createProgram(gl: WebGLRenderingContext, vertexSource: string, f return program; } - console.log(gl.getProgramInfoLog(program)); + console.error(gl.getProgramInfoLog(program)); gl.deleteProgram(program); } @@ -37,7 +37,7 @@ export function createShader(gl: WebGLRenderingContext, type: number, source: st return shader; } - console.log(gl.getShaderInfoLog(shader)); + console.error(gl.getShaderInfoLog(shader)); gl.deleteShader(shader); } diff --git a/demo/client.ts b/demo/client.ts index e2259841f7..3bd96c8c0a 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -235,6 +235,7 @@ function initOptions(term: TerminalType): void { fontFamily: null, fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], + logLevel: ['debug', 'info', 'warn', 'error', 'off'], rendererType: ['dom', 'canvas'], wordSeparator: null }; diff --git a/src/InputHandler.ts b/src/InputHandler.ts index da94209d49..f554a9adaa 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -324,7 +324,7 @@ export class InputHandler extends Disposable implements IInputHandler { const cursorStartX = buffer.x; const cursorStartY = buffer.y; - this._logService.debug('data: ' + data); + this._logService.debug('parsing data', data); if (this._parseBuffer.length < data.length) { this._parseBuffer = new Uint32Array(data.length); @@ -348,7 +348,7 @@ export class InputHandler extends Disposable implements IInputHandler { const cursorStartY = buffer.y; // TODO: Consolidate debug/logging #1560 - this._logService.debug('data: ' + data); + this._logService.debug('parsing data', data); if (this._parseBuffer.length < data.length) { this._parseBuffer = new Uint32Array(data.length); diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 9e6588af84..ac1fb8b3c0 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -11,10 +11,11 @@ import { MockBuffer, MockTerminal, TestTerminal } from './TestUtils.test'; import { CircularList } from 'common/CircularList'; import { BufferLine } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; +import { MockLogService } from 'common/TestUtils.test'; class TestLinkifier extends Linkifier { constructor(terminal: ITerminal) { - super(terminal); + super(terminal, new MockLogService()); Linkifier._timeBeforeLatency = 0; } diff --git a/src/Linkifier.ts b/src/Linkifier.ts index ded6f87a95..5398d3c59d 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -8,6 +8,7 @@ import { IBufferStringIteratorResult } from 'common/buffer/Types'; import { MouseZone } from './MouseZoneManager'; import { getStringCellWidth } from 'common/CharWidth'; import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { ILogService } from 'common/services/Services'; /** * Limit of the unwrapping line expansion (overscan) at the top and bottom @@ -42,7 +43,8 @@ export class Linkifier implements ILinkifier { public get onLinkTooltip(): IEvent { return this._onLinkTooltip.event; } constructor( - protected _terminal: ITerminal + protected _terminal: ITerminal, + private _logService: ILogService ) { this._rowsToLinkify = { start: null, @@ -212,7 +214,7 @@ export class Linkifier implements ILinkifier { // since this is most likely a bug the regex itself we simply do nothing here // DEBUG: print match and throw if ((this._terminal).debug) { - console.log({match, matcher}); + this._logService.error({ match, matcher }); throw new Error('match found without corresponding matchIndex'); } break; diff --git a/src/Terminal.ts b/src/Terminal.ts index 8fc41263b1..a8912b3fe3 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -88,7 +88,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp * The HTMLElement that the terminal is created in, set by Terminal.open. */ private _parent: HTMLElement; - private _context: Window; private _document: Document; private _viewportScrollArea: HTMLElement; private _viewportElement: HTMLElement; @@ -306,7 +305,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this.register(this._inputHandler); this._selectionService = this._selectionService || null; - this.linkifier = this.linkifier || new Linkifier(this); + this.linkifier = this.linkifier || new Linkifier(this, this._logService); this._mouseZoneManager = this._mouseZoneManager || null; if (this.options.windowsMode) { @@ -537,8 +536,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp throw new Error('Terminal requires a parent element.'); } - // Grab global elements - this._context = this._parent.ownerDocument.defaultView; this._document = this._parent.ownerDocument; // Create main element container @@ -1679,24 +1676,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp } } - /** - * Log the current state to the console. - */ - public log(text: string, data?: any): void { - if (!this.options.debug) return; - if (!this._context.console || !this._context.console.log) return; - this._context.console.log(text, data); - } - - /** - * Log the current state as error to the console. - */ - public error(text: string, data?: any): void { - if (!this.options.debug) return; - if (!this._context.console || !this._context.console.error) return; - this._context.console.error(text, data); - } - /** * Resizes the terminal. * diff --git a/src/Types.d.ts b/src/Types.d.ts index 0614d62634..238f70dc47 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -65,11 +65,9 @@ export interface IInputHandlingTerminal { is(term: string): boolean; setgCharset(g: number, charset: ICharset): void; resize(x: number, y: number): void; - log(text: string, data?: any): void; reset(): void; showCursor(): void; refresh(start: number, end: number): void; - error(text: string, data?: any): void; handleTitle(title: string): void; } @@ -212,7 +210,6 @@ export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAcc scrollLines(disp: number, suppressScrollEvent?: boolean): void; cancel(ev: Event, force?: boolean): boolean | void; - log(text: string): void; showCursor(): void; } diff --git a/src/browser/services/SelectionService.test.ts b/src/browser/services/SelectionService.test.ts index b00fa29f4b..62ca38193d 100644 --- a/src/browser/services/SelectionService.test.ts +++ b/src/browser/services/SelectionService.test.ts @@ -13,7 +13,6 @@ import { IBufferService, IOptionsService } from 'common/services/Services'; import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test'; import { CellData } from 'common/buffer/CellData'; import { IBuffer } from 'common/buffer/Types'; -import { isWindows } from 'common/Platform'; class TestSelectionService extends SelectionService { constructor( @@ -360,8 +359,6 @@ describe('SelectionService', () => { buffer.lines.set(3, stringToRow('4')); buffer.lines.set(4, stringToRow('5')); selectionService.selectAll(); - console.log(selectionService.selectionText.length); - console.log(isWindows); assert.equal(selectionService.selectionText, '1\n2\n3\n4\n5'); }); }); diff --git a/src/common/services/LogService.ts b/src/common/services/LogService.ts index 78e59e1c77..b89ee41e83 100644 --- a/src/common/services/LogService.ts +++ b/src/common/services/LogService.ts @@ -54,25 +54,25 @@ export class LogService implements ILogService { debug(message: any, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.Debug) { - console.log.call(console, message, optionalParams); + console.log.call(console, message, ...optionalParams); } } info(message: any, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.Info) { - console.info.call(console, message, optionalParams); + console.info.call(console, message, ...optionalParams); } } warn(message: any, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.Warn) { - console.warn.call(console, message, optionalParams); + console.warn.call(console, message, ...optionalParams); } } error(message: any, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.Error) { - console.error.call(console, message, optionalParams); + console.error.call(console, message, ...optionalParams); } } } From cd01d8ad56122d3749d8199bf09c96f9b43824c9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 09:47:11 -0700 Subject: [PATCH 6/9] Lint --- src/common/services/LogService.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/common/services/LogService.ts b/src/common/services/LogService.ts index b89ee41e83..62027513b1 100644 --- a/src/common/services/LogService.ts +++ b/src/common/services/LogService.ts @@ -19,19 +19,19 @@ declare const console: IConsole; export enum LogLevel { - Debug = 0, - Info = 1, - Warn = 2, - Error = 3, - Off = 4 + DEBUG = 0, + INFO = 1, + WARN = 2, + ERROR = 3, + OFF = 4 } const optionsKeyToLogLevel: { [key: string]: LogLevel } = { - debug: LogLevel.Debug, - info: LogLevel.Info, - warn: LogLevel.Warn, - error: LogLevel.Error, - off: LogLevel.Off + debug: LogLevel.DEBUG, + info: LogLevel.INFO, + warn: LogLevel.WARN, + error: LogLevel.ERROR, + off: LogLevel.OFF }; export class LogService implements ILogService { @@ -45,7 +45,7 @@ export class LogService implements ILogService { if (key === 'logLevel') { this._updateLogLevel(); } - }) + }); } private _updateLogLevel(): void { @@ -53,25 +53,25 @@ export class LogService implements ILogService { } debug(message: any, ...optionalParams: any[]): void { - if (this._logLevel <= LogLevel.Debug) { + if (this._logLevel <= LogLevel.DEBUG) { console.log.call(console, message, ...optionalParams); } } info(message: any, ...optionalParams: any[]): void { - if (this._logLevel <= LogLevel.Info) { + if (this._logLevel <= LogLevel.INFO) { console.info.call(console, message, ...optionalParams); } } warn(message: any, ...optionalParams: any[]): void { - if (this._logLevel <= LogLevel.Warn) { + if (this._logLevel <= LogLevel.WARN) { console.warn.call(console, message, ...optionalParams); } } error(message: any, ...optionalParams: any[]): void { - if (this._logLevel <= LogLevel.Error) { + if (this._logLevel <= LogLevel.ERROR) { console.error.call(console, message, ...optionalParams); } } From f3145431350920006b39f347e74bc78888f8055f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 09:48:16 -0700 Subject: [PATCH 7/9] Log bad linkifier instead of throwing --- src/Linkifier.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 5398d3c59d..769f3a5026 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -212,11 +212,7 @@ export class Linkifier implements ILinkifier { if (!uri) { // something matched but does not comply with the given matchIndex // since this is most likely a bug the regex itself we simply do nothing here - // DEBUG: print match and throw - if ((this._terminal).debug) { - this._logService.error({ match, matcher }); - throw new Error('match found without corresponding matchIndex'); - } + this._logService.debug('match found without corresponding matchIndex', match, matcher); break; } From 0c038352f3f0b429fce1b28b76ea3f34af1f7f8d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 09:55:53 -0700 Subject: [PATCH 8/9] Remove debug internal option completely and add option APIs --- demo/client.ts | 1 - src/InputHandler.ts | 1 - src/Types.d.ts | 1 - src/common/services/OptionsService.ts | 1 - src/common/services/Services.d.ts | 1 - src/public/Terminal.ts | 7 ++++--- typings/xterm.d.ts | 12 +++++++++--- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index 3bd96c8c0a..a28a720c3e 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -220,7 +220,6 @@ function initOptions(term: TerminalType): void { // Internal only options 'cancelEvents', 'convertEol', - 'debug', 'handler', 'screenKeys', 'termName', diff --git a/src/InputHandler.ts b/src/InputHandler.ts index f554a9adaa..0f4da04143 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -347,7 +347,6 @@ export class InputHandler extends Disposable implements IInputHandler { const cursorStartX = buffer.x; const cursorStartY = buffer.y; - // TODO: Consolidate debug/logging #1560 this._logService.debug('parsing data', data); if (this._parseBuffer.length < data.length) { diff --git a/src/Types.d.ts b/src/Types.d.ts index 238f70dc47..1aa05b6cc9 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -279,7 +279,6 @@ export interface ITerminalOptions extends IPublicTerminalOptions { [key: string]: any; cancelEvents?: boolean; convertEol?: boolean; - debug?: boolean; handler?: (data: string) => void; screenKeys?: boolean; termName?: string; diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 8b58de8db7..7396491e55 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -45,7 +45,6 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ convertEol: false, termName: 'xterm', screenKeys: false, - debug: false, cancelEvents: false, useFlowControl: false, wordSeparator: ' ()[]{}\'"' diff --git a/src/common/services/Services.d.ts b/src/common/services/Services.d.ts index 9ef5defc30..9a98ca9271 100644 --- a/src/common/services/Services.d.ts +++ b/src/common/services/Services.d.ts @@ -94,7 +94,6 @@ export interface ITerminalOptions { cols: number; cursorBlink: boolean; cursorStyle: 'block' | 'underline' | 'bar'; - debug: boolean; disableStdin: boolean; drawBoldTextInBrightColors: boolean; fontSize: number; diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index f06d003aa3..5d270ca715 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -133,8 +133,8 @@ export class Terminal implements ITerminalApi { public writeUtf8(data: Uint8Array): void { this._core.writeUtf8(data); } - public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'rendererType' | 'termName' | 'wordSeparator'): string; - public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; + public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; + public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; public getOption(key: 'colors'): string[]; public getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number; public getOption(key: 'handler'): (data: string) => void; @@ -144,9 +144,10 @@ export class Terminal implements ITerminalApi { } public setOption(key: 'bellSound' | 'fontFamily' | 'termName' | 'wordSeparator', value: string): void; public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + public setOption(key: 'logLevel', value: 'debug' | 'info' | 'warn' | 'error' | 'off'): void; public setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void; public setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void; - public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; + public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; public setOption(key: 'colors', value: string[]): void; public setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void; public setOption(key: 'handler', value: (data: string) => void): void; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index c4062db85b..d9e28b2656 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -693,12 +693,12 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold'| 'rendererType' | 'termName' | 'wordSeparator'): string; + getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; /** * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode'): boolean; + getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode'): boolean; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -732,6 +732,12 @@ declare module 'xterm' { * @param value The option value. */ setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'logLevel', value: LogLevel): void; /** * Sets an option on the terminal. * @param key The option key. @@ -749,7 +755,7 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode', value: boolean): void; + setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode', value: boolean): void; /** * Sets an option on the terminal. * @param key The option key. From 46002599d3b2d28ee36eb93c16d77e7d408bcf32 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 13 Jul 2019 10:09:48 -0700 Subject: [PATCH 9/9] Prefix all logging with 'xterm.js' This makes it easier to differentiate messages in large apps --- src/common/services/LogService.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/common/services/LogService.ts b/src/common/services/LogService.ts index 62027513b1..f7480078a1 100644 --- a/src/common/services/LogService.ts +++ b/src/common/services/LogService.ts @@ -34,6 +34,8 @@ const optionsKeyToLogLevel: { [key: string]: LogLevel } = { off: LogLevel.OFF }; +const LOG_PREFIX = 'xterm.js: '; + export class LogService implements ILogService { private _logLevel!: LogLevel; @@ -52,27 +54,27 @@ export class LogService implements ILogService { this._logLevel = optionsKeyToLogLevel[this._optionsService.options.logLevel]; } - debug(message: any, ...optionalParams: any[]): void { + debug(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.DEBUG) { - console.log.call(console, message, ...optionalParams); + console.log.call(console, LOG_PREFIX + message, ...optionalParams); } } - info(message: any, ...optionalParams: any[]): void { + info(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.INFO) { - console.info.call(console, message, ...optionalParams); + console.info.call(console, LOG_PREFIX + message, ...optionalParams); } } - warn(message: any, ...optionalParams: any[]): void { + warn(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.WARN) { - console.warn.call(console, message, ...optionalParams); + console.warn.call(console, LOG_PREFIX + message, ...optionalParams); } } - error(message: any, ...optionalParams: any[]): void { + error(message: string, ...optionalParams: any[]): void { if (this._logLevel <= LogLevel.ERROR) { - console.error.call(console, message, ...optionalParams); + console.error.call(console, LOG_PREFIX + message, ...optionalParams); } } }