Expand description
Bounded, WASM-clean CST-backed undo/redo history (E007 OBJ3, TR-010..014).
UndoStack is the reusable undo/redo model the editor surfaces wire a
document into. Each reversible unit is an UndoEntry: a snapshot of the
exact prior document bytes (source_text), the lossless CST at that
state (CstDocument, cheap to clone — see below), and a caller-supplied
cursor/metadata value. Restoring an entry therefore reproduces the prior
buffer byte-for-byte with no reflow or normalization (TR-010, SC-005).
§WASM-clean (TR-014, HINT-002)
This module adds no filesystem / native / I/O / network dependency to
ronin-core — it holds only CST + text + a generic cursor value, so the crate
stays rowan-only and the wasm32-unknown-unknown build gate keeps passing.
It also measures no wall-clock time: std::time::Instant is unavailable
on wasm32-unknown-unknown, so the timing of a coalesce boundary is decided
caller-side (the native ronin-app measures Instant elapsed against the
configured window) and handed in as the coalesce flag on record.
coalesce_window is retained only as reference
metadata; this module never reads a clock. All persistence (atomic save, the
recovery sidecar) lives in the native ronin-app; the undo model deliberately
knows nothing about it. The stack is reusable by downstream epics (E005/E008,
TR-013).
§Cheap snapshots via structural sharing (AD-002, ADR-0001)
CstDocument is Clone, and a rowan green tree is immutable /
structurally shared: cloning the document bumps an Arc refcount on the
green root, and an edit reuses every untouched subtree verbatim. Snapshotting
the CST per undo unit is therefore cheap (no deep copy of the tree), while the
retained source_text guarantees the exact-prior-byte restore. This is why
the undo unit is a CST + text snapshot rather than a reverse-delta log.
§Cursor / metadata generic (C)
UndoStack and UndoEntry are generic over a cursor/metadata type C
so ronin-core stays decoupled from any surface’s cursor representation: the
native editor supplies its own CursorState, a future headless surface could
supply (). C is restored alongside the document on undo/redo (TR-010).
§Bounds and coalescing (TR-011, TR-024, TR-027)
The undo ring is bounded by both a count cap and a byte-size cap
(UndoCap); when either binds, the oldest unit is dropped so memory stays
predictable on large files (SC-006/SC-009). A rapid run of edits the caller
marks coalesce: true collapses into a single unit (SC-006/SC-010); the first
edit after a pause (coalesce: false) commits the prior boundary and starts a
new unit (TR-027). A new edit after an undo clears the redo stack (TR-012).
§State model (current / undo ring / redo)
The stack tracks the current committed document state (current)
plus a bounded undo ring of prior boundaries and a redo
stack. The caller owns the live buffer; the stack owns the history. The
contract is:
record(entry, coalesce):entryis a snapshot of the document state after the edit just applied. Whencoalesceisfalse, the previouscurrentis pushed onto theundoring as a discrete boundary andentrybecomes the newcurrent(a new undo unit). Whencoalesceistrue,entryreplacescurrentin place without pushing a boundary, so a run of coalesced edits collapses to the single boundary captured before the run began. Either way, recording an edit clearsredo(TR-012). The very firstrecordon an empty stack just seedscurrent(there is no prior boundary to keep).undo(): pops the most recent boundary off theundoring, pushes the current state ontoredo, makes the popped boundary the newcurrent, and returns it for the caller to apply to the buffer. ReturnsNonewhen there is nothing to undo.redo(): pops the most recent state offredo, pushes the current state back onto theundoring, makes the popped state the newcurrent, and returns it. ReturnsNonewhen there is nothing to redo.
This keeps restore byte-faithful (the caller writes the returned entry’s
source_text verbatim — no reflow) and the history strictly bounded.
Structs§
- UndoCap
- The history bound for an
UndoStack: a unit-count cap and a total snapshot byte-size cap (TR-011, TR-024). - Undo
Entry - One reversible unit — a snapshot of a single document state (TR-010).
- Undo
Stack - The bounded undo/redo history for a single document (TR-010..014).
Constants§
- DEFAULT_
COALESCE_ WINDOW - Default coalesce window: edits less than 500 ms apart fold into one unit (TR-027). A pause longer than this boundary starts a new undo unit.
- DEFAULT_
UNDO_ BYTE_ CAP - Default maximum total snapshot byte-size retained: 64 MiB (TR-024).
- DEFAULT_
UNDO_ COUNT_ CAP - Default maximum number of undo units retained (TR-024).