From 79c1fff8531c887a877e58a872563505701f0cb6 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 28 Jul 2023 13:51:46 -0700 Subject: [PATCH 1/4] Add IntRange type for ColorIndex Fixes #4614 --- src/browser/Terminal.ts | 8 ++-- src/browser/services/ThemeService.ts | 8 ++-- src/common/InputHandler.test.ts | 60 ++++++++++++++-------------- src/common/InputHandler.ts | 18 +++++---- src/common/Types.d.ts | 11 ++++- 5 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index fe19f954..f5957076 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -35,7 +35,7 @@ import * as Strings from 'browser/LocalizableStrings'; import { AccessibilityManager } from './AccessibilityManager'; import { ITheme, IMarker, IDisposable, ILinkProvider, IDecorationOptions, IDecoration } from 'xterm'; import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; -import { KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IColorEvent, ColorIndex, ColorRequestType } from 'common/Types'; +import { KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IColorEvent, ColorIndex, ColorRequestType, ColorIndexValue } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; @@ -203,15 +203,15 @@ export class Terminal extends CoreTerminal implements ITerminal { let acc: 'foreground' | 'background' | 'cursor' | 'ansi'; let ident = ''; switch (req.index) { - case ColorIndex.FOREGROUND: // OSC 10 | 110 + case ColorIndexValue.FOREGROUND: // OSC 10 | 110 acc = 'foreground'; ident = '10'; break; - case ColorIndex.BACKGROUND: // OSC 11 | 111 + case ColorIndexValue.BACKGROUND: // OSC 11 | 111 acc = 'background'; ident = '11'; break; - case ColorIndex.CURSOR: // OSC 12 | 112 + case ColorIndexValue.CURSOR: // OSC 12 | 112 acc = 'cursor'; ident = '12'; break; diff --git a/src/browser/services/ThemeService.ts b/src/browser/services/ThemeService.ts index ac0104d5..d810d44b 100644 --- a/src/browser/services/ThemeService.ts +++ b/src/browser/services/ThemeService.ts @@ -10,7 +10,7 @@ import { channels, color, css, NULL_COLOR } from 'common/Color'; import { EventEmitter } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IOptionsService, ITheme } from 'common/services/Services'; -import { ColorIndex, IColor } from 'common/Types'; +import { ColorIndex, ColorIndexValue, IColor } from 'common/Types'; interface IRestoreColorSet { foreground: IColor; @@ -190,13 +190,13 @@ export class ThemeService extends Disposable implements IThemeService { return; } switch (slot) { - case ColorIndex.FOREGROUND: + case ColorIndexValue.FOREGROUND: this._colors.foreground = this._restoreColors.foreground; break; - case ColorIndex.BACKGROUND: + case ColorIndexValue.BACKGROUND: this._colors.background = this._restoreColors.background; break; - case ColorIndex.CURSOR: + case ColorIndexValue.CURSOR: this._colors.cursor = this._restoreColors.cursor; break; default: diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index 21afb194..9df46838 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { InputHandler } from 'common/InputHandler'; -import { IBufferLine, IAttributeData, IColorEvent, ColorIndex, ColorRequestType } from 'common/Types'; +import { IBufferLine, IAttributeData, IColorEvent, ColorIndex, ColorRequestType, ColorIndexValue } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { Attributes, BgFlags, UnderlineStyle } from 'common/buffer/Constants'; @@ -1950,14 +1950,14 @@ describe('InputHandler', () => { inputHandler.onColor(ev => stack.push(ev)); // single color query await inputHandler.parseP('\x1b]4;0;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: 0 as ColorIndex }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: 0 }]]); stack.length = 0; await inputHandler.parseP('\x1b]4;123;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: 123 as ColorIndex }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: 123 }]]); stack.length = 0; // multiple queries await inputHandler.parseP('\x1b]4;0;?;123;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: 0 as ColorIndex }, { type: ColorRequestType.REPORT, index: 123 as ColorIndex }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: 0 }, { type: ColorRequestType.REPORT, index: 123 }]]); stack.length = 0; }); it('4: set color events', async () => { @@ -1965,32 +1965,32 @@ describe('InputHandler', () => { inputHandler.onColor(ev => stack.push(ev)); // single color query await inputHandler.parseP('\x1b]4;0;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 0 as ColorIndex, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 0, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]4;123;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 123 as ColorIndex, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, 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, [[{ type: ColorRequestType.SET, index: 0 as ColorIndex, color: [170, 187, 204] }, { type: ColorRequestType.SET, index: 123 as ColorIndex, color: [0, 17, 34] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 0, color: [170, 187, 204] }, { type: ColorRequestType.SET, index: 123, color: [0, 17, 34] }]]); stack.length = 0; }); 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, [[{ type: ColorRequestType.SET, index: 0 as ColorIndex, color: [170, 187, 204] }, { type: ColorRequestType.SET, index: 123 as ColorIndex, color: [0, 17, 34] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 0, color: [170, 187, 204] }, { type: ColorRequestType.SET, index: 123, color: [0, 17, 34] }]]); stack.length = 0; }); it('104: restore events', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]104;0\x07\x1b]104;43\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: 0 as ColorIndex }], [{ type: ColorRequestType.RESTORE, index: 43 as ColorIndex }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: 0 }], [{ type: ColorRequestType.RESTORE, index: 43 }]]); stack.length = 0; // multiple in one command await inputHandler.parseP('\x1b]104;0;43\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: 0 as ColorIndex }, { type: ColorRequestType.RESTORE, index: 43 as ColorIndex }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: 0 }, { type: ColorRequestType.RESTORE, index: 43 }]]); stack.length = 0; // full ANSI table restore await inputHandler.parseP('\x1b]104\x07'); @@ -2002,87 +2002,87 @@ describe('InputHandler', () => { inputHandler.onColor(ev => stack.push(ev)); // single foreground query --> color undefined await inputHandler.parseP('\x1b]10;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndex.FOREGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.FOREGROUND }]]); stack.length = 0; // OSC with multiple values maps to OSC 10 & OSC 11 & OSC 12 await inputHandler.parseP('\x1b]10;?;?;?;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndex.FOREGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndex.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndex.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.FOREGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndexValue.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); stack.length = 0; // set foreground color events await inputHandler.parseP('\x1b]10;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndex.FOREGROUND, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.FOREGROUND, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]10;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndex.FOREGROUND, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.FOREGROUND, color: [170, 187, 204] }]]); stack.length = 0; // set FG, BG and cursor color at once await inputHandler.parseP('\x1b]10;rgb:aa/bb/cc;#001122;rgb:12/34/56\x07'); assert.deepEqual(stack, [ - [{ type: ColorRequestType.SET, index: ColorIndex.FOREGROUND, color: [170, 187, 204] }], - [{ type: ColorRequestType.SET, index: ColorIndex.BACKGROUND, color: [0, 17, 34] }], - [{ type: ColorRequestType.SET, index: ColorIndex.CURSOR, color: [18, 52, 86] }] + [{ type: ColorRequestType.SET, index: ColorIndexValue.FOREGROUND, color: [170, 187, 204] }], + [{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [0, 17, 34] }], + [{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [18, 52, 86] }] ]); }); it('110: restore FG color', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]110\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndex.FOREGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndexValue.FOREGROUND }]]); }); it('11: BG set & query events', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); // single background query --> color undefined await inputHandler.parseP('\x1b]11;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndex.BACKGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.BACKGROUND }]]); stack.length = 0; // OSC 11 with multiple values creates only BG and cursor event await inputHandler.parseP('\x1b]11;?;?;?;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndex.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndex.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); stack.length = 0; // set background color events await inputHandler.parseP('\x1b]11;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndex.BACKGROUND, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]11;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndex.BACKGROUND, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [170, 187, 204] }]]); stack.length = 0; // set BG and cursor color at once await inputHandler.parseP('\x1b]11;#001122;rgb:12/34/56\x07'); assert.deepEqual(stack, [ - [{ type: ColorRequestType.SET, index: ColorIndex.BACKGROUND, color: [0, 17, 34] }], - [{ type: ColorRequestType.SET, index: ColorIndex.CURSOR, color: [18, 52, 86] }] + [{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [0, 17, 34] }], + [{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [18, 52, 86] }] ]); }); it('111: restore BG color', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]111\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndex.BACKGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndexValue.BACKGROUND }]]); }); it('12: cursor color set & query events', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); // single cursor query --> color undefined await inputHandler.parseP('\x1b]12;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndex.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); stack.length = 0; // OSC 12 with multiple values creates only cursor event await inputHandler.parseP('\x1b]12;?;?;?;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndex.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); stack.length = 0; // set cursor color events await inputHandler.parseP('\x1b]12;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndex.CURSOR, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]12;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndex.CURSOR, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [170, 187, 204] }]]); }); it('112: restore cursor color', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]112\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndex.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndexValue.CURSOR }]]); }); }); diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index 9a32ea69..be1277b0 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType } from 'common/Types'; +import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, ColorIndexValue } from 'common/Types'; import { C0, C1 } from 'common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; @@ -2915,7 +2915,7 @@ export class InputHandler extends Disposable implements IInputHandler { const spec = slots.shift() as string; if (/^\d+$/.exec(idx)) { const index = parseInt(idx); - if (0 <= index && index < 256) { + if (isValidColorIndex(index) && index < 256) { if (spec === '?') { event.push({ type: ColorRequestType.REPORT, index }); } else { @@ -2988,7 +2988,7 @@ export class InputHandler extends Disposable implements IInputHandler { } // special colors - OSC 10 | 11 | 12 - private _specialColors = [ColorIndex.FOREGROUND, ColorIndex.BACKGROUND, ColorIndex.CURSOR]; + private _specialColors = [ColorIndexValue.FOREGROUND, ColorIndexValue.BACKGROUND, ColorIndexValue.CURSOR]; /** * Apply colors requests for special colors in OSC 10 | 11 | 12. @@ -3073,7 +3073,7 @@ export class InputHandler extends Disposable implements IInputHandler { for (let i = 0; i < slots.length; ++i) { if (/^\d+$/.exec(slots[i])) { const index = parseInt(slots[i]); - if (0 <= index && index < 256) { + if (isValidColorIndex(index) && index < 256) { event.push({ type: ColorRequestType.RESTORE, index }); } } @@ -3090,7 +3090,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 110 "Restore default foreground color" "OSC 110 BEL" "Restore default foreground to themed color." */ public restoreFgColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.FOREGROUND }]); + this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndexValue.FOREGROUND }]); return true; } @@ -3100,7 +3100,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 111 "Restore default background color" "OSC 111 BEL" "Restore default background to themed color." */ public restoreBgColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.BACKGROUND }]); + this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndexValue.BACKGROUND }]); return true; } @@ -3110,7 +3110,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 112 "Restore default cursor color" "OSC 112 BEL" "Restore default cursor to themed color." */ public restoreCursorColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.CURSOR }]); + this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndexValue.CURSOR }]); return true; } @@ -3429,3 +3429,7 @@ class DirtyRowTracker implements IDirtyRowTracker { this.markRangeDirty(0, this._bufferService.rows - 1); } } + +function isValidColorIndex(value: number): value is ColorIndex { + return 0 <= value && value < 259; +} diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 70143525..6268b77a 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -413,7 +413,16 @@ export const enum ColorRequestType { SET = 1, RESTORE = 2 } -export const enum ColorIndex { + +// IntRange from https://stackoverflow.com/a/39495173 +type Enumerate = Acc['length'] extends N + ? Acc[number] + : Enumerate; +type IntRange = Exclude, Enumerate>; + +type ColorIndex = IntRange<0, 259>; // number from 0 to 258 + +export const enum ColorIndexValue { FOREGROUND = 256, BACKGROUND = 257, CURSOR = 258 From 5660c404f0811deb45b7683cd5c46cb8bca22103 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 28 Jul 2023 16:32:05 -0700 Subject: [PATCH 2/4] Differentiate special color indexes and others --- src/browser/Terminal.ts | 8 +++--- src/browser/services/Services.ts | 5 ++-- src/browser/services/ThemeService.ts | 12 ++++---- src/common/InputHandler.test.ts | 42 ++++++++++++++-------------- src/common/InputHandler.ts | 10 +++---- src/common/Types.d.ts | 12 ++++---- 6 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index f5957076..7b407957 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -35,7 +35,7 @@ import * as Strings from 'browser/LocalizableStrings'; import { AccessibilityManager } from './AccessibilityManager'; import { ITheme, IMarker, IDisposable, ILinkProvider, IDecorationOptions, IDecoration } from 'xterm'; import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; -import { KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IColorEvent, ColorIndex, ColorRequestType, ColorIndexValue } from 'common/Types'; +import { KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IColorEvent, ColorIndex, ColorRequestType, SpecialColorIndex } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; @@ -203,15 +203,15 @@ export class Terminal extends CoreTerminal implements ITerminal { let acc: 'foreground' | 'background' | 'cursor' | 'ansi'; let ident = ''; switch (req.index) { - case ColorIndexValue.FOREGROUND: // OSC 10 | 110 + case SpecialColorIndex.FOREGROUND: // OSC 10 | 110 acc = 'foreground'; ident = '10'; break; - case ColorIndexValue.BACKGROUND: // OSC 11 | 111 + case SpecialColorIndex.BACKGROUND: // OSC 11 | 111 acc = 'background'; ident = '11'; break; - case ColorIndexValue.CURSOR: // OSC 12 | 112 + case SpecialColorIndex.CURSOR: // OSC 12 | 112 acc = 'cursor'; ident = '12'; break; diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index 76a0f7df..d96285f7 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -8,8 +8,7 @@ import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types'; import { IColorSet, ReadonlyColorSet } from 'browser/Types'; import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types'; import { createDecorator } from 'common/services/ServiceRegistry'; -import { ColorIndex, IDisposable } from 'common/Types'; -import { ITheme } from 'common/services/Services'; +import { AllColorIndex, IDisposable } from 'common/Types'; export const ICharSizeService = createDecorator('CharSizeService'); export interface ICharSizeService { @@ -130,7 +129,7 @@ export interface IThemeService { readonly onChangeColors: IEvent; - restoreColor(slot?: ColorIndex): void; + restoreColor(slot?: AllColorIndex): void; /** * Allows external modifying of colors in the theme, this is used instead of {@link colors} to * prevent accidental writes. diff --git a/src/browser/services/ThemeService.ts b/src/browser/services/ThemeService.ts index d810d44b..2411ce85 100644 --- a/src/browser/services/ThemeService.ts +++ b/src/browser/services/ThemeService.ts @@ -10,7 +10,7 @@ import { channels, color, css, NULL_COLOR } from 'common/Color'; import { EventEmitter } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IOptionsService, ITheme } from 'common/services/Services'; -import { ColorIndex, ColorIndexValue, IColor } from 'common/Types'; +import { ColorIndex, SpecialColorIndex, IColor, AllColorIndex } from 'common/Types'; interface IRestoreColorSet { foreground: IColor; @@ -176,12 +176,12 @@ export class ThemeService extends Disposable implements IThemeService { this._onChangeColors.fire(this.colors); } - public restoreColor(slot?: ColorIndex): void { + public restoreColor(slot?: AllColorIndex): void { this._restoreColor(slot); this._onChangeColors.fire(this.colors); } - private _restoreColor(slot: ColorIndex | undefined): void { + private _restoreColor(slot: AllColorIndex | undefined): void { // unset slot restores all ansi colors if (slot === undefined) { for (let i = 0; i < this._restoreColors.ansi.length; ++i) { @@ -190,13 +190,13 @@ export class ThemeService extends Disposable implements IThemeService { return; } switch (slot) { - case ColorIndexValue.FOREGROUND: + case SpecialColorIndex.FOREGROUND: this._colors.foreground = this._restoreColors.foreground; break; - case ColorIndexValue.BACKGROUND: + case SpecialColorIndex.BACKGROUND: this._colors.background = this._restoreColors.background; break; - case ColorIndexValue.CURSOR: + case SpecialColorIndex.CURSOR: this._colors.cursor = this._restoreColors.cursor; break; default: diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index 9df46838..8f9a988f 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { InputHandler } from 'common/InputHandler'; -import { IBufferLine, IAttributeData, IColorEvent, ColorIndex, ColorRequestType, ColorIndexValue } from 'common/Types'; +import { IBufferLine, IAttributeData, IColorEvent, ColorIndex, ColorRequestType, SpecialColorIndex } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { Attributes, BgFlags, UnderlineStyle } from 'common/buffer/Constants'; @@ -2002,87 +2002,87 @@ describe('InputHandler', () => { inputHandler.onColor(ev => stack.push(ev)); // single foreground query --> color undefined await inputHandler.parseP('\x1b]10;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.FOREGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: SpecialColorIndex.FOREGROUND }]]); stack.length = 0; // OSC with multiple values maps to OSC 10 & OSC 11 & OSC 12 await inputHandler.parseP('\x1b]10;?;?;?;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.FOREGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndexValue.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: SpecialColorIndex.FOREGROUND }], [{ type: ColorRequestType.REPORT, index: SpecialColorIndex.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: SpecialColorIndex.CURSOR }]]); stack.length = 0; // set foreground color events await inputHandler.parseP('\x1b]10;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.FOREGROUND, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: SpecialColorIndex.FOREGROUND, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]10;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.FOREGROUND, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: SpecialColorIndex.FOREGROUND, color: [170, 187, 204] }]]); stack.length = 0; // set FG, BG and cursor color at once await inputHandler.parseP('\x1b]10;rgb:aa/bb/cc;#001122;rgb:12/34/56\x07'); assert.deepEqual(stack, [ - [{ type: ColorRequestType.SET, index: ColorIndexValue.FOREGROUND, color: [170, 187, 204] }], - [{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [0, 17, 34] }], - [{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [18, 52, 86] }] + [{ type: ColorRequestType.SET, index: SpecialColorIndex.FOREGROUND, color: [170, 187, 204] }], + [{ type: ColorRequestType.SET, index: SpecialColorIndex.BACKGROUND, color: [0, 17, 34] }], + [{ type: ColorRequestType.SET, index: SpecialColorIndex.CURSOR, color: [18, 52, 86] }] ]); }); it('110: restore FG color', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]110\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndexValue.FOREGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: SpecialColorIndex.FOREGROUND }]]); }); it('11: BG set & query events', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); // single background query --> color undefined await inputHandler.parseP('\x1b]11;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.BACKGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: SpecialColorIndex.BACKGROUND }]]); stack.length = 0; // OSC 11 with multiple values creates only BG and cursor event await inputHandler.parseP('\x1b]11;?;?;?;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: SpecialColorIndex.BACKGROUND }], [{ type: ColorRequestType.REPORT, index: SpecialColorIndex.CURSOR }]]); stack.length = 0; // set background color events await inputHandler.parseP('\x1b]11;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: SpecialColorIndex.BACKGROUND, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]11;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: SpecialColorIndex.BACKGROUND, color: [170, 187, 204] }]]); stack.length = 0; // set BG and cursor color at once await inputHandler.parseP('\x1b]11;#001122;rgb:12/34/56\x07'); assert.deepEqual(stack, [ - [{ type: ColorRequestType.SET, index: ColorIndexValue.BACKGROUND, color: [0, 17, 34] }], - [{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [18, 52, 86] }] + [{ type: ColorRequestType.SET, index: SpecialColorIndex.BACKGROUND, color: [0, 17, 34] }], + [{ type: ColorRequestType.SET, index: SpecialColorIndex.CURSOR, color: [18, 52, 86] }] ]); }); it('111: restore BG color', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]111\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndexValue.BACKGROUND }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: SpecialColorIndex.BACKGROUND }]]); }); it('12: cursor color set & query events', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); // single cursor query --> color undefined await inputHandler.parseP('\x1b]12;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: SpecialColorIndex.CURSOR }]]); stack.length = 0; // OSC 12 with multiple values creates only cursor event await inputHandler.parseP('\x1b]12;?;?;?;?\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: ColorIndexValue.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.REPORT, index: SpecialColorIndex.CURSOR }]]); stack.length = 0; // set cursor color events await inputHandler.parseP('\x1b]12;rgb:01/02/03\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [1, 2, 3] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: SpecialColorIndex.CURSOR, color: [1, 2, 3] }]]); stack.length = 0; await inputHandler.parseP('\x1b]12;#aabbcc\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: ColorIndexValue.CURSOR, color: [170, 187, 204] }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: SpecialColorIndex.CURSOR, color: [170, 187, 204] }]]); }); it('112: restore cursor color', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); await inputHandler.parseP('\x1b]112\x07'); - assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: ColorIndexValue.CURSOR }]]); + assert.deepEqual(stack, [[{ type: ColorRequestType.RESTORE, index: SpecialColorIndex.CURSOR }]]); }); }); diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index be1277b0..fb8862a0 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, ColorIndexValue } from 'common/Types'; +import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, SpecialColorIndex } from 'common/Types'; import { C0, C1 } from 'common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; @@ -2988,7 +2988,7 @@ export class InputHandler extends Disposable implements IInputHandler { } // special colors - OSC 10 | 11 | 12 - private _specialColors = [ColorIndexValue.FOREGROUND, ColorIndexValue.BACKGROUND, ColorIndexValue.CURSOR]; + private _specialColors = [SpecialColorIndex.FOREGROUND, SpecialColorIndex.BACKGROUND, SpecialColorIndex.CURSOR]; /** * Apply colors requests for special colors in OSC 10 | 11 | 12. @@ -3090,7 +3090,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 110 "Restore default foreground color" "OSC 110 BEL" "Restore default foreground to themed color." */ public restoreFgColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndexValue.FOREGROUND }]); + this._onColor.fire([{ type: ColorRequestType.RESTORE, index: SpecialColorIndex.FOREGROUND }]); return true; } @@ -3100,7 +3100,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 111 "Restore default background color" "OSC 111 BEL" "Restore default background to themed color." */ public restoreBgColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndexValue.BACKGROUND }]); + this._onColor.fire([{ type: ColorRequestType.RESTORE, index: SpecialColorIndex.BACKGROUND }]); return true; } @@ -3110,7 +3110,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 112 "Restore default cursor color" "OSC 112 BEL" "Restore default cursor to themed color." */ public restoreCursorColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndexValue.CURSOR }]); + this._onColor.fire([{ type: ColorRequestType.RESTORE, index: SpecialColorIndex.CURSOR }]); return true; } diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 6268b77a..8fc7fe35 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -420,25 +420,25 @@ type Enumerate = Acc['length'] exte : Enumerate; type IntRange = Exclude, Enumerate>; -type ColorIndex = IntRange<0, 259>; // number from 0 to 258 - -export const enum ColorIndexValue { +type ColorIndex = IntRange<0, 256>; // number from 0 to 255 +type AllColorIndex = ColorIndex | SpecialColorIndex; +export const enum SpecialColorIndex { FOREGROUND = 256, BACKGROUND = 257, CURSOR = 258 } export interface IColorReportRequest { type: ColorRequestType.REPORT; - index: ColorIndex; + index: AllColorIndex; } export interface IColorSetRequest { type: ColorRequestType.SET; - index: ColorIndex; + index: AllColorIndex; color: IColorRGB; } export interface IColorRestoreRequest { type: ColorRequestType.RESTORE; - index?: ColorIndex; + index?: SpecialColorIndex; } export type IColorEvent = (IColorReportRequest | IColorSetRequest | IColorRestoreRequest)[]; From d22e3e093a35b90661a4173a8b6435c8c36f253e Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 29 Jul 2023 14:42:05 -0700 Subject: [PATCH 3/4] Fix compile --- src/common/Types.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 8fc7fe35..965104d5 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -438,7 +438,7 @@ export interface IColorSetRequest { } export interface IColorRestoreRequest { type: ColorRequestType.RESTORE; - index?: SpecialColorIndex; + index?: AllColorIndex; } export type IColorEvent = (IColorReportRequest | IColorSetRequest | IColorRestoreRequest)[]; From 2e638598e4818ad26ecfc6ba085b8ec5c890e266 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 30 Jul 2023 06:55:45 -0700 Subject: [PATCH 4/4] Simplify condition --- src/common/InputHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index fb8862a0..46db6110 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -2915,7 +2915,7 @@ export class InputHandler extends Disposable implements IInputHandler { const spec = slots.shift() as string; if (/^\d+$/.exec(idx)) { const index = parseInt(idx); - if (isValidColorIndex(index) && index < 256) { + if (isValidColorIndex(index)) { if (spec === '?') { event.push({ type: ColorRequestType.REPORT, index }); } else { @@ -3073,7 +3073,7 @@ export class InputHandler extends Disposable implements IInputHandler { for (let i = 0; i < slots.length; ++i) { if (/^\d+$/.exec(slots[i])) { const index = parseInt(slots[i]); - if (isValidColorIndex(index) && index < 256) { + if (isValidColorIndex(index)) { event.push({ type: ColorRequestType.RESTORE, index }); } } @@ -3431,5 +3431,5 @@ class DirtyRowTracker implements IDirtyRowTracker { } function isValidColorIndex(value: number): value is ColorIndex { - return 0 <= value && value < 259; + return 0 <= value && value < 256; }