pub struct UndoTree { /* private fields */ }Expand description
Undo tree with branching support.
Unlike a simple undo stack, an undo tree preserves all history. When you undo and then make new changes, a new branch is created rather than discarding the undone changes.
§Vim Comparison
This is similar to vim’s :undotree feature. The g- and g+
commands traverse changes in time order (seq_num), while u and
Ctrl-R traverse the tree structure.
§Memory Management
The tree has a configurable maximum number of nodes. When exceeded, the oldest nodes are pruned (but the path from root to current is always preserved).
Implementations§
Source§impl UndoTree
impl UndoTree
Sourcepub const DEFAULT_MAX_NODES: usize = 10000
pub const DEFAULT_MAX_NODES: usize = 10000
Default maximum number of nodes.
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new undo tree.
The tree starts with a root node representing the initial state.
Sourcepub fn with_max_nodes(max_nodes: usize) -> Self
pub fn with_max_nodes(max_nodes: usize) -> Self
Create a new undo tree with custom maximum nodes.
Sourcepub fn push(
&mut self,
edits: Vec<Edit>,
cursor_before: Position,
cursor_after: Position,
)
pub fn push( &mut self, edits: Vec<Edit>, cursor_before: Position, cursor_after: Position, )
Push a new change onto the tree with system origin.
Creates a new node as a child of the current node. If the current node already has children (we’re in the middle of the tree after an undo), this creates a new branch.
This is equivalent to push_with_origin(edits, cursor_before, cursor_after, EditOrigin::System).
Sourcepub fn push_with_origin(
&mut self,
edits: Vec<Edit>,
cursor_before: Position,
cursor_after: Position,
origin: EditOrigin,
)
pub fn push_with_origin( &mut self, edits: Vec<Edit>, cursor_before: Position, cursor_after: Position, origin: EditOrigin, )
Push a new change onto the tree with specified origin.
Creates a new node as a child of the current node, tagged with the specified origin. This enables per-client undo where each client can undo only their own changes.
If the current node already has children (we’re in the middle of the tree after an undo), this creates a new branch.
Sourcepub fn undo(&mut self) -> Option<UndoResult>
pub fn undo(&mut self) -> Option<UndoResult>
Undo the current change.
Moves to the parent node and returns the inverse edits along with the cursor position to restore.
Returns None if at the root (nothing to undo).
Sourcepub fn redo(&mut self) -> Option<UndoResult>
pub fn redo(&mut self) -> Option<UndoResult>
Redo the last undone change.
Moves to the first child node (or the active branch) and returns the edits along with cursor position to restore.
Returns None if there’s nothing to redo.
Sourcepub fn redo_branch(&mut self, branch_idx: usize) -> Option<UndoResult>
pub fn redo_branch(&mut self, branch_idx: usize) -> Option<UndoResult>
Redo a specific branch.
Like redo() but follows a specific branch index.
Sourcepub fn branches(&self) -> &[usize]
pub fn branches(&self) -> &[usize]
Get the available branches (children) from current node.
Returns indices that can be passed to redo_branch().
Sourcepub fn switch_branch(&mut self, branch_idx: usize) -> bool
pub fn switch_branch(&mut self, branch_idx: usize) -> bool
Switch the active branch at current node.
This affects which branch redo() will follow.
Returns false if the branch index is invalid.
Sourcepub fn current_node(&self) -> &UndoNode
pub fn current_node(&self) -> &UndoNode
Get the current node.
Sourcepub const fn current_index(&self) -> usize
pub const fn current_index(&self) -> usize
Get the current node index.
Sourcepub const fn node_count(&self) -> usize
pub const fn node_count(&self) -> usize
Get total number of nodes in the tree.
Sourcepub fn node(&self, index: usize) -> Option<&UndoNode>
pub fn node(&self, index: usize) -> Option<&UndoNode>
Get node by index.
Returns None if index is out of bounds.
Sourcepub const fn node_indices(&self) -> Range<usize>
pub const fn node_indices(&self) -> Range<usize>
Get all node indices for iteration.
Returns a range that can be used to iterate over all valid node indices.
Sourcepub fn active_branch_at(&self, node_index: usize) -> Option<usize>
pub fn active_branch_at(&self, node_index: usize) -> Option<usize>
Get active branch index at a node.
Returns the preferred child index that redo() would follow
from the specified node. Returns None if the node doesn’t exist
or has no active branch set.
Sourcepub fn set_max_nodes(&mut self, max: usize)
pub fn set_max_nodes(&mut self, max: usize)
Set the maximum nodes limit.
Sourcepub const fn seq_counter(&self) -> u64
pub const fn seq_counter(&self) -> u64
Get the current sequential change number.
Sourcepub fn edits_since(&self, from_idx: usize) -> Option<Vec<&Edit>>
pub fn edits_since(&self, from_idx: usize) -> Option<Vec<&Edit>>
Collect all edits applied between a node and the current head.
Walks from the current position back to from_idx via parent links,
collecting all edits from intermediate nodes in forward (application)
order. The edits from the from_idx node itself are NOT included.
Returns Some(empty_vec) if from_idx is the current position.
Returns None if from_idx is not an ancestor of the current position
or is out of bounds.
Sourcepub fn from_serializable(
nodes_data: Vec<(Vec<Edit>, Position, Position, Duration, Option<usize>, Vec<usize>, u64, EditOrigin)>,
current: usize,
seq_counter: u64,
max_nodes: usize,
active_branches: Vec<usize>,
) -> Self
pub fn from_serializable( nodes_data: Vec<(Vec<Edit>, Position, Position, Duration, Option<usize>, Vec<usize>, u64, EditOrigin)>, current: usize, seq_counter: u64, max_nodes: usize, active_branches: Vec<usize>, ) -> Self
Reconstruct an UndoTree from serialized data.
This is used by the persistence layer to restore undo history from disk. Timestamps are reconstructed relative to “now” using the provided durations.
§Arguments
nodes_data- Vector of tuples containing node data:Vec<Edit>: The edits in this nodePosition: Cursor before editsPosition: Cursor after editsDuration: Relative time from tree creationOption<usize>: Parent node indexVec<usize>: Child node indicesu64: Sequential change numberEditOrigin: Origin of this edit
current- Index of current position in treeseq_counter- Current sequential change countermax_nodes- Maximum nodes to retainactive_branches- Preferred branch at each node
§Panics
Panics if nodes_data is empty (tree must have at least a root node).