pub struct UndoStack<C> { /* private fields */ }Expand description
The bounded undo/redo history for a single document (TR-010..014).
Newest reversible boundary is at the back/top of undo. Generic
over the cursor/metadata type C carried in each UndoEntry. See the module
docs for the WASM-clean, structural-sharing, current/ring state model, and the
caller-side coalesce decision.
§Downstream reuse (E005 / E008 — TR-013)
This is the reusable undo/redo model the downstream editing epics edit against:
E005 (smart authoring) and E008 (structural / table editing). It lives
in ronin-core precisely so any surface can own a per-document handle, while the
editor-specific glue (cursor type, coalesce timing, dirty tracking) stays in the
host. The key reuse contract:
- Construct per document via
with_config(host’s NEW-CONFIG cap + coalesce window) ornewfor the defaults. - After each edit,
recordanUndoEntrysnapshot (CST, exact bytes, cursor) with the caller-measuredcoalesceflag — this module reads no clock, so the host decides run boundaries. - On undo/redo, apply the returned entry’s
source_textto the buffer verbatim for an exact-prior-byte restore (no reflow / normalization, TR-010 / SC-005); redo is invalidated automatically by the nextrecord.
Choose C to match the surface (the native editor uses its CursorState; a
headless consumer can use ()). The history is always bounded (count + bytes)
and adds no filesystem / native dependency, so it is WASM-clean for every
downstream surface.
Implementations§
Source§impl<C> UndoStack<C>
impl<C> UndoStack<C>
Sourcepub fn with_config(cap: UndoCap, coalesce_window: Duration) -> Self
pub fn with_config(cap: UndoCap, coalesce_window: Duration) -> Self
Create an empty stack with an explicit history cap and coalesce window.
Use this to apply the editor’s NEW-CONFIG values (ronin-app
AppSettings). The cap is taken as-is; build it through UndoCap::new
first so a zero/misconfigured field reverts to default (never unbounded).
Sourcepub fn coalesce_window(&self) -> Duration
pub fn coalesce_window(&self) -> Duration
The coalesce window: reference metadata for the caller’s timing decision.
This module never measures elapsed time against it (it stays WASM-clean);
the caller compares its own Instant elapsed against this and passes the
result as the coalesce flag to record.
Sourcepub fn current(&self) -> Option<&UndoEntry<C>>
pub fn current(&self) -> Option<&UndoEntry<C>>
The current committed document state, or None before the first record.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Number of committed undo boundaries currently retained (the steps undo
can take back from the current state).
Sourcepub fn has_pending(&self) -> bool
pub fn has_pending(&self) -> bool
Whether a coalescing keystroke run is currently open. The document seam (T036) closes it implicitly on the next non-coalescing record or on undo/redo; exposed for tests and host wiring.
Sourcepub fn redo_len(&self) -> usize
pub fn redo_len(&self) -> usize
Number of states currently replay-able by redo (cleared on a new edit).
Sourcepub fn retained_bytes(&self) -> usize
pub fn retained_bytes(&self) -> usize
Total retained snapshot byte-size across the committed undo boundaries (compared against the byte-size cap, TR-024).
Counts the undo ring only — the boundaries the cap drops oldest-first.
The live current is the caller’s buffer (not history) and redo is
cleared by any new edit, so the ring is the bounded retained history.
Sourcepub fn total_bytes(&self) -> usize
pub fn total_bytes(&self) -> usize
Total retained snapshot byte-size across both the undo ring and the redo stack plus the current state (the full in-memory history footprint).
Used by SC-009 to assert the whole undo/redo memory stays bounded by the
configured cap independent of file size; the per-cap drop is enforced
against retained_bytes (the bounded ring).
Sourcepub fn record(&mut self, entry: UndoEntry<C>, coalesce: bool)
pub fn record(&mut self, entry: UndoEntry<C>, coalesce: bool)
Record a new committed document state (T031/T032/T033/T034).
entry is a snapshot of the document after the edit just applied
(its source_text is the new exact buffer bytes, its cst_snapshot the
matching CST, and cursor the post-edit caret). coalesce is the
caller-supplied timing decision (this module measures no clock,
TR-014):
coalesce == false— start a new undo unit: the previouscurrentboundary is pushed onto the boundedundoring andentrybecomes the newcurrent(TR-010). The first record on an empty stack just seedscurrentwith no boundary to keep. This is the first edit of a run (the caller measured a pause, or a restore reset the timing anchor), so it is its own discrete undo step that a following within-window edit may then extend.coalesce == true— continue the current run:entryreplacescurrentin place without pushing a boundary, so the whole keystroke run collapses to the single boundary captured before the run began (TR-027, one unit per run — SC-006/SC-010).
In both forms entry becomes the live current and the run stays open, so
the next within-window edit folds in. Either form clears the redo stack
— a new edit after an undo invalidates redo (TR-012). After pushing a
boundary the bounded ring is trimmed oldest-first by BOTH the count and
byte-size cap (TR-011/TR-024).
Sourcepub fn undo(&mut self) -> Option<UndoEntry<C>>where
C: Clone,
pub fn undo(&mut self) -> Option<UndoEntry<C>>where
C: Clone,
Undo one step: restore the most recent prior boundary (T031).
Pops the newest boundary off the undo ring, pushes the current state
onto redo, makes the popped boundary the new current, and returns it so
the caller can apply its exact-prior source_text/cst/cursor to the
buffer byte-for-byte (no reflow — TR-010/SC-005). Closes any open coalesce
run. Returns None when there is nothing to undo.
Requires C: Clone so the restored boundary can become the new current
and also be returned to the caller (CursorState is Clone).
Sourcepub fn redo(&mut self) -> Option<UndoEntry<C>>where
C: Clone,
pub fn redo(&mut self) -> Option<UndoEntry<C>>where
C: Clone,
Redo one step: replay the most recently undone state (T031).
Pops the newest state off redo, pushes the current state back onto the
undo ring, makes the popped state the new current, and returns it for
the caller to apply exactly (TR-010/SC-005). Closes any open coalesce run.
Returns None when there is nothing to redo.
Requires C: Clone so the replayed state can become the new current
and also be returned to the caller (CursorState is Clone).