Skip to content

feat(keys): copy mode — scrollback navigation via <prefix> [ - #9

Closed
seamoss wants to merge 1 commit into
devfrom
feat/copy-mode
Closed

seamoss wants to merge 1 commit into
devfrom
feat/copy-mode

Conversation

@seamoss

@seamoss seamoss commented Apr 24, 2026

Copy link
Copy Markdown
Owner

Summary

` [` enters an alt-screen scrollback viewer. Client-side ring buffer (1 MiB default, `RAT_SCROLLBACK_BYTES` override) is populated by the output task and scrolled by the input task when copy mode activates. Live output keeps arriving during scroll — it's appended to a `pending` buffer and flushed on exit so the main screen catches up.

Keys: `j`/`k` line-by-line, `Space`/`b` page-by-page, `g`/`G` top/bottom, `q`/`Esc` to exit. Arrow + PgUp/PgDn mapped when the terminal sends them contiguously.

ANSI is stripped for rendering stability — colour goes away, line navigation stays predictable. `rat grep` is the coloured-transcript tool.

Test plan

  • cargo build + clippy + fmt + test green
  • CI green
  • Smoke: attach session, run `ls -la /` or similar, `Ctrl-A [`, scroll around, `q` exits cleanly and live view renders in place

New chord command `<prefix> [` enters an alt-screen scrollback viewer
while keeping the attached session alive in the background. Live
output accumulates in a client-side ring buffer (default 1 MiB,
overridable via `RAT_SCROLLBACK_BYTES`) and into a `pending` buffer
during copy mode; on exit the alt-screen pops off and `pending` is
flushed to stdout so the live view catches up.

Keys: `j`/`k` and arrow up/down for line-by-line scroll, `Space`/`b`
(or `Ctrl-F`/`Ctrl-B`, or PgDn/PgUp if the terminal sends them
contiguously) for page-by-page, `g`/`G` for top/bottom, `q`/`Esc` to
exit. Status bar shows the current visible-line / total-line counter.

Implementation notes:
- `InputFilter` gains `CMD_COPY = '['` and a non-terminal `copy_mode`
  flag in `FilterOutput` — same shape as the existing `help` flag.
- Output task routes filtered PtyOutput through `append_scrollback`
  (VecDeque with front-trim on overflow) and branches on an atomic
  `in_copy` flag: writes to stdout in normal mode, appends to the
  `pending` Vec while in copy mode.
- `run_copy_mode` uses `write_stdout_sync` helpers that lock +
  release `StdoutLock` per call. Holding the lock across `.await`
  breaks Send for the input task's spawned future; per-call locking
  sidesteps that without forcing the whole task into single-threaded.
- ANSI is stripped on render. Colour goes away in copy mode, but
  line-by-line navigation stays sane — raw cursor-movement sequences
  in the PTY byte stream would otherwise scramble the alt-screen
  rendering. Accepted trade-off; `rat grep` is the coloured search
  tool instead.

Banner + chord cheatsheet updated with `[=copy`.
@seamoss

seamoss commented Apr 24, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #11 — combined to avoid peer-merge conflict churn. Original commit preserved there.

@seamoss seamoss closed this Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant