feat(terminal): text selection + copy (custom model)
Drag to select terminal text and copy it with Ctrl-Shift-C. Built as a
custom selection model (xterm.js-style) rather than native selection,
because the virtual scroll only keeps ~60 rows in the DOM and rebuilds
them every frame — native selection would be destroyed and couldn't span
scrolled-out rows.
core.rs:
- selection_text(start, end) extracts a (row,col)→(row,col) range straight
from history_rows + screen_cache, so copy is correct across the whole
buffer regardless of what is currently rendered
- TerminalRow::text_in_cols slices a row by grid columns (using the
segment `cols` widths), trimming trailing whitespace
component.rs:
- Selection { anchor, head } in logical buffer coords; mousedown/move/up
drag updates it; point_to_cell maps pixels→cell (padding + scrollTop)
- selection_rects computes per-row highlight rects clipped to the rendered
window; rendered as an overlay inside the translated rows layer so the
highlight follows scrolling without splitting text segments
- cell_size signal kept in sync with viewport measurement
- Ctrl-Shift-C copies via navigator.clipboard.write_text; Ctrl-C is left
untouched (still SIGINT); typing clears the selection
style: .terminal-selection overlay, user-select:none on the grid, rows
above the highlight via z-index.
web-sys: add DomRect, MouseEvent, Navigator, Clipboard.
Adds point_to_cell / selection_rects / selection_text unit tests (16
terminal tests total). Marks P0 done in TERMINAL_ROADMAP.md.
Known follow-up: no auto-scroll when dragging past the viewport edge
(scroll first, then select); wide+combining column slicing is approximate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -634,9 +634,12 @@
|
||||
position: relative;
|
||||
display: block;
|
||||
min-height: 100%;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.terminal-row {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 18px;
|
||||
min-height: 18px;
|
||||
max-height: 18px;
|
||||
@@ -674,6 +677,13 @@
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.terminal-selection {
|
||||
position: absolute;
|
||||
background: rgb(56 189 248 / 30%);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.terminal-measure {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
|
||||
Reference in New Issue
Block a user