[FEATURE] $.ui.selection() should report where a selection is (element key and offsets), not just its text
Problem Statement
In a plugin (hooks module) pane, $.ui.selection() resolves only { text, requestId? }.requestId is only set for transcript rows, so for a selection inside a pane the plugin
learns what was selected but not where.
That makes any "annotate the selection" feature ambiguous whenever the selected text occurs
more than once in the underlying data. I hit this building a code/Markdown review pane
(select text, mark it, send all marks to Claude): selecting a common word such as storage
matches several places in the file, and the plugin cannot tell which one the user meant.
Workarounds are all lossy:
- Search the whole file for the text and refuse if there is more than one match.
- Rely on the
Codeline-number gutter being copied along with the text (only works if the
selection starts on the gutter, and the plugin must strip it from the text).
- Ask the user to pick among the matches in the pane (works, but the user already pointed
at one place and has to point again).
Proposed Solution
Extend the UiSelection result with the position of the selection inside the drawn tree:
type UiSelection = {
text: string
requestId?: string
// new, present for selections inside a plugin's Pane or Client surface
start?: { key: string; offset: number }
end?: { key: string; offset: number }
}
keyis thekeythe plugin gave the element (e.g. aBoxper Markdown block or per
code chunk), or the nearest keyed ancestor.
offsetis a character offset into that element's drawn text:sourceforCode, the
rendered text for Markdown/Text. Offsets into the rendered text are enough: the plugin
can already map rendered text back to its own source.
- For
CodewithstartLine, the line number would also be useful, but it can be derived
from offset and source.
Alternative Solutions
- Make the
Codegutter non-selectable and exposestartLinein the result, so the line is
known without parsing copied text.
- An
onSelect-style event onText/Code/Markdownthat carries the position, so the
plugin does not have to poll the selection after a button press.
Use Case Example
A review pane renders a file as keyed blocks. The user selects one occurrence of a word and
presses a hotkey to mark it as a question. The plugin gets { text: "storage", start: { key:, maps it to line 5 of the file, and stores the annotation
"seg-3", offset: 12 }, ... }
exactly there, with no lookup ambiguity and no extra step for the user.
Additional Context
- Related umbrella issue for the plugin/mod API: #91870.
- API surface:
$.ui.selection()inclaude-code/index.d.ts(UiSelection). - Sample plugin that needs this: a Markdown/code review pane that sends annotations to Claude.