Repository navigation
A Copy button on code blocks in the terminal, on hover (opt-in) #723
irisitymichaelgrundberg
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I often open the Response Viewer just to copy a code block. The blocks I copy most are the ones it draws in a box with a Copy button, because copying the same block from the terminal gets it wrong in three ways. Claude Code draws a code block without its fences, it indents every row by a two-column margin, and it word-wraps long lines with no marker, dropping the space at each break. So a terminal selection of a long shell command or a JSON snippet needs fixing by hand before it works.
Codeman already knows which text is a code block, so I built a shortcut. When you hover a code block in the terminal, the Response Viewer's Copy button appears next to it, and a click copies the block as the transcript has it. It's on the
feat/terminal-code-copybranch of my fork, and I'm holding the PR until you've had a look.What it does
(hover: hover) and (pointer: fine)), and off by default.rv-copy-btnthe Response Viewer uses, next to the block. A click copies the block's text from the transcript, flashes the same copied mark, and leaves focus in the terminal.last-responsealready reads. Remote sessions and the other CLIs get no button.How it finds the blocks
The browser fetches
GET /api/sessions/:id/last-response?context=full, the Response Viewer's own source, and extracts the code blocks withmarked.lexer. It then matches them against the rows on screen, comparing text with whitespace removed, so the margin and the wrapping don't matter. A block cut off at the top or bottom of the viewport still matches. When two blocks could both explain the same rows, those rows get no button, so it never copies the wrong block.To check this I built synthetic transcripts from 303 real code-bearing answers and had
claude --resumedraw them at 100x50. Then I graded a 50-row window at every scroll position. The button was on the right block in 7,358 of 7,416 sightings and never on a wrong one. Every block shown whole got its button. All 58 misses were blocks cut off at an edge, and 46 of them showed fewer than 12 characters. A short sliver gets a button only when it is a whole block line of 8 characters or more, because shorter or partial lines also turn up as prose.Two small API changes
Both add to
last-responsewithout changing what existing callers get:If-None-Matchgets a 304 before the file is read. The button refetches after output while the pointer moves, at most every three seconds, so this keeps an idle hover from re-reading a large transcript.source: 'pane'. Pane text is screen text, not markdown, so the button offers nothing for it.Questions
constants.js, next to the other pure helpers, with tests against a real Claude render.source: 'pane'fine on a/api/v1endpoint, or would you rather the button had an endpoint of its own?If it's a yes in some shape, I'll send it as one PR referencing this thread.
All reactions