From 1040b799ce813c76458cb6c40bb5dd4c6d755156 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 26 May 2026 17:07:14 +0000 Subject: [PATCH] Disallow single-line brace-style blocks Set allowSingleLine to false and expand multi-line braces across the codebase via eslint --fix. Co-authored-by: Daniel Imms --- addons/addon-image/src/ImageRenderer.ts | 4 +- addons/addon-image/src/ImageStorage.ts | 4 +- addons/addon-image/test/KittyGraphics.test.ts | 204 ++++-- .../test/LigaturesAddon.test.ts | 8 +- addons/addon-search/src/DecorationManager.ts | 8 +- .../addon-search/src/SearchResultTracker.ts | 4 +- .../src/SerializeAddon.test.ts | 16 +- addons/addon-serialize/src/SerializeAddon.ts | 84 ++- .../src/CursorBlinkStateManager.ts | 4 +- addons/addon-webgl/src/TextureAtlas.ts | 12 +- .../components/window/addonWebFontsWindow.ts | 4 +- demo/client/components/window/baseWindow.ts | 4 +- eslint.config.mjs | 2 +- src/browser/CoreBrowserTerminal.ts | 24 +- src/browser/Linkifier.ts | 4 +- src/browser/TestUtils.test.ts | 20 +- src/browser/input/CompositionHelper.ts | 4 +- src/browser/public/Terminal.ts | 88 ++- src/browser/services/CharSizeService.ts | 4 +- src/browser/services/RenderService.ts | 4 +- src/browser/services/SelectionService.test.ts | 20 +- src/browser/services/SelectionService.ts | 8 +- src/browser/services/ThemeService.ts | 4 +- src/common/CoreTerminal.ts | 16 +- src/common/Event.test.ts | 16 +- src/common/InputHandler.test.ts | 16 +- src/common/InputHandler.ts | 8 +- src/common/TestUtils.test.ts | 24 +- src/common/buffer/AttributeData.ts | 76 ++- src/common/buffer/Marker.ts | 4 +- src/common/input/WriteBuffer.test.ts | 76 ++- src/common/input/WriteBuffer.ts | 4 +- src/common/parser/ApcParser.test.ts | 56 +- src/common/parser/DcsParser.test.ts | 56 +- .../parser/EscapeSequenceParser.test.ts | 584 +++++++++++++----- src/common/parser/OscParser.test.ts | 56 +- src/common/public/AddonManager.test.ts | 4 +- src/common/public/BufferApiView.ts | 24 +- src/common/public/BufferLineApiView.ts | 8 +- src/common/public/BufferNamespaceApi.ts | 8 +- src/common/services/BufferService.ts | 4 +- src/common/services/DecorationService.ts | 4 +- src/common/services/LogService.ts | 4 +- src/common/services/MouseStateService.test.ts | 8 +- src/common/services/UnicodeService.test.ts | 8 +- src/headless/public/Terminal.test.ts | 24 +- src/headless/public/Terminal.ts | 48 +- .../EscapeSequenceParser.benchmark.ts | 12 +- test/benchmark/Event.benchmark.ts | 16 +- test/playwright/TestUtils.ts | 324 +++++++--- 50 files changed, 1520 insertions(+), 506 deletions(-) diff --git a/addons/addon-image/src/ImageRenderer.ts b/addons/addon-image/src/ImageRenderer.ts index b36cdd004..ff02536c7 100644 --- a/addons/addon-image/src/ImageRenderer.ts +++ b/addons/addon-image/src/ImageRenderer.ts @@ -21,7 +21,9 @@ const enum Constants { */ export class ImageRenderer extends Disposable implements IDisposable { /** @deprecated Kept for backward compat — points to top layer canvas. */ - public get canvas(): HTMLCanvasElement | undefined { return this._layers.get('top')?.canvas; } + public get canvas(): HTMLCanvasElement | undefined { + return this._layers.get('top')?.canvas; + } private _layers = new Map(); private _placeholder: HTMLCanvasElement | undefined; private _placeholderBitmap: ImageBitmap | undefined; diff --git a/addons/addon-image/src/ImageStorage.ts b/addons/addon-image/src/ImageStorage.ts index 8c89a16b0..c54ab893c 100644 --- a/addons/addon-image/src/ImageStorage.ts +++ b/addons/addon-image/src/ImageStorage.ts @@ -31,7 +31,9 @@ class ExtendedAttrsImage implements IExtendedAttrsImage { } return this._ext; } - public set ext(value: number) { this._ext = value; } + public set ext(value: number) { + this._ext = value; + } public get underlineStyle(): UnderlineStyle { // Always return the URL style if it has one diff --git a/addons/addon-image/test/KittyGraphics.test.ts b/addons/addon-image/test/KittyGraphics.test.ts index a9b5d6845..f57916c28 100644 --- a/addons/addon-image/test/KittyGraphics.test.ts +++ b/addons/addon-image/test/KittyGraphics.test.ts @@ -322,7 +322,9 @@ test.describe('Kitty Graphics Protocol', () => { test('chunked transfer responds OK on final chunk when i= on first only', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); const half = Math.floor(KITTY_BLACK_1X1_BASE64.length / 2); @@ -542,7 +544,9 @@ test.describe('Kitty Graphics Protocol', () => { let response = ''; await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write('\x1b_Gi=31,a=q;\x1b\\'); @@ -556,7 +560,9 @@ test.describe('Kitty Graphics Protocol', () => { let response = ''; await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=42,a=q,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -581,7 +587,9 @@ test.describe('Kitty Graphics Protocol', () => { let response = ''; await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write('\x1b_Gi=60,a=q,f=100;!!!invalid!!!\x1b\\'); @@ -595,7 +603,9 @@ test.describe('Kitty Graphics Protocol', () => { let response = ''; await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write('\x1b_Gi=70,a=q,f=24;AAAA\x1b\\'); @@ -608,7 +618,9 @@ test.describe('Kitty Graphics Protocol', () => { test('suppresses OK response when q=1', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Gi=80,a=q,q=1,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -620,7 +632,9 @@ test.describe('Kitty Graphics Protocol', () => { test('suppresses OK response when q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Gi=81,a=q,q=2,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -632,7 +646,9 @@ test.describe('Kitty Graphics Protocol', () => { test('suppresses error response when q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write('\x1b_Gi=90,a=q,q=2,f=100;!!!invalid!!!\x1b\\'); @@ -645,7 +661,9 @@ test.describe('Kitty Graphics Protocol', () => { let response = ''; await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); // Per spec: "Specifying both i and I keys in any command is an error" @@ -660,7 +678,9 @@ test.describe('Kitty Graphics Protocol', () => { let response = ''; await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); // Delete command with both i and I (no payload case) @@ -676,7 +696,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=t sends EINVAL on decode error when id is specified', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write('\x1b_Gi=110,a=t,f=100;!!!invalid!!!\x1b\\'); @@ -689,7 +711,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=t sends no response on decode error without id', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write('\x1b_Ga=t,f=100;!!!invalid!!!\x1b\\'); @@ -701,7 +725,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T sends EINVAL on decode error when id is specified', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write('\x1b_Gi=120,a=T,f=100;!!!invalid!!!\x1b\\'); @@ -714,7 +740,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T sends no response on decode error without id', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write('\x1b_Ga=T,f=100;!!!invalid!!!\x1b\\'); @@ -726,7 +754,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T sends EINVAL when raw pixel render fails (missing dimensions)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=130,a=T,f=24;${RAW_RGB_1X1_BLACK}\x1b\\`); @@ -739,7 +769,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T sends OK on successful render with id', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=140,a=T,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -752,7 +784,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=t sends OK on successful transmit with id', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=150,a=t,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -765,7 +799,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=t EINVAL suppressed by q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write('\x1b_Gi=160,a=t,q=2,f=100;!!!invalid!!!\x1b\\'); @@ -777,7 +813,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T EINVAL suppressed by q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write('\x1b_Gi=170,a=T,q=2,f=100;!!!invalid!!!\x1b\\'); @@ -789,7 +827,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=t OK suppressed by q=1', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Gi=180,a=t,q=1,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -801,7 +841,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T OK suppressed by q=1', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Gi=190,a=T,q=1,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -813,7 +855,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=t OK suppressed by q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Gi=181,a=t,q=2,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -825,7 +869,9 @@ test.describe('Kitty Graphics Protocol', () => { test('a=T OK suppressed by q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Gi=191,a=T,q=2,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -839,7 +885,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query rejects t=f (file transmission)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=200,a=q,t=f,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -852,7 +900,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query rejects t=s (shared memory)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=201,a=q,t=s,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -865,7 +915,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query rejects t=t (temp file)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=202,a=q,t=t,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -878,7 +930,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query accepts t=d (direct transmission)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=203,a=q,t=d,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -891,7 +945,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query without t key defaults to direct (OK)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=204,a=q,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -904,7 +960,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit rejects t=f with id (EINVAL response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=300,a=t,t=f,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -917,7 +975,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit rejects t=s with id (EINVAL response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=301,a=t,t=s,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -930,7 +990,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit rejects t=t with id (EINVAL response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=302,a=t,t=t,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -943,7 +1005,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit rejects t=f without id (no response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Ga=t,t=f,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -956,7 +1020,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit+display rejects t=f with id (EINVAL response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=310,a=T,t=f,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -969,7 +1035,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit+display rejects t=s with id (EINVAL response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=311,a=T,t=s,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -982,7 +1050,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit+display rejects t=t with id (EINVAL response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=312,a=T,t=t,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -995,7 +1065,9 @@ test.describe('Kitty Graphics Protocol', () => { test('transmit+display rejects t=f without id (no response)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Ga=T,t=f,f=100;${KITTY_BLACK_1X1_BASE64}\x1b\\`); @@ -1026,7 +1098,9 @@ test.describe('Kitty Graphics Protocol', () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=211\x1b\\`); @@ -1039,7 +1113,9 @@ test.describe('Kitty Graphics Protocol', () => { test('responds ENOENT for non-existent image id', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=9999\x1b\\`); @@ -1052,7 +1128,9 @@ test.describe('Kitty Graphics Protocol', () => { test('without id sends no response', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Ga=p\x1b\\`); @@ -1172,7 +1250,9 @@ test.describe('Kitty Graphics Protocol', () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=220,q=1\x1b\\`); @@ -1188,7 +1268,9 @@ test.describe('Kitty Graphics Protocol', () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=221,q=2\x1b\\`); @@ -1201,7 +1283,9 @@ test.describe('Kitty Graphics Protocol', () => { test('ENOENT error suppressed by q=2', async () => { await ctx.page.evaluate(() => { (window as any).kittyGotResponse = false; - (window as any).term.onData(() => { (window as any).kittyGotResponse = true; }); + (window as any).term.onData(() => { + (window as any).kittyGotResponse = true; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=9998,q=2\x1b\\`); @@ -1213,7 +1297,9 @@ test.describe('Kitty Graphics Protocol', () => { test('ENOENT still reported when q=1 (only suppresses OK)', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=9997,q=1\x1b\\`); @@ -1268,7 +1354,9 @@ test.describe('Kitty Graphics Protocol', () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Ga=p,i=224,p=42\x1b\\`); @@ -1803,7 +1891,9 @@ test.describe('Kitty Graphics Protocol', () => { test('responds with OK for valid 200x100 PNG query', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=600,a=q,f=100;${KITTY_MULTICOLOR_200X100_BASE64}\x1b\\`); @@ -1952,7 +2042,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query returns EINVAL without dimensions', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=200,a=q,f=24;${RAW_RGB_1X1_BLACK}\x1b\\`); await timeout(100); @@ -1963,7 +2055,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query returns EINVAL for insufficient pixel data', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=201,a=q,f=24,s=2,v=2;${RAW_RGB_1X1_BLACK}\x1b\\`); await timeout(100); @@ -1974,7 +2068,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query returns OK for valid RGB data with correct dimensions', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=202,a=q,f=24,s=1,v=1;${RAW_RGB_1X1_RED}\x1b\\`); await timeout(100); @@ -2086,7 +2182,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query returns EINVAL without dimensions', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=300,a=q,f=32;${RAW_RGBA_1X1_RED}\x1b\\`); await timeout(100); @@ -2097,7 +2195,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query returns EINVAL for insufficient pixel data', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=301,a=q,f=32,s=2,v=2;${RAW_RGBA_1X1_RED}\x1b\\`); await timeout(100); @@ -2108,7 +2208,9 @@ test.describe('Kitty Graphics Protocol', () => { test('query returns OK for valid RGBA data with correct dimensions', async () => { await ctx.page.evaluate(() => { (window as any).kittyResponse = ''; - (window as any).term.onData((data: string) => { (window as any).kittyResponse = data; }); + (window as any).term.onData((data: string) => { + (window as any).kittyResponse = data; + }); }); await ctx.proxy.write(`\x1b_Gi=302,a=q,f=32,s=1,v=1;${RAW_RGBA_1X1_RED}\x1b\\`); await timeout(100); diff --git a/addons/addon-ligatures/test/LigaturesAddon.test.ts b/addons/addon-ligatures/test/LigaturesAddon.test.ts index 0ba5ee5f7..8c50eac50 100644 --- a/addons/addon-ligatures/test/LigaturesAddon.test.ts +++ b/addons/addon-ligatures/test/LigaturesAddon.test.ts @@ -46,7 +46,9 @@ describe('LigaturesAddon', () => { }); beforeEach(() => { - onRefresh = Object.assign((..._args: any[]) => { onRefresh.called = true; onRefresh.callCount++; }, { called: false, callCount: 0 }); + onRefresh = Object.assign((..._args: any[]) => { + onRefresh.called = true; onRefresh.callCount++; + }, { called: false, callCount: 0 }); term = new MockTerminal(onRefresh); ligatureSupport.enableLigatures(term as any); }); @@ -127,7 +129,9 @@ class MockTerminal { public deregisterCharacterJoiner(id: number): void { this.joiner = undefined; } - public get options(): { [name: string]: string | number } { return this._options; } + public get options(): { [name: string]: string | number } { + return this._options; + } public set options(options: { [name: string]: string | number }) { for (const key in this._options) { this._options[key] = options[key]; diff --git a/addons/addon-search/src/DecorationManager.ts b/addons/addon-search/src/DecorationManager.ts index a8ec12017..ff827dd7a 100644 --- a/addons/addon-search/src/DecorationManager.ts +++ b/addons/addon-search/src/DecorationManager.ts @@ -64,7 +64,9 @@ export class DecorationManager extends Disposable { public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined { const decorations = this._createResultDecorations(result, options, true); if (decorations) { - return { decorations, match: result, dispose() { dispose(decorations); } }; + return { decorations, match: result, dispose() { + dispose(decorations); + } }; } return undefined; } @@ -85,7 +87,9 @@ export class DecorationManager extends Disposable { */ private _storeDecoration(decoration: IDecoration, match: ISearchResult): void { this._highlightedLines.add(decoration.marker.line); - this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } }); + this._highlightDecorations.push({ decoration, match, dispose() { + decoration.dispose(); + } }); } /** diff --git a/addons/addon-search/src/SearchResultTracker.ts b/addons/addon-search/src/SearchResultTracker.ts index 285345b7a..90a215897 100644 --- a/addons/addon-search/src/SearchResultTracker.ts +++ b/addons/addon-search/src/SearchResultTracker.ts @@ -25,7 +25,9 @@ export class SearchResultTracker extends Disposable { private _selectedDecoration: ISelectedDecoration | undefined; private readonly _onDidChangeResults = this._register(new Emitter()); - public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; } + public get onDidChangeResults(): IEvent { + return this._onDidChangeResults.event; + } /** * Gets the current search results. diff --git a/addons/addon-serialize/src/SerializeAddon.test.ts b/addons/addon-serialize/src/SerializeAddon.test.ts index 4f4fd5461..34ca86936 100644 --- a/addons/addon-serialize/src/SerializeAddon.test.ts +++ b/addons/addon-serialize/src/SerializeAddon.test.ts @@ -29,12 +29,20 @@ class TestSelectionService { this._model = new SelectionModel(bufferService); } - public get model(): SelectionModel { return this._model; } + public get model(): SelectionModel { + return this._model; + } - public get hasSelection(): boolean { return this._hasSelection; } + public get hasSelection(): boolean { + return this._hasSelection; + } - public get selectionStart(): [number, number] | undefined { return this._model.finalSelectionStart; } - public get selectionEnd(): [number, number] | undefined { return this._model.finalSelectionEnd; } + public get selectionStart(): [number, number] | undefined { + return this._model.finalSelectionStart; + } + public get selectionEnd(): [number, number] | undefined { + return this._model.finalSelectionEnd; + } public setSelection(col: number, row: number, length: number): void { this._model.selectionStart = [col, row]; diff --git a/addons/addon-serialize/src/SerializeAddon.ts b/addons/addon-serialize/src/SerializeAddon.ts index d7130040a..ce7baee8c 100644 --- a/addons/addon-serialize/src/SerializeAddon.ts +++ b/addons/addon-serialize/src/SerializeAddon.ts @@ -70,7 +70,9 @@ abstract class BaseSerializeHandler { protected _rowEnd(row: number, isLastRow: boolean): void { } protected _beforeSerialize(rows: number, startRow: number, endRow: number): void { } protected _afterSerialize(): void { } - protected _serializeString(excludeFinalCursorPosition?: boolean): string { return ''; } + protected _serializeString(excludeFinalCursorPosition?: boolean): string { + return ''; + } } function equalFg(cell1: IBufferCell | IAttributeData, cell2: IBufferCell): boolean { @@ -291,19 +293,39 @@ class StringSerializeHandler extends BaseSerializeHandler { } else { if (fgChanged) { const color = cell.getFgColor(); - if (cell.isFgRGB()) { sgrSeq.push(38, 2, (color >>> 16) & 0xFF, (color >>> 8) & 0xFF, color & 0xFF); } else if (cell.isFgPalette()) { - if (color >= 16) { sgrSeq.push(38, 5, color); } else { sgrSeq.push(color & 8 ? 90 + (color & 7) : 30 + (color & 7)); } - } else { sgrSeq.push(39); } + if (cell.isFgRGB()) { + sgrSeq.push(38, 2, (color >>> 16) & 0xFF, (color >>> 8) & 0xFF, color & 0xFF); + } else if (cell.isFgPalette()) { + if (color >= 16) { + sgrSeq.push(38, 5, color); + } else { + sgrSeq.push(color & 8 ? 90 + (color & 7) : 30 + (color & 7)); + } + } else { + sgrSeq.push(39); + } } if (bgChanged) { const color = cell.getBgColor(); - if (cell.isBgRGB()) { sgrSeq.push(48, 2, (color >>> 16) & 0xFF, (color >>> 8) & 0xFF, color & 0xFF); } else if (cell.isBgPalette()) { - if (color >= 16) { sgrSeq.push(48, 5, color); } else { sgrSeq.push(color & 8 ? 100 + (color & 7) : 40 + (color & 7)); } - } else { sgrSeq.push(49); } + if (cell.isBgRGB()) { + sgrSeq.push(48, 2, (color >>> 16) & 0xFF, (color >>> 8) & 0xFF, color & 0xFF); + } else if (cell.isBgPalette()) { + if (color >= 16) { + sgrSeq.push(48, 5, color); + } else { + sgrSeq.push(color & 8 ? 100 + (color & 7) : 40 + (color & 7)); + } + } else { + sgrSeq.push(49); + } } if (flagsChanged) { - if (cell.isInverse() !== oldCell.isInverse()) { sgrSeq.push(cell.isInverse() ? 7 : 27); } - if (cell.isBold() !== oldCell.isBold()) { sgrSeq.push(cell.isBold() ? 1 : 22); } + if (cell.isInverse() !== oldCell.isInverse()) { + sgrSeq.push(cell.isInverse() ? 7 : 27); + } + if (cell.isBold() !== oldCell.isBold()) { + sgrSeq.push(cell.isBold() ? 1 : 22); + } if (!equalUnderline(cell, oldCell)) { const style = cell.getUnderlineStyle(); if (style === UnderlineStyle.NONE) { @@ -326,12 +348,24 @@ class StringSerializeHandler extends BaseSerializeHandler { } else if (cell.isUnderline() !== oldCell.isUnderline()) { sgrSeq.push(cell.isUnderline() ? 4 : 24); } - if (cell.isOverline() !== oldCell.isOverline()) { sgrSeq.push(cell.isOverline() ? 53 : 55); } - if (cell.isBlink() !== oldCell.isBlink()) { sgrSeq.push(cell.isBlink() ? 5 : 25); } - if (cell.isInvisible() !== oldCell.isInvisible()) { sgrSeq.push(cell.isInvisible() ? 8 : 28); } - if (cell.isItalic() !== oldCell.isItalic()) { sgrSeq.push(cell.isItalic() ? 3 : 23); } - if (cell.isDim() !== oldCell.isDim()) { sgrSeq.push(cell.isDim() ? 2 : 22); } - if (cell.isStrikethrough() !== oldCell.isStrikethrough()) { sgrSeq.push(cell.isStrikethrough() ? 9 : 29); } + if (cell.isOverline() !== oldCell.isOverline()) { + sgrSeq.push(cell.isOverline() ? 53 : 55); + } + if (cell.isBlink() !== oldCell.isBlink()) { + sgrSeq.push(cell.isBlink() ? 5 : 25); + } + if (cell.isInvisible() !== oldCell.isInvisible()) { + sgrSeq.push(cell.isInvisible() ? 8 : 28); + } + if (cell.isItalic() !== oldCell.isItalic()) { + sgrSeq.push(cell.isItalic() ? 3 : 23); + } + if (cell.isDim() !== oldCell.isDim()) { + sgrSeq.push(cell.isDim() ? 2 : 22); + } + if (cell.isStrikethrough() !== oldCell.isStrikethrough()) { + sgrSeq.push(cell.isStrikethrough() ? 9 : 29); + } } } } @@ -745,8 +779,12 @@ export class HTMLSerializeHandler extends BaseSerializeHandler { content.push('background-color: ' + bgHexColor + ';'); } - if (cell.isInverse()) { content.push('color: #000000; background-color: #BFBFBF;'); } - if (cell.isBold()) { content.push('font-weight: bold;'); } + if (cell.isInverse()) { + content.push('color: #000000; background-color: #BFBFBF;'); + } + if (cell.isBold()) { + content.push('font-weight: bold;'); + } // Handle text-decoration (underline, overline, strikethrough, blink) const decorations: string[] = []; @@ -774,9 +812,15 @@ export class HTMLSerializeHandler extends BaseSerializeHandler { } } - if (cell.isInvisible()) { content.push('visibility: hidden;'); } - if (cell.isItalic()) { content.push('font-style: italic;'); } - if (cell.isDim()) { content.push('opacity: 0.5;'); } + if (cell.isInvisible()) { + content.push('visibility: hidden;'); + } + if (cell.isItalic()) { + content.push('font-style: italic;'); + } + if (cell.isDim()) { + content.push('opacity: 0.5;'); + } return content; } diff --git a/addons/addon-webgl/src/CursorBlinkStateManager.ts b/addons/addon-webgl/src/CursorBlinkStateManager.ts index 688aee7b7..7561b869a 100644 --- a/addons/addon-webgl/src/CursorBlinkStateManager.ts +++ b/addons/addon-webgl/src/CursorBlinkStateManager.ts @@ -40,7 +40,9 @@ export class CursorBlinkStateManager { } } - public get isPaused(): boolean { return !(this._blinkStartTimeout || this._blinkInterval); } + public get isPaused(): boolean { + return !(this._blinkStartTimeout || this._blinkInterval); + } public dispose(): void { if (this._blinkInterval) { diff --git a/addons/addon-webgl/src/TextureAtlas.ts b/addons/addon-webgl/src/TextureAtlas.ts index 34188235c..61dc31790 100644 --- a/addons/addon-webgl/src/TextureAtlas.ts +++ b/addons/addon-webgl/src/TextureAtlas.ts @@ -62,7 +62,9 @@ export class TextureAtlas implements ITextureAtlas { // The texture that the atlas is drawn to private _pages: AtlasPage[] = []; - public get pages(): { canvas: HTMLCanvasElement, version: number }[] { return this._pages; } + public get pages(): { canvas: HTMLCanvasElement, version: number }[] { + return this._pages; + } // The set of atlas pages that can be written to private _activePages: AtlasPage[] = []; @@ -1039,10 +1041,14 @@ class AtlasPage { public readonly ctx: CanvasRenderingContext2D; private _usedPixels: number = 0; - public get percentageUsed(): number { return this._usedPixels / (this.canvas.width * this.canvas.height); } + public get percentageUsed(): number { + return this._usedPixels / (this.canvas.width * this.canvas.height); + } private readonly _glyphs: IRasterizedGlyph[] = []; - public get glyphs(): ReadonlyArray { return this._glyphs; } + public get glyphs(): ReadonlyArray { + return this._glyphs; + } public addGlyph(glyph: IRasterizedGlyph): void { this._glyphs.push(glyph); this._usedPixels += glyph.size.x * glyph.size.y; diff --git a/demo/client/components/window/addonWebFontsWindow.ts b/demo/client/components/window/addonWebFontsWindow.ts index c8fb288d1..ac11c7785 100644 --- a/demo/client/components/window/addonWebFontsWindow.ts +++ b/demo/client/components/window/addonWebFontsWindow.ts @@ -30,7 +30,9 @@ export class AddonWebFontsWindow extends BaseWindow implements IControlWindow { this._terminal.options.lineHeight = 1.3; this._addons.fit.instance?.fit(); setTimeout(() => this._terminal.write('\x1b[?12h\x1b]12;#776CF9\x07\x1b[38;2;119;108;249;48;2;21;8;150m\x1b[2J\x1b[2;5H**** COMMODORE 64 BASIC V2 ****\r\n\r\n 64K RAM SYSTEM 38911 BASIC BYTES FREE\r\n\r\nREADY.\r\nLOAD '), 1000); - setTimeout(() => { this._terminal.write('🤣\x1b[m\x1b[99;1H'); this._terminal.input('\r'); }, 5000); + setTimeout(() => { + this._terminal.write('🤣\x1b[m\x1b[99;1H'); this._terminal.input('\r'); + }, 5000); }); ddKongtext.appendChild(btnKongtext); dl.appendChild(ddKongtext); diff --git a/demo/client/components/window/baseWindow.ts b/demo/client/components/window/baseWindow.ts index e2667ac83..ed463bb35 100644 --- a/demo/client/components/window/baseWindow.ts +++ b/demo/client/components/window/baseWindow.ts @@ -8,7 +8,9 @@ import type { IControlWindow } from '../controlBar'; import type { Terminal } from '@xterm/xterm'; export abstract class BaseWindow implements IControlWindow { - protected get _terminal(): Terminal { return this._terminalPrivate; } + protected get _terminal(): Terminal { + return this._terminalPrivate; + } constructor( private _terminalPrivate: Terminal, diff --git a/eslint.config.mjs b/eslint.config.mjs index b92202ba7..c945c63e5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -128,7 +128,7 @@ export default tseslint.config( 'no-fallthrough': 'off', 'prefer-spread': 'off', 'object-curly-spacing': ['warn', 'always'], - 'brace-style': ['warn', '1tbs', { allowSingleLine: true }], + 'brace-style': ['warn', '1tbs', { allowSingleLine: false }], 'prefer-const': 'warn', 'spaced-comment': ['warn', 'always', { markers: ['/'], exceptions: ['-'] }] } diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index 953f30180..c1438d05a 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -71,7 +71,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { private _compositionView: HTMLElement | undefined; private readonly _linkifier: MutableDisposable = this._register(new MutableDisposable()); - public get linkifier(): ILinkifier2 | undefined { return this._linkifier.value; } + public get linkifier(): ILinkifier2 | undefined { + return this._linkifier.value; + } private _overviewRulerRenderer: OverviewRulerRenderer | undefined; private _viewport: Viewport | undefined; @@ -136,15 +138,25 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { public readonly onBell = this._onBell.event; private _onFocus = this._register(new Emitter()); - public get onFocus(): IEvent { return this._onFocus.event; } + public get onFocus(): IEvent { + return this._onFocus.event; + } private _onBlur = this._register(new Emitter()); - public get onBlur(): IEvent { return this._onBlur.event; } + public get onBlur(): IEvent { + return this._onBlur.event; + } private _onA11yCharEmitter = this._register(new Emitter()); - public get onA11yChar(): IEvent { return this._onA11yCharEmitter.event; } + public get onA11yChar(): IEvent { + return this._onA11yCharEmitter.event; + } private _onA11yTabEmitter = this._register(new Emitter()); - public get onA11yTab(): IEvent { return this._onA11yTabEmitter.event; } + public get onA11yTab(): IEvent { + return this._onA11yTabEmitter.event; + } private _onWillOpen = this._register(new Emitter()); - public get onWillOpen(): IEvent { return this._onWillOpen.event; } + public get onWillOpen(): IEvent { + return this._onWillOpen.event; + } private readonly _onDimensionsChange = this._register(new Emitter()); public readonly onDimensionsChange = this._onDimensionsChange.event; diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index 31c91daee..bbc713d88 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -12,7 +12,9 @@ import { Emitter } from 'common/Event'; import { addDisposableListener } from 'browser/Dom'; export class Linkifier extends Disposable implements ILinkifier2 { - public get currentLink(): ILinkWithState | undefined { return this._currentLink; } + public get currentLink(): ILinkWithState | undefined { + return this._currentLink; + } protected _currentLink: ILinkWithState | undefined; private _mouseDownLink: ILinkWithState | undefined; private _lastMouseEvent: MouseEvent | undefined; diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 65a18da72..533a6989b 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -21,9 +21,15 @@ import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils'; import { Emitter, type IEvent } from 'common/Event'; export class TestTerminal extends CoreBrowserTerminal { - public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } - public keyDown(ev: any): boolean | undefined { return this._keyDown(ev); } - public keyPress(ev: any): boolean { return this._keyPress(ev); } + public get curAttrData(): IAttributeData { + return (this as any)._inputHandler._curAttrData; + } + public keyDown(ev: any): boolean | undefined { + return this._keyDown(ev); + } + public keyPress(ev: any): boolean { + return this._keyPress(ev); + } public writeP(data: string | Uint8Array): Promise { return new Promise(r => this.write(data, r)); } @@ -213,7 +219,9 @@ export class MockTerminal implements ITerminal { public refresh(start: number, end: number): void { throw new Error('Method not implemented.'); } - public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { + return 0; + } public deregisterCharacterJoiner(joinerId: number): void { } } @@ -377,7 +385,9 @@ export class MockCoreBrowserService implements ICoreBrowserService { export class MockCharSizeService implements ICharSizeService { public serviceBrand: undefined; - public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } + public get hasValidSize(): boolean { + return this.width > 0 && this.height > 0; + } public onCharSizeChange: IEvent = new Emitter().event; constructor(public width: number, public height: number) {} public measure(): void {} diff --git a/src/browser/input/CompositionHelper.ts b/src/browser/input/CompositionHelper.ts index 283874139..4b96acda7 100644 --- a/src/browser/input/CompositionHelper.ts +++ b/src/browser/input/CompositionHelper.ts @@ -23,7 +23,9 @@ export class CompositionHelper { * IME. This variable determines whether the compositionText should be displayed on the UI. */ private _isComposing: boolean; - public get isComposing(): boolean { return this._isComposing; } + public get isComposing(): boolean { + return this._isComposing; + } /** * The position within the input textarea's value of the current composition. diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index 75aada048..52a06dc9c 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -68,22 +68,52 @@ export class Terminal extends Disposable implements ITerminalApi { } } - public get onBell(): IEvent { return this._core.onBell; } - public get onBinary(): IEvent { return this._core.onBinary; } - public get onCursorMove(): IEvent { return this._core.onCursorMove; } - public get onData(): IEvent { return this._core.onData; } - public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._core.onKey; } - public get onLineFeed(): IEvent { return this._core.onLineFeed; } - public get onRender(): IEvent<{ start: number, end: number }> { return this._core.onRender; } - public get onResize(): IEvent<{ cols: number, rows: number }> { return this._core.onResize; } - public get onScroll(): IEvent { return this._core.onScroll; } - public get onSelectionChange(): IEvent { return this._core.onSelectionChange; } - public get onTitleChange(): IEvent { return this._core.onTitleChange; } - public get onWriteParsed(): IEvent { return this._core.onWriteParsed; } - public get onDimensionsChange(): IEvent { return this._core.onDimensionsChange; } + public get onBell(): IEvent { + return this._core.onBell; + } + public get onBinary(): IEvent { + return this._core.onBinary; + } + public get onCursorMove(): IEvent { + return this._core.onCursorMove; + } + public get onData(): IEvent { + return this._core.onData; + } + public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { + return this._core.onKey; + } + public get onLineFeed(): IEvent { + return this._core.onLineFeed; + } + public get onRender(): IEvent<{ start: number, end: number }> { + return this._core.onRender; + } + public get onResize(): IEvent<{ cols: number, rows: number }> { + return this._core.onResize; + } + public get onScroll(): IEvent { + return this._core.onScroll; + } + public get onSelectionChange(): IEvent { + return this._core.onSelectionChange; + } + public get onTitleChange(): IEvent { + return this._core.onTitleChange; + } + public get onWriteParsed(): IEvent { + return this._core.onWriteParsed; + } + public get onDimensionsChange(): IEvent { + return this._core.onDimensionsChange; + } - public get element(): HTMLElement | undefined { return this._core.element; } - public get screenElement(): HTMLElement | undefined { return this._core.screenElement; } + public get element(): HTMLElement | undefined { + return this._core.element; + } + public get screenElement(): HTMLElement | undefined { + return this._core.screenElement; + } public get parser(): IParser { return this._parser ??= new ParserApi(this._core); } @@ -91,9 +121,15 @@ export class Terminal extends Disposable implements ITerminalApi { this._checkProposedApi(); return new UnicodeApi(this._core); } - public get textarea(): HTMLTextAreaElement | undefined { return this._core.textarea; } - public get rows(): number { return this._core.rows; } - public get cols(): number { return this._core.cols; } + public get textarea(): HTMLTextAreaElement | undefined { + return this._core.textarea; + } + public get rows(): number { + return this._core.rows; + } + public get cols(): number { + return this._core.cols; + } public get buffer(): IBufferNamespaceApi { return this._buffer ??= this._register(new BufferNamespaceApi(this._core)); } @@ -247,10 +283,18 @@ export class Terminal extends Disposable implements ITerminalApi { public static get strings(): ILocalizableStrings { // A wrapper is required here because esbuild prevents setting an `export let` return { - get promptLabel(): string { return Strings.promptLabel.get(); }, - set promptLabel(value: string) { Strings.promptLabel.set(value); }, - get tooMuchOutput(): string { return Strings.tooMuchOutput.get(); }, - set tooMuchOutput(value: string) { Strings.tooMuchOutput.set(value); } + get promptLabel(): string { + return Strings.promptLabel.get(); + }, + set promptLabel(value: string) { + Strings.promptLabel.set(value); + }, + get tooMuchOutput(): string { + return Strings.tooMuchOutput.get(); + }, + set tooMuchOutput(value: string) { + Strings.tooMuchOutput.set(value); + } }; } diff --git a/src/browser/services/CharSizeService.ts b/src/browser/services/CharSizeService.ts index 6baf9b50a..8e8106227 100644 --- a/src/browser/services/CharSizeService.ts +++ b/src/browser/services/CharSizeService.ts @@ -15,7 +15,9 @@ export class CharSizeService extends Disposable implements ICharSizeService { public height: number = 0; private _measureStrategy: IMeasureStrategy; - public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } + public get hasValidSize(): boolean { + return this.width > 0 && this.height > 0; + } private readonly _onCharSizeChange = this._register(new Emitter()); public readonly onCharSizeChange = this._onCharSizeChange.event; diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 83e3d3379..06ee04908 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -52,7 +52,9 @@ export class RenderService extends Disposable implements IRenderService { private readonly _onRefreshRequest = this._register(new Emitter<{ start: number, end: number }>()); public readonly onRefreshRequest = this._onRefreshRequest.event; - public get dimensions(): IRenderDimensions { return this._renderer.value!.dimensions; } + public get dimensions(): IRenderDimensions { + return this._renderer.value!.dimensions; + } constructor( private _rowCount: number, diff --git a/src/browser/services/SelectionService.test.ts b/src/browser/services/SelectionService.test.ts index be62ccc6b..b2e4025a3 100644 --- a/src/browser/services/SelectionService.test.ts +++ b/src/browser/services/SelectionService.test.ts @@ -27,13 +27,23 @@ class TestSelectionService extends SelectionService { super(null!, null!, null!, bufferService, new MockCoreService(), new MockMouseService(), optionsService, renderService, new MockCoreBrowserService()); } - public get model(): SelectionModel { return this._model; } + public get model(): SelectionModel { + return this._model; + } - public set selectionMode(mode: SelectionMode) { this._activeSelectionMode = mode; } + public set selectionMode(mode: SelectionMode) { + this._activeSelectionMode = mode; + } - public selectLineAt(line: number): void { this._selectLineAt(line); } - public selectWordAt(coords: [number, number]): void { this._selectWordAt(coords, true); } - public areCoordsInSelection(coords: [number, number], start: [number, number], end: [number, number]): boolean { return this._areCoordsInSelection(coords, start, end); } + public selectLineAt(line: number): void { + this._selectLineAt(line); + } + public selectWordAt(coords: [number, number]): void { + this._selectWordAt(coords, true); + } + public areCoordsInSelection(coords: [number, number], start: [number, number], end: [number, number]): boolean { + return this._areCoordsInSelection(coords, start, end); + } // Disable DOM interaction public enable(): void {} diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index 39692a871..f6af80b1d 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -181,8 +181,12 @@ export class SelectionService extends Disposable implements ISelectionService { this._enabled = true; } - public get selectionStart(): [number, number] | undefined { return this._model.finalSelectionStart; } - public get selectionEnd(): [number, number] | undefined { return this._model.finalSelectionEnd; } + public get selectionStart(): [number, number] | undefined { + return this._model.finalSelectionStart; + } + public get selectionEnd(): [number, number] | undefined { + return this._model.finalSelectionEnd; + } /** * Gets whether there is an active text selection. diff --git a/src/browser/services/ThemeService.ts b/src/browser/services/ThemeService.ts index f2b23f3ce..1cbb1bc90 100644 --- a/src/browser/services/ThemeService.ts +++ b/src/browser/services/ThemeService.ts @@ -38,7 +38,9 @@ export class ThemeService extends Disposable implements IThemeService { private _halfContrastCache: IColorContrastCache = new ColorContrastCache(); private _restoreColors!: IRestoreColorSet; - public get colors(): ReadonlyColorSet { return this._colors; } + public get colors(): ReadonlyColorSet { + return this._colors; + } private readonly _onChangeColors = this._register(new Emitter()); public readonly onChangeColors = this._onChangeColors.event; diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 9bd7faaf5..22c0035d4 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -88,10 +88,18 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { return this._onScrollApi.event; } - public get cols(): number { return this._bufferService.cols; } - public get rows(): number { return this._bufferService.rows; } - public get buffers(): IBufferSet { return this._bufferService.buffers; } - public get options(): Required { return this.optionsService.options; } + public get cols(): number { + return this._bufferService.cols; + } + public get rows(): number { + return this._bufferService.rows; + } + public get buffers(): IBufferSet { + return this._bufferService.buffers; + } + public get options(): Required { + return this.optionsService.options; + } public set options(options: ITerminalOptions) { for (const key in options) { this.optionsService.options[key] = options[key]; diff --git a/src/common/Event.test.ts b/src/common/Event.test.ts index 8d1cfadd5..36f0dace7 100644 --- a/src/common/Event.test.ts +++ b/src/common/Event.test.ts @@ -15,14 +15,18 @@ describe('Emitter', () => { it('should fire with 1 listener', () => { const emitter = new Emitter(); let received: number | undefined; - emitter.event(e => { received = e; }); + emitter.event(e => { + received = e; + }); emitter.fire(42); assert.strictEqual(received, 42); }); it('should fire with 1 listener using thisArgs', () => { const emitter = new Emitter(); - const obj = { value: 0, handler(e: number) { this.value = e; } }; + const obj = { value: 0, handler(e: number) { + this.value = e; + } }; emitter.event(obj.handler, obj); emitter.fire(42); assert.strictEqual(obj.value, 42); @@ -54,7 +58,9 @@ describe('Emitter', () => { it('should not fire after dispose', () => { const emitter = new Emitter(); let called = false; - emitter.event(() => { called = true; }); + emitter.event(() => { + called = true; + }); emitter.dispose(); emitter.fire(42); assert.strictEqual(called, false); @@ -63,7 +69,9 @@ describe('Emitter', () => { it('should allow disposing a listener', () => { const emitter = new Emitter(); let count = 0; - const disposable = emitter.event(() => { count++; }); + const disposable = emitter.event(() => { + count++; + }); emitter.fire(1); disposable.dispose(); emitter.fire(2); diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index f9da81a25..f2f45e3a3 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -39,9 +39,15 @@ function getLines(bufferService: IBufferService, limit: number = bufferService.r } 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 get curAttrData(): IAttributeData { + return (this as any)._curAttrData; + } + public get windowTitleStack(): string[] { + return this._windowTitleStack; + } + public get iconNameStack(): string[] { + return this._iconNameStack; + } /** * Promise based parse call to await the full resolve of given input data. @@ -2511,7 +2517,9 @@ describe('InputHandler', () => { bufferService = new BufferService(optionsService, new MockLogService()); bufferService.resize(80, 30); coreService = new CoreService(bufferService, new MockLogService(), optionsService); - coreService.onData(data => { console.log(data); }); + coreService.onData(data => { + console.log(data); + }); inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockLogService(), optionsService, new MockOscLinkService(), new MockMouseStateService(), new MockUnicodeService()); }); diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index 53d0ef280..5234c2756 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -107,7 +107,9 @@ export class InputHandler extends Disposable implements IInputHandler { protected _iconNameStack: string[] = []; private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone(); - public getAttrData(): IAttributeData { return this._curAttrData; } + public getAttrData(): IAttributeData { + return this._curAttrData; + } private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone(); private _activeBuffer: IBuffer; @@ -283,7 +285,9 @@ export class InputHandler extends Disposable implements IInputHandler { * OSC handler */ // 0 - icon name + title - this._parser.registerOscHandler(0, new OscHandler(data => { this.setTitle(data); this.setIconName(data); return true; })); + this._parser.registerOscHandler(0, new OscHandler(data => { + this.setTitle(data); this.setIconName(data); return true; + })); // 1 - icon name this._parser.registerOscHandler(1, new OscHandler(data => this.setIconName(data))); // 2 - title diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 5940fa659..4ddeb4680 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -30,7 +30,9 @@ export const NULL_CELL_DATA = Object.freeze(createCellData(DEFAULT_ATTR, NULL_CE export class MockBufferService implements IBufferService { public serviceBrand: any; - public get buffer(): IBuffer { return this.buffers.active; } + public get buffer(): IBuffer { + return this.buffers.active; + } public buffers: IBufferSet = {} as any; public onResize: IEvent = new Emitter().event; public onScroll: IEvent = new Emitter().event; @@ -83,10 +85,16 @@ export class MockMouseStateService implements IMouseStateService { public addProtocol(name: string): void { } public reset(): void { } public onProtocolChange: IEvent = new Emitter().event; - public restrictMouseEvent(event: ICoreMouseEvent): boolean { return true; } - public encodeMouseEvent(event: ICoreMouseEvent): string { return ''; } + public restrictMouseEvent(event: ICoreMouseEvent): boolean { + return true; + } + public encodeMouseEvent(event: ICoreMouseEvent): string { + return ''; + } public setCustomWheelEventHandler(customWheelEventHandler: ((event: WheelEvent) => boolean) | undefined): void { } - public allowCustomWheelEvent(ev: WheelEvent): boolean { return true; } + public allowCustomWheelEvent(ev: WheelEvent): boolean { + return true; + } } export class MockCharsetService implements ICharsetService { @@ -233,10 +241,14 @@ export class MockUnicodeService implements IUnicodeService { export class MockDecorationService implements IDecorationService { public serviceBrand: any; - public get decorations(): IterableIterator { return [].values(); } + public get decorations(): IterableIterator { + return [].values(); + } public onDecorationRegistered = new Emitter().event; public onDecorationRemoved = new Emitter().event; - public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined { return undefined; } + public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined { + return undefined; + } public reset(): void { } public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void { } public dispose(): void { } diff --git a/src/common/buffer/AttributeData.ts b/src/common/buffer/AttributeData.ts index 6221fb81d..b266eb791 100644 --- a/src/common/buffer/AttributeData.ts +++ b/src/common/buffer/AttributeData.ts @@ -33,32 +33,68 @@ export class AttributeData implements IAttributeData { public extended: IExtendedAttrs = new ExtendedAttrs(); // flags - public isInverse(): number { return this.fg & FgFlags.INVERSE; } - public isBold(): number { return this.fg & FgFlags.BOLD; } + public isInverse(): number { + return this.fg & FgFlags.INVERSE; + } + public isBold(): number { + return this.fg & FgFlags.BOLD; + } public isUnderline(): number { if (this.hasExtendedAttrs() && this.extended.underlineStyle !== UnderlineStyle.NONE) { return 1; } return this.fg & FgFlags.UNDERLINE; } - public isBlink(): number { return this.fg & FgFlags.BLINK; } - public isInvisible(): number { return this.fg & FgFlags.INVISIBLE; } - public isItalic(): number { return this.bg & BgFlags.ITALIC; } - public isDim(): number { return this.bg & BgFlags.DIM; } - public isStrikethrough(): number { return this.fg & FgFlags.STRIKETHROUGH; } - public isProtected(): number { return this.bg & BgFlags.PROTECTED; } - public isOverline(): number { return this.bg & BgFlags.OVERLINE; } + public isBlink(): number { + return this.fg & FgFlags.BLINK; + } + public isInvisible(): number { + return this.fg & FgFlags.INVISIBLE; + } + public isItalic(): number { + return this.bg & BgFlags.ITALIC; + } + public isDim(): number { + return this.bg & BgFlags.DIM; + } + public isStrikethrough(): number { + return this.fg & FgFlags.STRIKETHROUGH; + } + public isProtected(): number { + return this.bg & BgFlags.PROTECTED; + } + public isOverline(): number { + return this.bg & BgFlags.OVERLINE; + } // color modes - public getFgColorMode(): number { return this.fg & Attributes.CM_MASK; } - public getBgColorMode(): number { return this.bg & Attributes.CM_MASK; } - public isFgRGB(): boolean { return (this.fg & Attributes.CM_MASK) === Attributes.CM_RGB; } - public isBgRGB(): boolean { return (this.bg & Attributes.CM_MASK) === Attributes.CM_RGB; } - public isFgPalette(): boolean { return (this.fg & Attributes.CM_MASK) === Attributes.CM_P16 || (this.fg & Attributes.CM_MASK) === Attributes.CM_P256; } - public isBgPalette(): boolean { return (this.bg & Attributes.CM_MASK) === Attributes.CM_P16 || (this.bg & Attributes.CM_MASK) === Attributes.CM_P256; } - public isFgDefault(): boolean { return (this.fg & Attributes.CM_MASK) === 0; } - public isBgDefault(): boolean { return (this.bg & Attributes.CM_MASK) === 0; } - public isAttributeDefault(): boolean { return this.fg === 0 && this.bg === 0; } + public getFgColorMode(): number { + return this.fg & Attributes.CM_MASK; + } + public getBgColorMode(): number { + return this.bg & Attributes.CM_MASK; + } + public isFgRGB(): boolean { + return (this.fg & Attributes.CM_MASK) === Attributes.CM_RGB; + } + public isBgRGB(): boolean { + return (this.bg & Attributes.CM_MASK) === Attributes.CM_RGB; + } + public isFgPalette(): boolean { + return (this.fg & Attributes.CM_MASK) === Attributes.CM_P16 || (this.fg & Attributes.CM_MASK) === Attributes.CM_P256; + } + public isBgPalette(): boolean { + return (this.bg & Attributes.CM_MASK) === Attributes.CM_P16 || (this.bg & Attributes.CM_MASK) === Attributes.CM_P256; + } + public isFgDefault(): boolean { + return (this.fg & Attributes.CM_MASK) === 0; + } + public isBgDefault(): boolean { + return (this.bg & Attributes.CM_MASK) === 0; + } + public isAttributeDefault(): boolean { + return this.fg === 0 && this.bg === 0; + } // colors public getFgColor(): number { @@ -147,7 +183,9 @@ export class ExtendedAttrs implements IExtendedAttrs { } return this._ext; } - public set ext(value: number) { this._ext = value; } + public set ext(value: number) { + this._ext = value; + } public get underlineStyle(): UnderlineStyle { // Always return the URL style if it has one diff --git a/src/common/buffer/Marker.ts b/src/common/buffer/Marker.ts index 59ad049b0..972ba5839 100644 --- a/src/common/buffer/Marker.ts +++ b/src/common/buffer/Marker.ts @@ -14,7 +14,9 @@ export class Marker implements IMarker { private readonly _disposables: IDisposable[] = []; private readonly _id: number = Marker._nextId++; - public get id(): number { return this._id; } + public get id(): number { + return this._id; + } private readonly _onDispose = this.register(new Emitter()); public readonly onDispose = this._onDispose.event; diff --git a/src/common/input/WriteBuffer.test.ts b/src/common/input/WriteBuffer.test.ts index f366a6320..14b4b103f 100644 --- a/src/common/input/WriteBuffer.test.ts +++ b/src/common/input/WriteBuffer.test.ts @@ -24,14 +24,20 @@ describe('WriteBuffer', () => { beforeEach(() => { stack = []; cbStack = []; - wb = new WriteBuffer(data => { stack.push(data); }); + wb = new WriteBuffer(data => { + stack.push(data); + }); }); describe('write input', () => { it('string', done => { wb.write('a._'); - wb.write('b.x', () => { cbStack.push('b'); }); + wb.write('b.x', () => { + cbStack.push('b'); + }); wb.write('c._'); - wb.write('d.x', () => { cbStack.push('d'); }); + wb.write('d.x', () => { + cbStack.push('d'); + }); wb.write('e', () => { assert.deepEqual(stack, ['a._', 'b.x', 'c._', 'd.x', 'e']); assert.deepEqual(cbStack, ['b', 'd']); @@ -40,9 +46,13 @@ describe('WriteBuffer', () => { }); it('bytes', done => { wb.write(toBytes('a._')); - wb.write(toBytes('b.x'), () => { cbStack.push('b'); }); + wb.write(toBytes('b.x'), () => { + cbStack.push('b'); + }); wb.write(toBytes('c._')); - wb.write(toBytes('d.x'), () => { cbStack.push('d'); }); + wb.write(toBytes('d.x'), () => { + cbStack.push('d'); + }); wb.write(toBytes('e'), () => { assert.deepEqual(stack.map(val => typeof val === 'string' ? '' : fromBytes(val)), ['a._', 'b.x', 'c._', 'd.x', 'e']); assert.deepEqual(cbStack, ['b', 'd']); @@ -51,9 +61,13 @@ describe('WriteBuffer', () => { }); it('string/bytes mixed', done => { wb.write('a._'); - wb.write('b.x', () => { cbStack.push('b'); }); + wb.write('b.x', () => { + cbStack.push('b'); + }); wb.write(toBytes('c._')); - wb.write(toBytes('d.x'), () => { cbStack.push('d'); }); + wb.write(toBytes('d.x'), () => { + cbStack.push('d'); + }); wb.write(toBytes('e'), () => { assert.deepEqual(stack.map(val => typeof val === 'string' ? val : fromBytes(val)), ['a._', 'b.x', 'c._', 'd.x', 'e']); assert.deepEqual(cbStack, ['b', 'd']); @@ -61,10 +75,18 @@ describe('WriteBuffer', () => { }); }); it('write callback works for empty chunks', done => { - wb.write('a', () => { cbStack.push('a'); }); - wb.write('', () => { cbStack.push('b'); }); - wb.write(toBytes('c'), () => { cbStack.push('c'); }); - wb.write(new Uint8Array(0), () => { cbStack.push('d'); }); + wb.write('a', () => { + cbStack.push('a'); + }); + wb.write('', () => { + cbStack.push('b'); + }); + wb.write(toBytes('c'), () => { + cbStack.push('c'); + }); + wb.write(new Uint8Array(0), () => { + cbStack.push('d'); + }); wb.write('e', () => { assert.deepEqual(stack.map(val => typeof val === 'string' ? val : fromBytes(val)), ['a', '', 'c', '', 'e']); assert.deepEqual(cbStack, ['a', 'b', 'c', 'd']); @@ -72,13 +94,21 @@ describe('WriteBuffer', () => { }); }); it('writeSync', done => { - wb.write('a', () => { cbStack.push('a'); }); - wb.write('b', () => { cbStack.push('b'); }); - wb.write('c', () => { cbStack.push('c'); }); + wb.write('a', () => { + cbStack.push('a'); + }); + wb.write('b', () => { + cbStack.push('b'); + }); + wb.write('c', () => { + cbStack.push('c'); + }); wb.writeSync('d'); assert.deepEqual(stack, ['a', 'b', 'c', 'd']); assert.deepEqual(cbStack, ['a', 'b', 'c']); - wb.write('x', () => { cbStack.push('x'); }); + wb.write('x', () => { + cbStack.push('x'); + }); wb.write('', () => { assert.deepEqual(stack, ['a', 'b', 'c', 'd', 'x', '']); assert.deepEqual(cbStack, ['a', 'b', 'c', 'x']); @@ -107,13 +137,21 @@ describe('WriteBuffer', () => { assert.equal(last, '11'); // 1 + 10 sub calls = 11 }); it('flushSync processes all pending writes', done => { - wb.write('a', () => { cbStack.push('a'); }); - wb.write('b', () => { cbStack.push('b'); }); - wb.write('c', () => { cbStack.push('c'); }); + wb.write('a', () => { + cbStack.push('a'); + }); + wb.write('b', () => { + cbStack.push('b'); + }); + wb.write('c', () => { + cbStack.push('c'); + }); wb.flushSync(); assert.deepEqual(stack, ['a', 'b', 'c']); assert.deepEqual(cbStack, ['a', 'b', 'c']); - wb.write('x', () => { cbStack.push('x'); }); + wb.write('x', () => { + cbStack.push('x'); + }); wb.write('', () => { assert.deepEqual(stack, ['a', 'b', 'c', 'x', '']); assert.deepEqual(cbStack, ['a', 'b', 'c', 'x']); diff --git a/src/common/input/WriteBuffer.ts b/src/common/input/WriteBuffer.ts index b936c9dbf..9b7880362 100644 --- a/src/common/input/WriteBuffer.ts +++ b/src/common/input/WriteBuffer.ts @@ -244,7 +244,9 @@ export class WriteBuffer extends Disposable { // 2. spawn a promise immediately resolving to `true` // (executed on the same queue, thus properly aligned before continuation happens) result.catch(err => { - queueMicrotask(() => {throw err;}); + queueMicrotask(() => { + throw err; + }); return Promise.resolve(false); }).then(continuation); return; diff --git a/src/common/parser/ApcParser.test.ts b/src/common/parser/ApcParser.test.ts index c2200d918..dd1bbe847 100644 --- a/src/common/parser/ApcParser.test.ts +++ b/src/common/parser/ApcParser.test.ts @@ -185,7 +185,9 @@ describe('ApcParser', () => { }); it('should be called once on end(true)', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(data); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(data); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -195,7 +197,9 @@ describe('ApcParser', () => { assert.deepEqual(reports, ['Here comes the mouse!']); }); it('should not be called on end(false)', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(data); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(data); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -205,8 +209,12 @@ describe('ApcParser', () => { assert.deepEqual(reports, []); }); it('should be disposable', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(['one', data]); return true; })); - const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(['two', data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(['one', data]); return true; + })); + const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(['two', data]); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -224,8 +232,12 @@ describe('ApcParser', () => { assert.deepEqual(reports, [['two', 'Here comes the mouse!'], ['one', 'some other data']]); }); it('should respect return false', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(['one', data]); return true; })); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(['two', data]); return false; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(['one', data]); return true; + })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(['two', data]); return false; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -236,7 +248,9 @@ describe('ApcParser', () => { }); it('should work up to payload limit', function(): void { this.timeout(30000); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(data); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(data); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); const data = toUtf32('A'.repeat(CHUNK_SIZE)); for (let i = 0; i < TEST_PAYLOAD_LIMIT; i += CHUNK_SIZE) { @@ -247,7 +261,9 @@ describe('ApcParser', () => { }); it('should abort for payload limit +1', function(): void { this.timeout(30000); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { reports.push(data); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(data => { + reports.push(data); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('A'.repeat(CHUNK_SIZE)); for (let i = 0; i < TEST_PAYLOAD_LIMIT; i += CHUNK_SIZE) { @@ -408,7 +424,9 @@ describe('ApcParser - async tests', () => { }); describe('ApcHandlerFactory', () => { it('should be called once on end(true)', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { reports.push(data); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { + reports.push(data); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -418,7 +436,9 @@ describe('ApcParser - async tests', () => { assert.deepEqual(reports, ['Here comes the mouse!']); }); it('should not be called on end(false)', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { reports.push(data); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { + reports.push(data); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -428,8 +448,12 @@ describe('ApcParser - async tests', () => { assert.deepEqual(reports, []); }); it('should be disposable', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { reports.push(['one', data]); return true; })); - const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { reports.push(['two', data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { + reports.push(['one', data]); return true; + })); + const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { + reports.push(['two', data]); return true; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -447,8 +471,12 @@ describe('ApcParser - async tests', () => { assert.deepEqual(reports, [['two', 'Here comes the mouse!'], ['one', 'some other data']]); }); it('should respect return false', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { reports.push(['one', data]); return true; })); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { reports.push(['two', data]); return false; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { + reports.push(['one', data]); return true; + })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new ApcHandler(async data => { + reports.push(['two', data]); return false; + })); parser.start(identifier({intermediates: '+', final: 'p'})); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); diff --git a/src/common/parser/DcsParser.test.ts b/src/common/parser/DcsParser.test.ts index 0296fa88e..e74e009bb 100644 --- a/src/common/parser/DcsParser.test.ts +++ b/src/common/parser/DcsParser.test.ts @@ -191,7 +191,9 @@ describe('DcsParser', () => { }); it('should be called once on end(true)', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push([params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push([params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -201,7 +203,9 @@ describe('DcsParser', () => { assert.deepEqual(reports, [[[1, 2, 3], 'Here comes the mouse!']]); }); it('should not be called on end(false)', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push([params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push([params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -211,8 +215,12 @@ describe('DcsParser', () => { assert.deepEqual(reports, []); }); it('should be disposable', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push(['one', params.toArray(), data]); return true; })); - const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push(['two', params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push(['one', params.toArray(), data]); return true; + })); + const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push(['two', params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -230,8 +238,12 @@ describe('DcsParser', () => { assert.deepEqual(reports, [['two', [1, 2, 3], 'Here comes the mouse!'], ['one', [1, 2, 3], 'some other data']]); }); it('should respect return false', () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push(['one', params.toArray(), data]); return true; })); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push(['two', params.toArray(), data]); return false; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push(['one', params.toArray(), data]); return true; + })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push(['two', params.toArray(), data]); return false; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -242,7 +254,9 @@ describe('DcsParser', () => { }); it('should work up to payload limit', function(): void { this.timeout(30000); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push([params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push([params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); const data = toUtf32('A'.repeat(CHUNK_SIZE)); for (let i = 0; i < TEST_PAYLOAD_LIMIT; i += CHUNK_SIZE) { @@ -253,7 +267,9 @@ describe('DcsParser', () => { }); it('should abort for payload limit +1', function(): void { this.timeout(30000); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { reports.push([params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler((data, params) => { + reports.push([params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('A'.repeat(CHUNK_SIZE)); for (let i = 0; i < TEST_PAYLOAD_LIMIT; i += CHUNK_SIZE) { @@ -419,7 +435,9 @@ describe('DcsParser - async tests', () => { }); describe('DcsHandlerFactory', () => { it('should be called once on end(true)', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { reports.push([params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { + reports.push([params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -429,7 +447,9 @@ describe('DcsParser - async tests', () => { assert.deepEqual(reports, [[[1, 2, 3], 'Here comes the mouse!']]); }); it('should not be called on end(false)', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { reports.push([params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { + reports.push([params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -439,8 +459,12 @@ describe('DcsParser - async tests', () => { assert.deepEqual(reports, []); }); it('should be disposable', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { reports.push(['one', params.toArray(), data]); return true; })); - const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { reports.push(['two', params.toArray(), data]); return true; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { + reports.push(['one', params.toArray(), data]); return true; + })); + const dispo = parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { + reports.push(['two', params.toArray(), data]); return true; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); @@ -458,8 +482,12 @@ describe('DcsParser - async tests', () => { assert.deepEqual(reports, [['two', [1, 2, 3], 'Here comes the mouse!'], ['one', [1, 2, 3], 'some other data']]); }); it('should respect return false', async () => { - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { reports.push(['one', params.toArray(), data]); return true; })); - parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { reports.push(['two', params.toArray(), data]); return false; })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { + reports.push(['one', params.toArray(), data]); return true; + })); + parser.registerHandler(identifier({intermediates: '+', final: 'p'}), new DcsHandler(async (data, params) => { + reports.push(['two', params.toArray(), data]); return false; + })); parser.hook(identifier({intermediates: '+', final: 'p'}), Params.fromArray([1, 2, 3])); let data = toUtf32('Here comes'); parser.put(data, 0, data.length); diff --git a/src/common/parser/EscapeSequenceParser.test.ts b/src/common/parser/EscapeSequenceParser.test.ts index 2d5a04df7..b51dce44b 100644 --- a/src/common/parser/EscapeSequenceParser.test.ts +++ b/src/common/parser/EscapeSequenceParser.test.ts @@ -1451,49 +1451,83 @@ describe('EscapeSequenceParser', () => { }); describe('ESC custom handlers', () => { it('prevent fallback', () => { - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('default - %G'); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom - %G'); return true; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('default - %G'); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom - %G'); return true; + }); parse(parser2, INPUT); assert.deepEqual(esc, ['custom - %G']); }); it('allow fallback', () => { - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('default - %G'); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom - %G'); return false; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('default - %G'); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom - %G'); return false; + }); parse(parser2, INPUT); assert.deepEqual(esc, ['custom - %G', 'default - %G']); }); it('Multiple custom handlers fallback once', () => { - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('default - %G'); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom - %G'); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom2 - %G'); return false; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('default - %G'); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom - %G'); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom2 - %G'); return false; + }); parse(parser2, INPUT); assert.deepEqual(esc, ['custom2 - %G', 'custom - %G']); }); it('Multiple custom handlers no fallback', () => { - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('default - %G'); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom - %G'); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom2 - %G'); return true; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('default - %G'); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom - %G'); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom2 - %G'); return true; + }); parse(parser2, INPUT); assert.deepEqual(esc, ['custom2 - %G']); }); it('Execution order should go from latest handler down to the original', () => { const order: number[] = []; - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { order.push(1); return true; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { order.push(2); return false; }); - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { order.push(3); return false; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + order.push(1); return true; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + order.push(2); return false; + }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + order.push(3); return false; + }); parse(parser2, '\x1b%G'); assert.deepEqual(order, [3, 2, 1]); }); it('Dispose should work', () => { - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('default - %G'); return true; }); - const dispo = parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom - %G'); return true; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('default - %G'); return true; + }); + const dispo = parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom - %G'); return true; + }); dispo.dispose(); parse(parser2, INPUT); assert.deepEqual(esc, ['default - %G']); }); it('Should not corrupt the parser when dispose is called twice', () => { - parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('default - %G'); return true; }); - const dispo = parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { esc.push('custom - %G'); return true; }); + parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('default - %G'); return true; + }); + const dispo = parser2.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + esc.push('custom - %G'); return true; + }); dispo.dispose(); dispo.dispose(); parse(parser2, INPUT); @@ -1516,16 +1550,24 @@ describe('EscapeSequenceParser', () => { describe('CSI custom handlers', () => { it('Prevent fallback', () => { const csiCustom: [string, ParamsArray, string][] = []; - parser2.registerCsiHandler({ final: 'm' }, params => { csi.push(['m', params.toArray(), '']); return true; }); - parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom.push(['m', params.toArray(), '']); return true; }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csi.push(['m', params.toArray(), '']); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom.push(['m', params.toArray(), '']); return true; + }); parse(parser2, INPUT); assert.deepEqual(csi, [], 'Should not fallback to original handler'); assert.deepEqual(csiCustom, [['m', [1, 31], ''], ['m', [0], '']]); }); it('Allow fallback', () => { const csiCustom: [string, ParamsArray, string][] = []; - parser2.registerCsiHandler({ final: 'm' }, params => { csi.push(['m', params.toArray(), '']); return true; }); - parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom.push(['m', params.toArray(), '']); return false; }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csi.push(['m', params.toArray(), '']); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom.push(['m', params.toArray(), '']); return false; + }); parse(parser2, INPUT); assert.deepEqual(csi, [['m', [1, 31], ''], ['m', [0], '']], 'Should fallback to original handler'); assert.deepEqual(csiCustom, [['m', [1, 31], ''], ['m', [0], '']]); @@ -1533,9 +1575,15 @@ describe('EscapeSequenceParser', () => { it('Multiple custom handlers fallback once', () => { const csiCustom: [string, ParamsArray, string][] = []; const csiCustom2: [string, ParamsArray, string][] = []; - parser2.registerCsiHandler({ final: 'm' }, params => { csi.push(['m', params.toArray(), '']); return true; }); - parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom.push(['m', params.toArray(), '']); return true; }); - parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom2.push(['m', params.toArray(), '']); return false; }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csi.push(['m', params.toArray(), '']); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom.push(['m', params.toArray(), '']); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom2.push(['m', params.toArray(), '']); return false; + }); parse(parser2, INPUT); assert.deepEqual(csi, [], 'Should not fallback to original handler'); assert.deepEqual(csiCustom, [['m', [1, 31], ''], ['m', [0], '']]); @@ -1544,9 +1592,15 @@ describe('EscapeSequenceParser', () => { it('Multiple custom handlers no fallback', () => { const csiCustom: [string, ParamsArray, string][] = []; const csiCustom2: [string, ParamsArray, string][] = []; - parser2.registerCsiHandler({ final: 'm' }, params => { csi.push(['m', params.toArray(), '']); return true; }); - parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom.push(['m', params.toArray(), '']); return true; }); - parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom2.push(['m', params.toArray(), '']); return true; }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csi.push(['m', params.toArray(), '']); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom.push(['m', params.toArray(), '']); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom2.push(['m', params.toArray(), '']); return true; + }); parse(parser2, INPUT); assert.deepEqual(csi, [], 'Should not fallback to original handler'); assert.deepEqual(csiCustom, [], 'Should not fallback once'); @@ -1554,16 +1608,26 @@ describe('EscapeSequenceParser', () => { }); it('Execution order should go from latest handler down to the original', () => { const order: number[] = []; - parser2.registerCsiHandler({ final: 'm' }, () => { order.push(1); return true; }); - parser2.registerCsiHandler({ final: 'm' }, () => { order.push(2); return false; }); - parser2.registerCsiHandler({ final: 'm' }, () => { order.push(3); return false; }); + parser2.registerCsiHandler({ final: 'm' }, () => { + order.push(1); return true; + }); + parser2.registerCsiHandler({ final: 'm' }, () => { + order.push(2); return false; + }); + parser2.registerCsiHandler({ final: 'm' }, () => { + order.push(3); return false; + }); parse(parser2, '\x1b[0m'); assert.deepEqual(order, [3, 2, 1]); }); it('Dispose should work', () => { const csiCustom: [string, ParamsArray, string][] = []; - parser2.registerCsiHandler({ final: 'm' }, params => { csi.push(['m', params.toArray(), '']); return true; }); - const customHandler = parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom.push(['m', params.toArray(), '']); return true; }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csi.push(['m', params.toArray(), '']); return true; + }); + const customHandler = parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom.push(['m', params.toArray(), '']); return true; + }); customHandler.dispose(); parse(parser2, INPUT); assert.deepEqual(csi, [['m', [1, 31], ''], ['m', [0], '']]); @@ -1571,8 +1635,12 @@ describe('EscapeSequenceParser', () => { }); it('Should not corrupt the parser when dispose is called twice', () => { const csiCustom: [string, ParamsArray, string][] = []; - parser2.registerCsiHandler({ final: 'm' }, params => { csi.push(['m', params.toArray(), '']); return true; }); - const customHandler = parser2.registerCsiHandler({ final: 'm' }, params => { csiCustom.push(['m', params.toArray(), '']); return true; }); + parser2.registerCsiHandler({ final: 'm' }, params => { + csi.push(['m', params.toArray(), '']); return true; + }); + const customHandler = parser2.registerCsiHandler({ final: 'm' }, params => { + csiCustom.push(['m', params.toArray(), '']); return true; + }); customHandler.dispose(); customHandler.dispose(); parse(parser2, INPUT); @@ -1613,16 +1681,24 @@ describe('EscapeSequenceParser', () => { describe('OSC custom handlers', () => { it('Prevent fallback', () => { const oscCustom: [number, string][] = []; - parser2.registerOscHandler(1, new OscHandler(data => { osc.push([1, data]); return true; })); - parser2.registerOscHandler(1, new OscHandler(data => { oscCustom.push([1, data]); return true; })); + parser2.registerOscHandler(1, new OscHandler(data => { + osc.push([1, data]); return true; + })); + parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom.push([1, data]); return true; + })); parse(parser2, INPUT); assert.deepEqual(osc, [], 'Should not fallback to original handler'); assert.deepEqual(oscCustom, [[1, 'foo=bar']]); }); it('Allow fallback', () => { const oscCustom: [number, string][] = []; - parser2.registerOscHandler(1, new OscHandler(data => { osc.push([1, data]); return true; })); - parser2.registerOscHandler(1, new OscHandler(data => { oscCustom.push([1, data]); return false; })); + parser2.registerOscHandler(1, new OscHandler(data => { + osc.push([1, data]); return true; + })); + parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom.push([1, data]); return false; + })); parse(parser2, INPUT); assert.deepEqual(osc, [[1, 'foo=bar']], 'Should fallback to original handler'); assert.deepEqual(oscCustom, [[1, 'foo=bar']]); @@ -1630,9 +1706,15 @@ describe('EscapeSequenceParser', () => { it('Multiple custom handlers fallback once', () => { const oscCustom: [number, string][] = []; const oscCustom2: [number, string][] = []; - parser2.registerOscHandler(1, new OscHandler(data => { osc.push([1, data]); return true; })); - parser2.registerOscHandler(1, new OscHandler(data => { oscCustom.push([1, data]); return true; })); - parser2.registerOscHandler(1, new OscHandler(data => { oscCustom2.push([1, data]); return false; })); + parser2.registerOscHandler(1, new OscHandler(data => { + osc.push([1, data]); return true; + })); + parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom.push([1, data]); return true; + })); + parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom2.push([1, data]); return false; + })); parse(parser2, INPUT); assert.deepEqual(osc, [], 'Should not fallback to original handler'); assert.deepEqual(oscCustom, [[1, 'foo=bar']]); @@ -1641,9 +1723,15 @@ describe('EscapeSequenceParser', () => { it('Multiple custom handlers no fallback', () => { const oscCustom: [number, string][] = []; const oscCustom2: [number, string][] = []; - parser2.registerOscHandler(1, new OscHandler(data => { osc.push([1, data]); return true; })); - parser2.registerOscHandler(1, new OscHandler(data => { oscCustom.push([1, data]); return true; })); - parser2.registerOscHandler(1, new OscHandler(data => { oscCustom2.push([1, data]); return true; })); + parser2.registerOscHandler(1, new OscHandler(data => { + osc.push([1, data]); return true; + })); + parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom.push([1, data]); return true; + })); + parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom2.push([1, data]); return true; + })); parse(parser2, INPUT); assert.deepEqual(osc, [], 'Should not fallback to original handler'); assert.deepEqual(oscCustom, [], 'Should not fallback once'); @@ -1651,16 +1739,26 @@ describe('EscapeSequenceParser', () => { }); it('Execution order should go from latest handler down to the original', () => { const order: number[] = []; - parser2.registerOscHandler(1, new OscHandler(() => { order.push(1); return true; })); - parser2.registerOscHandler(1, new OscHandler(() => { order.push(2); return false; })); - parser2.registerOscHandler(1, new OscHandler(() => { order.push(3); return false; })); + parser2.registerOscHandler(1, new OscHandler(() => { + order.push(1); return true; + })); + parser2.registerOscHandler(1, new OscHandler(() => { + order.push(2); return false; + })); + parser2.registerOscHandler(1, new OscHandler(() => { + order.push(3); return false; + })); parse(parser2, '\x1b]1;foo=bar\x1b\\'); assert.deepEqual(order, [3, 2, 1]); }); it('Dispose should work', () => { const oscCustom: [number, string][] = []; - parser2.registerOscHandler(1, new OscHandler(data => { osc.push([1, data]); return true; })); - const customHandler = parser2.registerOscHandler(1, new OscHandler(data => { oscCustom.push([1, data]); return true; })); + parser2.registerOscHandler(1, new OscHandler(data => { + osc.push([1, data]); return true; + })); + const customHandler = parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom.push([1, data]); return true; + })); customHandler.dispose(); parse(parser2, INPUT); assert.deepEqual(osc, [[1, 'foo=bar']]); @@ -1668,8 +1766,12 @@ describe('EscapeSequenceParser', () => { }); it('Should not corrupt the parser when dispose is called twice', () => { const oscCustom: [number, string][] = []; - parser2.registerOscHandler(1, new OscHandler(data => { osc.push([1, data]); return true; })); - const customHandler = parser2.registerOscHandler(1, new OscHandler(data => { oscCustom.push([1, data]); return true; })); + parser2.registerOscHandler(1, new OscHandler(data => { + osc.push([1, data]); return true; + })); + const customHandler = parser2.registerOscHandler(1, new OscHandler(data => { + oscCustom.push([1, data]); return true; + })); customHandler.dispose(); customHandler.dispose(); parse(parser2, INPUT); @@ -1712,54 +1814,88 @@ describe('EscapeSequenceParser', () => { const DCS_INPUT = '\x1bP1;2;3+pabc\x1b\\'; it('Prevent fallback', () => { const dcsCustom: [string, (number | number[])[], string][] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['A', params.toArray(), data]); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['B', params.toArray(), data]); return true; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['A', params.toArray(), data]); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['B', params.toArray(), data]); return true; + })); parse(parser2, DCS_INPUT); assert.deepEqual(dcsCustom, [['B', [1, 2, 3], 'abc']]); }); it('Allow fallback', () => { const dcsCustom: [string, (number | number[])[], string][] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['A', params.toArray(), data]); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['B', params.toArray(), data]); return false; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['A', params.toArray(), data]); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['B', params.toArray(), data]); return false; + })); parse(parser2, DCS_INPUT); assert.deepEqual(dcsCustom, [['B', [1, 2, 3], 'abc'], ['A', [1, 2, 3], 'abc']]); }); it('Multiple custom handlers fallback once', () => { const dcsCustom: [string, (number | number[])[], string][] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['A', params.toArray(), data]); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['B', params.toArray(), data]); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['C', params.toArray(), data]); return false; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['A', params.toArray(), data]); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['B', params.toArray(), data]); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['C', params.toArray(), data]); return false; + })); parse(parser2, DCS_INPUT); assert.deepEqual(dcsCustom, [['C', [1, 2, 3], 'abc'], ['B', [1, 2, 3], 'abc']]); }); it('Multiple custom handlers no fallback', () => { const dcsCustom: [string, (number | number[])[], string][] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['A', params.toArray(), data]); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['B', params.toArray(), data]); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['C', params.toArray(), data]); return true; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['A', params.toArray(), data]); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['B', params.toArray(), data]); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['C', params.toArray(), data]); return true; + })); parse(parser2, DCS_INPUT); assert.deepEqual(dcsCustom, [['C', [1, 2, 3], 'abc']]); }); it('Execution order should go from latest handler down to the original', () => { const order: number[] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler(() => { order.push(1); return true; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler(() => { order.push(2); return false; })); - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler(() => { order.push(3); return false; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler(() => { + order.push(1); return true; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler(() => { + order.push(2); return false; + })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler(() => { + order.push(3); return false; + })); parse(parser2, DCS_INPUT); assert.deepEqual(order, [3, 2, 1]); }); it('Dispose should work', () => { const dcsCustom: [string, (number | number[])[], string][] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['A', params.toArray(), data]); return true; })); - const dispo = parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['B', params.toArray(), data]); return true; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['A', params.toArray(), data]); return true; + })); + const dispo = parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['B', params.toArray(), data]); return true; + })); dispo.dispose(); parse(parser2, DCS_INPUT); assert.deepEqual(dcsCustom, [['A', [1, 2, 3], 'abc']]); }); it('Should not corrupt the parser when dispose is called twice', () => { const dcsCustom: [string, (number | number[])[], string][] = []; - parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['A', params.toArray(), data]); return true; })); - const dispo = parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { dcsCustom.push(['B', params.toArray(), data]); return true; })); + parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['A', params.toArray(), data]); return true; + })); + const dispo = parser2.registerDcsHandler({ intermediates: '+', final: 'p' }, new DcsHandler((data, params) => { + dcsCustom.push(['B', params.toArray(), data]); return true; + })); dispo.dispose(); dispo.dispose(); parse(parser2, DCS_INPUT); @@ -1801,54 +1937,88 @@ describe('EscapeSequenceParser', () => { const APC_INPUT = '\x1b_+pabc\x1b\\'; it('Prevent fallback', () => { const apcCustom: [string, string][] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['A', data]); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['B', data]); return true; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['A', data]); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['B', data]); return true; + })); parse(parser2, APC_INPUT); assert.deepEqual(apcCustom, [['B', 'abc']]); }); it('Allow fallback', () => { const apcCustom: [string, string][] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['A', data]); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['B', data]); return false; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['A', data]); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['B', data]); return false; + })); parse(parser2, APC_INPUT); assert.deepEqual(apcCustom, [['B', 'abc'], ['A', 'abc']]); }); it('Multiple custom handlers fallback once', () => { const apcCustom: [string, string][] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['A', data]); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['B', data]); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['C', data]); return false; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['A', data]); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['B', data]); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['C', data]); return false; + })); parse(parser2, APC_INPUT); assert.deepEqual(apcCustom, [['C', 'abc'], ['B', 'abc']]); }); it('Multiple custom handlers no fallback', () => { const apcCustom: [string, string][] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['A', data]); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['B', data]); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['C', data]); return true; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['A', data]); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['B', data]); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['C', data]); return true; + })); parse(parser2, APC_INPUT); assert.deepEqual(apcCustom, [['C', 'abc']]); }); it('Execution order should go from latest handler down to the original', () => { const order: number[] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(() => { order.push(1); return true; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(() => { order.push(2); return false; })); - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(() => { order.push(3); return false; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(() => { + order.push(1); return true; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(() => { + order.push(2); return false; + })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(() => { + order.push(3); return false; + })); parse(parser2, APC_INPUT); assert.deepEqual(order, [3, 2, 1]); }); it('Dispose should work', () => { const apcCustom: [string, string][] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['A', data]); return true; })); - const dispo = parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['B', data]); return true; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['A', data]); return true; + })); + const dispo = parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['B', data]); return true; + })); dispo.dispose(); parse(parser2, APC_INPUT); assert.deepEqual(apcCustom, [['A', 'abc']]); }); it('Should not corrupt the parser when dispose is called twice', () => { const apcCustom: [string, string][] = []; - parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['A', data]); return true; })); - const dispo = parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { apcCustom.push(['B', data]); return true; })); + parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['A', data]); return true; + })); + const dispo = parser2.registerApcHandler({ intermediates: '+', final: 'p' }, new ApcHandler(data => { + apcCustom.push(['B', data]); return true; + })); dispo.dispose(); dispo.dispose(); parse(parser2, APC_INPUT); @@ -1884,44 +2054,74 @@ describe('EscapeSequenceParser', () => { const c = String.fromCharCode(i); assert.equal(parser.identToString(parser.identifier({ prefix: c, final: 'z' })), c + 'z'); } - assert.throws(() => { parser.identifier({ prefix: '\x3b', final: 'z' }); }, 'prefix must be in range 0x3c .. 0x3f'); - assert.throws(() => { parser.identifier({ prefix: '\x40', final: 'z' }); }, 'prefix must be in range 0x3c .. 0x3f'); - assert.throws(() => { parser.identifier({ prefix: '??', final: 'z' }); }, 'only one byte as prefix supported'); + assert.throws(() => { + parser.identifier({ prefix: '\x3b', final: 'z' }); + }, 'prefix must be in range 0x3c .. 0x3f'); + assert.throws(() => { + parser.identifier({ prefix: '\x40', final: 'z' }); + }, 'prefix must be in range 0x3c .. 0x3f'); + assert.throws(() => { + parser.identifier({ prefix: '??', final: 'z' }); + }, 'only one byte as prefix supported'); }); it('intermediates range 0x20 .. 0x2f, up to two bytes', () => { for (let i = 0x20; i <= 0x2f; ++i) { const c = String.fromCharCode(i); assert.equal(parser.identToString(parser.identifier({ intermediates: c + c, final: 'z' })), c + c + 'z'); } - assert.throws(() => { parser.identifier({ intermediates: '\x1f', final: 'z' }); }, 'intermediate must be in range 0x20 .. 0x2f'); - assert.throws(() => { parser.identifier({ intermediates: '\x30', final: 'z' }); }, 'intermediate must be in range 0x20 .. 0x2f'); - assert.throws(() => { parser.identifier({ intermediates: '!!!', final: 'z' }); }, 'only two bytes as intermediates are supported'); + assert.throws(() => { + parser.identifier({ intermediates: '\x1f', final: 'z' }); + }, 'intermediate must be in range 0x20 .. 0x2f'); + assert.throws(() => { + parser.identifier({ intermediates: '\x30', final: 'z' }); + }, 'intermediate must be in range 0x20 .. 0x2f'); + assert.throws(() => { + parser.identifier({ intermediates: '!!!', final: 'z' }); + }, 'only two bytes as intermediates are supported'); }); it('final CSI/DCS range 0x40 .. 0x7e (default), one byte', () => { for (let i = 0x40; i <= 0x7e; ++i) { const c = String.fromCharCode(i); assert.equal(parser.identToString(parser.identifier({ final: c })), c); } - assert.throws(() => { parser.identifier({ final: '\x3f' }); }, 'final must be in range 64 .. 126'); - assert.throws(() => { parser.identifier({ final: '\x7f' }); }, 'final must be in range 64 .. 126'); - assert.throws(() => { parser.identifier({ final: 'zz' }); }, 'final must be a single byte'); + assert.throws(() => { + parser.identifier({ final: '\x3f' }); + }, 'final must be in range 64 .. 126'); + assert.throws(() => { + parser.identifier({ final: '\x7f' }); + }, 'final must be in range 64 .. 126'); + assert.throws(() => { + parser.identifier({ final: 'zz' }); + }, 'final must be a single byte'); }); it('final ESC + APC range 0x30 .. 0x7e, one byte', () => { for (let i = 0x30; i <= 0x7e; ++i) { const final = String.fromCharCode(i); let handler: IDisposable | undefined; - assert.doesNotThrow(() => { handler = parser.registerEscHandler({ final }, () => true); }, 'final must be in range 48 .. 126'); + assert.doesNotThrow(() => { + handler = parser.registerEscHandler({ final }, () => true); + }, 'final must be in range 48 .. 126'); if (handler) handler.dispose(); assert.doesNotThrow( - () => { handler = parser.registerApcHandler({ final }, {start: () => {}, put: ()=>{}, end: ()=>true}); }, + () => { + handler = parser.registerApcHandler({ final }, {start: () => {}, put: ()=>{}, end: ()=>true}); + }, 'final must be in range 48 .. 126' ); if (handler) handler.dispose(); } - assert.throws(() => { parser.registerEscHandler({ final: '\x2f' }, () => true); }, 'final must be in range 48 .. 126'); - assert.throws(() => { parser.registerEscHandler({ final: '\x7f' }, () => true); }, 'final must be in range 48 .. 126'); - assert.throws(() => { parser.registerApcHandler({ final: '\x2f' }, {start: () => {}, put: ()=>{}, end: ()=>true}); }, 'final must be in range 48 .. 126'); - assert.throws(() => { parser.registerApcHandler({ final: '\x7f' }, {start: () => {}, put: ()=>{}, end: ()=>true}); }, 'final must be in range 48 .. 126'); + assert.throws(() => { + parser.registerEscHandler({ final: '\x2f' }, () => true); + }, 'final must be in range 48 .. 126'); + assert.throws(() => { + parser.registerEscHandler({ final: '\x7f' }, () => true); + }, 'final must be in range 48 .. 126'); + assert.throws(() => { + parser.registerApcHandler({ final: '\x2f' }, {start: () => {}, put: ()=>{}, end: ()=>true}); + }, 'final must be in range 48 .. 126'); + assert.throws(() => { + parser.registerApcHandler({ final: '\x7f' }, {start: () => {}, put: ()=>{}, end: ()=>true}); + }, 'final must be in range 48 .. 126'); }); it('id calculation - should stacking prefix -> intermediate -> final', () => { assert.equal(parser.identToString(parser.identifier({ final: 'z' })), 'z'); @@ -1934,9 +2134,15 @@ describe('EscapeSequenceParser', () => { describe('identifier invocation', () => { it('ESC', () => { const callstack: string[] = []; - const h1 = parser.registerEscHandler({ final: 'z' }, () => { callstack.push('z'); return true; }); - const h2 = parser.registerEscHandler({ intermediates: '!', final: 'z' }, () => { callstack.push('!z'); return true; }); - const h3 = parser.registerEscHandler({ intermediates: '!!', final: 'z' }, () => { callstack.push('!!z'); return true; }); + const h1 = parser.registerEscHandler({ final: 'z' }, () => { + callstack.push('z'); return true; + }); + const h2 = parser.registerEscHandler({ intermediates: '!', final: 'z' }, () => { + callstack.push('!z'); return true; + }); + const h3 = parser.registerEscHandler({ intermediates: '!!', final: 'z' }, () => { + callstack.push('!!z'); return true; + }); parse(parser, '\x1bz\x1b!z\x1b!!z'); h1.dispose(); h2.dispose(); @@ -1946,12 +2152,24 @@ describe('EscapeSequenceParser', () => { }); it('CSI', () => { const callstack: any[] = []; - const h1 = parser.registerCsiHandler({ final: 'z' }, params => { callstack.push(['z', params.toArray()]); return true; }); - const h2 = parser.registerCsiHandler({ intermediates: '!', final: 'z' }, params => { callstack.push(['!z', params.toArray()]); return true; }); - const h3 = parser.registerCsiHandler({ intermediates: '!!', final: 'z' }, params => { callstack.push(['!!z', params.toArray()]); return true; }); - const h4 = parser.registerCsiHandler({ prefix: '?', final: 'z' }, params => { callstack.push(['?z', params.toArray()]); return true; }); - const h5 = parser.registerCsiHandler({ prefix: '?', intermediates: '!', final: 'z' }, params => { callstack.push(['?!z', params.toArray()]); return true; }); - const h6 = parser.registerCsiHandler({ prefix: '?', intermediates: '!!', final: 'z' }, params => { callstack.push(['?!!z', params.toArray()]); return true; }); + const h1 = parser.registerCsiHandler({ final: 'z' }, params => { + callstack.push(['z', params.toArray()]); return true; + }); + const h2 = parser.registerCsiHandler({ intermediates: '!', final: 'z' }, params => { + callstack.push(['!z', params.toArray()]); return true; + }); + const h3 = parser.registerCsiHandler({ intermediates: '!!', final: 'z' }, params => { + callstack.push(['!!z', params.toArray()]); return true; + }); + const h4 = parser.registerCsiHandler({ prefix: '?', final: 'z' }, params => { + callstack.push(['?z', params.toArray()]); return true; + }); + const h5 = parser.registerCsiHandler({ prefix: '?', intermediates: '!', final: 'z' }, params => { + callstack.push(['?!z', params.toArray()]); return true; + }); + const h6 = parser.registerCsiHandler({ prefix: '?', intermediates: '!!', final: 'z' }, params => { + callstack.push(['?!!z', params.toArray()]); return true; + }); parse(parser, '\x1b[1;z\x1b[1;!z\x1b[1;!!z\x1b[?1;z\x1b[?1;!z\x1b[?1;!!z'); h1.dispose(); h2.dispose(); @@ -1967,12 +2185,24 @@ describe('EscapeSequenceParser', () => { }); it('DCS', () => { const callstack: any[] = []; - const h1 = parser.registerDcsHandler({ final: 'z' }, new DcsHandler((data, params) => { callstack.push(['z', params.toArray(), data]); return true; })); - const h2 = parser.registerDcsHandler({ intermediates: '!', final: 'z' }, new DcsHandler((data, params) => { callstack.push(['!z', params.toArray(), data]); return true; })); - const h3 = parser.registerDcsHandler({ intermediates: '!!', final: 'z' }, new DcsHandler((data, params) => { callstack.push(['!!z', params.toArray(), data]); return true; })); - const h4 = parser.registerDcsHandler({ prefix: '?', final: 'z' }, new DcsHandler((data, params) => { callstack.push(['?z', params.toArray(), data]); return true; })); - const h5 = parser.registerDcsHandler({ prefix: '?', intermediates: '!', final: 'z' }, new DcsHandler((data, params) => { callstack.push(['?!z', params.toArray(), data]); return true; })); - const h6 = parser.registerDcsHandler({ prefix: '?', intermediates: '!!', final: 'z' }, new DcsHandler((data, params) => { callstack.push(['?!!z', params.toArray(), data]); return true; })); + const h1 = parser.registerDcsHandler({ final: 'z' }, new DcsHandler((data, params) => { + callstack.push(['z', params.toArray(), data]); return true; + })); + const h2 = parser.registerDcsHandler({ intermediates: '!', final: 'z' }, new DcsHandler((data, params) => { + callstack.push(['!z', params.toArray(), data]); return true; + })); + const h3 = parser.registerDcsHandler({ intermediates: '!!', final: 'z' }, new DcsHandler((data, params) => { + callstack.push(['!!z', params.toArray(), data]); return true; + })); + const h4 = parser.registerDcsHandler({ prefix: '?', final: 'z' }, new DcsHandler((data, params) => { + callstack.push(['?z', params.toArray(), data]); return true; + })); + const h5 = parser.registerDcsHandler({ prefix: '?', intermediates: '!', final: 'z' }, new DcsHandler((data, params) => { + callstack.push(['?!z', params.toArray(), data]); return true; + })); + const h6 = parser.registerDcsHandler({ prefix: '?', intermediates: '!!', final: 'z' }, new DcsHandler((data, params) => { + callstack.push(['?!!z', params.toArray(), data]); return true; + })); parse(parser, '\x1bP1;zAB\x1b\\\x1bP1;!zAB\x1b\\\x1bP1;!!zAB\x1b\\\x1bP?1;zAB\x1b\\\x1bP?1;!zAB\x1b\\\x1bP?1;!!zAB\x1b\\'); h1.dispose(); h2.dispose(); @@ -1995,9 +2225,15 @@ describe('EscapeSequenceParser', () => { }); it('APC', () => { const callstack: any[] = []; - const h1 = parser.registerApcHandler({ final: 'z' }, new ApcHandler(data => { callstack.push(['z', data]); return true; })); - const h2 = parser.registerApcHandler({ intermediates: '!', final: 'z' }, new ApcHandler(data => { callstack.push(['!z', data]); return true; })); - const h3 = parser.registerApcHandler({ intermediates: '!!', final: 'z' }, new ApcHandler(data => { callstack.push(['!!z', data]); return true; })); + const h1 = parser.registerApcHandler({ final: 'z' }, new ApcHandler(data => { + callstack.push(['z', data]); return true; + })); + const h2 = parser.registerApcHandler({ intermediates: '!', final: 'z' }, new ApcHandler(data => { + callstack.push(['!z', data]); return true; + })); + const h3 = parser.registerApcHandler({ intermediates: '!!', final: 'z' }, new ApcHandler(data => { + callstack.push(['!!z', data]); return true; + })); parse(parser, '\x1b_zAB\x1b\\\x1b_!zAB\x1b\\\x1b_!!zAB\x1b\\'); h1.dispose(); h2.dispose(); @@ -2106,14 +2342,30 @@ describe('EscapeSequenceParser - async', () => { } callstack.push(['PRINT', result]); }); - parser.registerCsiHandler({ final: 'm' }, params => { callstack.push(['SGR', params.toArray()]); return true; }); - parser.registerEscHandler({ intermediates: '%', final: 'G' }, () => { callstack.push(['ESC %G']); return true; }); - parser.registerEscHandler({ final: 'E' }, () => { callstack.push(['ESC E']); return true; }); - parser.setExecuteHandler('\r', () => { callstack.push(['EXE \r']); return true; }); - parser.setExecuteHandler('\n', () => { callstack.push(['EXE \n']); return true; }); - parser.registerOscHandler(1, new OscHandler(data => { callstack.push(['OSC 1', data]); return true; })); - parser.registerDcsHandler({ final: 'a' }, new DcsHandler((data, params) => { callstack.push(['DCS a', [data, params.toArray()]]); return true; })); - parser.registerApcHandler({ final: 'X' }, new ApcHandler(data => { callstack.push(['APC X', data]); return true; })); + parser.registerCsiHandler({ final: 'm' }, params => { + callstack.push(['SGR', params.toArray()]); return true; + }); + parser.registerEscHandler({ intermediates: '%', final: 'G' }, () => { + callstack.push(['ESC %G']); return true; + }); + parser.registerEscHandler({ final: 'E' }, () => { + callstack.push(['ESC E']); return true; + }); + parser.setExecuteHandler('\r', () => { + callstack.push(['EXE \r']); return true; + }); + parser.setExecuteHandler('\n', () => { + callstack.push(['EXE \n']); return true; + }); + parser.registerOscHandler(1, new OscHandler(data => { + callstack.push(['OSC 1', data]); return true; + })); + parser.registerDcsHandler({ final: 'a' }, new DcsHandler((data, params) => { + callstack.push(['DCS a', [data, params.toArray()]]); return true; + })); + parser.registerApcHandler({ final: 'X' }, new ApcHandler(data => { + callstack.push(['APC X', data]); return true; + })); }); it('sync handlers keep being parsed in sync mode', () => { @@ -2142,14 +2394,30 @@ describe('EscapeSequenceParser - async', () => { } callstack.push(['PRINT', result]); }); - parser.registerCsiHandler({ final: 'm' }, async params => { callstack.push(['SGR', params.toArray()]); return true; }); - parser.registerEscHandler({ intermediates: '%', final: 'G' }, async () => { callstack.push(['ESC %G']); return true; }); - parser.registerEscHandler({ final: 'E' }, async () => { callstack.push(['ESC E']); return true; }); - parser.setExecuteHandler('\r', () => { callstack.push(['EXE \r']); return true; }); - parser.setExecuteHandler('\n', () => { callstack.push(['EXE \n']); return true; }); - parser.registerOscHandler(1, new OscHandler(async data => { callstack.push(['OSC 1', data]); return true; })); - parser.registerDcsHandler({ final: 'a' }, new DcsHandler(async (data, params) => { callstack.push(['DCS a', [data, params.toArray()]]); return true; })); - parser.registerApcHandler({ final: 'X' }, new ApcHandler(async data => { callstack.push(['APC X', data]); return true; })); + parser.registerCsiHandler({ final: 'm' }, async params => { + callstack.push(['SGR', params.toArray()]); return true; + }); + parser.registerEscHandler({ intermediates: '%', final: 'G' }, async () => { + callstack.push(['ESC %G']); return true; + }); + parser.registerEscHandler({ final: 'E' }, async () => { + callstack.push(['ESC E']); return true; + }); + parser.setExecuteHandler('\r', () => { + callstack.push(['EXE \r']); return true; + }); + parser.setExecuteHandler('\n', () => { + callstack.push(['EXE \n']); return true; + }); + parser.registerOscHandler(1, new OscHandler(async data => { + callstack.push(['OSC 1', data]); return true; + })); + parser.registerDcsHandler({ final: 'a' }, new DcsHandler(async (data, params) => { + callstack.push(['DCS a', [data, params.toArray()]]); return true; + })); + parser.registerApcHandler({ final: 'X' }, new ApcHandler(async data => { + callstack.push(['APC X', data]); return true; + })); }); it('sync parse call does not work anymore', () => { @@ -2239,7 +2507,9 @@ describe('EscapeSequenceParser - async', () => { }); it('multiple async SGR handlers', async () => { // register with fallback - const SGR2 = parser.registerCsiHandler({ final: 'm' }, async params => { callstack.push(['2# SGR', params.toArray()]); return false; }); + const SGR2 = parser.registerCsiHandler({ final: 'm' }, async params => { + callstack.push(['2# SGR', params.toArray()]); return false; + }); await parseP(parser, INPUT); // should contain [2# SGR, SGR] call pairs for (let i = 0; i < callstack.length; ++i) { @@ -2274,7 +2544,9 @@ describe('EscapeSequenceParser - async', () => { clearAccu(); // register without fallback - const SGR22 = parser.registerCsiHandler({ final: 'm' }, async params => { callstack.push(['2# SGR', params.toArray()]); return true; }); + const SGR22 = parser.registerCsiHandler({ final: 'm' }, async params => { + callstack.push(['2# SGR', params.toArray()]); return true; + }); await parseP(parser, INPUT); // should only contain 2# SGR for (let i = 0; i < callstack.length; ++i) { @@ -2307,7 +2579,9 @@ describe('EscapeSequenceParser - async', () => { }); it('multiple async ESC handlers', async () => { // register with fallback - const ESC2 = parser.registerEscHandler({ final: 'E' }, async () => { callstack.push(['2# ESC E']); return false; }); + const ESC2 = parser.registerEscHandler({ final: 'E' }, async () => { + callstack.push(['2# ESC E']); return false; + }); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2340,7 +2614,9 @@ describe('EscapeSequenceParser - async', () => { clearAccu(); // register without fallback - const ESC22 = parser.registerEscHandler({ final: 'E' }, async () => { callstack.push(['2# ESC E']); return true; }); + const ESC22 = parser.registerEscHandler({ final: 'E' }, async () => { + callstack.push(['2# ESC E']); return true; + }); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2372,9 +2648,13 @@ describe('EscapeSequenceParser - async', () => { }); it('sync/async SGR mixed', async () => { // sync with fallback - const SGR2 = parser.registerCsiHandler({ final: 'm' }, params => { callstack.push(['2# SGR', params.toArray()]); return false; }); + const SGR2 = parser.registerCsiHandler({ final: 'm' }, params => { + callstack.push(['2# SGR', params.toArray()]); return false; + }); // async with fallback - const SGR3 = parser.registerCsiHandler({ final: 'm' }, async params => { callstack.push(['3# SGR', params.toArray()]); return false; }); + const SGR3 = parser.registerCsiHandler({ final: 'm' }, async params => { + callstack.push(['3# SGR', params.toArray()]); return false; + }); await parseP(parser, INPUT); // should contain [3# SGR, 2# SGR, SGR] call triples for (let i = 0; i < callstack.length; ++i) { @@ -2434,7 +2714,9 @@ describe('EscapeSequenceParser - async', () => { }); it('multiple async OSC handlers', async () => { // register with fallback - const OSC2 = parser.registerOscHandler(1, new OscHandler(async data => { callstack.push(['2# OSC 1', data]); return false; })); + const OSC2 = parser.registerOscHandler(1, new OscHandler(async data => { + callstack.push(['2# OSC 1', data]); return false; + })); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2467,7 +2749,9 @@ describe('EscapeSequenceParser - async', () => { clearAccu(); // register without fallback - const OSC22 = parser.registerOscHandler(1, new OscHandler(async data => { callstack.push(['2# OSC 1', data]); return true; })); + const OSC22 = parser.registerOscHandler(1, new OscHandler(async data => { + callstack.push(['2# OSC 1', data]); return true; + })); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2500,7 +2784,9 @@ describe('EscapeSequenceParser - async', () => { }); it('multiple async DCS handlers', async () => { // register with fallback - const DCS2 = parser.registerDcsHandler({ final: 'a' }, new DcsHandler(async (data, params) => { callstack.push(['#2 DCS a', [data, params.toArray()]]); return false; })); + const DCS2 = parser.registerDcsHandler({ final: 'a' }, new DcsHandler(async (data, params) => { + callstack.push(['#2 DCS a', [data, params.toArray()]]); return false; + })); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2533,7 +2819,9 @@ describe('EscapeSequenceParser - async', () => { clearAccu(); // register without fallback - const DCS22 = parser.registerDcsHandler({ final: 'a' }, new DcsHandler(async (data, params) => { callstack.push(['#2 DCS a', [data, params.toArray()]]); return true; })); + const DCS22 = parser.registerDcsHandler({ final: 'a' }, new DcsHandler(async (data, params) => { + callstack.push(['#2 DCS a', [data, params.toArray()]]); return true; + })); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2566,7 +2854,9 @@ describe('EscapeSequenceParser - async', () => { }); it('multiple async APC handlers', async () => { // register with fallback - const APC2 = parser.registerApcHandler({ final: 'X' }, new ApcHandler(async data => { callstack.push(['#2 APC X', data]); return false; })); + const APC2 = parser.registerApcHandler({ final: 'X' }, new ApcHandler(async data => { + callstack.push(['#2 APC X', data]); return false; + })); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; @@ -2599,7 +2889,9 @@ describe('EscapeSequenceParser - async', () => { clearAccu(); // register without fallback - const APC22 = parser.registerApcHandler({ final: 'X' }, new ApcHandler(async data => { callstack.push(['#2 APC X', data]); return true; })); + const APC22 = parser.registerApcHandler({ final: 'X' }, new ApcHandler(async data => { + callstack.push(['#2 APC X', data]); return true; + })); await parseP(parser, INPUT); for (let i = 0; i < callstack.length; ++i) { const entry = callstack[i]; diff --git a/src/common/parser/OscParser.test.ts b/src/common/parser/OscParser.test.ts index b6b96cbad..c19c04bfb 100644 --- a/src/common/parser/OscParser.test.ts +++ b/src/common/parser/OscParser.test.ts @@ -185,7 +185,9 @@ describe('OscParser', () => { }); it('should be called once on end(true)', () => { - parser.registerHandler(1234, new OscHandler(data => { reports.push([1234, data]); return true; })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push([1234, data]); return true; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -195,7 +197,9 @@ describe('OscParser', () => { assert.deepEqual(reports, [[1234, 'Here comes the mouse!']]); }); it('should not be called on end(false)', () => { - parser.registerHandler(1234, new OscHandler(data => { reports.push([1234, data]); return true; })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push([1234, data]); return true; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -205,8 +209,12 @@ describe('OscParser', () => { assert.deepEqual(reports, []); }); it('should be disposable', () => { - parser.registerHandler(1234, new OscHandler(data => { reports.push(['one', data]); return true; })); - const dispo = parser.registerHandler(1234, new OscHandler(data => { reports.push(['two', data]); return true; })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push(['one', data]); return true; + })); + const dispo = parser.registerHandler(1234, new OscHandler(data => { + reports.push(['two', data]); return true; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -224,8 +232,12 @@ describe('OscParser', () => { assert.deepEqual(reports, [['two', 'Here comes the mouse!'], ['one', 'some other data']]); }); it('should respect return false', () => { - parser.registerHandler(1234, new OscHandler(data => { reports.push(['one', data]); return true; })); - parser.registerHandler(1234, new OscHandler(data => { reports.push(['two', data]); return false; })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push(['one', data]); return true; + })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push(['two', data]); return false; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -236,7 +248,9 @@ describe('OscParser', () => { }); it('should work up to payload limit', function(): void { this.timeout(30000); - parser.registerHandler(1234, new OscHandler(data => { reports.push([1234, data]); return true; })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push([1234, data]); return true; + })); parser.start(); let data = toUtf32('1234;'); parser.put(data, 0, data.length); @@ -249,7 +263,9 @@ describe('OscParser', () => { }); it('should abort for payload limit +1', function(): void { this.timeout(30000); - parser.registerHandler(1234, new OscHandler(data => { reports.push([1234, data]); return true; })); + parser.registerHandler(1234, new OscHandler(data => { + reports.push([1234, data]); return true; + })); parser.start(); let data = toUtf32('1234;'); parser.put(data, 0, data.length); @@ -412,7 +428,9 @@ describe('OscParser - async tests', () => { }); describe('OscHandlerFactory', () => { it('should be called once on end(true)', async () => { - parser.registerHandler(1234, new OscHandler(async data => { reports.push([1234, data]); return true; })); + parser.registerHandler(1234, new OscHandler(async data => { + reports.push([1234, data]); return true; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -423,7 +441,9 @@ describe('OscParser - async tests', () => { assert.deepEqual(reports, [[1234, 'Here comes the mouse!']]); }); it('should not be called on end(false)', async () => { - parser.registerHandler(1234, new OscHandler(async data => { reports.push([1234, data]); return true; })); + parser.registerHandler(1234, new OscHandler(async data => { + reports.push([1234, data]); return true; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -433,8 +453,12 @@ describe('OscParser - async tests', () => { assert.deepEqual(reports, []); }); it('should be disposable', async () => { - parser.registerHandler(1234, new OscHandler(async data => { reports.push(['one', data]); return true; })); - const dispo = parser.registerHandler(1234, new OscHandler(async data => { reports.push(['two', data]); return true; })); + parser.registerHandler(1234, new OscHandler(async data => { + reports.push(['one', data]); return true; + })); + const dispo = parser.registerHandler(1234, new OscHandler(async data => { + reports.push(['two', data]); return true; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); @@ -452,8 +476,12 @@ describe('OscParser - async tests', () => { assert.deepEqual(reports, [['two', 'Here comes the mouse!'], ['one', 'some other data']]); }); it('should respect return false', async () => { - parser.registerHandler(1234, new OscHandler(async data => { reports.push(['one', data]); return true; })); - parser.registerHandler(1234, new OscHandler(async data => { reports.push(['two', data]); return false; })); + parser.registerHandler(1234, new OscHandler(async data => { + reports.push(['one', data]); return true; + })); + parser.registerHandler(1234, new OscHandler(async data => { + reports.push(['two', data]); return false; + })); parser.start(); let data = toUtf32('1234;Here comes'); parser.put(data, 0, data.length); diff --git a/src/common/public/AddonManager.test.ts b/src/common/public/AddonManager.test.ts index 239952eec..f4d6d0c0c 100644 --- a/src/common/public/AddonManager.test.ts +++ b/src/common/public/AddonManager.test.ts @@ -40,7 +40,9 @@ describe('AddonManager', () => { let called = 0; class Addon implements ITerminalAddon { public activate(): void {} - public dispose(): void { called++; } + public dispose(): void { + called++; + } } manager.loadAddon(null!, new Addon()); manager.loadAddon(null!, new Addon()); diff --git a/src/common/public/BufferApiView.ts b/src/common/public/BufferApiView.ts index 834cedbee..2a2038e9a 100644 --- a/src/common/public/BufferApiView.ts +++ b/src/common/public/BufferApiView.ts @@ -19,11 +19,21 @@ export class BufferApiView implements IBufferApi { return this; } - public get cursorY(): number { return this._buffer.y; } - public get cursorX(): number { return this._buffer.x; } - public get viewportY(): number { return this._buffer.ydisp; } - public get baseY(): number { return this._buffer.ybase; } - public get length(): number { return this._buffer.lines.length; } + public get cursorY(): number { + return this._buffer.y; + } + public get cursorX(): number { + return this._buffer.x; + } + public get viewportY(): number { + return this._buffer.ydisp; + } + public get baseY(): number { + return this._buffer.ybase; + } + public get length(): number { + return this._buffer.lines.length; + } public getLine(y: number): IBufferLineApi | undefined { const line = this._buffer.lines.get(y); if (!line) { @@ -31,5 +41,7 @@ export class BufferApiView implements IBufferApi { } return new BufferLineApiView(line); } - public getNullCell(): IBufferCellApi { return new CellData(); } + public getNullCell(): IBufferCellApi { + return new CellData(); + } } diff --git a/src/common/public/BufferLineApiView.ts b/src/common/public/BufferLineApiView.ts index 0a747fa41..8c11c7082 100644 --- a/src/common/public/BufferLineApiView.ts +++ b/src/common/public/BufferLineApiView.ts @@ -10,8 +10,12 @@ import { IBufferCell as IBufferCellApi, IBufferLine as IBufferLineApi } from '@x export class BufferLineApiView implements IBufferLineApi { constructor(private _line: IBufferLine) { } - public get isWrapped(): boolean { return this._line.isWrapped; } - public get length(): number { return this._line.length; } + public get isWrapped(): boolean { + return this._line.isWrapped; + } + public get length(): number { + return this._line.length; + } public getCell(x: number, cell?: IBufferCellApi): IBufferCellApi | undefined { if (x < 0 || x >= this._line.length) { return undefined; diff --git a/src/common/public/BufferNamespaceApi.ts b/src/common/public/BufferNamespaceApi.ts index 425b1798c..1da34c831 100644 --- a/src/common/public/BufferNamespaceApi.ts +++ b/src/common/public/BufferNamespaceApi.ts @@ -23,8 +23,12 @@ export class BufferNamespaceApi extends Disposable implements IBufferNamespaceAp this._core.buffers.onBufferActivate(() => this._onBufferChange.fire(this.active)); } public get active(): IBufferApi { - if (this._core.buffers.active === this._core.buffers.normal) { return this.normal; } - if (this._core.buffers.active === this._core.buffers.alt) { return this.alternate; } + if (this._core.buffers.active === this._core.buffers.normal) { + return this.normal; + } + if (this._core.buffers.active === this._core.buffers.alt) { + return this.alternate; + } throw new Error('Active buffer is neither normal nor alternate'); } public get normal(): IBufferApi { diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts index 06ac6b10a..f4e954870 100644 --- a/src/common/services/BufferService.ts +++ b/src/common/services/BufferService.ts @@ -29,7 +29,9 @@ export class BufferService extends Disposable implements IBufferService { private readonly _onScroll = this._register(new Emitter()); public readonly onScroll = this._onScroll.event; - public get buffer(): IBuffer { return this.buffers.active; } + public get buffer(): IBuffer { + return this.buffers.active; + } /** An IBufferline to clone/copy from for new blank lines */ private _cachedBlankLine: IBufferLine | undefined; diff --git a/src/common/services/DecorationService.ts b/src/common/services/DecorationService.ts index 133e1a985..0a3b014f3 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -32,7 +32,9 @@ export class DecorationService extends Disposable implements IDecorationService private readonly _onDecorationRemoved = this._register(new Emitter()); public readonly onDecorationRemoved = this._onDecorationRemoved.event; - public get decorations(): IterableIterator { return this._decorations.values(); } + public get decorations(): IterableIterator { + return this._decorations.values(); + } constructor(@ILogService private readonly _logService: ILogService) { super(); diff --git a/src/common/services/LogService.ts b/src/common/services/LogService.ts index 8bc1e0aaa..b2a269b85 100644 --- a/src/common/services/LogService.ts +++ b/src/common/services/LogService.ts @@ -35,7 +35,9 @@ export class LogService extends Disposable implements ILogService { public serviceBrand: any; private _logLevel: LogLevelEnum = LogLevelEnum.OFF; - public get logLevel(): LogLevelEnum { return this._logLevel; } + public get logLevel(): LogLevelEnum { + return this._logLevel; + } constructor( @IOptionsService private readonly _optionsService: IOptionsService diff --git a/src/common/services/MouseStateService.test.ts b/src/common/services/MouseStateService.test.ts index 0f2cd489a..a6d6126d5 100644 --- a/src/common/services/MouseStateService.test.ts +++ b/src/common/services/MouseStateService.test.ts @@ -40,8 +40,12 @@ describe('MouseStateService', () => { cms.reset(); assert.equal(cms.activeEncoding, 'DEFAULT'); assert.equal(cms.activeProtocol, 'NONE'); - assert.throws(() => { cms.activeEncoding = 'xyz'; }, 'unknown encoding "xyz"'); - assert.throws(() => { cms.activeProtocol = 'xyz'; }, 'unknown protocol "xyz"'); + assert.throws(() => { + cms.activeEncoding = 'xyz'; + }, 'unknown encoding "xyz"'); + assert.throws(() => { + cms.activeProtocol = 'xyz'; + }, 'unknown protocol "xyz"'); }); it('addEncoding', () => { const cms = new MouseStateService(); diff --git a/src/common/services/UnicodeService.test.ts b/src/common/services/UnicodeService.test.ts index 01e3c0862..229c81a18 100644 --- a/src/common/services/UnicodeService.test.ts +++ b/src/common/services/UnicodeService.test.ts @@ -25,11 +25,15 @@ describe('unicode provider', () => { it('default to V6', () => { assert.equal(us.activeVersion, '6'); assert.deepEqual(us.versions, ['6']); - assert.doesNotThrow(() => { us.activeVersion = '6'; }, `unknown Unicode version "6"`); + assert.doesNotThrow(() => { + us.activeVersion = '6'; + }, `unknown Unicode version "6"`); assert.equal(us.getStringCellWidth('hello'), 5); }); it('activate should throw for unknown version', () => { - assert.throws(() => { us.activeVersion = '55'; }, 'unknown Unicode version "55"'); + assert.throws(() => { + us.activeVersion = '55'; + }, 'unknown Unicode version "55"'); }); it('should notify about version change', () => { const notes: string[] = []; diff --git a/src/headless/public/Terminal.test.ts b/src/headless/public/Terminal.test.ts index 0b35fb0e7..c2a511c5c 100644 --- a/src/headless/public/Terminal.test.ts +++ b/src/headless/public/Terminal.test.ts @@ -35,8 +35,12 @@ describe('Headless API Tests', function (): void { it('write with callback', async () => { let result: string | undefined; await new Promise(r => { - term.write('foo', () => { result = 'a'; }); - term.write('bar', () => { result += 'b'; }); + term.write('foo', () => { + result = 'a'; + }); + term.write('bar', () => { + result += 'b'; + }); term.write('文', () => { result += 'c'; r(); @@ -56,8 +60,12 @@ describe('Headless API Tests', function (): void { it('write - bytes (UTF8) with callback', async () => { let result: string | undefined; await new Promise(r => { - term.write(new Uint8Array([102, 111, 111]), () => { result = 'A'; }); // foo - term.write(new Uint8Array([98, 97, 114]), () => { result += 'B'; }); // bar + term.write(new Uint8Array([102, 111, 111]), () => { + result = 'A'; + }); // foo + term.write(new Uint8Array([98, 97, 114]), () => { + result += 'B'; + }); // bar term.write(new Uint8Array([230, 150, 135]), () => { // 文 result += 'C'; r(); @@ -79,8 +87,12 @@ describe('Headless API Tests', function (): void { it('writeln with callback', async () => { let result: string | undefined; await new Promise(r => { - term.writeln('foo', () => { result = '1'; }); - term.writeln('bar', () => { result += '2'; }); + term.writeln('foo', () => { + result = '1'; + }); + term.writeln('bar', () => { + result += '2'; + }); term.writeln('文', () => { result += '3'; r(); diff --git a/src/headless/public/Terminal.ts b/src/headless/public/Terminal.ts index 0d4e6e93b..0d9c85329 100644 --- a/src/headless/public/Terminal.ts +++ b/src/headless/public/Terminal.ts @@ -72,16 +72,36 @@ export class Terminal extends Disposable implements ITerminalApi { } } - public get onBell(): IEvent { return this._core.onBell; } - public get onBinary(): IEvent { return this._core.onBinary; } - public get onCursorMove(): IEvent { return this._core.onCursorMove; } - public get onData(): IEvent { return this._core.onData; } - public get onLineFeed(): IEvent { return this._core.onLineFeed; } - public get onRender(): IEvent<{ start: number, end: number }> { return this._core.onRender; } - public get onResize(): IEvent<{ cols: number, rows: number }> { return this._core.onResize; } - public get onScroll(): IEvent { return this._core.onScroll; } - public get onTitleChange(): IEvent { return this._core.onTitleChange; } - public get onWriteParsed(): IEvent { return this._core.onWriteParsed; } + public get onBell(): IEvent { + return this._core.onBell; + } + public get onBinary(): IEvent { + return this._core.onBinary; + } + public get onCursorMove(): IEvent { + return this._core.onCursorMove; + } + public get onData(): IEvent { + return this._core.onData; + } + public get onLineFeed(): IEvent { + return this._core.onLineFeed; + } + public get onRender(): IEvent<{ start: number, end: number }> { + return this._core.onRender; + } + public get onResize(): IEvent<{ cols: number, rows: number }> { + return this._core.onResize; + } + public get onScroll(): IEvent { + return this._core.onScroll; + } + public get onTitleChange(): IEvent { + return this._core.onTitleChange; + } + public get onWriteParsed(): IEvent { + return this._core.onWriteParsed; + } public get parser(): IParser { this._parser ??= new ParserApi(this._core); @@ -91,8 +111,12 @@ export class Terminal extends Disposable implements ITerminalApi { this._checkProposedApi(); return new UnicodeApi(this._core); } - public get rows(): number { return this._core.rows; } - public get cols(): number { return this._core.cols; } + public get rows(): number { + return this._core.rows; + } + public get cols(): number { + return this._core.cols; + } public get buffer(): IBufferNamespaceApi { this._buffer ??= this._register(new BufferNamespaceApi(this._core)); return this._buffer; diff --git a/test/benchmark/EscapeSequenceParser.benchmark.ts b/test/benchmark/EscapeSequenceParser.benchmark.ts index 5c9f372fb..ada7e6af8 100644 --- a/test/benchmark/EscapeSequenceParser.benchmark.ts +++ b/test/benchmark/EscapeSequenceParser.benchmark.ts @@ -24,19 +24,25 @@ function toUtf32(s: string): Uint32Array { class FastDcsHandler implements IDcsHandler { public hook(params: IParams): void {} public put(data: Uint32Array, start: number, end: number): void {} - public unhook(success: boolean): boolean { return true; } + public unhook(success: boolean): boolean { + return true; + } } class FastOscHandler implements IOscHandler { public start(): void {} public put(data: Uint32Array, start: number, end: number): void {} - public end(success: boolean): boolean { return true; } + public end(success: boolean): boolean { + return true; + } } class FastApcHandler implements IApcHandler { public start(): void {} public put(data: Uint32Array, start: number, end: number): void {} - public end(success: boolean): boolean { return true; } + public end(success: boolean): boolean { + return true; + } } diff --git a/test/benchmark/Event.benchmark.ts b/test/benchmark/Event.benchmark.ts index 9cd8216dc..bf5e8b70e 100644 --- a/test/benchmark/Event.benchmark.ts +++ b/test/benchmark/Event.benchmark.ts @@ -27,7 +27,9 @@ perfContext('Emitter.fire()', () => { let sum = 0; before(() => { emitter = new Emitter(); - emitter.event(e => { sum += e; }); + emitter.event(e => { + sum += e; + }); }); new RuntimeCase('', () => { for (let i = 0; i < ITERATIONS; i++) { @@ -42,8 +44,12 @@ perfContext('Emitter.fire()', () => { let sum = 0; before(() => { emitter = new Emitter(); - emitter.event(e => { sum += e; }); - emitter.event(e => { sum += e * 2; }); + emitter.event(e => { + sum += e; + }); + emitter.event(e => { + sum += e * 2; + }); }); new RuntimeCase('', () => { for (let i = 0; i < ITERATIONS; i++) { @@ -59,7 +65,9 @@ perfContext('Emitter.fire()', () => { before(() => { emitter = new Emitter(); for (let j = 0; j < 5; j++) { - emitter.event(e => { sum += e; }); + emitter.event(e => { + sum += e; + }); } }); new RuntimeCase('', () => { diff --git a/test/playwright/TestUtils.ts b/test/playwright/TestUtils.ts index 8a76c8820..daf1d308b 100644 --- a/test/playwright/TestUtils.ts +++ b/test/playwright/TestUtils.ts @@ -202,76 +202,156 @@ export class TerminalProxy implements ITerminalProxyCustomMethods, PlaywrightApi // #region Events private _onBell = new EventEmitter(); - public get onBell(): IEvent { return this._onBell.event; } + public get onBell(): IEvent { + return this._onBell.event; + } private _onBinary = new EventEmitter(); - public get onBinary(): IEvent { return this._onBinary.event; } + public get onBinary(): IEvent { + return this._onBinary.event; + } private _onCursorMove = new EventEmitter(); - public get onCursorMove(): IEvent { return this._onCursorMove.event; } + public get onCursorMove(): IEvent { + return this._onCursorMove.event; + } private _onData = new EventEmitter(); - public get onData(): IEvent { return this._onData.event; } + public get onData(): IEvent { + return this._onData.event; + } private _onKey = new EventEmitter<{ key: string, domEvent: KeyboardEvent }>(); - public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; } + public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { + return this._onKey.event; + } private _onLineFeed = new EventEmitter(); - public get onLineFeed(): IEvent { return this._onLineFeed.event; } + public get onLineFeed(): IEvent { + return this._onLineFeed.event; + } private _onRender = new EventEmitter<{ start: number, end: number }>(); - public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; } + public get onRender(): IEvent<{ start: number, end: number }> { + return this._onRender.event; + } private _onResize = new EventEmitter<{ cols: number, rows: number }>(); - public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; } + public get onResize(): IEvent<{ cols: number, rows: number }> { + return this._onResize.event; + } private _onScroll = new EventEmitter(); - public get onScroll(): IEvent { return this._onScroll.event; } + public get onScroll(): IEvent { + return this._onScroll.event; + } private _onDimensionsChange = new EventEmitter(); - public get onDimensionsChange(): IEvent { return this._onDimensionsChange.event; } + public get onDimensionsChange(): IEvent { + return this._onDimensionsChange.event; + } private _onSelectionChange = new EventEmitter(); - public get onSelectionChange(): IEvent { return this._onSelectionChange.event; } + public get onSelectionChange(): IEvent { + return this._onSelectionChange.event; + } private _onTitleChange = new EventEmitter(); - public get onTitleChange(): IEvent { return this._onTitleChange.event; } + public get onTitleChange(): IEvent { + return this._onTitleChange.event; + } private _onWriteParsed = new EventEmitter(); - public get onWriteParsed(): IEvent { return this._onWriteParsed.event; } + public get onWriteParsed(): IEvent { + return this._onWriteParsed.event; + } // #endregion // #region Simple properties - public get cols(): Promise { return this.evaluate(([term]) => term.cols); } - public get rows(): Promise { return this.evaluate(([term]) => term.rows); } - public get modes(): Promise { return this.evaluate(([term]) => term.modes); } - public get dimensions(): Promise { return this.evaluate(([term]) => term.dimensions); } + public get cols(): Promise { + return this.evaluate(([term]) => term.cols); + } + public get rows(): Promise { + return this.evaluate(([term]) => term.rows); + } + public get modes(): Promise { + return this.evaluate(([term]) => term.modes); + } + public get dimensions(): Promise { + return this.evaluate(([term]) => term.dimensions); + } // #endregion // #region Complex properties - public get buffer(): TerminalBufferNamespaceProxy { return new TerminalBufferNamespaceProxy(this._page, this); } + public get buffer(): TerminalBufferNamespaceProxy { + return new TerminalBufferNamespaceProxy(this._page, this); + } /** * Exposes somewhat unsafe access to internals for testing things difficult to do with the regular * API */ - public get core(): TerminalCoreProxy { return new TerminalCoreProxy(this._page, this); } + public get core(): TerminalCoreProxy { + return new TerminalCoreProxy(this._page, this); + } // #endregion // #region Proxied methods - public async dispose(): Promise { return this.evaluate(([term]) => term.dispose()); } - public async reset(): Promise { return this.evaluate(([term]) => term.reset()); } - public async clear(): Promise { return this.evaluate(([term]) => term.clear()); } - public async focus(): Promise { return this.evaluate(([term]) => term.focus()); } - public async blur(): Promise { return this.evaluate(([term]) => term.blur()); } - public async hasSelection(): Promise { return this.evaluate(([term]) => term.hasSelection()); } - public async getSelection(): Promise { return this.evaluate(([term]) => term.getSelection()); } - public async getSelectionPosition(): Promise { return this.evaluate(([term]) => term.getSelectionPosition()); } - public async selectAll(): Promise { return this.evaluate(([term]) => term.selectAll()); } - public async selectLines(start: number, end: number): Promise { return this._page.evaluate(([term, start, end]) => term.selectLines(start, end), [await this.getHandle(), start, end] as const); } - public async clearSelection(): Promise { return this.evaluate(([term]) => term.clearSelection()); } - public async select(column: number, row: number, length: number): Promise { return this._page.evaluate(([term, column, row, length]) => term.select(column, row, length), [await this.getHandle(), column, row, length] as const); } - public async paste(data: string): Promise { return this._page.evaluate(([term, data]) => term.paste(data), [await this.getHandle(), data] as const); } - public async refresh(start: number, end: number): Promise { return this._page.evaluate(([term, start, end]) => term.refresh(start, end), [await this.getHandle(), start, end] as const); } - public async getOption(key: T): Promise { return this._page.evaluate(([term, key]) => term.options[key as T], [await this.getHandle(), key] as const); } - public async setOption(key: T, value: ITerminalOptions[T]): Promise { return this._page.evaluate(([term, key, value]) => term.options[key as T] = (value as ITerminalOptions[T]), [await this.getHandle(), key, value] as const); } + public async dispose(): Promise { + return this.evaluate(([term]) => term.dispose()); + } + public async reset(): Promise { + return this.evaluate(([term]) => term.reset()); + } + public async clear(): Promise { + return this.evaluate(([term]) => term.clear()); + } + public async focus(): Promise { + return this.evaluate(([term]) => term.focus()); + } + public async blur(): Promise { + return this.evaluate(([term]) => term.blur()); + } + public async hasSelection(): Promise { + return this.evaluate(([term]) => term.hasSelection()); + } + public async getSelection(): Promise { + return this.evaluate(([term]) => term.getSelection()); + } + public async getSelectionPosition(): Promise { + return this.evaluate(([term]) => term.getSelectionPosition()); + } + public async selectAll(): Promise { + return this.evaluate(([term]) => term.selectAll()); + } + public async selectLines(start: number, end: number): Promise { + return this._page.evaluate(([term, start, end]) => term.selectLines(start, end), [await this.getHandle(), start, end] as const); + } + public async clearSelection(): Promise { + return this.evaluate(([term]) => term.clearSelection()); + } + public async select(column: number, row: number, length: number): Promise { + return this._page.evaluate(([term, column, row, length]) => term.select(column, row, length), [await this.getHandle(), column, row, length] as const); + } + public async paste(data: string): Promise { + return this._page.evaluate(([term, data]) => term.paste(data), [await this.getHandle(), data] as const); + } + public async refresh(start: number, end: number): Promise { + return this._page.evaluate(([term, start, end]) => term.refresh(start, end), [await this.getHandle(), start, end] as const); + } + public async getOption(key: T): Promise { + return this._page.evaluate(([term, key]) => term.options[key as T], [await this.getHandle(), key] as const); + } + public async setOption(key: T, value: ITerminalOptions[T]): Promise { + return this._page.evaluate(([term, key, value]) => term.options[key as T] = (value as ITerminalOptions[T]), [await this.getHandle(), key, value] as const); + } public async setOptions(value: Partial): Promise { return this._page.evaluate(([term, value]) => { term.options = value; }, [await this.getHandle(), value] as const); } - public async scrollToTop(): Promise { return this.evaluate(([term]) => term.scrollToTop()); } - public async scrollToBottom(): Promise { return this.evaluate(([term]) => term.scrollToBottom()); } - public async scrollPages(pageCount: number): Promise { return this._page.evaluate(([term, pageCount]) => term.scrollPages(pageCount), [await this.getHandle(), pageCount] as const); } - public async scrollToLine(line: number): Promise { return this._page.evaluate(([term, line]) => term.scrollToLine(line), [await this.getHandle(), line] as const); } - public async scrollLines(amount: number): Promise { return this._page.evaluate(([term, amount]) => term.scrollLines(amount), [await this.getHandle(), amount] as const); } + public async scrollToTop(): Promise { + return this.evaluate(([term]) => term.scrollToTop()); + } + public async scrollToBottom(): Promise { + return this.evaluate(([term]) => term.scrollToBottom()); + } + public async scrollPages(pageCount: number): Promise { + return this._page.evaluate(([term, pageCount]) => term.scrollPages(pageCount), [await this.getHandle(), pageCount] as const); + } + public async scrollToLine(line: number): Promise { + return this._page.evaluate(([term, line]) => term.scrollToLine(line), [await this.getHandle(), line] as const); + } + public async scrollLines(amount: number): Promise { + return this._page.evaluate(([term, amount]) => term.scrollLines(amount), [await this.getHandle(), amount] as const); + } public async write(data: string | Uint8Array): Promise { return this._page.evaluate(([term, data]) => { return new Promise(r => term.write(typeof data === 'string' ? data : new Uint8Array(data), r)); @@ -282,11 +362,21 @@ export class TerminalProxy implements ITerminalProxyCustomMethods, PlaywrightApi return new Promise(r => term.writeln(typeof data === 'string' ? data : new Uint8Array(data), r)); }, [await this.getHandle(), typeof data === 'string' ? data : Array.from(data)] as const); } - public async input(data: string, wasUserInput: boolean = true): Promise { return this.evaluate(([term]) => term.input(data, wasUserInput)); } - public async resize(cols: number, rows: number): Promise { return this._page.evaluate(([term, cols, rows]) => term.resize(cols, rows), [await this.getHandle(), cols, rows] as const); } - public async registerMarker(y?: number | undefined): Promise { return this._page.evaluate(([term, y]) => term.registerMarker(y), [await this.getHandle(), y] as const); } - public async registerDecoration(decorationOptions: IDecorationOptions): Promise { return this._page.evaluate(([term, decorationOptions]) => term.registerDecoration(decorationOptions), [await this.getHandle(), decorationOptions] as const); } - public async clearTextureAtlas(): Promise { return this.evaluate(([term]) => term.clearTextureAtlas()); } + public async input(data: string, wasUserInput: boolean = true): Promise { + return this.evaluate(([term]) => term.input(data, wasUserInput)); + } + public async resize(cols: number, rows: number): Promise { + return this._page.evaluate(([term, cols, rows]) => term.resize(cols, rows), [await this.getHandle(), cols, rows] as const); + } + public async registerMarker(y?: number | undefined): Promise { + return this._page.evaluate(([term, y]) => term.registerMarker(y), [await this.getHandle(), y] as const); + } + public async registerDecoration(decorationOptions: IDecorationOptions): Promise { + return this._page.evaluate(([term, decorationOptions]) => term.registerDecoration(decorationOptions), [await this.getHandle(), decorationOptions] as const); + } + public async clearTextureAtlas(): Promise { + return this.evaluate(([term]) => term.clearTextureAtlas()); + } // #endregion public async evaluate(pageFunction: PageFunction): Promise { @@ -314,9 +404,15 @@ class TerminalBufferNamespaceProxy implements PlaywrightApiProxy term.buffer.active)); } - public get normal(): TerminalBufferProxy { return new TerminalBufferProxy(this._page, this._proxy, this._proxy.evaluateHandle(([term]) => term.buffer.normal)); } - public get alternate(): TerminalBufferProxy { return new TerminalBufferProxy(this._page, this._proxy, this._proxy.evaluateHandle(([term]) => term.buffer.alternate)); } + public get active(): TerminalBufferProxy { + return new TerminalBufferProxy(this._page, this._proxy, this._proxy.evaluateHandle(([term]) => term.buffer.active)); + } + public get normal(): TerminalBufferProxy { + return new TerminalBufferProxy(this._page, this._proxy, this._proxy.evaluateHandle(([term]) => term.buffer.normal)); + } + public get alternate(): TerminalBufferProxy { + return new TerminalBufferProxy(this._page, this._proxy, this._proxy.evaluateHandle(([term]) => term.buffer.alternate)); + } } // TODO: Adopt PlaywrightApiProxy @@ -328,12 +424,24 @@ class TerminalBufferProxy /* implements EnsureAsyncProperties*/ { ) { } - public get type(): Promise<'normal' | 'alternate'> { return this.evaluate(([buffer]) => buffer.type); } - public get cursorY(): Promise { return this.evaluate(([buffer]) => buffer.cursorY); } - public get cursorX(): Promise { return this.evaluate(([buffer]) => buffer.cursorX); } - public get viewportY(): Promise { return this.evaluate(([buffer]) => buffer.viewportY); } - public get baseY(): Promise { return this.evaluate(([buffer]) => buffer.baseY); } - public get length(): Promise { return this.evaluate(([buffer]) => buffer.length); } + public get type(): Promise<'normal' | 'alternate'> { + return this.evaluate(([buffer]) => buffer.type); + } + public get cursorY(): Promise { + return this.evaluate(([buffer]) => buffer.cursorY); + } + public get cursorX(): Promise { + return this.evaluate(([buffer]) => buffer.cursorX); + } + public get viewportY(): Promise { + return this.evaluate(([buffer]) => buffer.viewportY); + } + public get baseY(): Promise { + return this.evaluate(([buffer]) => buffer.baseY); + } + public get length(): Promise { + return this.evaluate(([buffer]) => buffer.length); + } public async getLine(y: number): Promise { const lineHandle = await this._page.evaluateHandle(([buffer, y]) => buffer.getLine(y), [await this._handle, y] as const); const value = await lineHandle.jsonValue(); @@ -356,8 +464,12 @@ class TerminalBufferLine { ) { } - public get length(): Promise { return this.evaluate(([bufferLine]) => bufferLine.length); } - public get isWrapped(): Promise { return this.evaluate(([bufferLine]) => bufferLine.isWrapped); } + public get length(): Promise { + return this.evaluate(([bufferLine]) => bufferLine.length); + } + public get isWrapped(): Promise { + return this.evaluate(([bufferLine]) => bufferLine.isWrapped); + } public translateToString(trimRight?: boolean, startColumn?: number, endColumn?: number): Promise { return this._page.evaluate(([bufferLine, trimRight, startColumn, endColumn]) => { @@ -387,33 +499,79 @@ class TerminalBufferCell { ) { } - public getWidth(): Promise { return this.evaluate(([cell]) => cell.getWidth()); } - public getChars(): Promise { return this.evaluate(([cell]) => cell.getChars()); } - public getCode(): Promise { return this.evaluate(([cell]) => cell.getCode()); } + public getWidth(): Promise { + return this.evaluate(([cell]) => cell.getWidth()); + } + public getChars(): Promise { + return this.evaluate(([cell]) => cell.getChars()); + } + public getCode(): Promise { + return this.evaluate(([cell]) => cell.getCode()); + } - public getFgColorMode(): Promise { return this.evaluate(([cell]) => cell.getFgColorMode()); } - public getBgColorMode(): Promise { return this.evaluate(([cell]) => cell.getBgColorMode()); } - public getFgColor(): Promise { return this.evaluate(([cell]) => cell.getFgColor()); } - public getBgColor(): Promise { return this.evaluate(([cell]) => cell.getBgColor()); } + public getFgColorMode(): Promise { + return this.evaluate(([cell]) => cell.getFgColorMode()); + } + public getBgColorMode(): Promise { + return this.evaluate(([cell]) => cell.getBgColorMode()); + } + public getFgColor(): Promise { + return this.evaluate(([cell]) => cell.getFgColor()); + } + public getBgColor(): Promise { + return this.evaluate(([cell]) => cell.getBgColor()); + } - public isBold(): Promise { return this.evaluate(([cell]) => cell.isBold()); } - public isItalic(): Promise { return this.evaluate(([cell]) => cell.isItalic()); } - public isDim(): Promise { return this.evaluate(([cell]) => cell.isDim()); } - public isUnderline(): Promise { return this.evaluate(([cell]) => cell.isUnderline()); } - public isBlink(): Promise { return this.evaluate(([cell]) => cell.isBlink()); } - public isInverse(): Promise { return this.evaluate(([cell]) => cell.isInverse()); } - public isInvisible(): Promise { return this.evaluate(([cell]) => cell.isInvisible()); } - public isStrikethrough(): Promise { return this.evaluate(([cell]) => cell.isStrikethrough()); } - public isOverline(): Promise { return this.evaluate(([cell]) => cell.isOverline()); } + public isBold(): Promise { + return this.evaluate(([cell]) => cell.isBold()); + } + public isItalic(): Promise { + return this.evaluate(([cell]) => cell.isItalic()); + } + public isDim(): Promise { + return this.evaluate(([cell]) => cell.isDim()); + } + public isUnderline(): Promise { + return this.evaluate(([cell]) => cell.isUnderline()); + } + public isBlink(): Promise { + return this.evaluate(([cell]) => cell.isBlink()); + } + public isInverse(): Promise { + return this.evaluate(([cell]) => cell.isInverse()); + } + public isInvisible(): Promise { + return this.evaluate(([cell]) => cell.isInvisible()); + } + public isStrikethrough(): Promise { + return this.evaluate(([cell]) => cell.isStrikethrough()); + } + public isOverline(): Promise { + return this.evaluate(([cell]) => cell.isOverline()); + } - public isFgRGB(): Promise { return this.evaluate(([cell]) => cell.isFgRGB()); } - public isBgRGB(): Promise { return this.evaluate(([cell]) => cell.isBgRGB()); } - public isFgPalette(): Promise { return this.evaluate(([cell]) => cell.isFgPalette()); } - public isBgPalette(): Promise { return this.evaluate(([cell]) => cell.isBgPalette()); } - public isFgDefault(): Promise { return this.evaluate(([cell]) => cell.isFgDefault()); } - public isBgDefault(): Promise { return this.evaluate(([cell]) => cell.isBgDefault()); } + public isFgRGB(): Promise { + return this.evaluate(([cell]) => cell.isFgRGB()); + } + public isBgRGB(): Promise { + return this.evaluate(([cell]) => cell.isBgRGB()); + } + public isFgPalette(): Promise { + return this.evaluate(([cell]) => cell.isFgPalette()); + } + public isBgPalette(): Promise { + return this.evaluate(([cell]) => cell.isBgPalette()); + } + public isFgDefault(): Promise { + return this.evaluate(([cell]) => cell.isFgDefault()); + } + public isBgDefault(): Promise { + return this.evaluate(([cell]) => cell.isBgDefault()); + } - public isAttributeDefault(): Promise { return this.evaluate(([cell]) => cell.isAttributeDefault()); } + public isAttributeDefault(): Promise { + return this.evaluate(([cell]) => cell.isAttributeDefault()); + } public async evaluate(pageFunction: PageFunction): Promise { return this._page.evaluate(pageFunction, [this._handle]); @@ -427,8 +585,12 @@ class TerminalCoreProxy { ) { } - public get isDisposed(): Promise { return this.evaluate(([core]) => (core as any)._isDisposed); } - public get renderDimensions(): Promise { return this.evaluate(([core]) => ((core as any)._renderService as IRenderService).dimensions); } + public get isDisposed(): Promise { + return this.evaluate(([core]) => (core as any)._isDisposed); + } + public get renderDimensions(): Promise { + return this.evaluate(([core]) => ((core as any)._renderService as IRenderService).dimensions); + } public async triggerBinaryEvent(data: string): Promise { return this._page.evaluate(([core, data]) => core.coreService.triggerBinaryEvent(data), [await this._getCoreHandle(), data] as const);