Skip to main content

reovim_kernel/block/
history.rs

1//! Change history log.
2//!
3//! Provides a linear log of all changes with timestamps,
4//! useful for debugging and change tracking.
5
6use {crate::mm::Edit, std::time::Instant};
7
8/// An entry in the change history.
9#[derive(Debug, Clone)]
10pub struct HistoryEntry {
11    /// Edits that were made.
12    edits: Vec<Edit>,
13    /// When the change occurred.
14    timestamp: Instant,
15    /// Sequential change number.
16    seq_num: u64,
17}
18
19impl HistoryEntry {
20    /// Get the edits in this entry.
21    #[must_use]
22    pub fn edits(&self) -> &[Edit] {
23        &self.edits
24    }
25
26    /// Get when this change occurred.
27    #[must_use]
28    pub const fn timestamp(&self) -> Instant {
29        self.timestamp
30    }
31
32    /// Get the sequential change number.
33    #[must_use]
34    pub const fn seq_num(&self) -> u64 {
35        self.seq_num
36    }
37}
38
39/// Change history log.
40///
41/// Records all changes made to a buffer in chronological order.
42/// Unlike `UndoTree`, this is a simple linear log without branching.
43///
44/// # Use Cases
45///
46/// - Debugging: See what changes were made and when
47/// - Auditing: Track modification history
48/// - Collaboration: Synchronize changes between editors
49///
50/// # Memory Management
51///
52/// The history has a configurable maximum number of entries.
53/// When exceeded, the oldest entries are removed.
54#[derive(Debug)]
55pub struct History {
56    /// All recorded entries.
57    entries: Vec<HistoryEntry>,
58    /// Maximum number of entries to retain.
59    max_entries: usize,
60    /// Sequential change counter.
61    seq_counter: u64,
62}
63
64impl Default for History {
65    fn default() -> Self {
66        Self::new()
67    }
68}
69
70impl History {
71    /// Default maximum number of entries.
72    pub const DEFAULT_MAX_ENTRIES: usize = 10000;
73
74    /// Create a new empty history.
75    #[must_use]
76    pub fn new() -> Self {
77        Self::with_max_entries(Self::DEFAULT_MAX_ENTRIES)
78    }
79
80    /// Create a new history with custom maximum entries.
81    #[must_use]
82    pub fn with_max_entries(max_entries: usize) -> Self {
83        Self {
84            entries: Vec::new(),
85            max_entries: max_entries.max(1),
86            seq_counter: 0,
87        }
88    }
89
90    /// Record a new change.
91    pub fn record(&mut self, edits: Vec<Edit>) {
92        if edits.is_empty() {
93            return;
94        }
95
96        self.seq_counter += 1;
97
98        let entry = HistoryEntry {
99            edits,
100            timestamp: Instant::now(),
101            seq_num: self.seq_counter,
102        };
103
104        self.entries.push(entry);
105
106        // Trim if over limit
107        while self.entries.len() > self.max_entries {
108            self.entries.remove(0);
109        }
110    }
111
112    /// Get all entries in chronological order.
113    #[must_use]
114    pub fn entries(&self) -> &[HistoryEntry] {
115        &self.entries
116    }
117
118    /// Get the most recent entry.
119    #[must_use]
120    pub fn last(&self) -> Option<&HistoryEntry> {
121        self.entries.last()
122    }
123
124    /// Get an entry by index.
125    #[must_use]
126    pub fn get(&self, index: usize) -> Option<&HistoryEntry> {
127        self.entries.get(index)
128    }
129
130    /// Clear all history.
131    pub fn clear(&mut self) {
132        self.entries.clear();
133        // Note: seq_counter is not reset to maintain uniqueness
134    }
135
136    /// Get the number of entries.
137    #[must_use]
138    pub const fn len(&self) -> usize {
139        self.entries.len()
140    }
141
142    /// Check if history is empty.
143    #[must_use]
144    pub const fn is_empty(&self) -> bool {
145        self.entries.is_empty()
146    }
147
148    /// Get the maximum entries limit.
149    #[must_use]
150    pub const fn max_entries(&self) -> usize {
151        self.max_entries
152    }
153
154    /// Set the maximum entries limit.
155    pub fn set_max_entries(&mut self, max: usize) {
156        self.max_entries = max.max(1);
157        while self.entries.len() > self.max_entries {
158            self.entries.remove(0);
159        }
160    }
161
162    /// Get the current sequential counter value.
163    #[must_use]
164    pub const fn seq_counter(&self) -> u64 {
165        self.seq_counter
166    }
167
168    /// Get entries since a given sequence number.
169    #[must_use]
170    pub fn since(&self, seq_num: u64) -> Vec<&HistoryEntry> {
171        self.entries
172            .iter()
173            .filter(|e| e.seq_num > seq_num)
174            .collect()
175    }
176
177    /// Get entries within a time range.
178    #[must_use]
179    pub fn between(&self, start: Instant, end: Instant) -> Vec<&HistoryEntry> {
180        self.entries
181            .iter()
182            .filter(|e| e.timestamp >= start && e.timestamp <= end)
183            .collect()
184    }
185}