feat(tui2): add multi-click transcript selection (#8471)

Support multi-click transcript selection using transcript/viewport
coordinates
(wrapped visual line index + content column), not terminal buffer
positions.

Gestures:
- double click: select word-ish token under cursor
- triple click: select entire wrapped line
- quad click: select paragraph (contiguous non-empty wrapped lines)
- quint+ click: select the entire history cell (all wrapped lines
belonging to a
  single `HistoryCell`, including blank lines inside the cell)

Selection expansion rebuilds the wrapped transcript view from
`HistoryCell::display_lines(width)` so boundaries match on-screen
wrapping during
scroll/resize/streaming reflow. Click grouping is resilient to minor
drag jitter
(some terminals emit tiny Drag events during clicks) and becomes more
tolerant as
the sequence progresses so quad/quint clicks are practical.

Tests cover expansion (word/line/paragraph/cell), sequence resets
(timing, motion,
line changes, real drags), drag jitter, and behavior on spacer lines
between
history cells (paragraph/cell selection prefers the cell above).
This commit is contained in:
Josh McKinney authored and GitHub committed 2025-12-23 21:05:06 +00:00
1 parent 53eb2e9f27
commit 0130a2fa40
13 files changed
+3256 -1021

No files matched your search

+12 -7
View File
@@ -183,13 +183,18 @@ Mouse interaction is a first‑class part of the new design:
that we use for bullets/prefixes.
- **Copy.**
- When the user triggers copy, the TUI reconstructs the same wrapped transcript lines used for
on-screen rendering.
- It then walks the content-relative selection range (even if the selection extends outside the
current viewport) and re-renders each selected visual line into a 1-row offscreen buffer to
reconstruct the exact text region the user highlighted (including internal spaces and empty
lines, while skipping wide-glyph continuation cells and right-margin padding).
- That text is sent to the system clipboard and a status footer indicates success or failure.
- When the user triggers copy, the TUI reconstructs the wrapped transcript lines using the same
flattening/wrapping rules as the visible view.
- It then reconstructs a high‑fidelity clipboard string from the selected logical lines:
- Preserves meaningful indentation (especially for code blocks).
- Treats soft-wrapped prose as a single logical line by joining wrap continuations instead of
inserting hard newlines.
- Emits Markdown source markers (e.g. backticks and fences) for copy/paste, even if the UI
chooses to render those constructs without showing the literal markers.
- Copy operates on the full selection range, even if the selection extends outside the current
viewport.
- The resulting text is sent to the system clipboard and a status footer indicates success or
failure.
Because scrolling, selection, and copy all operate on the same flattened transcript representation,
they remain consistent even as the viewport resizes or the chat composer grows/shrinks. Owning our