From ff689647155ce7b852e6a318301c7a54fa2687ff Mon Sep 17 00:00:00 2001 From: Ramiz Wachtler Date: Fri, 23 Oct 2026 19:32:30 +0200 Subject: [PATCH] fix(tui): use iterm2 word characters for fullscreen double-click selection (#11340) - add iterm2's default word characters (`+ \ ~ _ .`) to fullscreen double-click selection ([source](https://github.com/gnachman/iTerm2/blob/7f4ff739721f95d0b93003d8701c4523a7edf261/sources/Settings/iTermPreferences.m#L743)) - `~/...`, `~/.pi/...`, `~\...`, `foo+bar` now select whole - add regression cases for `~`, `.`, `\`, `+` - fixes #10980 --- packages/tui/CHANGELOG.md | 4 ++++ packages/tui/src/tui-alt-screen.ts | 5 +++-- packages/tui/test/tui-alt-screen.test.ts | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/tui/CHANGELOG.md b/packages/tui/CHANGELOG.md index da21edae9..0f53f56f4 100644 --- a/packages/tui/CHANGELOG.md +++ b/packages/tui/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed fullscreen double-click selection splitting paths and tokens at `~`, `.`, `\`, and `+`. Word characters now match iTerm2's defaults ([#10980](https://github.com/earendil-works/pi/issues/10980)) + ## [1.4.0] - 2026-10-21 ### Added diff --git a/packages/tui/src/tui-alt-screen.ts b/packages/tui/src/tui-alt-screen.ts index 5e6d76864..9596146a6 100644 --- a/packages/tui/src/tui-alt-screen.ts +++ b/packages/tui/src/tui-alt-screen.ts @@ -81,8 +81,9 @@ const MAX_CACHED_OFFSCREEN_KITTY_DECODED_BYTES = 64 * 1024 * 1024; const DOUBLE_CLICK_INTERVAL_MS = 500; const COPY_ERROR_FLASH_DURATION_MS = 5000; // Regular mode delegates double-click selection to the terminal emulator. Fullscreen owns mouse selection, -// so mirror common terminal word-selection behavior by keeping paths and kebab-case tokens whole. -const TERMINAL_WORD_SELECTION_JOINERS = new Set(["/", "-"]); +// so it uses iTerm2's default "characters considered part of a word" set: +// https://github.com/gnachman/iTerm2/blob/7f4ff739721f95d0b93003d8701c4523a7edf261/sources/Settings/iTermPreferences.m#L743 +const TERMINAL_WORD_SELECTION_JOINERS = new Set(["/", "-", "+", "\\", "~", "_", "."]); const wordSegmenter = getWordSegmenter(); interface CachedKittyImage { diff --git a/packages/tui/test/tui-alt-screen.test.ts b/packages/tui/test/tui-alt-screen.test.ts index 25772b54c..acead60ce 100644 --- a/packages/tui/test/tui-alt-screen.test.ts +++ b/packages/tui/test/tui-alt-screen.test.ts @@ -1544,6 +1544,9 @@ describe("TuiAltScreen", () => { for (const { line, needle } of [ { line: "extensions/starline/fixed-editor/compositor.ts", needle: "starline" }, { line: "earendil-works/pi-tui", needle: "works" }, + { line: "~/.pi/agent/settings.json", needle: "agent" }, + { line: "~\\Documents\\pi", needle: "Documents" }, + { line: "foo+bar", needle: "bar" }, ]) { const copied: string[] = []; const terminal = new RecordingTerminal(80, 1);