Skip to main content

revue/widget/input_widgets/textarea/
undo.rs

1//! Undo/redo methods for TextArea
2
3use super::edit::EditOperation;
4
5impl TextArea {
6    /// Undo the last operation
7    pub fn undo(&mut self) {
8        if let Some(op) = self.undo_stack.pop() {
9            match &op {
10                EditOperation::Insert { line, col, text } => {
11                    if let Some(l) = self.lines.get_mut(*line) {
12                        let end = (*col + text.len()).min(l.len());
13                        l.drain(*col..end);
14                    }
15                    self.set_primary_cursor(*line, *col);
16                }
17                EditOperation::Delete { line, col, text } => {
18                    if let Some(l) = self.lines.get_mut(*line) {
19                        l.insert_str(*col, text);
20                    }
21                    self.set_primary_cursor(*line, *col + text.len());
22                }
23                EditOperation::InsertLine { line, .. } => {
24                    if *line < self.lines.len() {
25                        self.lines.remove(*line);
26                    }
27                    self.set_primary_cursor(line.saturating_sub(1), 0);
28                }
29                EditOperation::DeleteLine { line, content } => {
30                    self.lines.insert(*line, content.clone());
31                    self.set_primary_cursor(*line, 0);
32                }
33                EditOperation::SplitLine { line, col } => {
34                    // Merge lines back
35                    if *line + 1 < self.lines.len() {
36                        let next = self.lines.remove(*line + 1);
37                        if let Some(l) = self.lines.get_mut(*line) {
38                            l.push_str(&next);
39                        }
40                    }
41                    self.set_primary_cursor(*line, *col);
42                }
43                EditOperation::MergeLines { line, col } => {
44                    // Split line again
45                    if let Some(l) = self.lines.get_mut(*line) {
46                        let rest: String = l.drain(*col..).collect();
47                        self.lines.insert(*line + 1, rest);
48                    }
49                    self.set_primary_cursor(*line + 1, 0);
50                }
51            }
52            self.redo_stack.push(op);
53        }
54    }
55
56    /// Redo the last undone operation
57    pub fn redo(&mut self) {
58        if let Some(op) = self.redo_stack.pop() {
59            match &op {
60                EditOperation::Insert { line, col, text } => {
61                    if let Some(l) = self.lines.get_mut(*line) {
62                        l.insert_str(*col, text);
63                    }
64                    self.set_primary_cursor(*line, *col + text.len());
65                }
66                EditOperation::Delete { line, col, text } => {
67                    if let Some(l) = self.lines.get_mut(*line) {
68                        let end = (*col + text.len()).min(l.len());
69                        l.drain(*col..end);
70                    }
71                    self.set_primary_cursor(*line, *col);
72                }
73                EditOperation::InsertLine { line, content } => {
74                    self.lines.insert(*line, content.clone());
75                    self.set_primary_cursor(*line, 0);
76                }
77                EditOperation::DeleteLine { line, .. } => {
78                    if *line < self.lines.len() {
79                        self.lines.remove(*line);
80                    }
81                    let new_line = *line.min(&self.lines.len().saturating_sub(1));
82                    self.set_primary_cursor(new_line, 0);
83                }
84                EditOperation::SplitLine { line, col } => {
85                    if let Some(l) = self.lines.get_mut(*line) {
86                        let rest: String = l.drain(*col..).collect();
87                        self.lines.insert(*line + 1, rest);
88                    }
89                    self.set_primary_cursor(*line + 1, 0);
90                }
91                EditOperation::MergeLines { line, col } => {
92                    if *line + 1 < self.lines.len() {
93                        let next = self.lines.remove(*line + 1);
94                        if let Some(l) = self.lines.get_mut(*line) {
95                            l.push_str(&next);
96                        }
97                    }
98                    self.set_primary_cursor(*line, *col);
99                }
100            }
101            self.undo_stack.push(op);
102        }
103    }
104}
105
106use super::TextArea;