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}