From ded011c5a5b4974c6c05ff2d6a9e63ed3e75655c Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 30 Apr 2026 17:50:49 -0500 Subject: [PATCH] fix(tui): tighten SGR fragment matching --- ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts | 6 ++++++ ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts | 2 +- ui-tui/src/__tests__/terminalModes.test.ts | 4 ++-- ui-tui/src/lib/terminalModes.ts | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts b/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts index 893eb42ed2..cee7ab39dd 100644 --- a/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts +++ b/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts @@ -127,4 +127,10 @@ describe('fragmented SGR mouse recovery', () => { expect(key).toMatchObject({ kind: 'key', sequence: 'see 1;2;3M for details' }) }) + + it('does not match prefixless fragments inside longer digit runs', () => { + const [[key]] = parseMultipleKeypresses(INITIAL_STATE, '1234;56;78M9;10;11M') + + expect(key).toMatchObject({ kind: 'key', sequence: '1234;56;78M9;10;11M' }) + }) }) diff --git a/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts b/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts index b79b839e85..a92a72b5c4 100644 --- a/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts +++ b/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts @@ -63,7 +63,7 @@ const XTVERSION_RE = /^\x1bP>\|(.*?)(?:\x07|\x1b\\)$/s // Button 32=left-drag (0x20 | motion-bit). Plain 0/1/2 = left/mid/right click. // eslint-disable-next-line no-control-regex const SGR_MOUSE_RE = /^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/ -const SGR_MOUSE_FRAGMENT_RE = /(?:\[<|<)?(?:[0-9]|[1-9][0-9]|1\d{2}|2[0-4]\d|25[0-5]);\d+;\d+[Mm]/g +const SGR_MOUSE_FRAGMENT_RE = /(? { it('includes common sticky input modes', () => { - expect(TERMINAL_MODE_RESET).toContain("\x1b[0'z") - expect(TERMINAL_MODE_RESET).toContain("\x1b[0'{") + expect(TERMINAL_MODE_RESET).toContain('\x1b[0\'z') + expect(TERMINAL_MODE_RESET).toContain('\x1b[0\'{') expect(TERMINAL_MODE_RESET).toContain('\x1b[?2029l') expect(TERMINAL_MODE_RESET).toContain('\x1b[?1016l') expect(TERMINAL_MODE_RESET).toContain('\x1b[?1015l') diff --git a/ui-tui/src/lib/terminalModes.ts b/ui-tui/src/lib/terminalModes.ts index 84d3f0850b..79d6981f27 100644 --- a/ui-tui/src/lib/terminalModes.ts +++ b/ui-tui/src/lib/terminalModes.ts @@ -1,8 +1,8 @@ import { writeSync } from 'node:fs' export const TERMINAL_MODE_RESET = - "\x1b[0'z" + // DEC locator reporting - "\x1b[0'{" + // selectable locator events + '\x1b[0\'z' + // DEC locator reporting + '\x1b[0\'{' + // selectable locator events '\x1b[?2029l' + // passive mouse '\x1b[?1016l' + // SGR-pixels mouse '\x1b[?1015l' + // urxvt decimal mouse