From 54822af73ae63eb051668e29fd6b0d4c940359b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Mon, 8 Nov 2021 19:40:35 +0100 Subject: [PATCH] use xcolor parser for OSC 4 --- src/common/InputHandler.test.ts | 82 ++++++++++++++------------------- src/common/InputHandler.ts | 38 +++++++-------- 2 files changed, 51 insertions(+), 69 deletions(-) diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index e17b23fd..d63a9654 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -17,7 +17,7 @@ import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { clone } from 'common/Clone'; import { BufferService } from 'common/services/BufferService'; import { CoreService } from 'common/services/CoreService'; -import { OscHandler } from 'common/parser/OscParser'; + function getCursor(bufferService: IBufferService): number[] { return [ @@ -41,7 +41,6 @@ class TestInputHandler extends InputHandler { public get curAttrData(): IAttributeData { return (this as any)._curAttrData; } public get windowTitleStack(): string[] { return this._windowTitleStack; } public get iconNameStack(): string[] { return this._iconNameStack; } - public parseAnsiColorChange(data: string): IColorEvent{ return this._parseAnsiColorChange(data); } /** * Promise based parse call to await the full resolve of given input data. @@ -1865,53 +1864,42 @@ describe('InputHandler', () => { }); }); describe('OSC', () => { - it('4: should parse correct Ansi color change data', () => { - // this is testing a private method - const event = inputHandler.parseAnsiColorChange('19;rgb:a1/b2/c3'); - - assert.isNotNull(event); - assert.deepEqual(event![0], { index: 19, color: [0xa1, 0xb2, 0xc3] }); + it('4: query color events', async () => { + const stack: IColorEvent[] = []; + inputHandler.onColor(ev => stack.push(ev)); + // single color query + await inputHandler.parseP('\x1b]4;0;?\x07'); + assert.deepEqual(stack, [[{ index: 0 }]]); + stack.length = 0; + await inputHandler.parseP('\x1b]4;123;?\x07'); + assert.deepEqual(stack, [[{ index: 123 }]]); + stack.length = 0; + // multiple queries + await inputHandler.parseP('\x1b]4;0;?;123;?\x07'); + assert.deepEqual(stack, [[{ index: 0 }, { index: 123 }]]); + stack.length = 0; }); - it('4: should ignore incorrect Ansi color change data', () => { - // this is testing a private method - assert.equal(inputHandler.parseAnsiColorChange('17;rgb:a/b/c').length, 0); - assert.equal(inputHandler.parseAnsiColorChange('17;rgb:#aabbcc').length, 0); - assert.equal(inputHandler.parseAnsiColorChange('17;rgba:aa/bb/cc').length, 0); - assert.equal(inputHandler.parseAnsiColorChange('rgb:aa/bb/cc').length, 0); + it('4: set color events', async () => { + const stack: IColorEvent[] = []; + inputHandler.onColor(ev => stack.push(ev)); + // single color query + await inputHandler.parseP('\x1b]4;0;rgb:01/02/03\x07'); + assert.deepEqual(stack, [[{ index: 0, color: [1, 2, 3] }]]); + stack.length = 0; + await inputHandler.parseP('\x1b]4;123;#aabbcc\x07'); + assert.deepEqual(stack, [[{ index: 123, color: [170, 187, 204] }]]); + stack.length = 0; + // multiple queries + await inputHandler.parseP('\x1b]4;0;rgb:aa/bb/cc;123;#001122\x07'); + assert.deepEqual(stack, [[{ index: 0, color: [170, 187, 204] }, { index: 123, color: [0, 17, 34] }]]); + stack.length = 0; }); - it('4: should parse a list of Ansi color changes', () => { - // this is testing a private method - const event = inputHandler.parseAnsiColorChange('19;rgb:a1/b2/c3;17;rgb:00/11/22;255;rgb:01/ef/2d'); - - assert.equal(event.length, 3); - assert.deepEqual(event[0], { index: 19, color: [0xa1, 0xb2, 0xc3] }); - assert.deepEqual(event[1], { index: 17, color: [0x00, 0x11, 0x22] }); - assert.deepEqual(event[2], { index: 255, color: [0x01, 0xef, 0x2d] }); - }); - it('4: should ignore incorrect colors in a list of Ansi color changes', () => { - // this is testing a private method - const event = inputHandler.parseAnsiColorChange('19;rgb:a1/b2/c3;17;rgb:WR/ON/G;255;rgb:01/ef/2d'); - - assert.equal(event.length, 2); - assert.deepEqual(event[0], { index: 19, color: [0xa1, 0xb2, 0xc3] }); - assert.deepEqual(event[1], { index: 255, color: [0x01, 0xef, 0x2d] }); - }); - it('4: should be case insensitive when parsing Ansi color changes', () => { - // this is testing a private method - const event = inputHandler.parseAnsiColorChange('19;rGb:A1/b2/C3'); - - assert.equal(event.length, 1); - assert.deepEqual(event[0], { index: 19, color: [0xa1, 0xb2, 0xc3] }); - }); - it('4: should fire event on Ansi color change', async () => { - return new Promise(async r => { - inputHandler.onColor(e => { - assert.deepEqual(e[0], { index: 17, color: [0x1a, 0x2b, 0x3c] }); - assert.deepEqual(e[1], { index: 12, color: [0x11, 0x22, 0x33] }); - r(); - }); - await inputHandler.parseP('\x1b]4;17;rgb:1a/2b/3c;12;rgb:11/22/33\x1b\\'); - }); + it('4: should ignore invalid values', async () => { + const stack: IColorEvent[] = []; + inputHandler.onColor(ev => stack.push(ev)); + await inputHandler.parseP('\x1b]4;0;rgb:aa/bb/cc;45;rgb:1/22/333;123;#001122\x07'); + assert.deepEqual(stack, [[{ index: 0, color: [170, 187, 204] }, { index: 123, color: [0, 17, 34] }]]); + stack.length = 0; }); it('10: should create appropriate events', async () => { diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index 168990bc..00943601 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -2842,24 +2842,6 @@ export class InputHandler extends Disposable implements IInputHandler { return true; } - protected _parseAnsiColorChange(data: string): IColorEvent { - const result: IColorEvent = []; - // example data: 5;rgb:aa/bb/cc - const regex = /(\d+);rgb:([\da-f]{2})\/([\da-f]{2})\/([\da-f]{2})/gi; - let match; - while ((match = regex.exec(data)) !== null) { - result.push({ - index: parseInt(match[1]), - color: [ - parseInt(match[2], 16), - parseInt(match[3], 16), - parseInt(match[4], 16) - ] - }); - } - return result; - } - /** * OSC 4; ; ST (set ANSI color to ) * @@ -2868,13 +2850,25 @@ export class InputHandler extends Disposable implements IInputHandler { * There may be multipe c ; spec elements present in the same instruction, e.g. 1;rgb:10/20/30;2;rgb:a0/b0/c0. */ public setOrReportIndexedColor(data: string): boolean { - const event = this._parseAnsiColorChange(data); + const event: IColorEvent = []; + const slots = data.split(';'); + while (slots.length > 1) { + const idx = slots.shift() as string; + const spec = slots.shift() as string; + if (/^\d+$/.exec(idx)) { + if (spec === '?') { + event.push({ index: parseInt(idx) }); + } else { + const color = parseColor(spec); + if (color) { + event.push({ index: parseInt(idx), color }); + } + } + } + } if (event.length) { this._onColor.fire(event); } - else { - this._logService.warn(`Expected format ;rgb:// but got data: ${data}`); - } return true; }