liner/
buffer.rs

1use std::fmt::{self, Write as FmtWrite};
2use std::io::{self, Write};
3use std::iter::FromIterator;
4use unicode_width::UnicodeWidthStr;
5
6/// A modification performed on a `Buffer`. These are used for the purpose of undo/redo.
7#[derive(Debug, Clone)]
8pub enum Action {
9    Insert { start: usize, text: Vec<char> },
10    Remove { start: usize, text: Vec<char> },
11    StartGroup,
12    EndGroup,
13}
14
15impl Action {
16    pub fn do_on(&self, buf: &mut Buffer) {
17        match *self {
18            Action::Insert { start, ref text } => buf.insert_raw(start, &text[..]),
19            Action::Remove { start, ref text } => {
20                buf.remove_raw(start, start + text.len());
21            }
22            Action::StartGroup | Action::EndGroup => {}
23        }
24    }
25
26    pub fn undo(&self, buf: &mut Buffer) {
27        match *self {
28            Action::Insert { start, ref text } => {
29                buf.remove_raw(start, start + text.len());
30            }
31            Action::Remove { start, ref text } => buf.insert_raw(start, &text[..]),
32            Action::StartGroup | Action::EndGroup => {}
33        }
34    }
35}
36
37/// A buffer for text in the line editor.
38///
39/// It keeps track of each action performed on it for use with undo/redo.
40#[derive(Debug, Clone)]
41pub struct Buffer {
42    data: Vec<char>,
43    actions: Vec<Action>,
44    undone_actions: Vec<Action>,
45}
46
47impl PartialEq for Buffer {
48    fn eq(&self, other: &Self) -> bool {
49        self.data == other.data
50    }
51}
52impl Eq for Buffer {}
53
54impl From<Buffer> for String {
55    fn from(buf: Buffer) -> Self {
56        String::from_iter(buf.data)
57    }
58}
59
60impl From<String> for Buffer {
61    fn from(s: String) -> Self {
62        Buffer::from_iter(s.chars())
63    }
64}
65
66impl<'a> From<&'a str> for Buffer {
67    fn from(s: &'a str) -> Self {
68        Buffer::from_iter(s.chars())
69    }
70}
71
72impl fmt::Display for Buffer {
73    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74        for &c in &self.data {
75            f.write_char(c)?;
76        }
77        Ok(())
78    }
79}
80
81impl FromIterator<char> for Buffer {
82    fn from_iter<T: IntoIterator<Item = char>>(t: T) -> Self {
83        Buffer {
84            data: t.into_iter().collect(),
85            actions: Vec::new(),
86            undone_actions: Vec::new(),
87        }
88    }
89}
90
91impl Default for Buffer {
92    fn default() -> Self {
93        Self::new()
94    }
95}
96
97impl Buffer {
98    pub fn new() -> Self {
99        Buffer {
100            data: Vec::new(),
101            actions: Vec::new(),
102            undone_actions: Vec::new(),
103        }
104    }
105
106    pub fn clear_actions(&mut self) {
107        self.actions.clear();
108        self.undone_actions.clear();
109    }
110
111    pub fn start_undo_group(&mut self) {
112        self.actions.push(Action::StartGroup);
113    }
114
115    pub fn end_undo_group(&mut self) {
116        self.actions.push(Action::EndGroup);
117    }
118
119    pub fn undo(&mut self) -> bool {
120        use Action::*;
121
122        let did = !self.actions.is_empty();
123        let mut group_nest = 0;
124        let mut group_count = 0;
125        while let Some(act) = self.actions.pop() {
126            act.undo(self);
127            self.undone_actions.push(act.clone());
128            match act {
129                EndGroup => {
130                    group_nest += 1;
131                    group_count = 0;
132                }
133                StartGroup => group_nest -= 1,
134                // count the actions in this group so we can ignore empty groups below
135                _ => group_count += 1,
136            }
137
138            // if we aren't in a group, and the last group wasn't empty
139            if group_nest == 0 && group_count > 0 {
140                break;
141            }
142        }
143        did
144    }
145
146    pub fn redo(&mut self) -> bool {
147        use Action::*;
148
149        let did = !self.undone_actions.is_empty();
150        let mut group_nest = 0;
151        let mut group_count = 0;
152        while let Some(act) = self.undone_actions.pop() {
153            act.do_on(self);
154            self.actions.push(act.clone());
155            match act {
156                StartGroup => {
157                    group_nest += 1;
158                    group_count = 0;
159                }
160                EndGroup => group_nest -= 1,
161                // count the actions in this group so we can ignore empty groups below
162                _ => group_count += 1,
163            }
164
165            // if we aren't in a group, and the last group wasn't empty
166            if group_nest == 0 && group_count > 0 {
167                break;
168            }
169        }
170        did
171    }
172
173    pub fn revert(&mut self) -> bool {
174        if self.actions.is_empty() {
175            return false;
176        }
177
178        while self.undo() {}
179        true
180    }
181
182    fn push_action(&mut self, act: Action) {
183        self.actions.push(act);
184        self.undone_actions.clear();
185    }
186
187    pub fn last_arg(&self) -> Option<&[char]> {
188        self.data
189            .split(|&c| c == ' ')
190            .filter(|s| !s.is_empty())
191            .last()
192    }
193
194    pub fn num_chars(&self) -> usize {
195        self.data.len()
196    }
197
198    pub fn num_bytes(&self) -> usize {
199        let s: String = self.clone().into();
200        s.len()
201    }
202
203    pub fn char_before(&self, cursor: usize) -> Option<char> {
204        if cursor == 0 {
205            None
206        } else {
207            self.data.get(cursor - 1).cloned()
208        }
209    }
210
211    pub fn char_after(&self, cursor: usize) -> Option<char> {
212        self.data.get(cursor).cloned()
213    }
214
215    /// Returns the number of characters removed.
216    pub fn remove(&mut self, start: usize, end: usize) -> usize {
217        let s = self.remove_raw(start, end);
218        let num_removed = s.len();
219        self.push_action(Action::Remove { start, text: s });
220        num_removed
221    }
222
223    pub fn insert(&mut self, start: usize, text: &[char]) {
224        let act = Action::Insert {
225            start,
226            text: text.into(),
227        };
228        act.do_on(self);
229        self.push_action(act);
230    }
231
232    // XXX rename, too confusing
233    pub fn insert_from_buffer(&mut self, other: &Buffer) {
234        let start = self.data.len();
235        self.insert(start, &other.data[start..])
236    }
237
238    pub fn copy_buffer(&mut self, other: &Buffer) {
239        let data_len = self.data.len();
240        self.remove(0, data_len);
241        self.insert(0, &other.data[0..])
242    }
243
244    pub fn range(&self, start: usize, end: usize) -> String {
245        self.data[start..end].iter().cloned().collect()
246    }
247
248    pub fn range_chars(&self, start: usize, end: usize) -> Vec<char> {
249        self.data[start..end].to_owned()
250    }
251
252    pub fn width(&self) -> Vec<usize> {
253        self.range_width(0, self.num_chars())
254    }
255
256    pub fn range_width(&self, start: usize, end: usize) -> Vec<usize> {
257        self.range(start, end)
258            .split('\n')
259            .map(|s| s.width())
260            .collect()
261    }
262
263    pub fn lines(&self) -> Vec<String> {
264        self.data
265            .split(|&c| c == '\n')
266            .map(|s| s.iter().cloned().collect())
267            .collect()
268    }
269
270    pub fn chars(&self) -> ::std::slice::Iter<char> {
271        self.data.iter()
272    }
273
274    pub fn truncate(&mut self, num: usize) {
275        let end = self.data.len();
276        self.remove(num, end);
277    }
278
279    pub fn print<W>(&self, out: &mut W) -> io::Result<()>
280    where
281        W: Write,
282    {
283        let string: String = self.data.iter().cloned().collect();
284        out.write_all(string.as_bytes())
285    }
286
287    pub fn as_bytes(&self) -> Vec<u8> {
288        // NOTE: not particularly efficient. Could make a proper byte iterator with minimal
289        // allocations if performance becomes an issue.
290        self.to_string().into_bytes()
291    }
292
293    /// Takes other buffer, measures its length and prints this buffer from the point where
294    /// the other stopped.
295    /// Used to implement autosuggestions.
296    pub fn print_rest<W>(&self, out: &mut W, after: usize) -> io::Result<usize>
297    where
298        W: Write,
299    {
300        let string: String = self.data.iter().skip(after).cloned().collect();
301        out.write_all(string.as_bytes())?;
302
303        Ok(string.len())
304    }
305
306    fn remove_raw(&mut self, start: usize, end: usize) -> Vec<char> {
307        self.data.drain(start..end).collect()
308    }
309
310    fn insert_raw(&mut self, start: usize, text: &[char]) {
311        for (i, &c) in text.iter().enumerate() {
312            self.data.insert(start + i, c)
313        }
314    }
315
316    /// Check if the other buffer starts with the same content as this one.
317    /// Used to implement autosuggestions.
318    pub fn starts_with(&self, other: &Buffer) -> bool {
319        let other_len = other.data.len();
320        let self_len = self.data.len();
321        if !other.data.is_empty() && self_len != other_len {
322            let match_let = self
323                .data
324                .iter()
325                .zip(&other.data)
326                .take_while(|&(s, o)| *s == *o)
327                .count();
328            match_let == other_len
329        } else {
330            false
331        }
332    }
333
334    /// Check if the buffer contains pattern.
335    /// Used to implement history search.
336    pub fn contains(&self, pattern: &Buffer) -> bool {
337        let search_term: &[char] = &pattern.data;
338        if search_term.is_empty() {
339            return false;
340        }
341        self.data
342            .windows(search_term.len())
343            .any(|window| window == search_term)
344    }
345
346    /// Return true if the buffer is empty.
347    pub fn is_empty(&self) -> bool {
348        self.data.is_empty()
349    }
350}
351
352#[cfg(test)]
353mod tests {
354    use super::*;
355
356    #[test]
357    fn test_insert() {
358        let mut buf = Buffer::new();
359        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
360        assert_eq!(String::from(buf), "abcdefg");
361    }
362
363    #[test]
364    fn test_truncate_empty() {
365        let mut buf = Buffer::new();
366        buf.truncate(0);
367        assert_eq!(String::from(buf), "");
368    }
369
370    #[test]
371    fn test_truncate_all() {
372        let mut buf = Buffer::new();
373        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
374        buf.truncate(0);
375        assert_eq!(String::from(buf), "");
376    }
377
378    #[test]
379    fn test_truncate_end() {
380        let mut buf = Buffer::new();
381        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
382        let end = buf.num_chars();
383        buf.truncate(end);
384        assert_eq!(String::from(buf), "abcdefg");
385    }
386
387    #[test]
388    fn test_truncate_part() {
389        let mut buf = Buffer::new();
390        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
391        buf.truncate(3);
392        assert_eq!(String::from(buf), "abc");
393    }
394
395    #[test]
396    fn test_truncate_empty_undo() {
397        let mut buf = Buffer::new();
398        buf.truncate(0);
399        buf.undo();
400        assert_eq!(String::from(buf), "");
401    }
402
403    #[test]
404    fn test_truncate_all_then_undo() {
405        let mut buf = Buffer::new();
406        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
407        buf.truncate(0);
408        buf.undo();
409        assert_eq!(String::from(buf), "abcdefg");
410    }
411
412    #[test]
413    fn test_truncate_end_then_undo() {
414        let mut buf = Buffer::new();
415        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
416        let end = buf.num_chars();
417        buf.truncate(end);
418        buf.undo();
419        assert_eq!(String::from(buf), "abcdefg");
420    }
421
422    #[test]
423    fn test_truncate_part_then_undo() {
424        let mut buf = Buffer::new();
425        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
426        buf.truncate(3);
427        buf.undo();
428        assert_eq!(String::from(buf), "abcdefg");
429    }
430
431    #[test]
432    fn test_undo_group() {
433        let mut buf = Buffer::new();
434        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
435        buf.start_undo_group();
436        buf.remove(0, 1);
437        buf.remove(0, 1);
438        buf.remove(0, 1);
439        buf.end_undo_group();
440        assert_eq!(buf.undo(), true);
441        assert_eq!(String::from(buf), "abcdefg");
442    }
443
444    #[test]
445    fn test_redo_group() {
446        let mut buf = Buffer::new();
447        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
448        buf.start_undo_group();
449        buf.remove(0, 1);
450        buf.remove(0, 1);
451        buf.remove(0, 1);
452        buf.end_undo_group();
453        assert_eq!(buf.undo(), true);
454        assert_eq!(buf.redo(), true);
455        assert_eq!(String::from(buf), "defg");
456    }
457
458    #[test]
459    fn test_nested_undo_group() {
460        let mut buf = Buffer::new();
461        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
462        buf.start_undo_group();
463        buf.remove(0, 1);
464        buf.start_undo_group();
465        buf.remove(0, 1);
466        buf.end_undo_group();
467        buf.remove(0, 1);
468        buf.end_undo_group();
469        assert_eq!(buf.undo(), true);
470        assert_eq!(String::from(buf), "abcdefg");
471    }
472
473    #[test]
474    fn test_nested_redo_group() {
475        let mut buf = Buffer::new();
476        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
477        buf.start_undo_group();
478        buf.remove(0, 1);
479        buf.start_undo_group();
480        buf.remove(0, 1);
481        buf.end_undo_group();
482        buf.remove(0, 1);
483        buf.end_undo_group();
484        assert_eq!(buf.undo(), true);
485        assert_eq!(buf.redo(), true);
486        assert_eq!(String::from(buf), "defg");
487    }
488
489    #[test]
490    fn test_starts_with() {
491        let mut buf = Buffer::new();
492        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
493        let mut buf2 = Buffer::new();
494        buf2.insert(0, &['a', 'b', 'c']);
495        assert_eq!(buf.starts_with(&buf2), true);
496    }
497
498    #[test]
499    fn test_does_not_start_with() {
500        let mut buf = Buffer::new();
501        buf.insert(0, &['a', 'b', 'c']);
502        let mut buf2 = Buffer::new();
503        buf2.insert(0, &['a', 'b', 'c']);
504        assert_eq!(buf.starts_with(&buf2), false);
505    }
506
507    #[test]
508    fn test_is_not_match2() {
509        let mut buf = Buffer::new();
510        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
511        let mut buf2 = Buffer::new();
512        buf2.insert(0, &['x', 'y', 'z']);
513        assert_eq!(buf.starts_with(&buf2), false);
514    }
515
516    #[test]
517    fn test_contains() {
518        let mut buf = Buffer::new();
519        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
520        let mut buf2 = Buffer::new();
521        buf2.insert(0, &['a', 'b', 'c']);
522        assert_eq!(buf.contains(&buf2), true);
523        let mut buf2 = Buffer::new();
524        buf2.insert(0, &['c', 'd', 'e']);
525        assert_eq!(buf.contains(&buf2), true);
526        let mut buf2 = Buffer::new();
527        buf2.insert(0, &['e', 'f', 'g']);
528        assert_eq!(buf.contains(&buf2), true);
529    }
530
531    #[test]
532    fn test_does_not_contain() {
533        let mut buf = Buffer::new();
534        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
535        let mut buf2 = Buffer::new();
536        buf2.insert(0, &['x', 'b', 'c']);
537        assert_eq!(buf.contains(&buf2), false);
538        let mut buf2 = Buffer::new();
539        buf2.insert(0, &['a', 'b', 'd']);
540        assert_eq!(buf.contains(&buf2), false);
541    }
542
543    #[test]
544    fn test_print_rest() {
545        let mut buf = Buffer::new();
546        buf.insert(0, &['a', 'b', 'c', 'd', 'e', 'f', 'g']);
547        let mut buf2 = Buffer::new();
548        buf2.insert(0, &['a', 'b', 'c']);
549        let mut out: Vec<u8> = vec![];
550        buf.print_rest(&mut out, buf2.data.len()).unwrap();
551        assert_eq!(out.len(), 4);
552    }
553}