From 43c3349494c7b922577fa80d50a57b23896e0818 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 21:20:11 -0800 Subject: [PATCH 01/13] Prevent wraparound mode from overriding last character --- src/InputHandler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 975d7c11..ff113f2d 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -60,7 +60,6 @@ export class InputHandler implements IInputHandler { this._terminal.scroll(); } } else { - this._terminal.x = this._terminal.cols - 1; if (ch_width === 2) // FIXME: check for xterm behavior return; } From d5f0fff5239185cba93819eab505a2b3fdfda515 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 21:22:16 -0800 Subject: [PATCH 02/13] Enable other tests and fix viewport check --- src/test/escape-sequences-test.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/test/escape-sequences-test.js b/src/test/escape-sequences-test.js index 6c64b562..b077f916 100644 --- a/src/test/escape-sequences-test.js +++ b/src/test/escape-sequences-test.js @@ -56,7 +56,7 @@ function formatError(in_, out_, expected) { function terminalToString(term) { var result = ''; var line_s = ''; - for (var line=0; line Date: Fri, 20 Jan 2017 21:39:27 -0800 Subject: [PATCH 03/13] Right trim expected output, we don't care for now This fixes 2 tests --- src/test/escape-sequences-test.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/escape-sequences-test.js b/src/test/escape-sequences-test.js index b077f916..1bbc4a26 100644 --- a/src/test/escape-sequences-test.js +++ b/src/test/escape-sequences-test.js @@ -102,7 +102,12 @@ describe('xterm output comparison', function() { var from_emulator = terminalToString(xterm); console.log = CONSOLE_LOG; var expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8'); - if (from_emulator != expected) { + // Some of the tests have whitespace on the right of lines, we trim all the linex + // from xterm.js so ignore this for now at least. + var expectedRightTrimmed = expected.split('\n').map(function (l) { + return l.replace(/\s+$/, ''); + }).join('\n'); + if (from_emulator != expectedRightTrimmed) { // uncomment to get noisy output throw new Error(formatError(in_file, from_emulator, expected)); // throw new Error('mismatch'); From 72063329fe19402e41e0b1ef33db6e7f4c28fc9f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 21:49:39 -0800 Subject: [PATCH 04/13] Fix index behavior Don't wrap cursor to column 0 after an index, fixes 2 tests --- src/xterm.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xterm.js b/src/xterm.js index 7ab69b8d..ca5b642e 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -2303,6 +2303,9 @@ Terminal.prototype.index = function() { this.y--; this.scroll(); } + if (this.x >= this.cols) { + this.x--; + } }; From 99fbcd3d6587103b0e8684063afd85de71d448ce Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 22:14:18 -0800 Subject: [PATCH 05/13] Fix LF/VT/FF behavior Don't wrap cursor to column 0 after an index, fixes 2 tests --- src/InputHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index ff113f2d..8e6949ba 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -123,6 +123,9 @@ export class InputHandler implements IInputHandler { this._terminal.y--; this._terminal.scroll(); } + if (this._terminal.x >= this._terminal.cols) { + this._terminal.x--; + } } /** From 1b344ce789a82bd873cc96e69c2a86d18cef147b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 23:03:38 -0800 Subject: [PATCH 06/13] Implement CAN (Cancel, ^X) This helps partially pass t0014-CAN.in, it won't work 100% however due to the very complex parsing logic of vanilla xterm that gnome-terminal doesn't even seem to match. xterm's source seems to have multiple ignore cases for a set of characters such that an escape sequence like \e!!!!!! prints nothing as the ! continually gets ignored. Our current logic is we ignore the escape sequence immediately in this case and print the !. --- src/Parser.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Parser.ts b/src/Parser.ts index 02028005..5390bd8f 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -74,6 +74,7 @@ escapedStateHandler['%'] = (parser, terminal) => { parser.setState(ParserState.NORMAL); parser.skipNextChar(); }; +escapedStateHandler[C0.CAN] = (parser) => parser.setState(ParserState.NORMAL); const csiParamStateHandler: {[key: string]: (parser: Parser) => void} = {}; csiParamStateHandler['?'] = (parser) => parser.setPrefix('?'); @@ -94,8 +95,9 @@ csiParamStateHandler['"'] = (parser) => parser.setPostfix('"'); csiParamStateHandler[' '] = (parser) => parser.setPostfix(' '); csiParamStateHandler['\''] = (parser) => parser.setPostfix('\''); csiParamStateHandler[';'] = (parser) => parser.finalizeParam(); +csiParamStateHandler[C0.CAN] = (parser) => parser.setState(ParserState.NORMAL); -const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string) => void} = {}; +const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string, parser: Parser) => void} = {}; csiStateHandler['@'] = (handler, params, prefix) => handler.insertChars(params); csiStateHandler['A'] = (handler, params, prefix) => handler.cursorUp(params); csiStateHandler['B'] = (handler, params, prefix) => handler.cursorDown(params); @@ -144,6 +146,7 @@ csiStateHandler['q'] = (handler, params, prefix, postfix) => { csiStateHandler['r'] = (handler, params) => handler.setScrollRegion(params); csiStateHandler['s'] = (handler, params) => handler.saveCursor(params); csiStateHandler['u'] = (handler, params) => handler.restoreCursor(params); +csiStateHandler[C0.CAN] = (handler, params, prefix, postfix, parser) => parser.setState(ParserState.NORMAL); // TODO: Many codes/charsets appear to not be supported // See: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html @@ -477,7 +480,7 @@ export class Parser { case ParserState.CSI: if (ch in csiStateHandler) { - csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix); + csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this); } else { this._terminal.error('Unknown CSI code: %s.', ch); } From d30fb89fde577631e8ca66bcb6fe53e1a3002bd0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 23:11:22 -0800 Subject: [PATCH 07/13] Fix CUB behavior Don't wrap cursor to column 0 after a CUB, fixes 3 tests --- src/InputHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 8e6949ba..6cb0f08c 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -246,6 +246,9 @@ export class InputHandler implements IInputHandler { if (param < 1) { param = 1; } + if (this._terminal.x >= this._terminal.cols) { + this._terminal.x--; + } this._terminal.x -= param; if (this._terminal.x < 0) { this._terminal.x = 0; From 74c3a4a6f76e687534625e326e894e092568281b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 23:12:54 -0800 Subject: [PATCH 08/13] Fix CUD behavior Don't wrap cursor to column 0 after a CUD, fixes 1 test --- src/InputHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 6cb0f08c..13a3145b 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -220,6 +220,9 @@ export class InputHandler implements IInputHandler { if (this._terminal.y >= this._terminal.rows) { this._terminal.y = this._terminal.rows - 1; } + if (this._terminal.x >= this._terminal.cols) { + this._terminal.x--; + } } /** From 2aa7608ac05f0effb1d8f04e43a1dfb32558d055 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 23:14:08 -0800 Subject: [PATCH 09/13] Fix VPR behavior Don't wrap cursor to column 0 after a VPR, fixes 1 test --- src/InputHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 13a3145b..bbf17b60 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -701,6 +701,9 @@ export class InputHandler implements IInputHandler { if (this._terminal.y >= this._terminal.rows) { this._terminal.y = this._terminal.rows - 1; } + if (this._terminal.x >= this._terminal.cols) { + this._terminal.x--; + } } /** From da16dd7cae952a85f301afb0b917a719a413870f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 23:20:13 -0800 Subject: [PATCH 10/13] Mock viewport.syncScrollArea --- src/test/escape-sequences-test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/escape-sequences-test.js b/src/test/escape-sequences-test.js index 1bbc4a26..bc5d5bfe 100644 --- a/src/test/escape-sequences-test.js +++ b/src/test/escape-sequences-test.js @@ -76,6 +76,9 @@ describe('xterm output comparison', function() { beforeEach(function () { xterm = new Terminal(COLS, ROWS); xterm.refresh = function() {}; + xterm.viewport = { + syncScrollArea: function() {} + }; }); // omit stack trace for escape sequence files From 4f7ee7dab0d75656607dc764ee50bb317a10adc2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 20 Jan 2017 23:38:56 -0800 Subject: [PATCH 11/13] Skip broken tests --- src/test/escape-sequences-test.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/test/escape-sequences-test.js b/src/test/escape-sequences-test.js index bc5d5bfe..f35bc00a 100644 --- a/src/test/escape-sequences-test.js +++ b/src/test/escape-sequences-test.js @@ -85,11 +85,16 @@ describe('xterm output comparison', function() { Error.stackTraceLimit = 0; var files = glob.sync('**/escape_sequence_files/*.in'); // only successful tests for now - var successful = [0, 2, 6, 12, 13, 18, 20, 22, 27, 28, 50]; + var skip = [ + 10, 16, 17, 19, 32, 33, 34, 35, 36, 39, + 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, + 63, 68 + ]; for (var i = 0; i < files.length; i++) { - // if (i !== 1) continue; - //for (var a in successful) { - // var i = successful[a]; + if (skip.indexOf(i) >= 0) { + continue; + } (function(filename) { it(filename.split('/').slice(-1)[0], function () { pty_reset(); From b789a7e85bc601f337be1d9d77f640c858bae17a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 25 Jan 2017 10:32:20 -0800 Subject: [PATCH 12/13] Fix failing test given new auto wraparound behavior --- src/test/test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/test.js b/src/test/test.js index 4f9342e5..890b9ad1 100644 --- a/src/test/test.js +++ b/src/test/test.js @@ -595,8 +595,9 @@ describe('xterm.js', function() { xterm.x = xterm.cols - 1; xterm.wraparoundMode = false; xterm.write('a' + high + String.fromCharCode(i)); - expect(xterm.lines.get(0)[xterm.cols-1][1]).eql(high + String.fromCharCode(i)); - expect(xterm.lines.get(0)[xterm.cols-1][1].length).eql(2); + // auto wraparound mode should cut off the rest of the line + expect(xterm.lines.get(0)[xterm.cols-1][1]).eql('a'); + expect(xterm.lines.get(0)[xterm.cols-1][1].length).eql(1); expect(xterm.lines.get(1)[1][1]).eql(' '); xterm.reset(); } From 5850cbcd0589aea9de269afed1eb3bcd9fc4e2ec Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 25 Jan 2017 10:34:43 -0800 Subject: [PATCH 13/13] Add comments explaining actions preventing x from wrapping --- src/InputHandler.ts | 4 ++++ src/xterm.js | 1 + 2 files changed, 5 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index bbf17b60..5dbdb420 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -123,6 +123,7 @@ export class InputHandler implements IInputHandler { this._terminal.y--; this._terminal.scroll(); } + // If the end of the line is hit, prevent this action from wrapping around to the next line. if (this._terminal.x >= this._terminal.cols) { this._terminal.x--; } @@ -220,6 +221,7 @@ export class InputHandler implements IInputHandler { if (this._terminal.y >= this._terminal.rows) { this._terminal.y = this._terminal.rows - 1; } + // If the end of the line is hit, prevent this action from wrapping around to the next line. if (this._terminal.x >= this._terminal.cols) { this._terminal.x--; } @@ -249,6 +251,7 @@ export class InputHandler implements IInputHandler { if (param < 1) { param = 1; } + // If the end of the line is hit, prevent this action from wrapping around to the next line. if (this._terminal.x >= this._terminal.cols) { this._terminal.x--; } @@ -701,6 +704,7 @@ export class InputHandler implements IInputHandler { if (this._terminal.y >= this._terminal.rows) { this._terminal.y = this._terminal.rows - 1; } + // If the end of the line is hit, prevent this action from wrapping around to the next line. if (this._terminal.x >= this._terminal.cols) { this._terminal.x--; } diff --git a/src/xterm.js b/src/xterm.js index ca5b642e..560db5fe 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -2303,6 +2303,7 @@ Terminal.prototype.index = function() { this.y--; this.scroll(); } + // If the end of the line is hit, prevent this action from wrapping around to the next line. if (this.x >= this.cols) { this.x--; }