Skip to content

feat(web): copy the terminal selection with ctrl+c - #26

Merged
rynfar merged 1 commit into
pylonfrom
feat/terminal-copy-shortcut
Aug 14, 2026
Merged

feat(web): copy the terminal selection with ctrl+c#26
rynfar merged 1 commit into
pylonfrom
feat/terminal-copy-shortcut

Conversation

@rynfar

@rynfar rynfar commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Adopts upstream #5638. On non-mac, copying a terminal selection required Ctrl+Shift+C; plain Ctrl+C now copies too.

The interesting part: this does not break interrupt

Ctrl+C in a terminal is normally SIGINT, so rebinding it to copy is the kind of change that can quietly ruin your ability to stop a runaway process. I read this one specifically to check, and it's handled:

  • No selection → nothing intercepts. The copy path is gated on isTerminalCopyShortcut(event) && this.hasSelection(), so with nothing selected Ctrl+C falls straight through to the shell as SIGINT.
  • With a selection, one press copies and then clears the selection, so the next Ctrl+C reaches the shell. clearSelectionAfterCopy is set only for the plain non-mac chord.
  • Cmd+C and Ctrl+Shift+C stay copy-only and keep the selection, since neither is SIGINT.

The tradeoff is real and worth stating: with text selected, the first Ctrl+C copies instead of interrupting. The auto-clear keeps that to a single press.

The rest is browser-compatibility plumbing: plain Ctrl+C isn't preventDefaulted so the native copy event still fires, with a token-guarded deferred clipboard.writeText racing it for WebKit, which omits the keyboard copy event when there's no DOM selection. Ctrl+Shift+C has no native event at all (Chrome binds it to inspect), so that branch synthesises one via execCommand("copy"). There's also a contextMenuFallback path and one new IPC contract member.

Verification

  • vp test run over the 3 touched test files: 47 passed.
  • Typecheck on @t3tools/web and @t3tools/contracts: no errors.
  • vp lint on the changed files: clean.

Clean cherry-pick, no Pylon adaptation needed.

No browser pass. Clipboard behaviour differs across engines and this change leans on those differences deliberately — the WebKit race in particular is the sort of thing unit tests can't settle. Worth a real pass in Chrome and Safari before trusting it fully; say the word and I'll run one.

Model: Claude Opus 5. Harness: Claude Code.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

…#5638)

(cherry picked from commit 1add47b322ab1dfb5010bb363613650176b88088)
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Aug 14, 2026
@github-actions

Copy link
Copy Markdown

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for cd3b7cb.

This comment will update automatically after the next completed run.

@rynfar

rynfar commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Browser pass attempted — the change is not verifiable on this host

Ran the app on this branch against seeded data, opened the terminal drawer (ghostty canvas and Terminal input both mount fine with the change in place), and tried to exercise the copy gesture. Two findings, the second decisive:

1. Synthetic key events cannot drive this code path. The implementation deliberately relies on the browser's native copy event, and on the transient user activation that clipboard.writeText requires. Neither a synthetic KeyboardEvent nor a CDP-level key press produced a copy event that a document-level observer could see.

2. More fundamentally: this host is macOS, so the changed line never executes. navigator.platform is MacIntel, so isTerminalCopyShortcut takes the isMacPlatform branch and checks event.metaKey. The entire behavioural diff is on the other branch — event.ctrlKey && event.shiftKey becoming event.ctrlKey. A macOS browser cannot reach it regardless of clipboard mechanics.

So the honest position: verifying this needs a Windows or Linux browser. What the pass does establish is narrower but not worthless — the terminal surface still mounts and initialises correctly with the new copy listener attached, so there's no regression in setup, and the mac path is untouched by the diff.

The reasoning behind the change still reads correctly on inspection: the copy path is gated on hasSelection() so an empty selection falls through as SIGINT, and clearSelectionAfterCopy is set only for the plain non-mac chord so the next press interrupts. That is inspection, not execution.

@rynfar
rynfar merged commit f630ab0 into pylon Aug 14, 2026
11 checks passed
@rynfar
rynfar deleted the feat/terminal-copy-shortcut branch August 14, 2026 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants