Skip to main content

reovim_kernel/block/
transaction.rs

1//! Transaction for grouping edits.
2//!
3//! A transaction groups multiple edits together so they can be
4//! undone/redone as a single unit.
5
6use crate::mm::Edit;
7
8/// A transaction groups multiple edits for atomic undo/redo.
9///
10/// When a transaction is undone, all its edits are reversed in reverse order.
11/// When redone, all edits are applied in original order.
12///
13/// # Example
14///
15/// ```
16/// use reovim_kernel::api::v1::*;
17///
18/// let mut txn = Transaction::new();
19/// txn.push(Edit::insert(Position::new(0, 0), "Hello"));
20/// txn.push(Edit::insert(Position::new(0, 5), " World"));
21///
22/// assert_eq!(txn.len(), 2);
23/// assert!(!txn.is_empty());
24///
25/// // Get inverse for undo
26/// let inverse = txn.inverse();
27/// assert_eq!(inverse.len(), 2);
28/// // Inverse edits are in reverse order
29/// ```
30#[derive(Debug, Clone, Default)]
31pub struct Transaction {
32    /// Edits in this transaction (in order applied).
33    edits: Vec<Edit>,
34}
35
36impl Transaction {
37    /// Create a new empty transaction.
38    #[must_use]
39    pub const fn new() -> Self {
40        Self { edits: Vec::new() }
41    }
42
43    /// Returns an iterator over the edits.
44    pub fn iter(&self) -> std::slice::Iter<'_, Edit> {
45        self.edits.iter()
46    }
47
48    /// Create a transaction with pre-allocated capacity.
49    #[must_use]
50    pub fn with_capacity(capacity: usize) -> Self {
51        Self {
52            edits: Vec::with_capacity(capacity),
53        }
54    }
55
56    /// Add an edit to this transaction.
57    pub fn push(&mut self, edit: Edit) {
58        self.edits.push(edit);
59    }
60
61    /// Get all edits in this transaction.
62    #[must_use]
63    pub fn edits(&self) -> &[Edit] {
64        &self.edits
65    }
66
67    /// Consume the transaction and return the edits.
68    #[must_use]
69    pub fn into_edits(self) -> Vec<Edit> {
70        self.edits
71    }
72
73    /// Check if this transaction has no edits.
74    #[must_use]
75    pub const fn is_empty(&self) -> bool {
76        self.edits.is_empty()
77    }
78
79    /// Get the number of edits in this transaction.
80    #[must_use]
81    pub const fn len(&self) -> usize {
82        self.edits.len()
83    }
84
85    /// Create the inverse of this transaction (for undo).
86    ///
87    /// The inverse contains the inverse of each edit, in reverse order.
88    /// Applying the inverse undoes the original transaction.
89    #[must_use]
90    pub fn inverse(&self) -> Self {
91        Self {
92            edits: self.edits.iter().rev().map(Edit::inverse).collect(),
93        }
94    }
95
96    /// Clear all edits from this transaction.
97    pub fn clear(&mut self) {
98        self.edits.clear();
99    }
100}
101
102impl From<Vec<Edit>> for Transaction {
103    fn from(edits: Vec<Edit>) -> Self {
104        Self { edits }
105    }
106}
107
108impl From<Edit> for Transaction {
109    fn from(edit: Edit) -> Self {
110        Self { edits: vec![edit] }
111    }
112}
113
114impl IntoIterator for Transaction {
115    type Item = Edit;
116    type IntoIter = std::vec::IntoIter<Edit>;
117
118    fn into_iter(self) -> Self::IntoIter {
119        self.edits.into_iter()
120    }
121}
122
123impl<'a> IntoIterator for &'a Transaction {
124    type Item = &'a Edit;
125    type IntoIter = std::slice::Iter<'a, Edit>;
126
127    fn into_iter(self) -> Self::IntoIter {
128        self.edits.iter()
129    }
130}