reedline/core_editor/
edit_stack.rs1#[derive(Debug, PartialEq, Eq)]
2pub struct EditStack<T> {
3 internal_list: Vec<T>,
4 index: usize,
5}
6
7impl<T> EditStack<T> {
8 pub fn new() -> Self
9 where
10 T: Default,
11 {
12 EditStack {
13 internal_list: vec![T::default()],
14 index: 0,
15 }
16 }
17}
18
19impl<T> EditStack<T>
20where
21 T: Default + Clone + Send,
22{
23 pub(super) fn undo(&mut self) -> &T {
25 self.index = if self.index == 0 { 0 } else { self.index - 1 };
26 &self.internal_list[self.index]
27 }
28
29 pub(super) fn redo(&mut self) -> &T {
31 self.index = if self.index == self.internal_list.len() - 1 {
32 self.index
33 } else {
34 self.index + 1
35 };
36 &self.internal_list[self.index]
37 }
38
39 pub(super) fn insert(&mut self, value: T) {
43 if self.index < self.internal_list.len() - 1 {
44 self.internal_list.resize_with(self.index + 1, || {
45 panic!("Impossible state reached: Bug in UndoStack logic")
46 });
47 }
48 self.internal_list.push(value);
49 self.index += 1;
50 }
51
52 pub(super) fn reset(&mut self) {
54 self.index = 0;
55 self.internal_list = vec![T::default()];
56 }
57
58 pub(super) fn current(&mut self) -> &T {
60 &self.internal_list[self.index]
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::*;
67 use pretty_assertions::assert_eq;
68 use rstest::rstest;
69
70 fn edit_stack<T>(values: &[T], index: usize) -> EditStack<T>
71 where
72 T: Clone,
73 {
74 EditStack {
75 internal_list: values.to_vec(),
76 index,
77 }
78 }
79
80 #[rstest]
81 #[case(edit_stack(&[1, 2, 3][..], 2), 2)]
82 #[case(edit_stack(&[1][..], 0), 1)]
83 fn undo_works(#[case] stack: EditStack<isize>, #[case] value_after_undo: isize) {
84 let mut stack = stack;
85
86 let value = stack.undo();
87 assert_eq!(*value, value_after_undo);
88 }
89
90 #[rstest]
91 #[case(edit_stack(&[1, 2, 3][..], 1), 3)]
92 #[case(edit_stack(&[1][..], 0), 1)]
93 fn redo_works(#[case] stack: EditStack<isize>, #[case] value_after_undo: isize) {
94 let mut stack = stack;
95
96 let value = stack.redo();
97 assert_eq!(*value, value_after_undo);
98 }
99
100 #[rstest]
101 #[case(edit_stack(&[1, 2, 3][..], 1), 4, edit_stack(&[1, 2, 4], 2))]
102 #[case(edit_stack(&[1, 2, 3][..], 2), 3, edit_stack(&[1, 2, 3, 3], 3))]
103 fn insert_works(
104 #[case] old_stack: EditStack<isize>,
105 #[case] value_to_insert: isize,
106 #[case] expected_stack: EditStack<isize>,
107 ) {
108 let mut stack = old_stack;
109
110 stack.insert(value_to_insert);
111 assert_eq!(stack, expected_stack);
112 }
113}