datafusion_rustyline/
line_buffer.rs

1//! Line buffer with current cursor position
2use keymap::{At, CharSearch, Movement, RepeatCount, Word};
3use std::cell::RefCell;
4use std::fmt;
5use std::iter;
6use std::ops::{Deref, Index, Range};
7use std::rc::Rc;
8use std::string::Drain;
9use std::sync::{Arc, Mutex};
10use unicode_segmentation::UnicodeSegmentation;
11
12/// Maximum buffer size for the line read
13pub(crate) static MAX_LINE: usize = 4096;
14
15/// Word's case change
16#[derive(Clone, Copy)]
17pub enum WordAction {
18    CAPITALIZE,
19    LOWERCASE,
20    UPPERCASE,
21}
22
23/// Delete (kill) direction
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub(crate) enum Direction {
26    Forward,
27    Backward,
28}
29
30impl Default for Direction {
31    fn default() -> Direction {
32        Direction::Forward
33    }
34}
35
36/// Listener to be notified when some text is deleted.
37pub(crate) trait DeleteListener {
38    fn start_killing(&mut self);
39    fn delete(&mut self, idx: usize, string: &str, dir: Direction);
40    fn stop_killing(&mut self);
41}
42
43/// Listener to be notified when the line is modified.
44pub(crate) trait ChangeListener: DeleteListener {
45    fn insert_char(&mut self, idx: usize, c: char);
46    fn insert_str(&mut self, idx: usize, string: &str);
47    fn replace(&mut self, idx: usize, old: &str, new: &str);
48}
49
50/// Represent the current input (text and cursor position).
51///
52/// The methods do text manipulations or/and cursor movements.
53pub struct LineBuffer {
54    buf: String, // Edited line buffer (rl_line_buffer)
55    pos: usize,  // Current cursor position (byte position) (rl_point)
56    dl: Option<Arc<Mutex<DeleteListener>>>,
57    cl: Option<Rc<RefCell<ChangeListener>>>,
58}
59
60impl fmt::Debug for LineBuffer {
61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62        f.debug_struct("LineBuffer")
63            .field("buf", &self.buf)
64            .field("pos", &self.pos)
65            .finish()
66    }
67}
68
69impl LineBuffer {
70    /// Create a new line buffer with the given maximum `capacity`.
71    pub fn with_capacity(capacity: usize) -> LineBuffer {
72        LineBuffer {
73            buf: String::with_capacity(capacity),
74            pos: 0,
75            dl: None,
76            cl: None,
77        }
78    }
79
80    #[cfg(test)]
81    pub(crate) fn init(
82        line: &str,
83        pos: usize,
84        cl: Option<Rc<RefCell<ChangeListener>>>,
85    ) -> LineBuffer {
86        let mut lb = Self::with_capacity(MAX_LINE);
87        assert!(lb.insert_str(0, line));
88        lb.set_pos(pos);
89        lb.cl = cl;
90        lb
91    }
92
93    pub(crate) fn set_delete_listener(&mut self, dl: Arc<Mutex<DeleteListener>>) {
94        self.dl = Some(dl);
95    }
96    pub(crate) fn set_change_listener(&mut self, dl: Rc<RefCell<ChangeListener>>) {
97        self.cl = Some(dl);
98    }
99    pub(crate) fn remove_change_listener(&mut self) {
100        self.cl = None;
101    }
102
103    /// Extracts a string slice containing the entire buffer.
104    pub fn as_str(&self) -> &str {
105        &self.buf
106    }
107
108    /// Converts a buffer into a `String` without copying or allocating.
109    pub fn into_string(self) -> String {
110        self.buf
111    }
112
113    /// Current cursor position (byte position)
114    pub fn pos(&self) -> usize {
115        self.pos
116    }
117    /// Set cursor position (byte position)
118    pub fn set_pos(&mut self, pos: usize) {
119        assert!(pos <= self.buf.len());
120        self.pos = pos;
121    }
122
123    /// Returns the length of this buffer, in bytes.
124    pub fn len(&self) -> usize {
125        self.buf.len()
126    }
127    /// Returns `true` if this buffer has a length of zero.
128    pub fn is_empty(&self) -> bool {
129        self.buf.is_empty()
130    }
131
132    /// Set line content (`buf`) and cursor position (`pos`).
133    pub fn update(&mut self, buf: &str, pos: usize) {
134        assert!(pos <= buf.len());
135        let end = self.len();
136        self.drain(0..end, Direction::default());
137        let max = self.buf.capacity();
138        if buf.len() > max {
139            self.insert_str(0, &buf[..max]);
140            if pos > max {
141                self.pos = max;
142            } else {
143                self.pos = pos;
144            }
145        } else {
146            self.insert_str(0, buf);
147            self.pos = pos;
148        }
149    }
150
151    /// Returns the character at current cursor position.
152    fn grapheme_at_cursor(&self) -> Option<&str> {
153        if self.pos == self.buf.len() {
154            None
155        } else {
156            self.buf[self.pos..].graphemes(true).next()
157        }
158    }
159
160    /// Returns the position of the character just after the current cursor
161    /// position.
162    pub fn next_pos(&self, n: RepeatCount) -> Option<usize> {
163        if self.pos == self.buf.len() {
164            return None;
165        }
166        self.buf[self.pos..]
167            .grapheme_indices(true)
168            .take(n)
169            .last()
170            .map(|(i, s)| i + self.pos + s.len())
171    }
172    /// Returns the position of the character just before the current cursor
173    /// position.
174    fn prev_pos(&self, n: RepeatCount) -> Option<usize> {
175        if self.pos == 0 {
176            return None;
177        }
178        self.buf[..self.pos]
179            .grapheme_indices(true)
180            .rev()
181            .take(n)
182            .last()
183            .map(|(i, _)| i)
184    }
185
186    /// Insert the character `ch` at current cursor position
187    /// and advance cursor position accordingly.
188    /// Return `None` when maximum buffer size has been reached,
189    /// `true` when the character has been appended to the end of the line.
190    pub fn insert(&mut self, ch: char, n: RepeatCount) -> Option<bool> {
191        let shift = ch.len_utf8() * n;
192        if self.buf.len() + shift > self.buf.capacity() {
193            return None;
194        }
195        let push = self.pos == self.buf.len();
196        if n == 1 {
197            self.buf.insert(self.pos, ch);
198            for cl in &self.cl {
199                cl.borrow_mut().insert_char(self.pos, ch);
200            }
201        } else {
202            let text = iter::repeat(ch).take(n).collect::<String>();
203            let pos = self.pos;
204            self.insert_str(pos, &text);
205        }
206        self.pos += shift;
207        Some(push)
208    }
209
210    /// Yank/paste `text` at current position.
211    /// Return `None` when maximum buffer size has been reached,
212    /// `true` when the character has been appended to the end of the line.
213    pub fn yank(&mut self, text: &str, n: RepeatCount) -> Option<bool> {
214        let shift = text.len() * n;
215        if text.is_empty() || (self.buf.len() + shift) > self.buf.capacity() {
216            return None;
217        }
218        let push = self.pos == self.buf.len();
219        let pos = self.pos;
220        if n == 1 {
221            self.insert_str(pos, text);
222        } else {
223            let text = iter::repeat(text).take(n).collect::<String>();
224            self.insert_str(pos, &text);
225        }
226        self.pos += shift;
227        Some(push)
228    }
229
230    /// Delete previously yanked text and yank/paste `text` at current position.
231    pub fn yank_pop(&mut self, yank_size: usize, text: &str) -> Option<bool> {
232        let end = self.pos;
233        let start = end - yank_size;
234        self.drain(start..end, Direction::default());
235        self.pos -= yank_size;
236        self.yank(text, 1)
237    }
238
239    /// Move cursor on the left.
240    pub fn move_backward(&mut self, n: RepeatCount) -> bool {
241        match self.prev_pos(n) {
242            Some(pos) => {
243                self.pos = pos;
244                true
245            }
246            None => false,
247        }
248    }
249
250    /// Move cursor on the right.
251    pub fn move_forward(&mut self, n: RepeatCount) -> bool {
252        match self.next_pos(n) {
253            Some(pos) => {
254                self.pos = pos;
255                true
256            }
257            None => false,
258        }
259    }
260
261    /// Move cursor to the start of the line.
262    pub fn move_home(&mut self) -> bool {
263        if self.pos > 0 {
264            self.pos = 0;
265            true
266        } else {
267            false
268        }
269    }
270
271    /// Move cursor to the end of the line.
272    pub fn move_end(&mut self) -> bool {
273        if self.pos == self.buf.len() {
274            false
275        } else {
276            self.pos = self.buf.len();
277            true
278        }
279    }
280
281    /// Delete the character at the right of the cursor without altering the
282    /// cursor position. Basically this is what happens with the "Delete"
283    /// keyboard key.
284    /// Return the number of characters deleted.
285    pub fn delete(&mut self, n: RepeatCount) -> Option<String> {
286        match self.next_pos(n) {
287            Some(pos) => {
288                let start = self.pos;
289                let chars = self
290                    .drain(start..pos, Direction::Forward)
291                    .collect::<String>();
292                Some(chars)
293            }
294            None => None,
295        }
296    }
297
298    /// Delete the character at the left of the cursor.
299    /// Basically that is what happens with the "Backspace" keyboard key.
300    pub fn backspace(&mut self, n: RepeatCount) -> bool {
301        match self.prev_pos(n) {
302            Some(pos) => {
303                let end = self.pos;
304                self.drain(pos..end, Direction::Backward);
305                self.pos = pos;
306                true
307            }
308            None => false,
309        }
310    }
311
312    /// Kill the text from point to the end of the line.
313    pub fn kill_line(&mut self) -> bool {
314        if !self.buf.is_empty() && self.pos < self.buf.len() {
315            let start = self.pos;
316            let end = self.buf.len();
317            self.drain(start..end, Direction::Forward);
318            true
319        } else {
320            false
321        }
322    }
323
324    /// Kill backward from point to the beginning of the line.
325    pub fn discard_line(&mut self) -> bool {
326        if self.pos > 0 && !self.buf.is_empty() {
327            let end = self.pos;
328            self.drain(0..end, Direction::Backward);
329            self.pos = 0;
330            true
331        } else {
332            false
333        }
334    }
335
336    /// Exchange the char before cursor with the character at cursor.
337    pub fn transpose_chars(&mut self) -> bool {
338        if self.pos == 0 || self.buf.graphemes(true).count() < 2 {
339            return false;
340        }
341        if self.pos == self.buf.len() {
342            self.move_backward(1);
343        }
344        let chars = self.delete(1).unwrap();
345        self.move_backward(1);
346        self.yank(&chars, 1);
347        self.move_forward(1);
348        true
349    }
350
351    /// Go left until start of word
352    fn prev_word_pos(&self, pos: usize, word_def: Word, n: RepeatCount) -> Option<usize> {
353        if pos == 0 {
354            return None;
355        }
356        let mut sow = 0;
357        let mut gis = self.buf[..pos].grapheme_indices(true).rev();
358        'outer: for _ in 0..n {
359            sow = 0;
360            let mut gj = gis.next();
361            'inner: loop {
362                match gj {
363                    Some((j, y)) => {
364                        let gi = gis.next();
365                        match gi {
366                            Some((_, x)) => {
367                                if is_start_of_word(word_def, x, y) {
368                                    sow = j;
369                                    break 'inner;
370                                }
371                                gj = gi;
372                            }
373                            None => {
374                                break 'outer;
375                            }
376                        }
377                    }
378                    None => {
379                        break 'outer;
380                    }
381                }
382            }
383        }
384        Some(sow)
385    }
386
387    /// Moves the cursor to the beginning of previous word.
388    pub fn move_to_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
389        if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
390            self.pos = pos;
391            true
392        } else {
393            false
394        }
395    }
396
397    /// Delete the previous word, maintaining the cursor at the start of the
398    /// current word.
399    pub fn delete_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
400        if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
401            let end = self.pos;
402            self.drain(pos..end, Direction::Backward);
403            self.pos = pos;
404            true
405        } else {
406            false
407        }
408    }
409
410    fn next_word_pos(&self, pos: usize, at: At, word_def: Word, n: RepeatCount) -> Option<usize> {
411        if pos == self.buf.len() {
412            return None;
413        }
414        let mut wp = 0;
415        let mut gis = self.buf[pos..].grapheme_indices(true);
416        let mut gi = if at == At::BeforeEnd {
417            // TODO Validate
418            gis.next()
419        } else {
420            None
421        };
422        'outer: for _ in 0..n {
423            wp = 0;
424            gi = gis.next();
425            'inner: loop {
426                match gi {
427                    Some((i, x)) => {
428                        let gj = gis.next();
429                        match gj {
430                            Some((j, y)) => {
431                                if at == At::Start && is_start_of_word(word_def, x, y) {
432                                    wp = j;
433                                    break 'inner;
434                                } else if at != At::Start && is_end_of_word(word_def, x, y) {
435                                    if word_def == Word::Emacs || at == At::AfterEnd {
436                                        wp = j;
437                                    } else {
438                                        wp = i;
439                                    }
440                                    break 'inner;
441                                }
442                                gi = gj;
443                            }
444                            None => {
445                                break 'outer;
446                            }
447                        }
448                    }
449                    None => {
450                        break 'outer;
451                    }
452                }
453            }
454        }
455        if wp == 0 {
456            if word_def == Word::Emacs || at == At::AfterEnd {
457                Some(self.buf.len())
458            } else {
459                match gi {
460                    Some((i, _)) if i != 0 => Some(i + pos),
461                    _ => None,
462                }
463            }
464        } else {
465            Some(wp + pos)
466        }
467    }
468
469    /// Moves the cursor to the end of next word.
470    pub fn move_to_next_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
471        if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
472            self.pos = pos;
473            true
474        } else {
475            false
476        }
477    }
478
479    fn search_char_pos(&self, cs: CharSearch, n: RepeatCount) -> Option<usize> {
480        let mut shift = 0;
481        let search_result = match cs {
482            CharSearch::Backward(c) | CharSearch::BackwardAfter(c) => self.buf[..self.pos]
483                .char_indices()
484                .rev()
485                .filter(|&(_, ch)| ch == c)
486                .take(n)
487                .last()
488                .map(|(i, _)| i),
489            CharSearch::Forward(c) | CharSearch::ForwardBefore(c) => {
490                if let Some(cc) = self.grapheme_at_cursor() {
491                    shift = self.pos + cc.len();
492                    if shift < self.buf.len() {
493                        self.buf[shift..]
494                            .char_indices()
495                            .filter(|&(_, ch)| ch == c)
496                            .take(n)
497                            .last()
498                            .map(|(i, _)| i)
499                    } else {
500                        None
501                    }
502                } else {
503                    None
504                }
505            }
506        };
507        if let Some(pos) = search_result {
508            Some(match cs {
509                CharSearch::Backward(_) => pos,
510                CharSearch::BackwardAfter(c) => pos + c.len_utf8(),
511                CharSearch::Forward(_) => shift + pos,
512                CharSearch::ForwardBefore(_) => {
513                    shift + pos
514                        - self.buf[..shift + pos]
515                            .chars()
516                            .next_back()
517                            .unwrap()
518                            .len_utf8()
519                }
520            })
521        } else {
522            None
523        }
524    }
525
526    /// Move cursor to the matching character position.
527    /// Return `true` when the search succeeds.
528    pub fn move_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
529        if let Some(pos) = self.search_char_pos(cs, n) {
530            self.pos = pos;
531            true
532        } else {
533            false
534        }
535    }
536
537    /// Kill from the cursor to the end of the current word,
538    /// or, if between words, to the end of the next word.
539    pub fn delete_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
540        if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
541            let start = self.pos;
542            self.drain(start..pos, Direction::Forward);
543            true
544        } else {
545            false
546        }
547    }
548
549    pub fn delete_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
550        let search_result = match cs {
551            CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
552            _ => self.search_char_pos(cs, n),
553        };
554        if let Some(pos) = search_result {
555            match cs {
556                CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
557                    let end = self.pos;
558                    self.pos = pos;
559                    self.drain(pos..end, Direction::Backward);
560                }
561                CharSearch::ForwardBefore(_) => {
562                    let start = self.pos;
563                    self.drain(start..pos, Direction::Forward);
564                }
565                CharSearch::Forward(c) => {
566                    let start = self.pos;
567                    self.drain(start..pos + c.len_utf8(), Direction::Forward);
568                }
569            };
570            true
571        } else {
572            false
573        }
574    }
575
576    fn skip_whitespace(&self) -> Option<usize> {
577        if self.pos == self.buf.len() {
578            return None;
579        }
580        self.buf[self.pos..]
581            .grapheme_indices(true)
582            .filter(|&(_, ch)| ch.chars().all(|c| c.is_alphanumeric()))
583            .map(|(i, _)| i)
584            .next()
585            .map(|i| i + self.pos)
586    }
587    /// Alter the next word.
588    pub fn edit_word(&mut self, a: WordAction) -> bool {
589        if let Some(start) = self.skip_whitespace() {
590            if let Some(end) = self.next_word_pos(start, At::AfterEnd, Word::Emacs, 1) {
591                if start == end {
592                    return false;
593                }
594                let word = self
595                    .drain(start..end, Direction::default())
596                    .collect::<String>();
597                let result = match a {
598                    WordAction::CAPITALIZE => {
599                        let ch = (&word).graphemes(true).next().unwrap();
600                        let cap = ch.to_uppercase();
601                        cap + &word[ch.len()..].to_lowercase()
602                    }
603                    WordAction::LOWERCASE => word.to_lowercase(),
604                    WordAction::UPPERCASE => word.to_uppercase(),
605                };
606                self.insert_str(start, &result);
607                self.pos = start + result.len();
608                return true;
609            }
610        }
611        false
612    }
613
614    /// Transpose two words
615    pub fn transpose_words(&mut self, n: RepeatCount) -> bool {
616        let word_def = Word::Emacs;
617        self.move_to_next_word(At::AfterEnd, word_def, n);
618        let w2_end = self.pos;
619        self.move_to_prev_word(word_def, 1);
620        let w2_beg = self.pos;
621        self.move_to_prev_word(word_def, n);
622        let w1_beg = self.pos;
623        self.move_to_next_word(At::AfterEnd, word_def, 1);
624        let w1_end = self.pos;
625        if w1_beg == w2_beg || w2_beg < w1_end {
626            return false;
627        }
628
629        let w1 = self.buf[w1_beg..w1_end].to_owned();
630
631        let w2 = self
632            .drain(w2_beg..w2_end, Direction::default())
633            .collect::<String>();
634        self.insert_str(w2_beg, &w1);
635
636        self.drain(w1_beg..w1_end, Direction::default());
637        self.insert_str(w1_beg, &w2);
638
639        self.pos = w2_end;
640        true
641    }
642
643    /// Replaces the content between [`start`..`end`] with `text`
644    /// and positions the cursor to the end of text.
645    pub fn replace(&mut self, range: Range<usize>, text: &str) {
646        let start = range.start;
647        for cl in &self.cl {
648            cl.borrow_mut()
649                .replace(start, self.buf.index(range.clone()), text);
650        }
651        self.buf.drain(range);
652        if start == self.buf.len() {
653            self.buf.push_str(text);
654        } else {
655            self.buf.insert_str(start, text);
656        }
657        self.pos = start + text.len();
658    }
659
660    /// Insert the `s`tring at the specified position.
661    /// Return `true` if the text has been inserted at the end of the line.
662    pub fn insert_str(&mut self, idx: usize, s: &str) -> bool {
663        for cl in &self.cl {
664            cl.borrow_mut().insert_str(idx, s);
665        }
666        if idx == self.buf.len() {
667            self.buf.push_str(s);
668            true
669        } else {
670            self.buf.insert_str(idx, s);
671            false
672        }
673    }
674
675    /// Remove the specified `range` in the line.
676    pub fn delete_range(&mut self, range: Range<usize>) {
677        self.set_pos(range.start);
678        self.drain(range, Direction::default());
679    }
680
681    fn drain(&mut self, range: Range<usize>, dir: Direction) -> Drain {
682        for dl in &self.dl {
683            let mut lock = dl.try_lock();
684            if let Ok(mut dl) = lock {
685                dl.delete(range.start, &self.buf[range.start..range.end], dir);
686            }
687        }
688        for cl in &self.cl {
689            cl.borrow_mut()
690                .delete(range.start, &self.buf[range.start..range.end], dir);
691        }
692        self.buf.drain(range)
693    }
694
695    /// Return the content between current cursor position and `mvt` position.
696    /// Return `None` when the buffer is empty or when the movement fails.
697    pub fn copy(&self, mvt: &Movement) -> Option<String> {
698        if self.is_empty() {
699            return None;
700        }
701        match *mvt {
702            Movement::WholeLine => Some(self.buf.clone()),
703            Movement::BeginningOfLine => if self.pos == 0 {
704                None
705            } else {
706                Some(self.buf[..self.pos].to_owned())
707            },
708            Movement::ViFirstPrint => if self.pos == 0 {
709                None
710            } else if let Some(pos) = self.next_word_pos(0, At::Start, Word::Big, 1) {
711                Some(self.buf[pos..self.pos].to_owned())
712            } else {
713                None
714            },
715            Movement::EndOfLine => if self.pos == self.buf.len() {
716                None
717            } else {
718                Some(self.buf[self.pos..].to_owned())
719            },
720            Movement::BackwardWord(n, word_def) => {
721                if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
722                    Some(self.buf[pos..self.pos].to_owned())
723                } else {
724                    None
725                }
726            }
727            Movement::ForwardWord(n, at, word_def) => {
728                if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
729                    Some(self.buf[self.pos..pos].to_owned())
730                } else {
731                    None
732                }
733            }
734            Movement::ViCharSearch(n, cs) => {
735                let search_result = match cs {
736                    CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
737                    _ => self.search_char_pos(cs, n),
738                };
739                if let Some(pos) = search_result {
740                    Some(match cs {
741                        CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
742                            self.buf[pos..self.pos].to_owned()
743                        }
744                        CharSearch::ForwardBefore(_) => self.buf[self.pos..pos].to_owned(),
745                        CharSearch::Forward(c) => self.buf[self.pos..pos + c.len_utf8()].to_owned(),
746                    })
747                } else {
748                    None
749                }
750            }
751            Movement::BackwardChar(n) => if let Some(pos) = self.prev_pos(n) {
752                Some(self.buf[pos..self.pos].to_owned())
753            } else {
754                None
755            },
756            Movement::ForwardChar(n) => if let Some(pos) = self.next_pos(n) {
757                Some(self.buf[self.pos..pos].to_owned())
758            } else {
759                None
760            },
761        }
762    }
763
764    pub fn kill(&mut self, mvt: &Movement) -> bool {
765        let notify = match *mvt {
766            Movement::ForwardChar(_) => false,
767            Movement::BackwardChar(_) => false,
768            _ => true,
769        };
770        if notify {
771            if let Some(dl) = self.dl.as_ref() {
772                let mut dl = dl.lock().unwrap();
773                dl.start_killing()
774            }
775        }
776        let killed = match *mvt {
777            Movement::ForwardChar(n) => {
778                // Delete (forward) `n` characters at point.
779                self.delete(n).is_some()
780            }
781            Movement::BackwardChar(n) => {
782                // Delete `n` characters backward.
783                self.backspace(n)
784            }
785            Movement::EndOfLine => {
786                // Kill the text from point to the end of the line.
787                self.kill_line()
788            }
789            Movement::WholeLine => {
790                self.move_home();
791                self.kill_line()
792            }
793            Movement::BeginningOfLine => {
794                // Kill backward from point to the beginning of the line.
795                self.discard_line()
796            }
797            Movement::BackwardWord(n, word_def) => {
798                // kill `n` words backward (until start of word)
799                self.delete_prev_word(word_def, n)
800            }
801            Movement::ForwardWord(n, at, word_def) => {
802                // kill `n` words forward (until start/end of word)
803                self.delete_word(at, word_def, n)
804            }
805            Movement::ViCharSearch(n, cs) => self.delete_to(cs, n),
806            Movement::ViFirstPrint => {
807                false // TODO
808            }
809        };
810        if notify {
811            if let Some(dl) = self.dl.as_ref() {
812                let mut dl = dl.lock().unwrap();
813                dl.stop_killing()
814            }
815        }
816        killed
817    }
818}
819
820impl Deref for LineBuffer {
821    type Target = str;
822
823    fn deref(&self) -> &str {
824        self.as_str()
825    }
826}
827
828fn is_start_of_word(word_def: Word, previous: &str, grapheme: &str) -> bool {
829    (!is_word_char(word_def, previous) && is_word_char(word_def, grapheme))
830        || (word_def == Word::Vi && !is_other_char(previous) && is_other_char(grapheme))
831}
832fn is_end_of_word(word_def: Word, grapheme: &str, next: &str) -> bool {
833    (!is_word_char(word_def, next) && is_word_char(word_def, grapheme))
834        || (word_def == Word::Vi && !is_other_char(next) && is_other_char(grapheme))
835}
836
837fn is_word_char(word_def: Word, grapheme: &str) -> bool {
838    match word_def {
839        Word::Emacs => grapheme.chars().all(|c| c.is_alphanumeric()),
840        Word::Vi => is_vi_word_char(grapheme),
841        Word::Big => !grapheme.chars().any(|c| c.is_whitespace()),
842    }
843}
844fn is_vi_word_char(grapheme: &str) -> bool {
845    grapheme.chars().all(|c| c.is_alphanumeric()) || grapheme == "_"
846}
847fn is_other_char(grapheme: &str) -> bool {
848    !(grapheme.chars().any(|c| c.is_whitespace()) || is_vi_word_char(grapheme))
849}
850
851#[cfg(test)]
852mod test {
853    use super::{ChangeListener, DeleteListener, Direction, LineBuffer, WordAction, MAX_LINE};
854    use keymap::{At, CharSearch, Word};
855    use std::cell::RefCell;
856    use std::rc::Rc;
857
858    struct Listener {
859        deleted_str: Option<String>,
860    }
861
862    impl Listener {
863        fn new() -> Rc<RefCell<Listener>> {
864            let l = Listener { deleted_str: None };
865            Rc::new(RefCell::new(l))
866        }
867
868        fn assert_deleted_str_eq(&self, expected: &str) {
869            let actual = self.deleted_str.as_ref().expect("no deleted string");
870            assert_eq!(expected, actual)
871        }
872    }
873
874    impl DeleteListener for Listener {
875        fn start_killing(&mut self) {}
876        fn delete(&mut self, _: usize, string: &str, _: Direction) {
877            self.deleted_str = Some(string.to_owned());
878        }
879        fn stop_killing(&mut self) {}
880    }
881    impl ChangeListener for Listener {
882        fn insert_char(&mut self, _: usize, _: char) {}
883        fn insert_str(&mut self, _: usize, _: &str) {}
884        fn replace(&mut self, _: usize, _: &str, _: &str) {}
885    }
886
887    #[test]
888    fn next_pos() {
889        let s = LineBuffer::init("ö̲g̈", 0, None);
890        assert_eq!(7, s.len());
891        let pos = s.next_pos(1);
892        assert_eq!(Some(4), pos);
893
894        let s = LineBuffer::init("ö̲g̈", 4, None);
895        let pos = s.next_pos(1);
896        assert_eq!(Some(7), pos);
897    }
898
899    #[test]
900    fn prev_pos() {
901        let s = LineBuffer::init("ö̲g̈", 4, None);
902        assert_eq!(7, s.len());
903        let pos = s.prev_pos(1);
904        assert_eq!(Some(0), pos);
905
906        let s = LineBuffer::init("ö̲g̈", 7, None);
907        let pos = s.prev_pos(1);
908        assert_eq!(Some(4), pos);
909    }
910
911    #[test]
912    fn insert() {
913        let mut s = LineBuffer::with_capacity(MAX_LINE);
914        let push = s.insert('α', 1).unwrap();
915        assert_eq!("α", s.buf);
916        assert_eq!(2, s.pos);
917        assert_eq!(true, push);
918
919        let push = s.insert('ß', 1).unwrap();
920        assert_eq!("αß", s.buf);
921        assert_eq!(4, s.pos);
922        assert_eq!(true, push);
923
924        s.pos = 0;
925        let push = s.insert('γ', 1).unwrap();
926        assert_eq!("γαß", s.buf);
927        assert_eq!(2, s.pos);
928        assert_eq!(false, push);
929    }
930
931    #[test]
932    fn yank_after() {
933        let mut s = LineBuffer::init("αß", 2, None);
934        s.move_forward(1);
935        let ok = s.yank("γδε", 1);
936        assert_eq!(Some(true), ok);
937        assert_eq!("αßγδε", s.buf);
938        assert_eq!(10, s.pos);
939    }
940
941    #[test]
942    fn yank_before() {
943        let mut s = LineBuffer::init("αε", 2, None);
944        let ok = s.yank("ßγδ", 1);
945        assert_eq!(Some(false), ok);
946        assert_eq!("αßγδε", s.buf);
947        assert_eq!(8, s.pos);
948    }
949
950    #[test]
951    fn moves() {
952        let mut s = LineBuffer::init("αß", 4, None);
953        let ok = s.move_backward(1);
954        assert_eq!("αß", s.buf);
955        assert_eq!(2, s.pos);
956        assert_eq!(true, ok);
957
958        let ok = s.move_forward(1);
959        assert_eq!("αß", s.buf);
960        assert_eq!(4, s.pos);
961        assert_eq!(true, ok);
962
963        let ok = s.move_home();
964        assert_eq!("αß", s.buf);
965        assert_eq!(0, s.pos);
966        assert_eq!(true, ok);
967
968        let ok = s.move_end();
969        assert_eq!("αß", s.buf);
970        assert_eq!(4, s.pos);
971        assert_eq!(true, ok);
972    }
973
974    #[test]
975    fn move_grapheme() {
976        let mut s = LineBuffer::init("ag̈", 4, None);
977        assert_eq!(4, s.len());
978        let ok = s.move_backward(1);
979        assert_eq!(true, ok);
980        assert_eq!(1, s.pos);
981
982        let ok = s.move_forward(1);
983        assert_eq!(true, ok);
984        assert_eq!(4, s.pos);
985    }
986
987    #[test]
988    fn delete() {
989        let cl = Listener::new();
990        let mut s = LineBuffer::init("αß", 2, Some(cl.clone()));
991        let chars = s.delete(1);
992        assert_eq!("α", s.buf);
993        assert_eq!(2, s.pos);
994        assert_eq!(Some("ß".to_owned()), chars);
995
996        let ok = s.backspace(1);
997        assert_eq!("", s.buf);
998        assert_eq!(0, s.pos);
999        assert_eq!(true, ok);
1000        cl.borrow().assert_deleted_str_eq("α");
1001    }
1002
1003    #[test]
1004    fn kill() {
1005        let cl = Listener::new();
1006        let mut s = LineBuffer::init("αßγδε", 6, Some(cl.clone()));
1007        let ok = s.kill_line();
1008        assert_eq!("αßγ", s.buf);
1009        assert_eq!(6, s.pos);
1010        assert_eq!(true, ok);
1011        cl.borrow().assert_deleted_str_eq("δε");
1012
1013        s.pos = 4;
1014        let ok = s.discard_line();
1015        assert_eq!("γ", s.buf);
1016        assert_eq!(0, s.pos);
1017        assert_eq!(true, ok);
1018        cl.borrow().assert_deleted_str_eq("αß");
1019    }
1020
1021    #[test]
1022    fn transpose() {
1023        let mut s = LineBuffer::init("aßc", 1, None);
1024        let ok = s.transpose_chars();
1025        assert_eq!("ßac", s.buf);
1026        assert_eq!(3, s.pos);
1027        assert_eq!(true, ok);
1028
1029        s.buf = String::from("aßc");
1030        s.pos = 3;
1031        let ok = s.transpose_chars();
1032        assert_eq!("acß", s.buf);
1033        assert_eq!(4, s.pos);
1034        assert_eq!(true, ok);
1035
1036        s.buf = String::from("aßc");
1037        s.pos = 4;
1038        let ok = s.transpose_chars();
1039        assert_eq!("acß", s.buf);
1040        assert_eq!(4, s.pos);
1041        assert_eq!(true, ok);
1042    }
1043
1044    #[test]
1045    fn move_to_prev_word() {
1046        let mut s = LineBuffer::init("a ß  c", 6, None); // before 'c'
1047        let ok = s.move_to_prev_word(Word::Emacs, 1);
1048        assert_eq!("a ß  c", s.buf);
1049        assert_eq!(2, s.pos); // before 'ß'
1050        assert!(true, ok);
1051
1052        assert!(s.move_end()); // after 'c'
1053        assert_eq!(7, s.pos);
1054        let ok = s.move_to_prev_word(Word::Emacs, 1);
1055        assert!(true, ok);
1056        assert_eq!(6, s.pos); // before 'c'
1057
1058        let ok = s.move_to_prev_word(Word::Emacs, 2);
1059        assert!(true, ok);
1060        assert_eq!(0, s.pos);
1061    }
1062
1063    #[test]
1064    fn move_to_prev_vi_word() {
1065        let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19, None);
1066        let ok = s.move_to_prev_word(Word::Vi, 1);
1067        assert!(ok);
1068        assert_eq!(17, s.pos);
1069        let ok = s.move_to_prev_word(Word::Vi, 1);
1070        assert!(ok);
1071        assert_eq!(15, s.pos);
1072        let ok = s.move_to_prev_word(Word::Vi, 1);
1073        assert!(ok);
1074        assert_eq!(12, s.pos);
1075        let ok = s.move_to_prev_word(Word::Vi, 1);
1076        assert!(ok);
1077        assert_eq!(11, s.pos);
1078        let ok = s.move_to_prev_word(Word::Vi, 1);
1079        assert!(ok);
1080        assert_eq!(7, s.pos);
1081        let ok = s.move_to_prev_word(Word::Vi, 1);
1082        assert!(ok);
1083        assert_eq!(6, s.pos);
1084        let ok = s.move_to_prev_word(Word::Vi, 1);
1085        assert!(ok);
1086        assert_eq!(0, s.pos);
1087        let ok = s.move_to_prev_word(Word::Vi, 1);
1088        assert!(!ok);
1089    }
1090
1091    #[test]
1092    fn move_to_prev_big_word() {
1093        let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19, None);
1094        let ok = s.move_to_prev_word(Word::Big, 1);
1095        assert!(ok);
1096        assert_eq!(17, s.pos);
1097        let ok = s.move_to_prev_word(Word::Big, 1);
1098        assert!(ok);
1099        assert_eq!(6, s.pos);
1100        let ok = s.move_to_prev_word(Word::Big, 1);
1101        assert!(ok);
1102        assert_eq!(0, s.pos);
1103        let ok = s.move_to_prev_word(Word::Big, 1);
1104        assert!(!ok);
1105    }
1106
1107    #[test]
1108    fn move_to_forward() {
1109        let mut s = LineBuffer::init("αßγδε", 2, None);
1110        let ok = s.move_to(CharSearch::ForwardBefore('ε'), 1);
1111        assert_eq!(true, ok);
1112        assert_eq!(6, s.pos);
1113
1114        let mut s = LineBuffer::init("αßγδε", 2, None);
1115        let ok = s.move_to(CharSearch::Forward('ε'), 1);
1116        assert_eq!(true, ok);
1117        assert_eq!(8, s.pos);
1118
1119        let mut s = LineBuffer::init("αßγδε", 2, None);
1120        let ok = s.move_to(CharSearch::Forward('ε'), 10);
1121        assert_eq!(true, ok);
1122        assert_eq!(8, s.pos);
1123    }
1124
1125    #[test]
1126    fn move_to_backward() {
1127        let mut s = LineBuffer::init("αßγδε", 8, None);
1128        let ok = s.move_to(CharSearch::BackwardAfter('ß'), 1);
1129        assert_eq!(true, ok);
1130        assert_eq!(4, s.pos);
1131
1132        let mut s = LineBuffer::init("αßγδε", 8, None);
1133        let ok = s.move_to(CharSearch::Backward('ß'), 1);
1134        assert_eq!(true, ok);
1135        assert_eq!(2, s.pos);
1136    }
1137
1138    #[test]
1139    fn delete_prev_word() {
1140        let cl = Listener::new();
1141        let mut s = LineBuffer::init("a ß  c", 6, Some(cl.clone()));
1142        let ok = s.delete_prev_word(Word::Big, 1);
1143        assert_eq!("a c", s.buf);
1144        assert_eq!(2, s.pos);
1145        assert_eq!(true, ok);
1146        cl.borrow().assert_deleted_str_eq("ß  ");
1147    }
1148
1149    #[test]
1150    fn move_to_next_word() {
1151        let mut s = LineBuffer::init("a ß  c", 1, None); // after 'a'
1152        let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1153        assert_eq!("a ß  c", s.buf);
1154        assert_eq!(true, ok);
1155        assert_eq!(4, s.pos); // after 'ß'
1156
1157        let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1158        assert_eq!(true, ok);
1159        assert_eq!(7, s.pos); // after 'c'
1160
1161        s.move_home();
1162        let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1163        assert_eq!(true, ok);
1164        assert_eq!(1, s.pos); // after 'a'
1165
1166        let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 2);
1167        assert_eq!(true, ok);
1168        assert_eq!(7, s.pos); // after 'c'
1169    }
1170
1171    #[test]
1172    fn move_to_end_of_word() {
1173        let mut s = LineBuffer::init("a ßeta  c", 1, None);
1174        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1175        assert_eq!("a ßeta  c", s.buf);
1176        assert_eq!(6, s.pos);
1177        assert_eq!(true, ok);
1178    }
1179
1180    #[test]
1181    fn move_to_end_of_vi_word() {
1182        let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1183        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1184        assert!(ok);
1185        assert_eq!(4, s.pos);
1186        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1187        assert!(ok);
1188        assert_eq!(6, s.pos);
1189        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1190        assert!(ok);
1191        assert_eq!(10, s.pos);
1192        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1193        assert!(ok);
1194        assert_eq!(11, s.pos);
1195        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1196        assert!(ok);
1197        assert_eq!(14, s.pos);
1198        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1199        assert!(ok);
1200        assert_eq!(15, s.pos);
1201        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1202        assert!(ok);
1203        assert_eq!(18, s.pos);
1204        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1205        assert!(!ok);
1206    }
1207
1208    #[test]
1209    fn move_to_end_of_big_word() {
1210        let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1211        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1212        assert!(ok);
1213        assert_eq!(4, s.pos);
1214        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1215        assert!(ok);
1216        assert_eq!(15, s.pos);
1217        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1218        assert!(ok);
1219        assert_eq!(18, s.pos);
1220        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1221        assert!(!ok);
1222    }
1223
1224    #[test]
1225    fn move_to_start_of_word() {
1226        let mut s = LineBuffer::init("a ß  c", 2, None);
1227        let ok = s.move_to_next_word(At::Start, Word::Emacs, 1);
1228        assert_eq!("a ß  c", s.buf);
1229        assert_eq!(6, s.pos);
1230        assert_eq!(true, ok);
1231    }
1232
1233    #[test]
1234    fn move_to_start_of_vi_word() {
1235        let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1236        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1237        assert!(ok);
1238        assert_eq!(6, s.pos);
1239        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1240        assert!(ok);
1241        assert_eq!(7, s.pos);
1242        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1243        assert!(ok);
1244        assert_eq!(11, s.pos);
1245        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1246        assert!(ok);
1247        assert_eq!(12, s.pos);
1248        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1249        assert!(ok);
1250        assert_eq!(15, s.pos);
1251        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1252        assert!(ok);
1253        assert_eq!(17, s.pos);
1254        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1255        assert!(ok);
1256        assert_eq!(18, s.pos);
1257        let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1258        assert!(!ok);
1259    }
1260
1261    #[test]
1262    fn move_to_start_of_big_word() {
1263        let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1264        let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1265        assert!(ok);
1266        assert_eq!(6, s.pos);
1267        let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1268        assert!(ok);
1269        assert_eq!(17, s.pos);
1270        let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1271        assert!(ok);
1272        assert_eq!(18, s.pos);
1273        let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1274        assert!(!ok);
1275    }
1276
1277    #[test]
1278    fn delete_word() {
1279        let cl = Listener::new();
1280        let mut s = LineBuffer::init("a ß  c", 1, Some(cl.clone()));
1281        let ok = s.delete_word(At::AfterEnd, Word::Emacs, 1);
1282        assert_eq!("a  c", s.buf);
1283        assert_eq!(1, s.pos);
1284        assert_eq!(true, ok);
1285        cl.borrow().assert_deleted_str_eq(" ß");
1286
1287        let mut s = LineBuffer::init("test", 0, Some(cl.clone()));
1288        let ok = s.delete_word(At::AfterEnd, Word::Vi, 1);
1289        assert_eq!("", s.buf);
1290        assert_eq!(0, s.pos);
1291        assert_eq!(true, ok);
1292        cl.borrow().assert_deleted_str_eq("test");
1293    }
1294
1295    #[test]
1296    fn delete_til_start_of_word() {
1297        let cl = Listener::new();
1298        let mut s = LineBuffer::init("a ß  c", 2, Some(cl.clone()));
1299        let ok = s.delete_word(At::Start, Word::Emacs, 1);
1300        assert_eq!("a c", s.buf);
1301        assert_eq!(2, s.pos);
1302        assert_eq!(true, ok);
1303        cl.borrow().assert_deleted_str_eq("ß  ");
1304    }
1305
1306    #[test]
1307    fn delete_to_forward() {
1308        let cl = Listener::new();
1309        let mut s = LineBuffer::init("αßγδε", 2, Some(cl.clone()));
1310        let ok = s.delete_to(CharSearch::ForwardBefore('ε'), 1);
1311        assert_eq!(true, ok);
1312        cl.borrow().assert_deleted_str_eq("ßγδ");
1313        assert_eq!("αε", s.buf);
1314        assert_eq!(2, s.pos);
1315
1316        let mut s = LineBuffer::init("αßγδε", 2, Some(cl.clone()));
1317        let ok = s.delete_to(CharSearch::Forward('ε'), 1);
1318        assert_eq!(true, ok);
1319        cl.borrow().assert_deleted_str_eq("ßγδε");
1320        assert_eq!("α", s.buf);
1321        assert_eq!(2, s.pos);
1322    }
1323
1324    #[test]
1325    fn delete_to_backward() {
1326        let cl = Listener::new();
1327        let mut s = LineBuffer::init("αßγδε", 8, Some(cl.clone()));
1328        let ok = s.delete_to(CharSearch::BackwardAfter('α'), 1);
1329        assert_eq!(true, ok);
1330        cl.borrow().assert_deleted_str_eq("ßγδ");
1331        assert_eq!("αε", s.buf);
1332        assert_eq!(2, s.pos);
1333
1334        let mut s = LineBuffer::init("αßγδε", 8, Some(cl.clone()));
1335        let ok = s.delete_to(CharSearch::Backward('ß'), 1);
1336        assert_eq!(true, ok);
1337        cl.borrow().assert_deleted_str_eq("ßγδ");
1338        assert_eq!("αε", s.buf);
1339        assert_eq!(2, s.pos);
1340    }
1341
1342    #[test]
1343    fn edit_word() {
1344        let mut s = LineBuffer::init("a ßeta  c", 1, None);
1345        assert!(s.edit_word(WordAction::UPPERCASE));
1346        assert_eq!("a SSETA  c", s.buf);
1347        assert_eq!(7, s.pos);
1348
1349        let mut s = LineBuffer::init("a ßetA  c", 1, None);
1350        assert!(s.edit_word(WordAction::LOWERCASE));
1351        assert_eq!("a ßeta  c", s.buf);
1352        assert_eq!(7, s.pos);
1353
1354        let mut s = LineBuffer::init("a ßETA  c", 1, None);
1355        assert!(s.edit_word(WordAction::CAPITALIZE));
1356        assert_eq!("a SSeta  c", s.buf);
1357        assert_eq!(7, s.pos);
1358
1359        let mut s = LineBuffer::init("test", 1, None);
1360        assert!(s.edit_word(WordAction::CAPITALIZE));
1361        assert_eq!("tEst", s.buf);
1362        assert_eq!(4, s.pos);
1363    }
1364
1365    #[test]
1366    fn transpose_words() {
1367        let mut s = LineBuffer::init("ßeta / δelta__", 15, None);
1368        assert!(s.transpose_words(1));
1369        assert_eq!("δelta__ / ßeta", s.buf);
1370        assert_eq!(16, s.pos);
1371
1372        let mut s = LineBuffer::init("ßeta / δelta", 14, None);
1373        assert!(s.transpose_words(1));
1374        assert_eq!("δelta / ßeta", s.buf);
1375        assert_eq!(14, s.pos);
1376
1377        let mut s = LineBuffer::init(" / δelta", 8, None);
1378        assert!(!s.transpose_words(1));
1379
1380        let mut s = LineBuffer::init("ßeta / __", 9, None);
1381        assert!(!s.transpose_words(1));
1382    }
1383}