Skip to main content

hjkl_buffer/
undo.rs

1//! Undo/redo entry type for per-buffer undo history.
2//!
3//! Lives in `hjkl-buffer` so that [`crate::Buffer`] can own the undo stack
4//! directly, keeping per-buffer state co-located with the rope.
5
6use std::collections::BTreeMap;
7use std::time::SystemTime;
8
9/// A single entry in the undo or redo stack.
10///
11/// The `timestamp` records the wall-clock time at which the snapshot was
12/// taken (i.e. when `push_undo` was called), enabling the `:earlier` /
13/// `:later` time-travel ex commands to walk the stack by duration rather
14/// than by step count.
15///
16/// Stored as a `ropey::Rope` (O(1) Arc-clone) rather than a `String` so
17/// snapshot cost is negligible even on multi-MB buffers.
18#[derive(Debug, Clone)]
19pub struct UndoEntry {
20    pub rope: ropey::Rope,
21    pub cursor: (usize, usize),
22    pub timestamp: SystemTime,
23    /// Local marks / jumplist / changelist / this-buffer's-global-marks
24    /// snapshot, so undo/redo restore mark-ish positions alongside the
25    /// text instead of leaving them shifted by the edit being undone
26    /// (audit-r2 fix 2). `Default::default()` (all empty) for callers
27    /// that don't populate it — restoring an all-empty snapshot is a
28    /// no-op against a freshly-constructed buffer's own empty state, so
29    /// existing fixtures that only care about text/cursor stay valid.
30    pub marks: MarkSnapshot,
31}
32
33/// Buffer-scoped "edit coherence" state snapshotted alongside a
34/// [`UndoEntry`]'s rope so undo/redo can restore marks, not just text.
35///
36/// Positions are plain `(row, col)` (or `(row, col)` values keyed by
37/// mark char) — no buffer-id tagging needed here even for
38/// `global_marks`, because a `MarkSnapshot` always belongs to exactly
39/// one buffer's undo stack; the engine is responsible for reattaching
40/// its own `buffer_id` when writing entries back into the session-global
41/// marks map (see `Editor::restore_marks`).
42#[derive(Debug, Clone, Default, PartialEq, Eq)]
43pub struct MarkSnapshot {
44    /// `ma`-`mz` local marks (`View::marks_cloned`).
45    pub local_marks: BTreeMap<char, (usize, usize)>,
46    /// Back-jumplist (`Ctrl-o` stack), newest at the back.
47    pub jump_back: Vec<(usize, usize)>,
48    /// Forward-jumplist (`Ctrl-i` stack), newest at the back.
49    pub jump_fwd: Vec<(usize, usize)>,
50    /// `` `. ``  / `'.` — position of the most recent change.
51    pub change_last_edit: Option<(usize, usize)>,
52    /// Changelist ring (`g;` / `g,`).
53    pub change_list: Vec<(usize, usize)>,
54    /// Walk cursor into `change_list`; `None` outside a walk.
55    pub change_cursor: Option<usize>,
56    /// `mA`-`mZ` global marks that belong to THIS buffer (bare
57    /// `(row, col)` — the buffer-id is implicit, this buffer).
58    pub global_marks: BTreeMap<char, (usize, usize)>,
59}