feat(tui): add selection to prompt as quoted context - #44443
feat(tui): add selection to prompt as quoted context#44443AdityaTeltia wants to merge 4 commits into
Conversation
Selecting text in the transcript copies it, but there was no way to carry it into the next message. Add a prompt.add_selection command, bound to <leader>p, that inserts the selection at the cursor as a blockquote chip that expands on submit. Copy-on-select previously cleared the highlight on mouse release, so any command running afterwards saw nothing selected. It is now retained and dismissed by the next click, or by the first key no binding consumed. Leader sequences and open dialogs are exempt so the keybind and the command palette can both read it.
|
The following comment was made by an LLM, it may be inaccurate: |
Nice, well-tested feature — the retention lifecycle (retain on copy-on-select, dismiss on unconsumed key or click, exempt dialogs) is thoughtfully handled, tests cover both the keymap plumbing and the selection helpers, and
Minor:
|
Blank and padded lines no longer carry trailing whitespace into the quote. The highlight is cleared only after the quote reaches the prompt. Dialog escape and ctrl+c dismiss a retained highlight before closing, restoring the old two-step behaviour for every dialog rather than only the palette.
Issue for this PR
Related to #21025. That issue was closed as not planned and the earlier attempt in #21026 was closed by automated PR cleanup rather than review, so the feature is still missing.
Type of change
What does this PR do?
Selecting text in the transcript copies it, but there is no way to carry that text into the next message short of pasting it back by hand.
Adds
prompt.add_selection(<leader>p, and "Add selection to chat" in the palette). It takes the selection, prefixes each line with>, and inserts it at the cursor as a collapsed chip via the existing pasted-text part machinery, so it stashes, restores and expands on submit like any other pasted block. Blockquote rather than a wrapper tag is deliberate: there is no closing delimiter for selected text to break out of.The catch is that copy-on-select called
clearSelection()on mouse release, so a command running afterwards saw nothing selected.Selection.copynow takes{ retain: true }on that path. Three things depended on selections being short-lived:key:afterintercept dismisses the retained highlight on the first key no binding consumed. It skips whilependingSequenceis non-empty, otherwise<leader>would clear the selection before the second key lands, and skips while a dialog is open, otherwise typing to filter the palette would drop it.onMouseDownnow clears a leftover highlight. Drag-to-select is unaffected because opentui'sstartSelectionclears first, so the selection is empty at mouse-down time.How did you verify your code works?
bun typecheckacross the monorepo (30/30) andbun testinpackages/tui(200 pass, 0 fail).test/selection-retention.test.tsdrives a realcreateTestRendererplus the actual opencode keymap:ctrl+xretains the selection,pdispatches the command, an unbound key dismisses, palette-filter keys do not.test/selection.test.tscovers retain vs clear, and thattakereads only the live selection so no stale text can be added.prompt_add_selectionresolves throughCommandMapto<leader>p. I also checked<leader>pis unused across every other default binding.Screenshots / recordings
Screen_Recording_2026-08-23_compressed.mp4
Checklist