Skip to content

feat: copy selected text - #58

Merged
denolfe merged 2 commits into
mainfrom
feat/text-select-copy
Sep 7, 2026
Merged

denolfe merged 2 commits into
mainfrom
feat/text-select-copy

Conversation

@denolfe

@denolfe denolfe commented Sep 7, 2026 •

Copy link
Copy Markdown
Owner

Dragging over text in the viewer now copies it to the clipboard when the mouse button is released. The status line reports the result.

Key Changes

  • Copy on mouse release
    • The renderer emits a selection event once per finished drag. A handler in App copies the text and shows a Copied N chars status.
    • Empty and whitespace-only selections stay silent. A bare click finishes an empty selection, so it must not report anything.
  • Clipboard path chosen once per session
    • resolveCopyStrategy prefers a local clipboard command: pbcopy, wl-copy, xclip, xsel, or clip.exe.
    • SSH sessions use OSC 52, an escape sequence that asks the terminal to set the clipboard. The Linux tools are also skipped when no display server is set, since they error or hang without one.
  • Inline code copies clean
    • A codespan is padded with half-block cells that share a text renderable with the code itself. Those cells are stripped from the copied text.
    • A drag that catches only the padding counts as an empty selection.
  • Themed selection highlight
    • Selections paint theme.selectionBg instead of reverse video. Text keeps its own foreground color.

Design Decisions

The clipboard path is resolved before the copy, not after a failure. tmux configured with set-clipboard external discards an application's OSC 52 request, and the OpenTUI call still reports success. A fallback triggered by failure would never fire, so a local command wins whenever the session is not remote.

The selection color is seeded on OpenTUI's shared text renderable base class rather than passed as a prop. OpenTUI exposes selectionBg per renderable with no app-wide default. The viewer mounts blocks progressively, so every current and future text element would otherwise have to carry the prop.

References / Links

Dragging over text now puts it on the clipboard when the button is released,
with a `Copied N chars` status line.

Prefers the local clipboard command (pbcopy, wl-copy, xclip, xsel, clip.exe)
and falls back to OSC 52 over SSH. Command-first because a multiplexer can
swallow OSC 52 while still reporting success — tmux `set-clipboard external`
drops it silently, leaving nothing to detect and fall back from.

The half-block cells padding an inline-code pill are stripped from the copied
text, and selections paint `theme.selectionBg` instead of reverse video.
@denolfe denolfe changed the title feat(copy): copy selected text on mouse release feat: copy selected text Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Startup benchmark (--render test/exhaustive.md, linux-x64)

build mean ratio verdict
baseline (main@beedc6d) 359.7ms ± 5.3ms —
PR 364.5ms ± 9.2ms 1.01× ✅ ok

Thresholds: warn ≥ 1.1×, fail ≥ 1.25×. Baseline built from main.

First-frame (large.md, runs=10)

metric baseline (main@beedc6d) PR ratio verdict
first-frame 271.1ms 273.1ms 1.01× ✅ ok

Thresholds: warn ≥ 1.1×, fail ≥ 1.25×. Baseline built from main.

Scroll (large.md)

metric baseline (main@beedc6d) PR ratio verdict
full_mount 10248.0ms 10772.0ms 1.05× ✅ ok
step_p50 23.2ms 22.3ms 0.96× ✅ ok
step_search_p50 22.8ms 23.3ms 1.03× ✅ ok
stepMatch_p50 17.2ms 17.9ms 1.04× ✅ ok
commit 139.7ms 146.7ms 1.05× ✅ ok

Thresholds: warn ≥ 1.1×, fail ≥ 1.25×. Baseline built from main.

@denolfe
denolfe merged commit a9f836e into main Sep 7, 2026
8 checks passed
@denolfe
denolfe deleted the feat/text-select-copy branch September 7, 2026 04:21
denolfe added a commit that referenced this pull request Sep 9, 2026
- feat: copy selected text (#58) (a9f836e)
- fix(hr): stop adding a resize listener per horizontal rule (#57) (beedc6d)
- ci: add first-frame and scroll benchmarks to the PR bench job (#56) (b7ab07d)
- perf: improve first frame and progressive-mount speed, optimize large documents (#54) (3b6d9f2)
- chore(ci): pin bun 1.4.1 via mise (#53) (f596175)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant