feat: add keyboard-only copy mode#11
Merged
Merged
Conversation
Add a grid-owned copy-mode model (cursor, anchor, selection kinds, word/line motions) plus Screen/Terminal integration, including copy point tracking across scrollback eviction and resize.
Extend FrameSnapshot with copy-mode selection and hollow-cursor state, render them in the cell pipeline, and invalidate the row cache when pinned-scroll translation cannot prove reuse. Includes cache and cursor regression tests.
Wire copy-mode commands, keybindings, and palette entries into input dispatch; recheck directional entry under the terminal lock and fall back to PTY encoding on rejection; keep redraw snapshots atomic with copy-mode coordinate repair and held synchronized-output frames.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a keyboard-only copy mode (Ghostty parity): enter with directional keybinds, move a copy cursor through the viewport and scrollback, select by cell/word/line, and copy without touching the mouse. Implemented per the locked spec in
docs/specs/copy-mode.md.Changes
noa-grid: grid-owned copy-mode model (cursor, anchor, selection kinds, word/line motions) with copy-point tracking across scrollback eviction and resizenoa-render:FrameSnapshotselection/hollow-cursor state, cell-pipeline rendering, and row-cache invalidation when pinned-scroll translation cannot prove reusenoa-app: commands, keybindings, and palette entries wired into input dispatch; directional entry rechecked under the terminal lock with PTY fallback on rejection; redraw snapshots kept atomic with held synchronized-output framesdocs: copy-mode spec andKEYBINDINGS.mdupdateHistory is reshaped into these four layer commits (grid → render → app → docs); commit-by-commit review is recommended.
Test plan
cargo clippy, andcargo fmt --checkgreen (noa-pty/noa-ipc suites re-run unsandboxed)Risk
Medium: touches the render-cache and synchronized-output paths in
noa-app/src/app/render.rs, today's highest-churn hotspot. Mitigated by viewport-identity checks, screen-generation regression coverage, and tree-equivalence-verified history reshape. Revert is a single PR revert; the feature is inert until a copy-mode keybind is pressed.