From edee1a106788e839651c1bc12269bd375d695d0d Mon Sep 17 00:00:00 2001 From: Mmis1000 Date: Sun, 13 Sep 2020 21:33:32 +0800 Subject: [PATCH] Handle alt screen --- .../src/SerializeAddon.ts | 28 +++++++++++++--- .../test/SerializeAddon.api.ts | 32 +++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index dad6aa4f..ba366c37 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -11,6 +11,11 @@ function constrain(value: number, low: number, high: number): number { return Math.max(low, Math.min(value, high)); } +interface ISerializeOptions { + withAlternate?: boolean; + +} + // TODO: Refine this template class later abstract class BaseSerializeHandler { constructor(private _buffer: IBuffer) { } @@ -167,7 +172,7 @@ export class SerializeAddon implements ITerminalAddon { this._terminal = terminal; } - public serialize(rows?: number): string { + public serialize(rows?: number, options: ISerializeOptions = {}): string { // TODO: Add re-position cursor support // TODO: Add word wrap mode support // TODO: Add combinedData support @@ -175,12 +180,25 @@ export class SerializeAddon implements ITerminalAddon { throw new Error('Cannot use addon until it has been loaded'); } - const maxRows = this._terminal.buffer.active.length; - const handler = new StringSerializeHandler(this._terminal.buffer.active); + if (this._terminal.buffer.active.type === 'normal' || !(options?.withAlternate ?? false)) { + const maxRows = this._terminal.buffer.active.length; + const handler = new StringSerializeHandler(this._terminal.buffer.active); - rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows); + rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows); - return handler.serialize(maxRows - rows, maxRows); + return handler.serialize(maxRows - rows, maxRows); + } + + const maxNormalRows = this._terminal.buffer.normal.length; + const maxAltRows = this._terminal.buffer.alternate.length; + const normalHandler = new StringSerializeHandler(this._terminal.buffer.normal); + const altHandler = new StringSerializeHandler(this._terminal.buffer.alternate); + const normalRows = (rows === undefined) ? maxNormalRows : constrain(rows, 0, maxNormalRows); + const altRows = (rows === undefined) ? maxAltRows : constrain(rows, 0, maxAltRows); + + return normalHandler.serialize(maxNormalRows - normalRows, maxNormalRows) + + '\u001b[?1049h\u001b[H' + + altHandler.serialize(maxAltRows - altRows, maxAltRows); } public dispose(): void { } diff --git a/addons/xterm-addon-serialize/test/SerializeAddon.api.ts b/addons/xterm-addon-serialize/test/SerializeAddon.api.ts index 5b615db1..32e816a1 100644 --- a/addons/xterm-addon-serialize/test/SerializeAddon.api.ts +++ b/addons/xterm-addon-serialize/test/SerializeAddon.api.ts @@ -299,6 +299,38 @@ describe('SerializeAddon', () => { await writeSync(page, lines.join('\\r\\n')); assert.equal(await page.evaluate(`serializeAddon.serialize();`), expected.join('\r\n')); }); + + it('serialize with alt screen correctly', async () => { + const SMCUP = '\u001b[?1049h'; + const CUP = '\u001b[H'; + + const lines = [ + `1${SMCUP}${CUP}2` + ]; + const expected = [ + `1${SMCUP}${CUP}2` + ]; + + await writeSync(page, lines.join('\\r\\n')); + assert.equal(JSON.stringify(await page.evaluate(`window.term.buffer.active.type`)), '"alternate"'); + assert.equal(JSON.stringify(await page.evaluate(`serializeAddon.serialize(undefined, { withAlternate: true });`)), JSON.stringify(expected.join('\r\n'))); + }); + + it('serialize without alt screen correctly', async () => { + const SMCUP = '\u001b[?1049h'; + const RMCUP = '\u001b[?1049l'; + + const lines = [ + `1${SMCUP}2${RMCUP}` + ]; + const expected = [ + `1` + ]; + + await writeSync(page, lines.join('\\r\\n')); + assert.equal(JSON.stringify(await page.evaluate(`window.term.buffer.active === window.term.buffer.alt`)), 'false'); + assert.equal(JSON.stringify(await page.evaluate(`serializeAddon.serialize(undefined, { withAlternate: true });`)), JSON.stringify(expected.join('\r\n'))); + }); }); function newArray(initial: T | ((index: number) => T), count: number): T[] {