Add serde-based terminal state snapshot/restore - #3
Open
dsturnbull wants to merge 6 commits into
Open
Conversation
added 6 commits
March 3, 2026 16:35
Add Term::snapshot() and Term::restore() for capturing and restoring full terminal state (both grid buffers, cursor, mode flags, scroll region) via any serde-compatible format. Includes TermState struct in the serialize module with round-trip tests for JSON and bincode. Grid, Storage, Row, Cell, and related types gain Serialize/Deserialize derives behind the existing serde feature flag.
Compress old scrollback rows to reduce terminal memory usage. Rows are trimmed of trailing default cells, serialized with bincode, and compressed with zstd, achieving ~28x compression on typical mixed terminal content. Grid<Cell> gains: - compress_old_scrollback(keep_hot) / thaw_compressed_history(count) - compact_scrollback_if_needed() for automatic compression - scroll_display_with_thaw() for transparent decompression on scroll 192 tests passing including 40+ new compression tests covering round-trip fidelity, compression ratios, freeze/thaw integration, and automatic compress/thaw triggers.
Mirrors Term::scroll_display but delegates to Grid::scroll_display_with_thaw, which automatically decompresses compressed scrollback rows when the scroll target reaches into compressed history.
No-op hot path: 10k calls in <5ms (single integer comparison). Compression: 11.2 µs/row (release), 269 µs per screenful. Decompression: 5.3 µs/row (release), 127 µs per screenful. The decompression latency assertion only fires in release builds to avoid false positives from debug-mode overhead.
compact_scrollback_if_needed was unconditionally compressing all hot history beyond 2x screen lines, ignoring display_offset. The subsequent clamp in compress_old_scrollback would yank the viewport back, making it impossible to scroll more than ~2 screens into compressed history. Account for display_offset when choosing how many rows to keep hot.
Search methods now take &mut self so regex_search_internal can thaw compressed history before iterating. This makes search find content that has been compressed into scrollback. Also adds Grid::total_topmost_line() for callers that want the search range to include compressed rows.
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.
Add serde-based terminal state snapshot/restore
Adds
Term::snapshot()andTerm::restore()for capturing and restoring terminal state via any serde-compatible format. This enables session persistence across PTY reconnects (used bypty-host) without coupling to a specific serialisation format.What changed
alacritty_terminal/src/term/serialize.rs(new)Introduces
TermState— a serde-derived struct capturing the subset ofTermstate needed for restore:gridinactive_gridmode_bitsTermModebitflags (bracketed paste, mouse mode, alt screen, …)scroll_regionNot captured: tab stops, charsets, window title, keyboard mode stack, cursor style, selection, vi mode cursor — these are either reconstructed from defaults or owned by the client (full list).
alacritty_terminal/src/term/mod.rsTerm::snapshot()andTerm::restore()added as methods onTerm, following the existing convention where all state-mutating operations live directly on the type. Both are gated behind#[cfg(feature = "serde")].alacritty_terminal/src/grid/mod.rsCursor<T>gainsSerialize/Deserializederives.cursorandsaved_cursoronGridflip from#[serde(skip)]to#[serde(default)]so they survive round-trips.charsetsis marked#[serde(skip)]becausevte::ansi::StandardCharsetlacks serde derives upstream (see known limitation below).alacritty_terminal/Cargo.tomlbincodeadded as a dev-dependency for binary round-trip tests.serde_jsonwas already present.Known limitation
Cursor.charsetsis skipped during serialisation becauseStandardCharsetandCharsetIndexin thevtecrate don't deriveSerialize/Deserialize. A fix adding the two derives is ready in a localvtebranch — once merged upstream,charsetscan flip fromskiptodefault.Testing
11 tests in
serialize.rs:WRAPLINEpreservation, scrollbacksnapshot→restorepreserves: content + cursor, mode flags, alternate screen, scroll region, scrollback