Skip to main content

collection_selection_confection/list/
cursor.rs

1use super::LinkedList;
2use super::selection::SelectionMut;
3
4// Not bothering with an immutable cursor for now.
5pub struct CursorMut<'a, T> {
6    list: &'a mut LinkedList<T>,
7    index: usize,
8}
9
10impl<'a, T> CursorMut<'a, T> {
11    pub(super) fn new(list: &'a mut LinkedList<T>, index: usize) -> Self {
12        Self { list, index }
13    }
14
15    /// Converts into an empty selection at the cursor's position.
16    pub fn into_selection(self) -> SelectionMut<'a, T> {
17        SelectionMut::new(self.list, self.index, self.index)
18    }
19
20    /// Moves back one element.
21    ///
22    /// Returns `false`, without moving, if already at the start.
23    pub fn move_prev(&mut self) -> bool {
24        if self.index == 0 {
25            return false;
26        }
27        self.index -= 1;
28        true
29    }
30
31    /// Moves forward one element.
32    ///
33    /// Returns `false`, without moving, if already at the end.
34    pub fn move_next(&mut self) -> bool {
35        if self.index == self.list.items.len() {
36            return false;
37        }
38        self.index += 1;
39        true
40    }
41
42    /// Returns the element just before the cursor.
43    pub fn peek_before(&self) -> Option<&T> {
44        let i = self.index.checked_sub(1)?;
45        self.list.items.get(i)
46    }
47
48    /// Returns the element just after the cursor.
49    pub fn peek_after(&self) -> Option<&T> {
50        self.list.items.get(self.index)
51    }
52
53    pub fn peek_before_mut(&mut self) -> Option<&mut T> {
54        let i = self.index.checked_sub(1)?;
55        self.list.items.get_mut(i)
56    }
57
58    pub fn peek_after_mut(&mut self) -> Option<&mut T> {
59        self.list.items.get_mut(self.index)
60    }
61
62    /// Inserts an element just before the cursor.
63    pub fn insert_before(&mut self, value: T) {
64        self.list.items.insert(self.index, value);
65        self.index += 1;
66    }
67
68    /// Inserts an element just after the cursor.
69    pub fn insert_after(&mut self, value: T) {
70        self.list.items.insert(self.index, value);
71    }
72
73    /// Removes and returns the element just before the cursor.
74    pub fn remove_before(&mut self) -> Option<T> {
75        if self.index == 0 {
76            return None;
77        }
78        self.index -= 1;
79        Some(self.list.items.remove(self.index))
80    }
81
82    /// Removes and returns the element just after the cursor.
83    pub fn remove_after(&mut self) -> Option<T> {
84        if self.index == self.list.items.len() {
85            return None;
86        }
87        Some(self.list.items.remove(self.index))
88    }
89
90    /// Inserts all elements of `other` just before the cursor.
91    pub fn splice_before(&mut self, other: LinkedList<T>) {
92        let len = other.items.len();
93        self.list.items.splice(self.index..self.index, other.items);
94        self.index += len;
95    }
96
97    /// Inserts all elements of `other` just after the cursor.
98    pub fn splice_after(&mut self, other: LinkedList<T>) {
99        self.list.items.splice(self.index..self.index, other.items);
100    }
101
102    /// Splits off and returns all elements before the cursor.
103    pub fn split_before(&mut self) -> LinkedList<T> {
104        let after = self.list.items.split_off(self.index);
105        let before = std::mem::replace(&mut self.list.items, after);
106        self.index = 0;
107        LinkedList { items: before }
108    }
109
110    /// Splits off and returns all elements after the cursor.
111    pub fn split_after(&mut self) -> LinkedList<T> {
112        LinkedList {
113            items: self.list.items.split_off(self.index),
114        }
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use crate::list::tests::list_of;
122
123    #[test]
124    fn insert_before_into_empty() {
125        let mut list = LinkedList::new();
126        list.cursor_mut_at_start().insert_before(1);
127        assert_eq!(list.items, [1]);
128    }
129
130    #[test]
131    fn insert_before_twice_keeps_order() {
132        let mut list = LinkedList::new();
133        let mut cursor = list.cursor_mut_at_start();
134        cursor.insert_before(1);
135        cursor.insert_before(2);
136        assert_eq!(list.items, [1, 2]);
137    }
138
139    #[test]
140    fn insert_after_twice_keeps_order() {
141        let mut list = LinkedList::new();
142        let mut cursor = list.cursor_mut_at_start();
143        cursor.insert_after(2);
144        cursor.insert_after(1);
145        assert_eq!(cursor.peek_before(), None);
146        assert_eq!(cursor.peek_after(), Some(&1));
147        assert_eq!(list.items, [1, 2]);
148    }
149
150    #[test]
151    fn peek_around_cursor() {
152        let mut list = LinkedList::new();
153        list.cursor_mut_at_start().insert_before(1);
154        let mut cursor = list.cursor_mut_at_start();
155        assert_eq!(cursor.peek_before(), None);
156        assert_eq!(cursor.peek_after(), Some(&1));
157        cursor.insert_before(0);
158        assert_eq!(cursor.peek_before(), Some(&0));
159        assert_eq!(cursor.peek_after(), Some(&1));
160    }
161
162    #[test]
163    fn peek_mut_modifies_values() {
164        let mut list = LinkedList::new();
165        list.cursor_mut_at_start().insert_before(1);
166        let mut cursor = list.cursor_mut_at_start();
167        cursor.insert_before(0);
168        *cursor.peek_before_mut().unwrap() += 10;
169        *cursor.peek_after_mut().unwrap() += 20;
170        assert_eq!(list.items, [10, 21]);
171    }
172
173    #[test]
174    fn split_before_takes_elements_before_cursor() {
175        let mut list = LinkedList::new();
176        list.cursor_mut_at_start().insert_before(2);
177        let mut cursor = list.cursor_mut_at_start();
178        cursor.insert_before(0);
179        cursor.insert_before(1);
180        let before = cursor.split_before();
181        assert_eq!(cursor.peek_before(), None);
182        assert_eq!(cursor.peek_after(), Some(&2));
183        assert_eq!(before.items, [0, 1]);
184        assert_eq!(list.items, [2]);
185    }
186
187    #[test]
188    fn split_after_takes_elements_after_cursor() {
189        let mut list = LinkedList::new();
190        list.cursor_mut_at_start().insert_before(2);
191        let mut cursor = list.cursor_mut_at_start();
192        cursor.insert_before(0);
193        cursor.insert_before(1);
194        let after = cursor.split_after();
195        assert_eq!(cursor.peek_before(), Some(&1));
196        assert_eq!(cursor.peek_after(), None);
197        assert_eq!(after.items, [2]);
198        assert_eq!(list.items, [0, 1]);
199    }
200
201    #[test]
202    fn cursor_at_end_peeks_last() {
203        let mut list = list_of(&[0, 1]);
204        let cursor = list.cursor_mut_at_end();
205        assert_eq!(cursor.peek_before(), Some(&1));
206        assert_eq!(cursor.peek_after(), None);
207    }
208
209    #[test]
210    fn move_stops_at_ends() {
211        let mut list = list_of(&[0, 1]);
212        let mut cursor = list.cursor_mut_at_start();
213        assert!(!cursor.move_prev());
214        assert!(cursor.move_next());
215        assert_eq!(cursor.peek_before(), Some(&0));
216        assert_eq!(cursor.peek_after(), Some(&1));
217        assert!(cursor.move_next());
218        assert!(!cursor.move_next());
219        assert_eq!(cursor.peek_before(), Some(&1));
220        assert!(cursor.move_prev());
221        assert_eq!(cursor.peek_after(), Some(&1));
222    }
223
224    #[test]
225    fn remove_on_each_side() {
226        let mut list = list_of(&[0, 1, 2]);
227        let mut cursor = list.cursor_mut_at_start();
228        cursor.move_next();
229        assert_eq!(cursor.remove_before(), Some(0));
230        assert_eq!(cursor.remove_before(), None);
231        assert_eq!(cursor.remove_after(), Some(1));
232        assert_eq!(cursor.peek_after(), Some(&2));
233        assert_eq!(cursor.remove_after(), Some(2));
234        assert_eq!(cursor.remove_after(), None);
235        assert!(list.is_empty());
236    }
237
238    #[test]
239    fn splice_before_puts_cursor_after_spliced() {
240        let mut list = list_of(&[0, 3]);
241        let mut cursor = list.cursor_mut_at_start();
242        cursor.move_next();
243        cursor.splice_before(list_of(&[1, 2]));
244        assert_eq!(cursor.peek_before(), Some(&2));
245        assert_eq!(cursor.peek_after(), Some(&3));
246        assert_eq!(list.items, [0, 1, 2, 3]);
247    }
248
249    #[test]
250    fn splice_after_keeps_cursor_before_spliced() {
251        let mut list = list_of(&[0, 3]);
252        let mut cursor = list.cursor_mut_at_start();
253        cursor.move_next();
254        cursor.splice_after(list_of(&[1, 2]));
255        assert_eq!(cursor.peek_before(), Some(&0));
256        assert_eq!(cursor.peek_after(), Some(&1));
257        assert_eq!(list.items, [0, 1, 2, 3]);
258    }
259}