Skip to main content

liner/keymap/
vi.rs

1use std::{mem, cmp};
2use std::io::{self, Write};
3use termion::event::Key;
4
5use KeyMap;
6use Editor;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9enum CharMovement {
10    RightUntil,
11    RightAt,
12    LeftUntil,
13    LeftAt,
14    Repeat,
15    ReverseRepeat,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19enum MoveType {
20    Inclusive,
21    Exclusive,
22}
23
24/// The editing mode.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26enum Mode {
27    Insert,
28    Normal,
29    Replace,
30    Delete(usize),
31    MoveToChar(CharMovement),
32    G,
33    Tilde,
34}
35
36struct ModeStack(Vec<Mode>);
37
38impl ModeStack {
39    fn with_insert() -> Self {
40        ModeStack(vec![Mode::Insert])
41    }
42
43    /// Get the current mode.
44    ///
45    /// If the stack is empty, we are in normal mode.
46    fn mode(&self) -> Mode {
47        self.0.last()
48            .map(|&m| m)
49            .unwrap_or(Mode::Normal)
50    }
51
52    /// Empty the stack and return to normal mode.
53    fn clear(&mut self) {
54        self.0.clear()
55    }
56
57    /// Push the given mode on to the stack.
58    fn push(&mut self, m: Mode) {
59        self.0.push(m)
60    }
61
62    fn pop(&mut self) -> Mode {
63        self.0.pop()
64            .unwrap_or(Mode::Normal)
65    }
66}
67
68fn is_movement_key(key: Key) -> bool {
69    match key {
70        Key::Char('h') | Key::Char('l') | Key::Left | Key::Right |
71            Key::Char('w') | Key::Char('W') | Key::Char('b') | Key::Char('B') |
72            Key::Char('e') | Key::Char('E') | Key::Char('g') |
73            Key::Backspace | Key::Char(' ') | Key::Home | Key::End |
74            Key::Char('$') |
75            Key::Char('t') | Key::Char('f') | Key::Char('T') | Key::Char('F') |
76            Key::Char(';') | Key::Char(',')
77        => true,
78        _ => false,
79    }
80}
81
82#[derive(PartialEq)]
83enum ViMoveMode {
84    Keyword,
85    Whitespace,
86}
87
88#[derive(PartialEq, Clone, Copy)]
89enum ViMoveDir {
90    Left,
91    Right,
92}
93
94impl ViMoveDir {
95    pub fn advance(&self, cursor: &mut usize, max: usize) -> bool {
96        self.move_cursor(cursor, max, *self)
97    }
98
99    pub fn go_back(&self, cursor: &mut usize, max: usize) -> bool {
100        match *self {
101            ViMoveDir::Right => self.move_cursor(cursor, max, ViMoveDir::Left),
102            ViMoveDir::Left => self.move_cursor(cursor, max, ViMoveDir::Right),
103        }
104    }
105
106    fn move_cursor(&self, cursor: &mut usize, max: usize, dir: ViMoveDir) -> bool {
107        if dir == ViMoveDir::Right && *cursor == max {
108            return false;
109        }
110
111        if dir == ViMoveDir::Left && *cursor == 0 {
112            return false;
113        }
114
115        match dir {
116            ViMoveDir::Right => *cursor += 1,
117            ViMoveDir::Left => *cursor -= 1,
118        };
119        true
120    }
121}
122
123/// All alphanumeric characters and _ are considered valid for keywords in vi by default.
124fn is_vi_keyword(c: char) -> bool {
125    c == '_' || c.is_alphanumeric()
126}
127
128fn move_word<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
129    vi_move_word(ed, ViMoveMode::Keyword, ViMoveDir::Right, count)
130}
131
132fn move_word_ws<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
133    vi_move_word(ed, ViMoveMode::Whitespace, ViMoveDir::Right, count)
134}
135
136fn move_to_end_of_word_back<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
137    vi_move_word(ed, ViMoveMode::Keyword, ViMoveDir::Left, count)
138}
139
140fn move_to_end_of_word_ws_back<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
141    vi_move_word(ed, ViMoveMode::Whitespace, ViMoveDir::Left, count)
142}
143
144fn vi_move_word<W: Write>(ed: &mut Editor<W>, move_mode: ViMoveMode, direction: ViMoveDir, count: usize) -> io::Result<()> {
145    enum State {
146        Whitespace,
147        Keyword,
148        NonKeyword,
149    };
150
151    let mut cursor = ed.cursor();
152    'repeat: for _ in 0..count {
153        let buf = ed.current_buffer();
154        let mut state = match buf.char_after(cursor) {
155            None => break,
156            Some(c) => match c {
157                c if c.is_whitespace() => State::Whitespace,
158                c if is_vi_keyword(c) => State::Keyword,
159                _ => State::NonKeyword,
160            },
161        };
162
163        while direction.advance(&mut cursor, buf.num_chars()) {
164            let c = match buf.char_after(cursor) {
165                Some(c) => c,
166                _ => break 'repeat,
167            };
168
169            match state {
170                State::Whitespace => match c {
171                    c if c.is_whitespace() => {},
172                    _ => break,
173                },
174                State::Keyword => match c {
175                    c if c.is_whitespace() => state = State::Whitespace,
176                    c if move_mode == ViMoveMode::Keyword
177                        && !is_vi_keyword(c)
178                    => break,
179                    _ => {}
180                },
181                State::NonKeyword => match c {
182                    c if c.is_whitespace() => state = State::Whitespace,
183                    c if move_mode == ViMoveMode::Keyword
184                        && is_vi_keyword(c)
185                    => break,
186                    _ => {}
187                },
188            }
189        }
190    }
191
192    ed.move_cursor_to(cursor)
193}
194
195fn move_to_end_of_word<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
196    vi_move_word_end(ed, ViMoveMode::Keyword, ViMoveDir::Right, count)
197}
198
199fn move_to_end_of_word_ws<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
200    vi_move_word_end(ed, ViMoveMode::Whitespace, ViMoveDir::Right, count)
201}
202
203fn move_word_back<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
204    vi_move_word_end(ed, ViMoveMode::Keyword, ViMoveDir::Left, count)
205}
206
207fn move_word_ws_back<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
208    vi_move_word_end(ed, ViMoveMode::Whitespace, ViMoveDir::Left, count)
209}
210
211fn vi_move_word_end<W: Write>(ed: &mut Editor<W>, move_mode: ViMoveMode, direction: ViMoveDir, count: usize) -> io::Result<()> {
212    enum State {
213        Whitespace,
214        EndOnWord,
215        EndOnOther,
216        EndOnWhitespace,
217    };
218
219    let mut cursor = ed.cursor();
220    'repeat: for _ in 0..count {
221        let buf = ed.current_buffer();
222        let mut state = State::Whitespace;
223
224        while direction.advance(&mut cursor, buf.num_chars()) {
225            let c = match buf.char_after(cursor) {
226                Some(c) => c,
227                _ => break 'repeat,
228            };
229
230            match state {
231                State::Whitespace => match c {
232                    // skip initial whitespace
233                    c if c.is_whitespace() => {},
234                    // if we are in keyword mode and found a keyword, stop on word
235                    c if move_mode == ViMoveMode::Keyword
236                        && is_vi_keyword(c) =>
237                    {
238                        state = State::EndOnWord;
239                    },
240                    // not in keyword mode, stop on whitespace
241                    _ if move_mode == ViMoveMode::Whitespace => {
242                        state = State::EndOnWhitespace;
243                    }
244                    // in keyword mode, found non-whitespace non-keyword, stop on anything
245                    _ => {
246                        state = State::EndOnOther;
247                    }
248                },
249                State::EndOnWord if !is_vi_keyword(c) => {
250                    direction.go_back(&mut cursor, buf.num_chars());
251                    break;
252                },
253                State::EndOnWhitespace if c.is_whitespace() => {
254                    direction.go_back(&mut cursor, buf.num_chars());
255                    break;
256                },
257                State::EndOnOther if c.is_whitespace() || is_vi_keyword(c) => {
258                    direction.go_back(&mut cursor, buf.num_chars());
259                    break;
260                },
261                _ => {},
262            }
263        }
264    }
265
266    ed.move_cursor_to(cursor)
267}
268
269fn find_char(buf: &::buffer::Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
270    assert!(count > 0);
271    buf.chars()
272        .enumerate()
273        .skip(start)
274        .filter(|&(_, &c)| c == ch)
275        .skip(count - 1)
276        .next()
277        .map(|(i, _)| i)
278}
279
280fn find_char_rev(buf: &::buffer::Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
281    assert!(count > 0);
282    let rstart = buf.num_chars() - start;
283    buf.chars()
284        .enumerate()
285        .rev()
286        .skip(rstart)
287        .filter(|&(_, &c)| c == ch)
288        .skip(count - 1)
289        .next()
290        .map(|(i, _)| i)
291}
292
293/// Vi keybindings for `Editor`.
294///
295/// ```
296/// use liner::*;
297/// let mut context = Context::new();
298/// context.key_bindings = KeyBindings::Vi;
299/// ```
300pub struct Vi<'a, W: Write> {
301    ed: Editor<'a, W>,
302    mode_stack: ModeStack,
303    current_command: Vec<Key>,
304    last_command: Vec<Key>,
305    current_insert: Option<Key>,
306    last_insert: Option<Key>,
307    count: u32,
308    secondary_count: u32,
309    last_count: u32,
310    movement_reset: bool,
311    last_char_movement: Option<(char, CharMovement)>,
312}
313
314impl<'a, W: Write> Vi<'a, W> {
315    pub fn new(mut ed: Editor<'a, W>) -> Self {
316        // since we start in insert mode, we need to start an undo group
317        ed.current_buffer_mut().start_undo_group();
318
319        Vi {
320            ed: ed,
321            mode_stack: ModeStack::with_insert(),
322            current_command: Vec::new(),
323            last_command: Vec::new(),
324            current_insert: None,
325            // we start vi in insert mode
326            last_insert: Some(Key::Char('i')),
327            count: 0,
328            secondary_count: 0,
329            last_count: 0,
330            movement_reset: false,
331            last_char_movement: None,
332        }
333    }
334
335    /// Get the current mode.
336    fn mode(&self) -> Mode {
337        self.mode_stack.mode()
338    }
339
340    fn set_mode(&mut self, mode: Mode) {
341        use self::Mode::*;
342        self.set_mode_preserve_last(mode);
343        if mode == Insert {
344            self.last_count = 0;
345            self.last_command.clear();
346        }
347    }
348
349    fn set_mode_preserve_last(&mut self, mode: Mode) {
350        use self::Mode::*;
351
352        self.ed.no_eol = mode == Normal;
353        self.movement_reset = mode != Insert;
354        self.mode_stack.push(mode);
355
356        if mode == Insert || mode == Tilde {
357            self.ed.current_buffer_mut().start_undo_group();
358        }
359    }
360
361    fn pop_mode_after_movement(&mut self, move_type: MoveType) -> io::Result<()> {
362        use self::Mode::*;
363        use self::MoveType::*;
364
365        let original_mode = self.mode_stack.pop();
366        let last_mode = {
367            // after popping, if mode is delete or change, pop that too. This is used for movements
368            // with sub commands like 't' (MoveToChar) and 'g' (G).
369            match self.mode() {
370                Delete(_) => self.mode_stack.pop(),
371                _ => original_mode,
372            }
373        };
374
375        self.ed.no_eol = self.mode() == Mode::Normal;
376        self.movement_reset = self.mode() != Mode::Insert;
377
378        match last_mode {
379            Delete(start_pos) => {
380                // perform the delete operation
381                match move_type {
382                    Exclusive => try!(self.ed.delete_until(start_pos)),
383                    Inclusive => try!(self.ed.delete_until_inclusive(start_pos)),
384                }
385
386                // update the last state
387                mem::swap(&mut self.last_command, &mut self.current_command);
388                self.last_insert = self.current_insert;
389                self.last_count = self.count;
390
391                // reset our counts
392                self.count = 0;
393                self.secondary_count = 0;
394            }
395            _ => {}
396        };
397
398        // in normal mode, count goes back to 0 after movement
399        if original_mode == Normal {
400            self.count = 0;
401        }
402
403        Ok(())
404    }
405
406    fn pop_mode(&mut self) {
407        use self::Mode::*;
408
409        let last_mode = self.mode_stack.pop();
410        self.ed.no_eol = self.mode() == Normal;
411        self.movement_reset = self.mode() != Insert;
412
413        if last_mode == Insert || last_mode == Tilde {
414            self.ed.current_buffer_mut().end_undo_group();
415        }
416
417        if last_mode == Tilde {
418            self.ed.display().unwrap();
419        }
420    }
421
422    /// Return to normal mode.
423    fn normal_mode_abort(&mut self) {
424        self.mode_stack.clear();
425        self.ed.no_eol = true;
426        self.count = 0;
427    }
428
429    /// When doing a move, 0 should behave the same as 1 as far as the count goes.
430    fn move_count(&mut self) -> usize {
431        match self.count {
432            0 => 1,
433            _ => self.count as usize,
434        }
435    }
436
437    /// Get the current count or the number of remaining chars in the buffer.
438    fn move_count_left(&mut self) -> usize {
439        cmp::min(self.ed.cursor(), self.move_count())
440    }
441
442    /// Get the current count or the number of remaining chars in the buffer.
443    fn move_count_right(&mut self) -> usize {
444        cmp::min(self.ed.current_buffer().num_chars() - self.ed.cursor(), self.move_count())
445    }
446
447    fn repeat(&mut self) -> io::Result<()> {
448        self.last_count = self.count;
449        let keys = mem::replace(&mut self.last_command, Vec::new());
450
451        if let Some(insert_key) = self.last_insert {
452            // enter insert mode if necessary
453            try!(self.handle_key_core(insert_key));
454        }
455
456        for k in keys.iter() {
457            try!(self.handle_key_core(*k));
458        }
459
460        if self.last_insert.is_some() {
461            // leave insert mode
462            try!(self.handle_key_core(Key::Esc));
463        }
464
465        // restore the last command
466        mem::replace(&mut self.last_command, keys);
467
468        Ok(())
469    }
470
471    fn handle_key_common(&mut self, key: Key) -> io::Result<()> {
472        match key {
473            Key::Ctrl('l') => self.ed.clear(),
474            Key::Left => self.ed.move_cursor_left(1),
475            Key::Right => self.ed.move_cursor_right(1),
476            Key::Up => self.ed.move_up(),
477            Key::Down => self.ed.move_down(),
478            Key::Home => self.ed.move_cursor_to_start_of_line(),
479            Key::End => self.ed.move_cursor_to_end_of_line(),
480            Key::Backspace => self.ed.delete_before_cursor(),
481            Key::Delete => self.ed.delete_after_cursor(),
482            Key::Null => Ok(()),
483            _ => Ok(()),
484        }
485    }
486
487    fn handle_key_insert(&mut self, key: Key) -> io::Result<()> {
488        match key {
489            Key::Esc => {
490                // perform any repeats
491                if self.count > 0 {
492                    self.last_count = self.count;
493                    for _ in 1..self.count {
494                        let keys = mem::replace(&mut self.last_command, Vec::new());
495                        for k in keys.into_iter() {
496                            try!(self.handle_key_core(k));
497                        }
498                    }
499                    self.count = 0;
500                }
501                // cursor moves to the left when switching from insert to normal mode
502                try!(self.ed.move_cursor_left(1));
503                self.pop_mode();
504                Ok(())
505            }
506            Key::Char(c) => {
507                if self.movement_reset {
508                    self.ed.current_buffer_mut().end_undo_group();
509                    self.ed.current_buffer_mut().start_undo_group();
510                    self.last_command.clear();
511                    self.movement_reset = false;
512                    // vim behaves as if this was 'i'
513                    self.last_insert = Some(Key::Char('i'));
514                }
515                self.last_command.push(key);
516                self.ed.insert_after_cursor(c)
517            }
518            // delete and backspace need to be included in the command buffer
519            Key::Backspace | Key::Delete => {
520                if self.movement_reset {
521                    self.ed.current_buffer_mut().end_undo_group();
522                    self.ed.current_buffer_mut().start_undo_group();
523                    self.last_command.clear();
524                    self.movement_reset = false;
525                    // vim behaves as if this was 'i'
526                    self.last_insert = Some(Key::Char('i'));
527                }
528                self.last_command.push(key);
529                self.handle_key_common(key)
530            }
531            // if this is a movement while in insert mode, reset the repeat count
532            Key::Left | Key::Right | Key::Home | Key::End => {
533                self.count = 0;
534                self.movement_reset = true;
535                self.handle_key_common(key)
536            }
537            // up and down require even more special handling
538            Key::Up => {
539                self.count = 0;
540                self.movement_reset = true;
541                self.ed.current_buffer_mut().end_undo_group();
542                try!(self.ed.move_up());
543                self.ed.current_buffer_mut().start_undo_group();
544                Ok(())
545            }
546            Key::Down => {
547                self.count = 0;
548                self.movement_reset = true;
549                self.ed.current_buffer_mut().end_undo_group();
550                try!(self.ed.move_down());
551                self.ed.current_buffer_mut().start_undo_group();
552                Ok(())
553            }
554            _ => self.handle_key_common(key),
555        }
556    }
557
558    fn handle_key_normal(&mut self, key: Key) -> io::Result<()> {
559        use self::Mode::*;
560        use self::CharMovement::*;
561        use self::MoveType::*;
562
563        match key {
564            Key::Esc => {
565                self.count = 0;
566                Ok(())
567            }
568            Key::Char('i') => {
569                self.last_insert = Some(key);
570                self.set_mode(Insert);
571                Ok(())
572            }
573            Key::Char('a') => {
574                self.last_insert = Some(key);
575                self.set_mode(Insert);
576                self.ed.move_cursor_right(1)
577            }
578            Key::Char('A') => {
579                self.last_insert = Some(key);
580                self.set_mode(Insert);
581                self.ed.move_cursor_to_end_of_line()
582            }
583            Key::Char('I') => {
584                self.last_insert = Some(key);
585                self.set_mode(Insert);
586                self.ed.move_cursor_to_start_of_line()
587            }
588            Key::Char('s') => {
589                self.last_insert = Some(key);
590                self.set_mode(Insert);
591                let pos = self.ed.cursor() + self.move_count_right();
592                try!(self.ed.delete_until(pos));
593                self.last_count = self.count;
594                self.count = 0;
595                Ok(())
596            }
597            Key::Char('r') => {
598                self.set_mode(Mode::Replace);
599                Ok(())
600            }
601            Key::Char('d') | Key::Char('c') => {
602                self.current_command.clear();
603
604                if key == Key::Char('d') {
605                    // handle special 'd' key stuff
606                    self.current_insert = None;
607                    self.current_command.push(key);
608                }
609                else {
610                    // handle special 'c' key stuff
611                    self.current_insert = Some(key);
612                    self.current_command.clear();
613                    self.set_mode(Insert);
614                }
615
616                let start_pos = self.ed.cursor();
617                self.set_mode(Mode::Delete(start_pos));
618                self.secondary_count = self.count;
619                self.count = 0;
620                Ok(())
621            }
622            Key::Char('D') => {
623                // update the last command state
624                self.last_insert = None;
625                self.last_command.clear();
626                self.last_command.push(key);
627                self.count = 0;
628                self.last_count = 0;
629
630                self.ed.delete_all_after_cursor()
631            }
632            Key::Char('C') => {
633                // update the last command state
634                self.last_insert = None;
635                self.last_command.clear();
636                self.last_command.push(key);
637                self.count = 0;
638                self.last_count = 0;
639
640                self.set_mode_preserve_last(Insert);
641                self.ed.delete_all_after_cursor()
642            }
643            Key::Char('.') => {
644                // repeat the last command
645                self.count = match (self.count, self.last_count) {
646                    // if both count and last_count are zero, use 1
647                    (0, 0) => 1,
648                    // if count is zero, use last_count
649                    (0, _) => self.last_count,
650                    // otherwise use count
651                    (_, _) => self.count,
652                };
653                self.repeat()
654            }
655            Key::Char('h') | Key::Left | Key::Backspace => {
656                let count = self.move_count_left();
657                try!(self.ed.move_cursor_left(count));
658                self.pop_mode_after_movement(Exclusive)
659            }
660            Key::Char('l') | Key::Right | Key::Char(' ') => {
661                let count = self.move_count_right();
662                try!(self.ed.move_cursor_right(count));
663                self.pop_mode_after_movement(Exclusive)
664            }
665            Key::Char('k') | Key::Up =>  {
666                try!(self.ed.move_up());
667                self.pop_mode_after_movement(Exclusive)
668            }
669            Key::Char('j') | Key::Down => {
670                try!(self.ed.move_down());
671                self.pop_mode_after_movement(Exclusive)
672            }
673            Key::Char('t') => {
674                self.set_mode(Mode::MoveToChar(RightUntil));
675                Ok(())
676            }
677            Key::Char('T') => {
678                self.set_mode(Mode::MoveToChar(LeftUntil));
679                Ok(())
680            }
681            Key::Char('f') => {
682                self.set_mode(Mode::MoveToChar(RightAt));
683                Ok(())
684            }
685            Key::Char('F') => {
686                self.set_mode(Mode::MoveToChar(LeftAt));
687                Ok(())
688            }
689            Key::Char(';') => self.handle_key_move_to_char(key, Repeat),
690            Key::Char(',') => self.handle_key_move_to_char(key, ReverseRepeat),
691            Key::Char('w') => {
692                let count = self.move_count();
693                try!(move_word(&mut self.ed, count));
694                self.pop_mode_after_movement(Exclusive)
695            }
696            Key::Char('W') => {
697                let count = self.move_count();
698                try!(move_word_ws(&mut self.ed, count));
699                self.pop_mode_after_movement(Exclusive)
700            }
701            Key::Char('e') => {
702                let count = self.move_count();
703                try!(move_to_end_of_word(&mut self.ed, count));
704                self.pop_mode_after_movement(Exclusive)
705            }
706            Key::Char('E') => {
707                let count = self.move_count();
708                try!(move_to_end_of_word_ws(&mut self.ed, count));
709                self.pop_mode_after_movement(Exclusive)
710            }
711            Key::Char('b') => {
712                let count = self.move_count();
713                try!(move_word_back(&mut self.ed, count));
714                self.pop_mode_after_movement(Exclusive)
715            }
716            Key::Char('B') => {
717                let count = self.move_count();
718                try!(move_word_ws_back(&mut self.ed, count));
719                self.pop_mode_after_movement(Exclusive)
720            }
721            Key::Char('g') => {
722                self.set_mode(Mode::G);
723                Ok(())
724            }
725            // if count is 0, 0 should move to start of line
726            Key::Char('0') if self.count == 0 => {
727                try!(self.ed.move_cursor_to_start_of_line());
728                self.pop_mode_after_movement(Exclusive)
729            }
730            Key::Char(i @ '0'...'9') => {
731                let i = i.to_digit(10).unwrap();
732                // count = count * 10 + i
733                self.count = self.count
734                    .saturating_mul(10)
735                    .saturating_add(i);
736                Ok(())
737            }
738            Key::Char('$') => {
739                try!(self.ed.move_cursor_to_end_of_line());
740                self.pop_mode_after_movement(Exclusive)
741            }
742            Key::Char('x') | Key::Delete => {
743                // update the last command state
744                self.last_insert = None;
745                self.last_command.clear();
746                self.last_command.push(key);
747                self.last_count = self.count;
748
749                let pos = self.ed.cursor() + self.move_count_right();
750                try!(self.ed.delete_until(pos));
751                self.count = 0;
752                Ok(())
753            }
754            Key::Char('~') => {
755                // update the last command state
756                self.last_insert = None;
757                self.last_command.clear();
758                self.last_command.push(key);
759                self.last_count = self.count;
760
761                self.set_mode(Tilde);
762                for _ in 0..self.move_count_right() {
763                    let c = self.ed.current_buffer().char_after(self.ed.cursor()).unwrap();
764                    if c.is_lowercase() {
765                        try!(self.ed.delete_after_cursor());
766                        for c in c.to_uppercase() {
767                            try!(self.ed.insert_after_cursor(c));
768                        }
769                    }
770                    else if c.is_uppercase() {
771                        try!(self.ed.delete_after_cursor());
772                        for c in c.to_lowercase() {
773                            try!(self.ed.insert_after_cursor(c));
774                        }
775                    }
776                    else {
777                        try!(self.ed.move_cursor_right(1));
778                    }
779                }
780                self.pop_mode();
781                Ok(())
782            }
783            Key::Char('u') => {
784                let count = self.move_count();
785                self.count = 0;
786                for _ in 0..count {
787                    let did = try!(self.ed.undo());
788                    if !did {
789                        break;
790                    }
791                }
792                Ok(())
793            }
794            Key::Ctrl('r') => {
795                let count = self.move_count();
796                self.count = 0;
797                for _ in 0..count {
798                    let did = try!(self.ed.redo());
799                    if !did {
800                        break;
801                    }
802                }
803                Ok(())
804            }
805            _ => self.handle_key_common(key),
806        }
807    }
808
809    fn handle_key_replace(&mut self, key: Key) -> io::Result<()> {
810        match key {
811            Key::Char(c) => {
812                // make sure there are enough chars to replace
813                if self.move_count_right() == self.move_count() {
814                    // update the last command state
815                    self.last_insert = None;
816                    self.last_command.clear();
817                    self.last_command.push(Key::Char('r'));
818                    self.last_command.push(key);
819                    self.last_count = self.count;
820
821                    // replace count characters
822                    self.ed.current_buffer_mut().start_undo_group();
823                    for _ in 0..self.move_count_right() {
824                        try!(self.ed.delete_after_cursor());
825                        try!(self.ed.insert_after_cursor(c));
826                    }
827                    self.ed.current_buffer_mut().end_undo_group();
828
829                    try!(self.ed.move_cursor_left(1));
830                }
831                self.pop_mode();
832            }
833            // not a char
834            _ => {
835                self.normal_mode_abort();
836            }
837        };
838
839        // back to normal mode
840        self.count = 0;
841        Ok(())
842    }
843
844    fn handle_key_delete_or_change(&mut self, key: Key) -> io::Result<()> {
845        match (key, self.current_insert) {
846            // check if this is a movement key
847            (key, _) if is_movement_key(key) | (key == Key::Char('0') && self.count == 0) => {
848                // set count
849                self.count = match (self.count, self.secondary_count) {
850                    (0, 0) => 0,
851                    (_, 0) => self.count,
852                    (0, _) => self.secondary_count,
853                    _ => {
854                        // secondary_count * count
855                        self.secondary_count
856                            .saturating_mul(self.count)
857                    }
858                };
859
860                // update the last command state
861                self.current_command.push(key);
862
863                // execute movement
864                self.handle_key_normal(key)
865            }
866            // handle numeric keys
867            (Key::Char('0'...'9'), _) => {
868                self.handle_key_normal(key)
869            }
870            (Key::Char('c'), Some(Key::Char('c'))) | (Key::Char('d'), None) => {
871                // updating the last command buffer doesn't really make sense in this context.
872                // Repeating 'dd' will simply erase and already erased line. Any other commands
873                // will then become the new last command and the user will need to press 'dd' again
874                // to clear the line. The same largely applies to the 'cc' command. We update the
875                // last command here anyway ¯\_(ツ)_/¯
876                self.current_command.push(key);
877
878                // delete the whole line
879                self.count = 0;
880                self.secondary_count = 0;
881                try!(self.ed.move_cursor_to_start_of_line());
882                try!(self.ed.delete_all_after_cursor());
883
884                // return to the previous mode
885                self.pop_mode();
886                Ok(())
887            }
888            // not a delete or change command, back to normal mode
889            _ => {
890                self.normal_mode_abort();
891                Ok(())
892            }
893        }
894    }
895
896    fn handle_key_move_to_char(&mut self, key: Key, movement: CharMovement) -> io::Result<()> {
897        use self::CharMovement::*;
898        use self::MoveType::*;
899
900        let count = self.move_count();
901        self.count = 0;
902
903        let (key, movement) = match (key, movement, self.last_char_movement) {
904            // repeat the last movement
905            (_, Repeat, Some((c, last_movement))) => (Key::Char(c), last_movement),
906            // repeat the last movement in the opposite direction
907            (_, ReverseRepeat, Some((c, LeftUntil))) => (Key::Char(c), RightUntil),
908            (_, ReverseRepeat, Some((c, RightUntil))) => (Key::Char(c), LeftUntil),
909            (_, ReverseRepeat, Some((c, LeftAt))) => (Key::Char(c), RightAt),
910            (_, ReverseRepeat, Some((c, RightAt))) => (Key::Char(c), LeftAt),
911            // pass valid keys through as is
912            (Key::Char(c), _, _) => {
913                // store last command info
914                self.last_char_movement = Some((c, movement));
915                self.current_command.push(key);
916                (key, movement)
917            }
918            // all other combinations are invalid, abort. This includes repeats with no
919            // last_char_movement stored, and non char key presses.
920            _ => {
921                self.normal_mode_abort();
922                return Ok(());
923            }
924        };
925
926        match key {
927            Key::Char(c) => {
928                let move_type;
929                try!(match movement {
930                    RightUntil => {
931                        move_type = Inclusive;
932                        match find_char(self.ed.current_buffer(), self.ed.cursor() + 1, c, count) {
933                            Some(i) => self.ed.move_cursor_to(i - 1),
934                            None => Ok(()),
935                        }
936                    }
937                    RightAt => {
938                        move_type = Inclusive;
939                        match find_char(self.ed.current_buffer(), self.ed.cursor() + 1, c, count) {
940                            Some(i) => self.ed.move_cursor_to(i),
941                            None => Ok(()),
942                        }
943                    }
944                    LeftUntil => {
945                        move_type = Exclusive;
946                        match find_char_rev(self.ed.current_buffer(), self.ed.cursor(), c, count) {
947                            Some(i) => self.ed.move_cursor_to(i + 1),
948                            None => Ok(()),
949                        }
950                    }
951                    LeftAt => {
952                        move_type = Exclusive;
953                        match find_char_rev(self.ed.current_buffer(), self.ed.cursor(), c, count) {
954                            Some(i) => self.ed.move_cursor_to(i),
955                            None => Ok(()),
956                        }
957                    }
958                    Repeat | ReverseRepeat => unreachable!(),
959                });
960
961                // go back to the previous mode
962                self.pop_mode_after_movement(move_type)
963            }
964
965            // can't get here due to our match above
966            _ => unreachable!(),
967        }
968    }
969
970    fn handle_key_g(&mut self, key: Key) -> io::Result<()> {
971        use self::MoveType::*;
972
973        let count = self.move_count();
974        self.current_command.push(key);
975
976        let res = match key {
977            Key::Char('e') => {
978                try!(move_to_end_of_word_back(&mut self.ed, count));
979                self.pop_mode_after_movement(Inclusive)
980            }
981            Key::Char('E') => {
982                try!(move_to_end_of_word_ws_back(&mut self.ed, count));
983                self.pop_mode_after_movement(Inclusive)
984            }
985
986            // not a supported command
987            _ => {
988                self.normal_mode_abort();
989                Ok(())
990            }
991        };
992
993        self.count = 0;
994        res
995    }
996}
997
998impl<'a, W: Write> KeyMap<'a, W, Vi<'a, W>> for Vi<'a, W> {
999    fn handle_key_core(&mut self, key: Key) -> io::Result<()> {
1000        match self.mode() {
1001            Mode::Normal => self.handle_key_normal(key),
1002            Mode::Insert => self.handle_key_insert(key),
1003            Mode::Replace => self.handle_key_replace(key),
1004            Mode::Delete(_) => self.handle_key_delete_or_change(key),
1005            Mode::MoveToChar(movement) => self.handle_key_move_to_char(key, movement),
1006            Mode::G => self.handle_key_g(key),
1007            Mode::Tilde => unreachable!(),
1008        }
1009    }
1010
1011    fn editor_mut(&mut self) ->  &mut Editor<'a, W> {
1012        &mut self.ed
1013    }
1014
1015    fn editor(&self) ->  &Editor<'a, W> {
1016        &self.ed
1017    }
1018}
1019
1020impl<'a, W: Write> From<Vi<'a, W>> for String {
1021    fn from(vi: Vi<'a, W>) -> String {
1022        vi.ed.into()
1023    }
1024}
1025
1026#[cfg(test)]
1027mod tests {
1028    use super::*;
1029    use termion::event::Key;
1030    use termion::event::Key::*;
1031    use Buffer;
1032    use Context;
1033    use Editor;
1034    use KeyMap;
1035    use std::io::Write;
1036
1037    macro_rules! simulate_keys {
1038        ($keymap:ident, $keys:expr) => {{
1039            simulate_keys(&mut $keymap, $keys.into_iter())
1040        }}
1041    }
1042
1043    fn simulate_keys<'a, 'b, W: Write, T, M: KeyMap<'a, W, T>, I>(keymap: &mut M, keys: I) -> bool
1044        where I: Iterator<Item=&'b Key>
1045    {
1046        for k in keys {
1047            if keymap.handle_key(*k, &mut |_| {}).unwrap() {
1048                return true;
1049            }
1050        }
1051
1052        false
1053    }
1054
1055    #[test]
1056    fn enter_is_done() {
1057        let mut context = Context::new();
1058        let out = Vec::new();
1059        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1060        let mut map = Vi::new(ed);
1061        map.ed.insert_str_after_cursor("done").unwrap();
1062        assert_eq!(map.ed.cursor(), 4);
1063
1064        assert!(simulate_keys!(map, [
1065            Char('\n'),
1066        ]));
1067
1068        assert_eq!(map.ed.cursor(), 4);
1069        assert_eq!(String::from(map), "done");
1070    }
1071
1072    #[test]
1073    fn move_cursor_left() {
1074        let mut context = Context::new();
1075        let out = Vec::new();
1076        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1077        let mut map = Vi::new(ed);
1078        map.editor_mut().insert_str_after_cursor("let").unwrap();
1079        assert_eq!(map.ed.cursor(), 3);
1080
1081        simulate_keys!(map, [
1082            Left,
1083            Char('f'),
1084        ]);
1085
1086        assert_eq!(map.ed.cursor(), 3);
1087        assert_eq!(String::from(map), "left");
1088    }
1089
1090    #[test]
1091    fn cursor_movement() {
1092        let mut context = Context::new();
1093        let out = Vec::new();
1094        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1095        let mut map = Vi::new(ed);
1096        map.ed.insert_str_after_cursor("right").unwrap();
1097        assert_eq!(map.ed.cursor(), 5);
1098
1099        simulate_keys!(map, [
1100            Left,
1101            Left,
1102            Right,
1103        ]);
1104
1105        assert_eq!(map.ed.cursor(), 4);
1106    }
1107
1108    #[test]
1109    fn vi_initial_insert() {
1110        let mut context = Context::new();
1111        let out = Vec::new();
1112        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1113        let mut map = Vi::new(ed);
1114
1115        simulate_keys!(map, [
1116            Char('i'),
1117            Char('n'),
1118            Char('s'),
1119            Char('e'),
1120            Char('r'),
1121            Char('t'),
1122        ]);
1123
1124        assert_eq!(map.ed.cursor(), 6);
1125        assert_eq!(String::from(map), "insert");
1126    }
1127
1128    #[test]
1129    fn vi_left_right_movement() {
1130        let mut context = Context::new();
1131        let out = Vec::new();
1132        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1133        let mut map = Vi::new(ed);
1134        map.ed.insert_str_after_cursor("data").unwrap();
1135        assert_eq!(map.ed.cursor(), 4);
1136
1137        simulate_keys!(map, [Left]);
1138        assert_eq!(map.ed.cursor(), 3);
1139        simulate_keys!(map, [Right]);
1140        assert_eq!(map.ed.cursor(), 4);
1141
1142        // switching from insert mode moves the cursor left
1143        simulate_keys!(map, [Esc, Left]);
1144        assert_eq!(map.ed.cursor(), 2);
1145        simulate_keys!(map, [Right]);
1146        assert_eq!(map.ed.cursor(), 3);
1147
1148        simulate_keys!(map, [Char('h')]);
1149        assert_eq!(map.ed.cursor(), 2);
1150        simulate_keys!(map, [Char('l')]);
1151        assert_eq!(map.ed.cursor(), 3);
1152    }
1153
1154    #[test]
1155    /// Shouldn't be able to move past the last char in vi normal mode
1156    fn vi_no_eol() {
1157        let mut context = Context::new();
1158        let out = Vec::new();
1159        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1160        let mut map = Vi::new(ed);
1161        map.ed.insert_str_after_cursor("data").unwrap();
1162        assert_eq!(map.ed.cursor(), 4);
1163
1164        simulate_keys!(map, [Esc]);
1165        assert_eq!(map.ed.cursor(), 3);
1166
1167        simulate_keys!(map, [Right, Right]);
1168        assert_eq!(map.ed.cursor(), 3);
1169
1170        // in insert mode, we can move past the last char, but no further
1171        simulate_keys!(map, [Char('i'), Right, Right]);
1172        assert_eq!(map.ed.cursor(), 4);
1173    }
1174
1175    #[test]
1176    /// Cursor moves left when exiting insert mode.
1177    fn vi_switch_from_insert() {
1178        let mut context = Context::new();
1179        let out = Vec::new();
1180        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1181        let mut map = Vi::new(ed);
1182        map.ed.insert_str_after_cursor("data").unwrap();
1183        assert_eq!(map.ed.cursor(), 4);
1184
1185        simulate_keys!(map, [Esc]);
1186        assert_eq!(map.ed.cursor(), 3);
1187
1188        simulate_keys!(map, [
1189            Char('i'),
1190            Esc,
1191            Char('i'),
1192            Esc,
1193            Char('i'),
1194            Esc,
1195            Char('i'),
1196            Esc,
1197        ]);
1198        assert_eq!(map.ed.cursor(), 0);
1199    }
1200
1201    #[test]
1202    fn vi_normal_history_cursor_eol() {
1203        let mut context = Context::new();
1204        context.history.push("history".into()).unwrap();
1205        context.history.push("history".into()).unwrap();
1206        let out = Vec::new();
1207        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1208        let mut map = Vi::new(ed);
1209        map.ed.insert_str_after_cursor("data").unwrap();
1210        assert_eq!(map.ed.cursor(), 4);
1211
1212        simulate_keys!(map, [Up]);
1213        assert_eq!(map.ed.cursor(), 7);
1214
1215        // in normal mode, make sure we don't end up past the last char
1216        simulate_keys!(map, [Esc, Up]);
1217        assert_eq!(map.ed.cursor(), 6);
1218    }
1219
1220    #[test]
1221    fn vi_normal_delete() {
1222        let mut context = Context::new();
1223        context.history.push("history".into()).unwrap();
1224        context.history.push("history".into()).unwrap();
1225        let out = Vec::new();
1226        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1227        let mut map = Vi::new(ed);
1228        map.ed.insert_str_after_cursor("data").unwrap();
1229        assert_eq!(map.ed.cursor(), 4);
1230
1231        simulate_keys!(map, [
1232            Esc,
1233            Char('0'),
1234            Delete,
1235            Char('x'),
1236        ]);
1237        assert_eq!(map.ed.cursor(), 0);
1238        assert_eq!(String::from(map), "ta");
1239    }
1240
1241    #[test]
1242    fn vi_substitute_command() {
1243        let mut context = Context::new();
1244        let out = Vec::new();
1245        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1246        let mut map = Vi::new(ed);
1247        map.ed.insert_str_after_cursor("data").unwrap();
1248        assert_eq!(map.ed.cursor(), 4);
1249
1250        simulate_keys!(map, [
1251            Esc,
1252            Char('0'),
1253            Char('s'),
1254            Char('s'),
1255        ]);
1256        assert_eq!(String::from(map), "sata");
1257    }
1258
1259    #[test]
1260    fn substitute_with_count() {
1261        let mut context = Context::new();
1262        let out = Vec::new();
1263        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1264        let mut map = Vi::new(ed);
1265        map.ed.insert_str_after_cursor("data").unwrap();
1266        assert_eq!(map.ed.cursor(), 4);
1267
1268        simulate_keys!(map, [
1269            Esc,
1270            Char('0'),
1271            Char('2'),
1272            Char('s'),
1273            Char('b'),
1274            Char('e'),
1275        ]);
1276        assert_eq!(String::from(map), "beta");
1277    }
1278
1279    #[test]
1280    fn substitute_with_count_repeat() {
1281        let mut context = Context::new();
1282        let out = Vec::new();
1283        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1284        let mut map = Vi::new(ed);
1285        map.ed.insert_str_after_cursor("data data").unwrap();
1286
1287        simulate_keys!(map, [
1288            Esc,
1289            Char('0'),
1290            Char('2'),
1291            Char('s'),
1292            Char('b'),
1293            Char('e'),
1294            Esc,
1295            Char('4'),
1296            Char('l'),
1297            Char('.'),
1298        ]);
1299        assert_eq!(String::from(map), "beta beta");
1300    }
1301
1302    #[test]
1303    /// make sure our count is accurate
1304    fn vi_count() {
1305        let mut context = Context::new();
1306        let out = Vec::new();
1307        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1308        let mut map = Vi::new(ed);
1309
1310        simulate_keys!(map, [
1311            Esc,
1312        ]);
1313        assert_eq!(map.count, 0);
1314
1315        simulate_keys!(map, [
1316            Char('1'),
1317        ]);
1318        assert_eq!(map.count, 1);
1319
1320        simulate_keys!(map, [
1321            Char('1'),
1322        ]);
1323        assert_eq!(map.count, 11);
1324
1325        // switching to insert mode and back to edit mode should reset the count
1326        simulate_keys!(map, [
1327            Char('i'),
1328            Esc,
1329        ]);
1330        assert_eq!(map.count, 0);
1331
1332        assert_eq!(String::from(map), "");
1333    }
1334
1335    #[test]
1336    /// make sure large counts don't overflow
1337    fn vi_count_overflow() {
1338        let mut context = Context::new();
1339        let out = Vec::new();
1340        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1341        let mut map = Vi::new(ed);
1342
1343        // make sure large counts don't overflow our u32
1344        simulate_keys!(map, [
1345            Esc,
1346            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1347            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1348            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1349            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1350            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1351            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1352            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1353            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1354            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1355            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1356            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1357            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1358            Char('9'), Char('9'), Char('9'), Char('9'), Char('9'),
1359        ]);
1360        assert_eq!(String::from(map), "");
1361    }
1362
1363    #[test]
1364    /// make sure large counts ending in zero don't overflow
1365    fn vi_count_overflow_zero() {
1366        let mut context = Context::new();
1367        let out = Vec::new();
1368        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1369        let mut map = Vi::new(ed);
1370
1371        // make sure large counts don't overflow our u32
1372        simulate_keys!(map, [
1373            Esc,
1374            Char('1'), Char('0'), Char('0'), Char('0'), Char('0'),
1375            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1376            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1377            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1378            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1379            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1380            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1381            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1382            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1383            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1384            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1385            Char('0'), Char('0'), Char('0'), Char('0'), Char('0'),
1386        ]);
1387        assert_eq!(String::from(map), "");
1388    }
1389
1390    #[test]
1391    /// Esc should cancel the count
1392    fn vi_count_cancel() {
1393        let mut context = Context::new();
1394        let out = Vec::new();
1395        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1396        let mut map = Vi::new(ed);
1397
1398        simulate_keys!(map, [
1399            Esc,
1400            Char('1'),
1401            Char('0'),
1402            Esc,
1403        ]);
1404        assert_eq!(map.count, 0);
1405        assert_eq!(String::from(map), "");
1406    }
1407
1408    #[test]
1409    /// test insert with a count
1410    fn vi_count_simple() {
1411        let mut context = Context::new();
1412        let out = Vec::new();
1413        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1414        let mut map = Vi::new(ed);
1415
1416        simulate_keys!(map, [
1417            Esc,
1418            Char('3'),
1419            Char('i'),
1420            Char('t'),
1421            Char('h'),
1422            Char('i'),
1423            Char('s'),
1424            Esc,
1425        ]);
1426        assert_eq!(String::from(map), "thisthisthis");
1427    }
1428
1429    #[test]
1430    /// test dot command
1431    fn vi_dot_command() {
1432        let mut context = Context::new();
1433        let out = Vec::new();
1434        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1435        let mut map = Vi::new(ed);
1436
1437        simulate_keys!(map, [
1438            Char('i'),
1439            Char('f'),
1440            Esc,
1441            Char('.'),
1442            Char('.'),
1443        ]);
1444        assert_eq!(String::from(map), "iiifff");
1445    }
1446
1447    #[test]
1448    /// test dot command with repeat
1449    fn vi_dot_command_repeat() {
1450        let mut context = Context::new();
1451        let out = Vec::new();
1452        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1453        let mut map = Vi::new(ed);
1454
1455        simulate_keys!(map, [
1456            Char('i'),
1457            Char('f'),
1458            Esc,
1459            Char('3'),
1460            Char('.'),
1461        ]);
1462        assert_eq!(String::from(map), "iifififf");
1463    }
1464
1465    #[test]
1466    /// test dot command with repeat
1467    fn vi_dot_command_repeat_multiple() {
1468        let mut context = Context::new();
1469        let out = Vec::new();
1470        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1471        let mut map = Vi::new(ed);
1472
1473        simulate_keys!(map, [
1474            Char('i'),
1475            Char('f'),
1476            Esc,
1477            Char('3'),
1478            Char('.'),
1479            Char('.'),
1480        ]);
1481        assert_eq!(String::from(map), "iififiifififff");
1482    }
1483
1484    #[test]
1485    /// test dot command with append
1486    fn vi_dot_command_append() {
1487        let mut context = Context::new();
1488        let out = Vec::new();
1489        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1490        let mut map = Vi::new(ed);
1491
1492        simulate_keys!(map, [
1493            Esc,
1494            Char('a'),
1495            Char('i'),
1496            Char('f'),
1497            Esc,
1498            Char('.'),
1499            Char('.'),
1500        ]);
1501        assert_eq!(String::from(map), "ififif");
1502    }
1503
1504    #[test]
1505    /// test dot command with append and repeat
1506    fn vi_dot_command_append_repeat() {
1507        let mut context = Context::new();
1508        let out = Vec::new();
1509        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1510        let mut map = Vi::new(ed);
1511
1512        simulate_keys!(map, [
1513            Esc,
1514            Char('a'),
1515            Char('i'),
1516            Char('f'),
1517            Esc,
1518            Char('3'),
1519            Char('.'),
1520        ]);
1521        assert_eq!(String::from(map), "ifififif");
1522    }
1523
1524    #[test]
1525    /// test dot command with movement
1526    fn vi_dot_command_movement() {
1527        let mut context = Context::new();
1528        let out = Vec::new();
1529        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1530        let mut map = Vi::new(ed);
1531
1532        simulate_keys!(map, [
1533            Esc,
1534            Char('a'),
1535            Char('d'),
1536            Char('t'),
1537            Char(' '),
1538            Left,
1539            Left,
1540            Char('a'),
1541            Esc,
1542            Right,
1543            Right,
1544            Char('.'),
1545        ]);
1546        assert_eq!(String::from(map), "data ");
1547    }
1548
1549    #[test]
1550    /// test move_count function
1551    fn move_count() {
1552        let mut context = Context::new();
1553        let out = Vec::new();
1554        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1555        let mut map = Vi::new(ed);
1556
1557        assert_eq!(map.move_count(), 1);
1558        map.count = 1;
1559        assert_eq!(map.move_count(), 1);
1560        map.count = 99;
1561        assert_eq!(map.move_count(), 99);
1562    }
1563
1564    #[test]
1565    /// make sure the count is reset if movement occurs
1566    fn vi_count_movement_reset() {
1567        let mut context = Context::new();
1568        let out = Vec::new();
1569        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1570        let mut map = Vi::new(ed);
1571
1572        simulate_keys!(map, [
1573            Esc,
1574            Char('3'),
1575            Char('i'),
1576            Char('t'),
1577            Char('h'),
1578            Char('i'),
1579            Char('s'),
1580            Left,
1581            Esc,
1582        ]);
1583        assert_eq!(String::from(map), "this");
1584    }
1585
1586    #[test]
1587    /// test movement with counts
1588    fn movement_with_count() {
1589        let mut context = Context::new();
1590        let out = Vec::new();
1591        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1592        let mut map = Vi::new(ed);
1593        map.ed.insert_str_after_cursor("right").unwrap();
1594        assert_eq!(map.ed.cursor(), 5);
1595
1596        simulate_keys!(map, [
1597            Esc,
1598            Char('3'),
1599            Left,
1600        ]);
1601
1602        assert_eq!(map.ed.cursor(), 1);
1603    }
1604
1605    #[test]
1606    /// test movement with counts, then insert (count should be reset before insert)
1607    fn movement_with_count_then_insert() {
1608        let mut context = Context::new();
1609        let out = Vec::new();
1610        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1611        let mut map = Vi::new(ed);
1612        map.ed.insert_str_after_cursor("right").unwrap();
1613        assert_eq!(map.ed.cursor(), 5);
1614
1615        simulate_keys!(map, [
1616            Esc,
1617            Char('3'),
1618            Left,
1619            Char('i'),
1620            Char(' '),
1621            Esc,
1622        ]);
1623        assert_eq!(String::from(map), "r ight");
1624    }
1625
1626    #[test]
1627    /// make sure we only attempt to repeat for as many chars are in the buffer
1628    fn count_at_buffer_edge() {
1629        let mut context = Context::new();
1630        let out = Vec::new();
1631        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1632        let mut map = Vi::new(ed);
1633        map.ed.insert_str_after_cursor("replace").unwrap();
1634        assert_eq!(map.ed.cursor(), 7);
1635
1636        simulate_keys!(map, [
1637            Esc,
1638            Char('3'),
1639            Char('r'),
1640            Char('x'),
1641        ]);
1642        // the cursor should not have moved and no change should have occured
1643        assert_eq!(map.ed.cursor(), 6);
1644        assert_eq!(String::from(map), "replace");
1645    }
1646
1647    #[test]
1648    /// test basic replace
1649    fn basic_replace() {
1650        let mut context = Context::new();
1651        let out = Vec::new();
1652        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1653        let mut map = Vi::new(ed);
1654        map.ed.insert_str_after_cursor("replace").unwrap();
1655        assert_eq!(map.ed.cursor(), 7);
1656
1657        simulate_keys!(map, [
1658            Esc,
1659            Char('r'),
1660            Char('x'),
1661        ]);
1662        assert_eq!(map.ed.cursor(), 6);
1663        assert_eq!(String::from(map), "replacx");
1664    }
1665
1666    #[test]
1667    fn replace_with_count() {
1668        let mut context = Context::new();
1669        let out = Vec::new();
1670        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1671        let mut map = Vi::new(ed);
1672        map.ed.insert_str_after_cursor("replace").unwrap();
1673        assert_eq!(map.ed.cursor(), 7);
1674
1675        simulate_keys!(map, [
1676            Esc,
1677            Char('0'),
1678            Char('3'),
1679            Char('r'),
1680            Char(' '),
1681        ]);
1682        // cursor should be on the last replaced char
1683        assert_eq!(map.ed.cursor(), 2);
1684        assert_eq!(String::from(map), "   lace");
1685    }
1686
1687    #[test]
1688    /// make sure replace won't work if there aren't enough chars
1689    fn replace_with_count_eol() {
1690        let mut context = Context::new();
1691        let out = Vec::new();
1692        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1693        let mut map = Vi::new(ed);
1694        map.ed.insert_str_after_cursor("replace").unwrap();
1695        assert_eq!(map.ed.cursor(), 7);
1696
1697        simulate_keys!(map, [
1698            Esc,
1699            Char('3'),
1700            Char('r'),
1701            Char('x'),
1702        ]);
1703        // the cursor should not have moved and no change should have occured
1704        assert_eq!(map.ed.cursor(), 6);
1705        assert_eq!(String::from(map), "replace");
1706    }
1707
1708    #[test]
1709    /// make sure normal mode is enabled after replace
1710    fn replace_then_normal() {
1711        let mut context = Context::new();
1712        let out = Vec::new();
1713        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1714        let mut map = Vi::new(ed);
1715        map.ed.insert_str_after_cursor("replace").unwrap();
1716        assert_eq!(map.ed.cursor(), 7);
1717
1718        simulate_keys!(map, [
1719            Esc,
1720            Char('r'),
1721            Char('x'),
1722            Char('0'),
1723        ]);
1724        assert_eq!(map.ed.cursor(), 0);
1725        assert_eq!(String::from(map), "replacx");
1726    }
1727
1728    #[test]
1729    /// test replace with dot
1730    fn dot_replace() {
1731        let mut context = Context::new();
1732        let out = Vec::new();
1733        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1734        let mut map = Vi::new(ed);
1735        map.ed.insert_str_after_cursor("replace").unwrap();
1736        assert_eq!(map.ed.cursor(), 7);
1737
1738        simulate_keys!(map, [
1739            Esc,
1740            Char('0'),
1741            Char('r'),
1742            Char('x'),
1743            Char('.'),
1744            Char('.'),
1745            Char('7'),
1746            Char('.'),
1747        ]);
1748        assert_eq!(String::from(map), "xxxxxxx");
1749    }
1750
1751    #[test]
1752    /// test replace with dot
1753    fn dot_replace_count() {
1754        let mut context = Context::new();
1755        let out = Vec::new();
1756        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1757        let mut map = Vi::new(ed);
1758        map.ed.insert_str_after_cursor("replace").unwrap();
1759        assert_eq!(map.ed.cursor(), 7);
1760
1761        simulate_keys!(map, [
1762            Esc,
1763            Char('0'),
1764            Char('2'),
1765            Char('r'),
1766            Char('x'),
1767            Char('.'),
1768            Char('.'),
1769            Char('.'),
1770            Char('.'),
1771            Char('.'),
1772        ]);
1773        assert_eq!(String::from(map), "xxxxxxx");
1774    }
1775
1776    #[test]
1777    /// test replace with dot at eol
1778    fn dot_replace_eol() {
1779        let mut context = Context::new();
1780        let out = Vec::new();
1781        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1782        let mut map = Vi::new(ed);
1783        map.ed.insert_str_after_cursor("test").unwrap();
1784
1785        simulate_keys!(map, [
1786            Esc,
1787            Char('0'),
1788            Char('3'),
1789            Char('r'),
1790            Char('x'),
1791            Char('.'),
1792            Char('.'),
1793        ]);
1794        assert_eq!(String::from(map), "xxxt");
1795    }
1796
1797    #[test]
1798    /// test replace with dot at eol multiple times
1799    fn dot_replace_eol_multiple() {
1800        let mut context = Context::new();
1801        let out = Vec::new();
1802        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1803        let mut map = Vi::new(ed);
1804        map.ed.insert_str_after_cursor("this is a test").unwrap();
1805
1806        simulate_keys!(map, [
1807            Esc,
1808            Char('0'),
1809            Char('3'),
1810            Char('r'),
1811            Char('x'),
1812            Char('$'),
1813            Char('.'),
1814            Char('4'),
1815            Char('h'),
1816            Char('.'),
1817        ]);
1818        assert_eq!(String::from(map), "xxxs is axxxst");
1819    }
1820
1821    #[test]
1822    /// verify our move count
1823    fn move_count_right() {
1824        let mut context = Context::new();
1825        let out = Vec::new();
1826        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1827        let mut map = Vi::new(ed);
1828        map.ed.insert_str_after_cursor("replace").unwrap();
1829        assert_eq!(map.ed.cursor(), 7);
1830        assert_eq!(map.move_count_right(), 0);
1831        map.count = 10;
1832        assert_eq!(map.move_count_right(), 0);
1833
1834        map.count = 0;
1835        simulate_keys!(map, [
1836            Esc,
1837            Left,
1838        ]);
1839        assert_eq!(map.move_count_right(), 1);
1840    }
1841
1842    #[test]
1843    /// verify our move count
1844    fn move_count_left() {
1845        let mut context = Context::new();
1846        let out = Vec::new();
1847        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1848        let mut map = Vi::new(ed);
1849        map.ed.insert_str_after_cursor("replace").unwrap();
1850        assert_eq!(map.ed.cursor(), 7);
1851        assert_eq!(map.move_count_left(), 1);
1852        map.count = 10;
1853        assert_eq!(map.move_count_left(), 7);
1854
1855        map.count = 0;
1856        simulate_keys!(map, [
1857            Esc,
1858            Char('0'),
1859        ]);
1860        assert_eq!(map.move_count_left(), 0);
1861    }
1862
1863    #[test]
1864    /// test delete with dot
1865    fn dot_x_delete() {
1866        let mut context = Context::new();
1867        let out = Vec::new();
1868        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1869        let mut map = Vi::new(ed);
1870        map.ed.insert_str_after_cursor("replace").unwrap();
1871        assert_eq!(map.ed.cursor(), 7);
1872
1873        simulate_keys!(map, [
1874            Esc,
1875            Char('0'),
1876            Char('2'),
1877            Char('x'),
1878            Char('.'),
1879        ]);
1880        assert_eq!(String::from(map), "ace");
1881    }
1882
1883    #[test]
1884    /// test deleting a line
1885    fn delete_line() {
1886        let mut context = Context::new();
1887        let out = Vec::new();
1888        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1889        let mut map = Vi::new(ed);
1890        map.ed.insert_str_after_cursor("delete").unwrap();
1891
1892        simulate_keys!(map, [
1893            Esc,
1894            Char('d'),
1895            Char('d'),
1896        ]);
1897        assert_eq!(map.ed.cursor(), 0);
1898        assert_eq!(String::from(map), "");
1899    }
1900
1901    #[test]
1902    /// test for normal mode after deleting a line
1903    fn delete_line_normal() {
1904        let mut context = Context::new();
1905        let out = Vec::new();
1906        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1907        let mut map = Vi::new(ed);
1908        map.ed.insert_str_after_cursor("delete").unwrap();
1909
1910        simulate_keys!(map, [
1911            Esc,
1912            Char('d'),
1913            Char('d'),
1914            Char('i'),
1915            Char('n'),
1916            Char('e'),
1917            Char('w'),
1918            Esc,
1919        ]);
1920        assert_eq!(map.ed.cursor(), 2);
1921        assert_eq!(String::from(map), "new");
1922    }
1923
1924    #[test]
1925    /// test aborting a delete (and change)
1926    fn delete_abort() {
1927        let mut context = Context::new();
1928        let out = Vec::new();
1929        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1930        let mut map = Vi::new(ed);
1931        map.ed.insert_str_after_cursor("don't delete").unwrap();
1932
1933        simulate_keys!(map, [
1934            Esc,
1935            Char('d'),
1936            Esc,
1937            Char('d'),
1938            Char('c'),
1939            Char('c'),
1940            Char('d'),
1941        ]);
1942        assert_eq!(map.ed.cursor(), 11);
1943        assert_eq!(String::from(map), "don't delete");
1944    }
1945
1946    #[test]
1947    /// test deleting a single char to the left
1948    fn delete_char_left() {
1949        let mut context = Context::new();
1950        let out = Vec::new();
1951        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1952        let mut map = Vi::new(ed);
1953        map.ed.insert_str_after_cursor("delete").unwrap();
1954
1955        simulate_keys!(map, [
1956            Esc,
1957            Char('d'),
1958            Char('h'),
1959        ]);
1960        assert_eq!(map.ed.cursor(), 4);
1961        assert_eq!(String::from(map), "delee");
1962    }
1963
1964    #[test]
1965    /// test deleting multiple chars to the left
1966    fn delete_chars_left() {
1967        let mut context = Context::new();
1968        let out = Vec::new();
1969        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1970        let mut map = Vi::new(ed);
1971        map.ed.insert_str_after_cursor("delete").unwrap();
1972
1973        simulate_keys!(map, [
1974            Esc,
1975            Char('3'),
1976            Char('d'),
1977            Char('h'),
1978        ]);
1979        assert_eq!(map.ed.cursor(), 2);
1980        assert_eq!(String::from(map), "dee");
1981    }
1982
1983    #[test]
1984    /// test deleting a single char to the right
1985    fn delete_char_right() {
1986        let mut context = Context::new();
1987        let out = Vec::new();
1988        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
1989        let mut map = Vi::new(ed);
1990        map.ed.insert_str_after_cursor("delete").unwrap();
1991
1992        simulate_keys!(map, [
1993            Esc,
1994            Char('0'),
1995            Char('d'),
1996            Char('l'),
1997        ]);
1998        assert_eq!(map.ed.cursor(), 0);
1999        assert_eq!(String::from(map), "elete");
2000    }
2001
2002    #[test]
2003    /// test deleting multiple chars to the right
2004    fn delete_chars_right() {
2005        let mut context = Context::new();
2006        let out = Vec::new();
2007        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2008        let mut map = Vi::new(ed);
2009        map.ed.insert_str_after_cursor("delete").unwrap();
2010
2011        simulate_keys!(map, [
2012            Esc,
2013            Char('0'),
2014            Char('3'),
2015            Char('d'),
2016            Char('l'),
2017        ]);
2018        assert_eq!(map.ed.cursor(), 0);
2019        assert_eq!(String::from(map), "ete");
2020    }
2021
2022    #[test]
2023    /// test repeat with delete
2024    fn delete_and_repeat() {
2025        let mut context = Context::new();
2026        let out = Vec::new();
2027        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2028        let mut map = Vi::new(ed);
2029        map.ed.insert_str_after_cursor("delete").unwrap();
2030
2031        simulate_keys!(map, [
2032            Esc,
2033            Char('0'),
2034            Char('d'),
2035            Char('l'),
2036            Char('.'),
2037        ]);
2038        assert_eq!(map.ed.cursor(), 0);
2039        assert_eq!(String::from(map), "lete");
2040    }
2041
2042    #[test]
2043    /// test delete until end of line
2044    fn delete_until_end() {
2045        let mut context = Context::new();
2046        let out = Vec::new();
2047        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2048        let mut map = Vi::new(ed);
2049        map.ed.insert_str_after_cursor("delete").unwrap();
2050
2051        simulate_keys!(map, [
2052            Esc,
2053            Char('0'),
2054            Char('d'),
2055            Char('$'),
2056        ]);
2057        assert_eq!(map.ed.cursor(), 0);
2058        assert_eq!(String::from(map), "");
2059    }
2060
2061    #[test]
2062    /// test delete until end of line
2063    fn delete_until_end_shift_d() {
2064        let mut context = Context::new();
2065        let out = Vec::new();
2066        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2067        let mut map = Vi::new(ed);
2068        map.ed.insert_str_after_cursor("delete").unwrap();
2069
2070        simulate_keys!(map, [
2071            Esc,
2072            Char('0'),
2073            Char('D'),
2074        ]);
2075        assert_eq!(map.ed.cursor(), 0);
2076        assert_eq!(String::from(map), "");
2077    }
2078
2079    #[test]
2080    /// test delete until start of line
2081    fn delete_until_start() {
2082        let mut context = Context::new();
2083        let out = Vec::new();
2084        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2085        let mut map = Vi::new(ed);
2086        map.ed.insert_str_after_cursor("delete").unwrap();
2087
2088        simulate_keys!(map, [
2089            Esc,
2090            Char('$'),
2091            Char('d'),
2092            Char('0'),
2093        ]);
2094        assert_eq!(map.ed.cursor(), 0);
2095        assert_eq!(String::from(map), "e");
2096    }
2097
2098    #[test]
2099    /// test a compound count with delete
2100    fn delete_with_count() {
2101        let mut context = Context::new();
2102        let out = Vec::new();
2103        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2104        let mut map = Vi::new(ed);
2105        map.ed.insert_str_after_cursor("delete").unwrap();
2106
2107        simulate_keys!(map, [
2108            Esc,
2109            Char('0'),
2110            Char('2'),
2111            Char('d'),
2112            Char('2'),
2113            Char('l'),
2114        ]);
2115        assert_eq!(map.ed.cursor(), 0);
2116        assert_eq!(String::from(map), "te");
2117    }
2118
2119    #[test]
2120    /// test a compound count with delete and repeat
2121    fn delete_with_count_and_repeat() {
2122        let mut context = Context::new();
2123        let out = Vec::new();
2124        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2125        let mut map = Vi::new(ed);
2126        map.ed.insert_str_after_cursor("delete delete").unwrap();
2127
2128        simulate_keys!(map, [
2129            Esc,
2130            Char('0'),
2131            Char('2'),
2132            Char('d'),
2133            Char('2'),
2134            Char('l'),
2135            Char('.'),
2136        ]);
2137        assert_eq!(map.ed.cursor(), 0);
2138        assert_eq!(String::from(map), "elete");
2139    }
2140
2141    #[test]
2142    fn move_to_end_of_word_simple() {
2143        let mut context = Context::new();
2144        let out = Vec::new();
2145        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2146
2147        ed.insert_str_after_cursor("here are").unwrap();
2148        let start_pos = ed.cursor();
2149        ed.insert_str_after_cursor(" som").unwrap();
2150        let end_pos = ed.cursor();
2151        ed.insert_str_after_cursor("e words").unwrap();
2152        ed.move_cursor_to(start_pos).unwrap();
2153
2154        super::move_to_end_of_word(&mut ed, 1).unwrap();
2155        assert_eq!(ed.cursor(), end_pos);
2156    }
2157
2158    #[test]
2159    fn move_to_end_of_word_comma() {
2160        let mut context = Context::new();
2161        let out = Vec::new();
2162        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2163
2164        ed.insert_str_after_cursor("here ar").unwrap();
2165        let start_pos = ed.cursor();
2166        ed.insert_after_cursor('e').unwrap();
2167        let end_pos1 = ed.cursor();
2168        ed.insert_str_after_cursor(", som").unwrap();
2169        let end_pos2 = ed.cursor();
2170        ed.insert_str_after_cursor("e words").unwrap();
2171        ed.move_cursor_to(start_pos).unwrap();
2172
2173        super::move_to_end_of_word(&mut ed, 1).unwrap();
2174        assert_eq!(ed.cursor(), end_pos1);
2175        super::move_to_end_of_word(&mut ed, 1).unwrap();
2176        assert_eq!(ed.cursor(), end_pos2);
2177    }
2178
2179    #[test]
2180    fn move_to_end_of_word_nonkeywords() {
2181        let mut context = Context::new();
2182        let out = Vec::new();
2183        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2184
2185        ed.insert_str_after_cursor("here ar").unwrap();
2186        let start_pos = ed.cursor();
2187        ed.insert_str_after_cursor("e,,,").unwrap();
2188        let end_pos1 = ed.cursor();
2189        ed.insert_str_after_cursor(",som").unwrap();
2190        let end_pos2 = ed.cursor();
2191        ed.insert_str_after_cursor("e words").unwrap();
2192        ed.move_cursor_to(start_pos).unwrap();
2193
2194        super::move_to_end_of_word(&mut ed, 1).unwrap();
2195        assert_eq!(ed.cursor(), end_pos1);
2196        super::move_to_end_of_word(&mut ed, 1).unwrap();
2197        assert_eq!(ed.cursor(), end_pos2);
2198    }
2199
2200    #[test]
2201    fn move_to_end_of_word_whitespace() {
2202        let mut context = Context::new();
2203        let out = Vec::new();
2204        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2205
2206        assert_eq!(ed.cursor(), 0);
2207        ed.insert_str_after_cursor("here are").unwrap();
2208        let start_pos = ed.cursor();
2209        assert_eq!(ed.cursor(), 8);
2210        ed.insert_str_after_cursor("      som").unwrap();
2211        assert_eq!(ed.cursor(), 17);
2212        ed.insert_str_after_cursor("e words").unwrap();
2213        assert_eq!(ed.cursor(), 24);
2214        ed.move_cursor_to(start_pos).unwrap();
2215        assert_eq!(ed.cursor(), 8);
2216
2217        super::move_to_end_of_word(&mut ed, 1).unwrap();
2218        assert_eq!(ed.cursor(), 17);
2219    }
2220
2221    #[test]
2222    fn move_to_end_of_word_whitespace_nonkeywords() {
2223        let mut context = Context::new();
2224        let out = Vec::new();
2225        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2226
2227        ed.insert_str_after_cursor("here ar").unwrap();
2228        let start_pos = ed.cursor();
2229        ed.insert_str_after_cursor("e   ,,,").unwrap();
2230        let end_pos1 = ed.cursor();
2231        ed.insert_str_after_cursor(", som").unwrap();
2232        let end_pos2 = ed.cursor();
2233        ed.insert_str_after_cursor("e words").unwrap();
2234        ed.move_cursor_to(start_pos).unwrap();
2235
2236        super::move_to_end_of_word(&mut ed, 1).unwrap();
2237        assert_eq!(ed.cursor(), end_pos1);
2238        super::move_to_end_of_word(&mut ed, 1).unwrap();
2239        assert_eq!(ed.cursor(), end_pos2);
2240    }
2241
2242    #[test]
2243    fn move_to_end_of_word_ws_simple() {
2244        let mut context = Context::new();
2245        let out = Vec::new();
2246        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2247
2248        ed.insert_str_after_cursor("here are").unwrap();
2249        let start_pos = ed.cursor();
2250        ed.insert_str_after_cursor(" som").unwrap();
2251        let end_pos = ed.cursor();
2252        ed.insert_str_after_cursor("e words").unwrap();
2253        ed.move_cursor_to(start_pos).unwrap();
2254
2255        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2256        assert_eq!(ed.cursor(), end_pos);
2257    }
2258
2259    #[test]
2260    fn move_to_end_of_word_ws_comma() {
2261        let mut context = Context::new();
2262        let out = Vec::new();
2263        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2264
2265        ed.insert_str_after_cursor("here ar").unwrap();
2266        let start_pos = ed.cursor();
2267        ed.insert_after_cursor('e').unwrap();
2268        let end_pos1 = ed.cursor();
2269        ed.insert_str_after_cursor(", som").unwrap();
2270        let end_pos2 = ed.cursor();
2271        ed.insert_str_after_cursor("e words").unwrap();
2272        ed.move_cursor_to(start_pos).unwrap();
2273
2274        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2275        assert_eq!(ed.cursor(), end_pos1);
2276        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2277        assert_eq!(ed.cursor(), end_pos2);
2278    }
2279
2280    #[test]
2281    fn move_to_end_of_word_ws_nonkeywords() {
2282        let mut context = Context::new();
2283        let out = Vec::new();
2284        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2285
2286        ed.insert_str_after_cursor("here ar").unwrap();
2287        let start_pos = ed.cursor();
2288        ed.insert_str_after_cursor("e,,,,som").unwrap();
2289        let end_pos = ed.cursor();
2290        ed.insert_str_after_cursor("e words").unwrap();
2291        ed.move_cursor_to(start_pos).unwrap();
2292        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2293        assert_eq!(ed.cursor(), end_pos);
2294    }
2295
2296    #[test]
2297    fn move_to_end_of_word_ws_whitespace() {
2298        let mut context = Context::new();
2299        let out = Vec::new();
2300        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2301
2302        ed.insert_str_after_cursor("here are").unwrap();
2303        let start_pos = ed.cursor();
2304        ed.insert_str_after_cursor("      som").unwrap();
2305        let end_pos = ed.cursor();
2306        ed.insert_str_after_cursor("e words").unwrap();
2307        ed.move_cursor_to(start_pos).unwrap();
2308
2309        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2310        assert_eq!(ed.cursor(), end_pos);
2311    }
2312
2313    #[test]
2314    fn move_to_end_of_word_ws_whitespace_nonkeywords() {
2315        let mut context = Context::new();
2316        let out = Vec::new();
2317        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2318
2319        ed.insert_str_after_cursor("here ar").unwrap();
2320        let start_pos = ed.cursor();
2321        ed.insert_str_after_cursor("e   ,,,").unwrap();
2322        let end_pos1 = ed.cursor();
2323        ed.insert_str_after_cursor(", som").unwrap();
2324        let end_pos2 = ed.cursor();
2325        ed.insert_str_after_cursor("e words").unwrap();
2326        ed.move_cursor_to(start_pos).unwrap();
2327
2328        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2329        assert_eq!(ed.cursor(), end_pos1);
2330        super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
2331        assert_eq!(ed.cursor(), end_pos2);
2332    }
2333
2334    #[test]
2335    fn move_word_simple() {
2336        let mut context = Context::new();
2337        let out = Vec::new();
2338        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2339
2340        ed.insert_str_after_cursor("here ").unwrap();
2341        let pos1 = ed.cursor();
2342        ed.insert_str_after_cursor("are ").unwrap();
2343        let pos2 = ed.cursor();
2344        ed.insert_str_after_cursor("some words").unwrap();
2345        ed.move_cursor_to_start_of_line().unwrap();
2346
2347        super::move_word(&mut ed, 1).unwrap();
2348        assert_eq!(ed.cursor(), pos1);
2349        super::move_word(&mut ed, 1).unwrap();
2350        assert_eq!(ed.cursor(), pos2);
2351
2352        ed.move_cursor_to_start_of_line().unwrap();
2353        super::move_word_ws(&mut ed, 1).unwrap();
2354        assert_eq!(ed.cursor(), pos1);
2355        super::move_word_ws(&mut ed, 1).unwrap();
2356        assert_eq!(ed.cursor(), pos2);
2357    }
2358
2359    #[test]
2360    fn move_word_whitespace() {
2361        let mut context = Context::new();
2362        let out = Vec::new();
2363        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2364
2365        ed.insert_str_after_cursor("   ").unwrap();
2366        let pos1 = ed.cursor();
2367        ed.insert_str_after_cursor("word").unwrap();
2368        let pos2 = ed.cursor();
2369        ed.move_cursor_to_start_of_line().unwrap();
2370
2371        super::move_word(&mut ed, 1).unwrap();
2372        assert_eq!(ed.cursor(), pos1);
2373        super::move_word(&mut ed, 1).unwrap();
2374        assert_eq!(ed.cursor(), pos2);
2375
2376        ed.move_cursor_to_start_of_line().unwrap();
2377        super::move_word_ws(&mut ed, 1).unwrap();
2378        assert_eq!(ed.cursor(), pos1);
2379        super::move_word_ws(&mut ed, 1).unwrap();
2380        assert_eq!(ed.cursor(), pos2);
2381    }
2382
2383    #[test]
2384    fn move_word_nonkeywords() {
2385        let mut context = Context::new();
2386        let out = Vec::new();
2387        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2388
2389        ed.insert_str_after_cursor("...").unwrap();
2390        let pos1 = ed.cursor();
2391        ed.insert_str_after_cursor("word").unwrap();
2392        let pos2 = ed.cursor();
2393        ed.move_cursor_to_start_of_line().unwrap();
2394
2395        super::move_word(&mut ed, 1).unwrap();
2396        assert_eq!(ed.cursor(), pos1);
2397        super::move_word(&mut ed, 1).unwrap();
2398        assert_eq!(ed.cursor(), pos2);
2399
2400        ed.move_cursor_to_start_of_line().unwrap();
2401        super::move_word_ws(&mut ed, 1).unwrap();
2402        assert_eq!(ed.cursor(), pos2);
2403    }
2404
2405    #[test]
2406    fn move_word_whitespace_nonkeywords() {
2407        let mut context = Context::new();
2408        let out = Vec::new();
2409        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2410
2411        ed.insert_str_after_cursor("...   ").unwrap();
2412        let pos1 = ed.cursor();
2413        ed.insert_str_after_cursor("...").unwrap();
2414        let pos2 = ed.cursor();
2415        ed.insert_str_after_cursor("word").unwrap();
2416        let pos3 = ed.cursor();
2417        ed.move_cursor_to_start_of_line().unwrap();
2418
2419        super::move_word(&mut ed, 1).unwrap();
2420        assert_eq!(ed.cursor(), pos1);
2421        super::move_word(&mut ed, 1).unwrap();
2422        assert_eq!(ed.cursor(), pos2);
2423
2424        ed.move_cursor_to_start_of_line().unwrap();
2425        super::move_word_ws(&mut ed, 1).unwrap();
2426        assert_eq!(ed.cursor(), pos1);
2427        super::move_word_ws(&mut ed, 1).unwrap();
2428        assert_eq!(ed.cursor(), pos3);
2429    }
2430
2431    #[test]
2432    fn move_word_and_back() {
2433        let mut context = Context::new();
2434        let out = Vec::new();
2435        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2436
2437        ed.insert_str_after_cursor("here ").unwrap();
2438        let pos1 = ed.cursor();
2439        ed.insert_str_after_cursor("are ").unwrap();
2440        let pos2 = ed.cursor();
2441        ed.insert_str_after_cursor("some").unwrap();
2442        let pos3 = ed.cursor();
2443        ed.insert_str_after_cursor("... ").unwrap();
2444        let pos4 = ed.cursor();
2445        ed.insert_str_after_cursor("words").unwrap();
2446        let pos5 = ed.cursor();
2447
2448        // make sure move_word() and move_word_back() are reflections of eachother
2449
2450        ed.move_cursor_to_start_of_line().unwrap();
2451        super::move_word(&mut ed, 1).unwrap();
2452        assert_eq!(ed.cursor(), pos1);
2453        super::move_word(&mut ed, 1).unwrap();
2454        assert_eq!(ed.cursor(), pos2);
2455        super::move_word(&mut ed, 1).unwrap();
2456        assert_eq!(ed.cursor(), pos3);
2457        super::move_word(&mut ed, 1).unwrap();
2458        assert_eq!(ed.cursor(), pos4);
2459        super::move_word(&mut ed, 1).unwrap();
2460        assert_eq!(ed.cursor(), pos5);
2461
2462        super::move_word_back(&mut ed, 1).unwrap();
2463        assert_eq!(ed.cursor(), pos4);
2464        super::move_word_back(&mut ed, 1).unwrap();
2465        assert_eq!(ed.cursor(), pos3);
2466        super::move_word_back(&mut ed, 1).unwrap();
2467        assert_eq!(ed.cursor(), pos2);
2468        super::move_word_back(&mut ed, 1).unwrap();
2469        assert_eq!(ed.cursor(), pos1);
2470        super::move_word_back(&mut ed, 1).unwrap();
2471        assert_eq!(ed.cursor(), 0);
2472
2473        ed.move_cursor_to_start_of_line().unwrap();
2474        super::move_word_ws(&mut ed, 1).unwrap();
2475        assert_eq!(ed.cursor(), pos1);
2476        super::move_word_ws(&mut ed, 1).unwrap();
2477        assert_eq!(ed.cursor(), pos2);
2478        super::move_word_ws(&mut ed, 1).unwrap();
2479        assert_eq!(ed.cursor(), pos4);
2480        super::move_word_ws(&mut ed, 1).unwrap();
2481        assert_eq!(ed.cursor(), pos5);
2482
2483        super::move_word_ws_back(&mut ed, 1).unwrap();
2484        assert_eq!(ed.cursor(), pos4);
2485        super::move_word_ws_back(&mut ed, 1).unwrap();
2486        assert_eq!(ed.cursor(), pos2);
2487        super::move_word_ws_back(&mut ed, 1).unwrap();
2488        assert_eq!(ed.cursor(), pos1);
2489        super::move_word_ws_back(&mut ed, 1).unwrap();
2490        assert_eq!(ed.cursor(), 0);
2491    }
2492
2493    #[test]
2494    fn move_word_and_back_with_count() {
2495        let mut context = Context::new();
2496        let out = Vec::new();
2497        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2498
2499        ed.insert_str_after_cursor("here ").unwrap();
2500        ed.insert_str_after_cursor("are ").unwrap();
2501        let pos1 = ed.cursor();
2502        ed.insert_str_after_cursor("some").unwrap();
2503        let pos2 = ed.cursor();
2504        ed.insert_str_after_cursor("... ").unwrap();
2505        ed.insert_str_after_cursor("words").unwrap();
2506        let pos3 = ed.cursor();
2507
2508        // make sure move_word() and move_word_back() are reflections of eachother
2509        ed.move_cursor_to_start_of_line().unwrap();
2510        super::move_word(&mut ed, 3).unwrap();
2511        assert_eq!(ed.cursor(), pos2);
2512        super::move_word(&mut ed, 2).unwrap();
2513        assert_eq!(ed.cursor(), pos3);
2514
2515        super::move_word_back(&mut ed, 2).unwrap();
2516        assert_eq!(ed.cursor(), pos2);
2517        super::move_word_back(&mut ed, 3).unwrap();
2518        assert_eq!(ed.cursor(), 0);
2519
2520        ed.move_cursor_to_start_of_line().unwrap();
2521        super::move_word_ws(&mut ed, 2).unwrap();
2522        assert_eq!(ed.cursor(), pos1);
2523        super::move_word_ws(&mut ed, 2).unwrap();
2524        assert_eq!(ed.cursor(), pos3);
2525
2526        super::move_word_ws_back(&mut ed, 2).unwrap();
2527        assert_eq!(ed.cursor(), pos1);
2528        super::move_word_ws_back(&mut ed, 2).unwrap();
2529        assert_eq!(ed.cursor(), 0);
2530    }
2531
2532    #[test]
2533    fn move_to_end_of_word_ws_whitespace_count() {
2534        let mut context = Context::new();
2535        let out = Vec::new();
2536        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2537
2538        ed.insert_str_after_cursor("here are").unwrap();
2539        let start_pos = ed.cursor();
2540        ed.insert_str_after_cursor("      som").unwrap();
2541        ed.insert_str_after_cursor("e word").unwrap();
2542        let end_pos = ed.cursor();
2543        ed.insert_str_after_cursor("s and some").unwrap();
2544
2545        ed.move_cursor_to(start_pos).unwrap();
2546        super::move_to_end_of_word_ws(&mut ed, 2).unwrap();
2547        assert_eq!(ed.cursor(), end_pos);
2548    }
2549
2550    #[test]
2551    /// test delete word
2552    fn delete_word() {
2553        let mut context = Context::new();
2554        let out = Vec::new();
2555        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2556        let mut map = Vi::new(ed);
2557        map.ed.insert_str_after_cursor("delete some words").unwrap();
2558
2559        simulate_keys!(map, [
2560            Esc,
2561            Char('0'),
2562            Char('d'),
2563            Char('w'),
2564        ]);
2565        assert_eq!(map.ed.cursor(), 0);
2566        assert_eq!(String::from(map), "some words");
2567    }
2568
2569    #[test]
2570    /// test changing a line
2571    fn change_line() {
2572        let mut context = Context::new();
2573        let out = Vec::new();
2574        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2575        let mut map = Vi::new(ed);
2576        map.ed.insert_str_after_cursor("change").unwrap();
2577
2578        simulate_keys!(map, [
2579            Esc,
2580            Char('c'),
2581            Char('c'),
2582            Char('d'),
2583            Char('o'),
2584            Char('n'),
2585            Char('e'),
2586        ]);
2587        assert_eq!(map.ed.cursor(), 4);
2588        assert_eq!(String::from(map), "done");
2589    }
2590
2591    #[test]
2592    /// test deleting a single char to the left
2593    fn change_char_left() {
2594        let mut context = Context::new();
2595        let out = Vec::new();
2596        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2597        let mut map = Vi::new(ed);
2598        map.ed.insert_str_after_cursor("change").unwrap();
2599
2600        simulate_keys!(map, [
2601            Esc,
2602            Char('c'),
2603            Char('h'),
2604            Char('e'),
2605            Esc,
2606        ]);
2607        assert_eq!(map.ed.cursor(), 4);
2608        assert_eq!(String::from(map), "chanee");
2609    }
2610
2611    #[test]
2612    /// test deleting multiple chars to the left
2613    fn change_chars_left() {
2614        let mut context = Context::new();
2615        let out = Vec::new();
2616        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2617        let mut map = Vi::new(ed);
2618        map.ed.insert_str_after_cursor("change").unwrap();
2619
2620        simulate_keys!(map, [
2621            Esc,
2622            Char('3'),
2623            Char('c'),
2624            Char('h'),
2625            Char('e'),
2626        ]);
2627        assert_eq!(map.ed.cursor(), 3);
2628        assert_eq!(String::from(map), "chee");
2629    }
2630
2631    #[test]
2632    /// test deleting a single char to the right
2633    fn change_char_right() {
2634        let mut context = Context::new();
2635        let out = Vec::new();
2636        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2637        let mut map = Vi::new(ed);
2638        map.ed.insert_str_after_cursor("change").unwrap();
2639
2640        simulate_keys!(map, [
2641            Esc,
2642            Char('0'),
2643            Char('c'),
2644            Char('l'),
2645            Char('s'),
2646        ]);
2647        assert_eq!(map.ed.cursor(), 1);
2648        assert_eq!(String::from(map), "shange");
2649    }
2650
2651    #[test]
2652    /// test changing multiple chars to the right
2653    fn change_chars_right() {
2654        let mut context = Context::new();
2655        let out = Vec::new();
2656        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2657        let mut map = Vi::new(ed);
2658        map.ed.insert_str_after_cursor("change").unwrap();
2659
2660        simulate_keys!(map, [
2661            Esc,
2662            Char('0'),
2663            Char('3'),
2664            Char('c'),
2665            Char('l'),
2666            Char('s'),
2667            Char('t'),
2668            Char('r'),
2669            Char('a'),
2670            Esc,
2671        ]);
2672        assert_eq!(map.ed.cursor(), 3);
2673        assert_eq!(String::from(map), "strange");
2674    }
2675
2676    #[test]
2677    /// test repeat with change
2678    fn change_and_repeat() {
2679        let mut context = Context::new();
2680        let out = Vec::new();
2681        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2682        let mut map = Vi::new(ed);
2683        map.ed.insert_str_after_cursor("change").unwrap();
2684
2685        simulate_keys!(map, [
2686            Esc,
2687            Char('0'),
2688            Char('c'),
2689            Char('l'),
2690            Char('s'),
2691            Esc,
2692            Char('l'),
2693            Char('.'),
2694            Char('l'),
2695            Char('.'),
2696        ]);
2697        assert_eq!(map.ed.cursor(), 2);
2698        assert_eq!(String::from(map), "sssnge");
2699    }
2700
2701    #[test]
2702    /// test change until end of line
2703    fn change_until_end() {
2704        let mut context = Context::new();
2705        let out = Vec::new();
2706        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2707        let mut map = Vi::new(ed);
2708        map.ed.insert_str_after_cursor("change").unwrap();
2709
2710        simulate_keys!(map, [
2711            Esc,
2712            Char('0'),
2713            Char('c'),
2714            Char('$'),
2715            Char('o'),
2716            Char('k'),
2717            Esc,
2718        ]);
2719        assert_eq!(map.ed.cursor(), 1);
2720        assert_eq!(String::from(map), "ok");
2721    }
2722
2723    #[test]
2724    /// test change until end of line
2725    fn change_until_end_shift_c() {
2726        let mut context = Context::new();
2727        let out = Vec::new();
2728        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2729        let mut map = Vi::new(ed);
2730        map.ed.insert_str_after_cursor("change").unwrap();
2731
2732        simulate_keys!(map, [
2733            Esc,
2734            Char('0'),
2735            Char('C'),
2736            Char('o'),
2737            Char('k'),
2738        ]);
2739        assert_eq!(map.ed.cursor(), 2);
2740        assert_eq!(String::from(map), "ok");
2741    }
2742
2743    #[test]
2744    /// test change until end of line
2745    fn change_until_end_from_middle_shift_c() {
2746        let mut context = Context::new();
2747        let out = Vec::new();
2748        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2749        let mut map = Vi::new(ed);
2750        map.ed.insert_str_after_cursor("change").unwrap();
2751
2752        simulate_keys!(map, [
2753            Esc,
2754            Char('0'),
2755            Char('2'),
2756            Char('l'),
2757            Char('C'),
2758            Char(' '),
2759            Char('o'),
2760            Char('k'),
2761            Esc,
2762        ]);
2763        assert_eq!(String::from(map), "ch ok");
2764    }
2765
2766    #[test]
2767    /// test change until start of line
2768    fn change_until_start() {
2769        let mut context = Context::new();
2770        let out = Vec::new();
2771        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2772        let mut map = Vi::new(ed);
2773        map.ed.insert_str_after_cursor("change").unwrap();
2774
2775        simulate_keys!(map, [
2776            Esc,
2777            Char('$'),
2778            Char('c'),
2779            Char('0'),
2780            Char('s'),
2781            Char('t'),
2782            Char('r'),
2783            Char('a'),
2784            Char('n'),
2785            Char('g'),
2786        ]);
2787        assert_eq!(map.ed.cursor(), 6);
2788        assert_eq!(String::from(map), "strange");
2789    }
2790
2791    #[test]
2792    /// test a compound count with change
2793    fn change_with_count() {
2794        let mut context = Context::new();
2795        let out = Vec::new();
2796        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2797        let mut map = Vi::new(ed);
2798        map.ed.insert_str_after_cursor("change").unwrap();
2799
2800        simulate_keys!(map, [
2801            Esc,
2802            Char('0'),
2803            Char('2'),
2804            Char('c'),
2805            Char('2'),
2806            Char('l'),
2807            Char('s'),
2808            Char('t'),
2809            Char('r'),
2810            Char('a'),
2811            Char('n'),
2812            Esc,
2813        ]);
2814        assert_eq!(map.ed.cursor(), 4);
2815        assert_eq!(String::from(map), "strange");
2816    }
2817
2818    #[test]
2819    /// test a compound count with change and repeat
2820    fn change_with_count_and_repeat() {
2821        let mut context = Context::new();
2822        let out = Vec::new();
2823        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2824        let mut map = Vi::new(ed);
2825        map.ed.insert_str_after_cursor("change change").unwrap();
2826
2827        simulate_keys!(map, [
2828            Esc,
2829            Char('0'),
2830            Char('2'),
2831            Char('c'),
2832            Char('2'),
2833            Char('l'),
2834            Char('o'),
2835            Esc,
2836            Char('.'),
2837        ]);
2838        assert_eq!(map.ed.cursor(), 0);
2839        assert_eq!(String::from(map), "ochange");
2840    }
2841
2842    #[test]
2843    /// test change word
2844    fn change_word() {
2845        let mut context = Context::new();
2846        let out = Vec::new();
2847        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2848        let mut map = Vi::new(ed);
2849        map.ed.insert_str_after_cursor("change some words").unwrap();
2850
2851        simulate_keys!(map, [
2852            Esc,
2853            Char('0'),
2854            Char('c'),
2855            Char('w'),
2856            Char('t'),
2857            Char('w'),
2858            Char('e'),
2859            Char('a'),
2860            Char('k'),
2861            Char(' '),
2862        ]);
2863        assert_eq!(String::from(map), "tweak some words");
2864    }
2865
2866    #[test]
2867    /// make sure the count is properly reset
2868    fn test_count_reset_around_insert_and_delete() {
2869        let mut context = Context::new();
2870        let out = Vec::new();
2871        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2872        let mut map = Vi::new(ed);
2873        map.ed.insert_str_after_cursor("these are some words").unwrap();
2874
2875        simulate_keys!(map, [
2876            Esc,
2877            Char('0'),
2878            Char('d'),
2879            Char('3'),
2880            Char('w'),
2881            Char('i'),
2882            Char('w'),
2883            Char('o'),
2884            Char('r'),
2885            Char('d'),
2886            Char('s'),
2887            Char(' '),
2888            Esc,
2889            Char('l'),
2890            Char('.'),
2891        ]);
2892        assert_eq!(String::from(map), "words words words");
2893    }
2894
2895    #[test]
2896    /// make sure t command does nothing if nothing was found
2897    fn test_t_not_found() {
2898        let mut context = Context::new();
2899        let out = Vec::new();
2900        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2901        let mut map = Vi::new(ed);
2902        map.ed.insert_str_after_cursor("abc defg").unwrap();
2903
2904        simulate_keys!(map, [
2905            Esc,
2906            Char('0'),
2907            Char('t'),
2908            Char('z'),
2909        ]);
2910        assert_eq!(map.ed.cursor(), 0);
2911    }
2912
2913    #[test]
2914    /// make sure t command moves the cursor
2915    fn test_t_movement() {
2916        let mut context = Context::new();
2917        let out = Vec::new();
2918        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2919        let mut map = Vi::new(ed);
2920        map.ed.insert_str_after_cursor("abc defg").unwrap();
2921
2922        simulate_keys!(map, [
2923            Esc,
2924            Char('0'),
2925            Char('t'),
2926            Char('d'),
2927        ]);
2928        assert_eq!(map.ed.cursor(), 3);
2929    }
2930
2931    #[test]
2932    /// make sure t command moves the cursor
2933    fn test_t_movement_with_count() {
2934        let mut context = Context::new();
2935        let out = Vec::new();
2936        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2937        let mut map = Vi::new(ed);
2938        map.ed.insert_str_after_cursor("abc defg d").unwrap();
2939
2940        simulate_keys!(map, [
2941            Esc,
2942            Char('0'),
2943            Char('2'),
2944            Char('t'),
2945            Char('d'),
2946        ]);
2947        assert_eq!(map.ed.cursor(), 8);
2948    }
2949
2950    #[test]
2951    /// test normal mode after char movement
2952    fn test_t_movement_then_normal() {
2953        let mut context = Context::new();
2954        let out = Vec::new();
2955        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2956        let mut map = Vi::new(ed);
2957        map.ed.insert_str_after_cursor("abc defg").unwrap();
2958
2959        simulate_keys!(map, [
2960            Esc,
2961            Char('0'),
2962            Char('t'),
2963            Char('d'),
2964            Char('l'),
2965        ]);
2966        assert_eq!(map.ed.cursor(), 4);
2967    }
2968
2969    #[test]
2970    /// test delete with char movement
2971    fn test_t_movement_with_delete() {
2972        let mut context = Context::new();
2973        let out = Vec::new();
2974        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2975        let mut map = Vi::new(ed);
2976        map.ed.insert_str_after_cursor("abc defg").unwrap();
2977
2978        simulate_keys!(map, [
2979            Esc,
2980            Char('0'),
2981            Char('d'),
2982            Char('t'),
2983            Char('d'),
2984        ]);
2985        assert_eq!(map.ed.cursor(), 0);
2986        assert_eq!(String::from(map), "defg");
2987    }
2988
2989    #[test]
2990    /// test change with char movement
2991    fn test_t_movement_with_change() {
2992        let mut context = Context::new();
2993        let out = Vec::new();
2994        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
2995        let mut map = Vi::new(ed);
2996        map.ed.insert_str_after_cursor("abc defg").unwrap();
2997
2998        simulate_keys!(map, [
2999            Esc,
3000            Char('0'),
3001            Char('c'),
3002            Char('t'),
3003            Char('d'),
3004            Char('z'),
3005            Char(' '),
3006            Esc,
3007        ]);
3008        assert_eq!(map.ed.cursor(), 1);
3009        assert_eq!(String::from(map), "z defg");
3010    }
3011
3012    #[test]
3013    /// make sure f command moves the cursor
3014    fn test_f_movement() {
3015        let mut context = Context::new();
3016        let out = Vec::new();
3017        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3018        let mut map = Vi::new(ed);
3019        map.ed.insert_str_after_cursor("abc defg").unwrap();
3020
3021        simulate_keys!(map, [
3022            Esc,
3023            Char('0'),
3024            Char('f'),
3025            Char('d'),
3026        ]);
3027        assert_eq!(map.ed.cursor(), 4);
3028    }
3029
3030    #[test]
3031    /// make sure T command moves the cursor
3032    fn test_cap_t_movement() {
3033        let mut context = Context::new();
3034        let out = Vec::new();
3035        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3036        let mut map = Vi::new(ed);
3037        map.ed.insert_str_after_cursor("abc defg").unwrap();
3038
3039        simulate_keys!(map, [
3040            Esc,
3041            Char('$'),
3042            Char('T'),
3043            Char('d'),
3044        ]);
3045        assert_eq!(map.ed.cursor(), 5);
3046    }
3047
3048    #[test]
3049    /// make sure F command moves the cursor
3050    fn test_cap_f_movement() {
3051        let mut context = Context::new();
3052        let out = Vec::new();
3053        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3054        let mut map = Vi::new(ed);
3055        map.ed.insert_str_after_cursor("abc defg").unwrap();
3056
3057        simulate_keys!(map, [
3058            Esc,
3059            Char('$'),
3060            Char('F'),
3061            Char('d'),
3062        ]);
3063        assert_eq!(map.ed.cursor(), 4);
3064    }
3065
3066    #[test]
3067    /// make sure ; command moves the cursor
3068    fn test_semi_movement() {
3069        let mut context = Context::new();
3070        let out = Vec::new();
3071        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3072        let mut map = Vi::new(ed);
3073        map.ed.insert_str_after_cursor("abc abc").unwrap();
3074
3075        simulate_keys!(map, [
3076            Esc,
3077            Char('0'),
3078            Char('f'),
3079            Char('c'),
3080            Char(';'),
3081        ]);
3082        assert_eq!(map.ed.cursor(), 6);
3083    }
3084
3085    #[test]
3086    /// make sure , command moves the cursor
3087    fn test_comma_movement() {
3088        let mut context = Context::new();
3089        let out = Vec::new();
3090        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3091        let mut map = Vi::new(ed);
3092        map.ed.insert_str_after_cursor("abc abc").unwrap();
3093
3094        simulate_keys!(map, [
3095            Esc,
3096            Char('0'),
3097            Char('f'),
3098            Char('c'),
3099            Char('$'),
3100            Char(','),
3101        ]);
3102        assert_eq!(map.ed.cursor(), 2);
3103    }
3104
3105    #[test]
3106    /// test delete with semi (;)
3107    fn test_semi_delete() {
3108        let mut context = Context::new();
3109        let out = Vec::new();
3110        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3111        let mut map = Vi::new(ed);
3112        map.ed.insert_str_after_cursor("abc abc").unwrap();
3113
3114        simulate_keys!(map, [
3115            Esc,
3116            Char('0'),
3117            Char('f'),
3118            Char('c'),
3119            Char('d'),
3120            Char(';'),
3121        ]);
3122        assert_eq!(map.ed.cursor(), 1);
3123        assert_eq!(String::from(map), "ab");
3124    }
3125
3126    #[test]
3127    /// test delete with semi (;) and repeat
3128    fn test_semi_delete_repeat() {
3129        let mut context = Context::new();
3130        let out = Vec::new();
3131        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3132        let mut map = Vi::new(ed);
3133        map.ed.insert_str_after_cursor("abc abc abc abc").unwrap();
3134
3135        simulate_keys!(map, [
3136            Esc,
3137            Char('0'),
3138            Char('f'),
3139            Char('c'),
3140            Char('d'),
3141            Char(';'),
3142            Char('.'),
3143            Char('.'),
3144        ]);
3145        assert_eq!(String::from(map), "ab");
3146    }
3147
3148    #[test]
3149    /// test find_char
3150    fn test_find_char() {
3151        let mut context = Context::new();
3152        let out = Vec::new();
3153        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3154        ed.insert_str_after_cursor("abcdefg").unwrap();
3155        assert_eq!(super::find_char(ed.current_buffer(), 0, 'd', 1), Some(3));
3156    }
3157
3158    #[test]
3159    /// test find_char with non-zero start
3160    fn test_find_char_with_start() {
3161        let mut context = Context::new();
3162        let out = Vec::new();
3163        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3164        ed.insert_str_after_cursor("abcabc").unwrap();
3165        assert_eq!(super::find_char(ed.current_buffer(), 1, 'a', 1), Some(3));
3166    }
3167
3168    #[test]
3169    /// test find_char with count
3170    fn test_find_char_with_count() {
3171        let mut context = Context::new();
3172        let out = Vec::new();
3173        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3174        ed.insert_str_after_cursor("abcabc").unwrap();
3175        assert_eq!(super::find_char(ed.current_buffer(), 0, 'a', 2), Some(3));
3176    }
3177
3178    #[test]
3179    /// test find_char not found
3180    fn test_find_char_not_found() {
3181        let mut context = Context::new();
3182        let out = Vec::new();
3183        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3184        ed.insert_str_after_cursor("abcdefg").unwrap();
3185        assert_eq!(super::find_char(ed.current_buffer(), 0, 'z', 1), None);
3186    }
3187
3188    #[test]
3189    /// test find_char_rev
3190    fn test_find_char_rev() {
3191        let mut context = Context::new();
3192        let out = Vec::new();
3193        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3194        ed.insert_str_after_cursor("abcdefg").unwrap();
3195        assert_eq!(super::find_char_rev(ed.current_buffer(), 6, 'd', 1), Some(3));
3196    }
3197
3198    #[test]
3199    /// test find_char_rev with non-zero start
3200    fn test_find_char_rev_with_start() {
3201        let mut context = Context::new();
3202        let out = Vec::new();
3203        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3204        ed.insert_str_after_cursor("abcabc").unwrap();
3205        assert_eq!(super::find_char_rev(ed.current_buffer(), 5, 'c', 1), Some(2));
3206    }
3207
3208    #[test]
3209    /// test find_char_rev with count
3210    fn test_find_char_rev_with_count() {
3211        let mut context = Context::new();
3212        let out = Vec::new();
3213        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3214        ed.insert_str_after_cursor("abcabc").unwrap();
3215        assert_eq!(super::find_char_rev(ed.current_buffer(), 6, 'c', 2), Some(2));
3216    }
3217
3218    #[test]
3219    /// test find_char_rev not found
3220    fn test_find_char_rev_not_found() {
3221        let mut context = Context::new();
3222        let out = Vec::new();
3223        let mut ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3224        ed.insert_str_after_cursor("abcdefg").unwrap();
3225        assert_eq!(super::find_char_rev(ed.current_buffer(), 6, 'z', 1), None);
3226    }
3227
3228    #[test]
3229    /// undo with counts
3230    fn test_undo_with_counts() {
3231        let mut context = Context::new();
3232        let out = Vec::new();
3233        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3234        let mut map = Vi::new(ed);
3235        map.ed.insert_str_after_cursor("abcdefg").unwrap();
3236
3237        simulate_keys!(map, [
3238            Esc,
3239            Char('x'),
3240            Char('x'),
3241            Char('x'),
3242            Char('3'),
3243            Char('u'),
3244        ]);
3245        assert_eq!(String::from(map), "abcdefg");
3246    }
3247
3248    #[test]
3249    /// redo with counts
3250    fn test_redo_with_counts() {
3251        let mut context = Context::new();
3252        let out = Vec::new();
3253        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3254        let mut map = Vi::new(ed);
3255        map.ed.insert_str_after_cursor("abcdefg").unwrap();
3256
3257        simulate_keys!(map, [
3258            Esc,
3259            Char('x'),
3260            Char('x'),
3261            Char('x'),
3262            Char('u'),
3263            Char('u'),
3264            Char('u'),
3265            Char('2'),
3266            Ctrl('r'),
3267        ]);
3268        assert_eq!(String::from(map), "abcde");
3269    }
3270
3271    #[test]
3272    /// test change word with 'gE'
3273    fn change_word_ge_ws() {
3274        let mut context = Context::new();
3275        let out = Vec::new();
3276        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3277        let mut map = Vi::new(ed);
3278        map.ed.insert_str_after_cursor("change some words").unwrap();
3279
3280        simulate_keys!(map, [
3281            Esc,
3282            Char('c'),
3283            Char('g'),
3284            Char('E'),
3285            Char('e'),
3286            Char('t'),
3287            Char('h'),
3288            Char('i'),
3289            Char('n'),
3290            Char('g'),
3291            Esc,
3292        ]);
3293        assert_eq!(String::from(map), "change something");
3294    }
3295
3296    #[test]
3297    /// test undo in groups
3298    fn undo_insert() {
3299        let mut context = Context::new();
3300        let out = Vec::new();
3301        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3302        let mut map = Vi::new(ed);
3303
3304        simulate_keys!(map, [
3305            Char('i'),
3306            Char('n'),
3307            Char('s'),
3308            Char('e'),
3309            Char('r'),
3310            Char('t'),
3311            Esc,
3312            Char('u'),
3313        ]);
3314        assert_eq!(String::from(map), "");
3315    }
3316
3317    #[test]
3318    /// test undo in groups
3319    fn undo_insert2() {
3320        let mut context = Context::new();
3321        let out = Vec::new();
3322        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3323        let mut map = Vi::new(ed);
3324
3325        simulate_keys!(map, [
3326            Esc,
3327            Char('i'),
3328            Char('i'),
3329            Char('n'),
3330            Char('s'),
3331            Char('e'),
3332            Char('r'),
3333            Char('t'),
3334            Esc,
3335            Char('u'),
3336        ]);
3337        assert_eq!(String::from(map), "");
3338    }
3339
3340    #[test]
3341    /// test undo in groups
3342    fn undo_insert_with_history() {
3343        let mut context = Context::new();
3344        context.history.push(Buffer::from("")).unwrap();
3345        let out = Vec::new();
3346        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3347        let mut map = Vi::new(ed);
3348
3349        simulate_keys!(map, [
3350            Esc,
3351            Char('i'),
3352            Char('i'),
3353            Char('n'),
3354            Char('s'),
3355            Char('e'),
3356            Char('r'),
3357            Char('t'),
3358            Up,
3359            Char('h'),
3360            Char('i'),
3361            Char('s'),
3362            Char('t'),
3363            Char('o'),
3364            Char('r'),
3365            Char('y'),
3366            Down,
3367            Char(' '),
3368            Char('t'),
3369            Char('e'),
3370            Char('x'),
3371            Char('t'),
3372            Esc,
3373            Char('u'),
3374        ]);
3375        assert_eq!(String::from(map), "insert");
3376    }
3377
3378    #[test]
3379    /// test undo in groups
3380    fn undo_insert_with_history2() {
3381        let mut context = Context::new();
3382        context.history.push(Buffer::from("")).unwrap();
3383        let out = Vec::new();
3384        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3385        let mut map = Vi::new(ed);
3386
3387        simulate_keys!(map, [
3388            Esc,
3389            Char('i'),
3390            Char('i'),
3391            Char('n'),
3392            Char('s'),
3393            Char('e'),
3394            Char('r'),
3395            Char('t'),
3396            Up,
3397            Esc,
3398            Down,
3399            Char('u'),
3400        ]);
3401        assert_eq!(String::from(map), "");
3402    }
3403
3404    #[test]
3405    /// test undo in groups
3406    fn undo_insert_with_movement_reset() {
3407        let mut context = Context::new();
3408        let out = Vec::new();
3409        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3410        let mut map = Vi::new(ed);
3411
3412        simulate_keys!(map, [
3413            Esc,
3414            Char('i'),
3415            Char('i'),
3416            Char('n'),
3417            Char('s'),
3418            Char('e'),
3419            Char('r'),
3420            Char('t'),
3421            // movement reset will get triggered here
3422            Left,
3423            Right,
3424            Char(' '),
3425            Char('t'),
3426            Char('e'),
3427            Char('x'),
3428            Char('t'),
3429            Esc,
3430            Char('u'),
3431        ]);
3432        assert_eq!(String::from(map), "insert");
3433    }
3434
3435    #[test]
3436    /// test undo in groups
3437    fn undo_3x() {
3438        let mut context = Context::new();
3439        let out = Vec::new();
3440        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3441        let mut map = Vi::new(ed);
3442        map.ed.insert_str_after_cursor("rm some words").unwrap();
3443
3444        simulate_keys!(map, [
3445            Esc,
3446            Char('0'),
3447            Char('3'),
3448            Char('x'),
3449            Char('u'),
3450        ]);
3451        assert_eq!(String::from(map), "rm some words");
3452    }
3453
3454    #[test]
3455    /// test undo in groups
3456    fn undo_insert_with_count() {
3457        let mut context = Context::new();
3458        let out = Vec::new();
3459        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3460        let mut map = Vi::new(ed);
3461
3462        simulate_keys!(map, [
3463            Char('i'),
3464            Char('n'),
3465            Char('s'),
3466            Char('e'),
3467            Char('r'),
3468            Char('t'),
3469            Esc,
3470            Char('3'),
3471            Char('i'),
3472            Char('i'),
3473            Char('n'),
3474            Char('s'),
3475            Char('e'),
3476            Char('r'),
3477            Char('t'),
3478            Esc,
3479            Char('u'),
3480        ]);
3481        assert_eq!(String::from(map), "insert");
3482    }
3483
3484    #[test]
3485    /// test undo in groups
3486    fn undo_insert_with_repeat() {
3487        let mut context = Context::new();
3488        let out = Vec::new();
3489        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3490        let mut map = Vi::new(ed);
3491
3492        simulate_keys!(map, [
3493            Char('i'),
3494            Char('n'),
3495            Char('s'),
3496            Char('e'),
3497            Char('r'),
3498            Char('t'),
3499            Esc,
3500            Char('3'),
3501            Char('.'),
3502            Esc,
3503            Char('u'),
3504        ]);
3505        assert_eq!(String::from(map), "insert");
3506    }
3507
3508    #[test]
3509    /// test undo in groups
3510    fn undo_s_with_count() {
3511        let mut context = Context::new();
3512        let out = Vec::new();
3513        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3514        let mut map = Vi::new(ed);
3515        map.ed.insert_str_after_cursor("replace some words").unwrap();
3516
3517        simulate_keys!(map, [
3518            Esc,
3519            Char('0'),
3520            Char('8'),
3521            Char('s'),
3522            Char('o'),
3523            Char('k'),
3524            Esc,
3525            Char('u'),
3526        ]);
3527        assert_eq!(String::from(map), "replace some words");
3528    }
3529
3530    #[test]
3531    /// test undo in groups
3532    fn undo_multiple_groups() {
3533        let mut context = Context::new();
3534        let out = Vec::new();
3535        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3536        let mut map = Vi::new(ed);
3537        map.ed.insert_str_after_cursor("replace some words").unwrap();
3538
3539        simulate_keys!(map, [
3540            Esc,
3541            Char('A'),
3542            Char(' '),
3543            Char('h'),
3544            Char('e'),
3545            Char('r'),
3546            Char('e'),
3547            Esc,
3548            Char('0'),
3549            Char('8'),
3550            Char('s'),
3551            Char('o'),
3552            Char('k'),
3553            Esc,
3554            Char('2'),
3555            Char('u'),
3556        ]);
3557        assert_eq!(String::from(map), "replace some words");
3558    }
3559
3560    #[test]
3561    /// test undo in groups
3562    fn undo_r_command_with_count() {
3563        let mut context = Context::new();
3564        let out = Vec::new();
3565        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3566        let mut map = Vi::new(ed);
3567        map.ed.insert_str_after_cursor("replace some words").unwrap();
3568
3569        simulate_keys!(map, [
3570            Esc,
3571            Char('0'),
3572            Char('8'),
3573            Char('r'),
3574            Char(' '),
3575            Char('u'),
3576        ]);
3577        assert_eq!(String::from(map), "replace some words");
3578    }
3579
3580    #[test]
3581    /// test tilde
3582    fn tilde_basic() {
3583        let mut context = Context::new();
3584        let out = Vec::new();
3585        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3586        let mut map = Vi::new(ed);
3587        map.ed.insert_str_after_cursor("tilde").unwrap();
3588
3589        simulate_keys!(map, [
3590            Esc,
3591            Char('~'),
3592        ]);
3593        assert_eq!(String::from(map), "tildE");
3594    }
3595
3596    #[test]
3597    /// test tilde
3598    fn tilde_basic2() {
3599        let mut context = Context::new();
3600        let out = Vec::new();
3601        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3602        let mut map = Vi::new(ed);
3603        map.ed.insert_str_after_cursor("tilde").unwrap();
3604
3605        simulate_keys!(map, [
3606            Esc,
3607            Char('~'),
3608            Char('~'),
3609        ]);
3610        assert_eq!(String::from(map), "tilde");
3611    }
3612
3613    #[test]
3614    /// test tilde
3615    fn tilde_move() {
3616        let mut context = Context::new();
3617        let out = Vec::new();
3618        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3619        let mut map = Vi::new(ed);
3620        map.ed.insert_str_after_cursor("tilde").unwrap();
3621
3622        simulate_keys!(map, [
3623            Esc,
3624            Char('0'),
3625            Char('~'),
3626            Char('~'),
3627        ]);
3628        assert_eq!(String::from(map), "TIlde");
3629    }
3630
3631
3632    #[test]
3633    /// test tilde
3634    fn tilde_repeat() {
3635        let mut context = Context::new();
3636        let out = Vec::new();
3637        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3638        let mut map = Vi::new(ed);
3639        map.ed.insert_str_after_cursor("tilde").unwrap();
3640
3641        simulate_keys!(map, [
3642            Esc,
3643            Char('~'),
3644            Char('.'),
3645        ]);
3646        assert_eq!(String::from(map), "tilde");
3647    }
3648
3649    #[test]
3650    /// test tilde
3651    fn tilde_count() {
3652        let mut context = Context::new();
3653        let out = Vec::new();
3654        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3655        let mut map = Vi::new(ed);
3656        map.ed.insert_str_after_cursor("tilde").unwrap();
3657
3658        simulate_keys!(map, [
3659            Esc,
3660            Char('0'),
3661            Char('1'),
3662            Char('0'),
3663            Char('~'),
3664        ]);
3665        assert_eq!(String::from(map), "TILDE");
3666    }
3667
3668    #[test]
3669    /// test tilde
3670    fn tilde_count_short() {
3671        let mut context = Context::new();
3672        let out = Vec::new();
3673        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3674        let mut map = Vi::new(ed);
3675        map.ed.insert_str_after_cursor("TILDE").unwrap();
3676
3677        simulate_keys!(map, [
3678            Esc,
3679            Char('0'),
3680            Char('2'),
3681            Char('~'),
3682        ]);
3683        assert_eq!(String::from(map), "tiLDE");
3684    }
3685
3686    #[test]
3687    /// test tilde
3688    fn tilde_nocase() {
3689        let mut context = Context::new();
3690        let out = Vec::new();
3691        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3692        let mut map = Vi::new(ed);
3693        map.ed.insert_str_after_cursor("ti_lde").unwrap();
3694
3695        simulate_keys!(map, [
3696            Esc,
3697            Char('0'),
3698            Char('6'),
3699            Char('~'),
3700        ]);
3701        assert_eq!(String::from(map), "TI_LDE");
3702    }
3703
3704    #[test]
3705    /// ctrl-h should act as backspace
3706    fn ctrl_h() {
3707        let mut context = Context::new();
3708        let out = Vec::new();
3709        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
3710        let mut map = Vi::new(ed);
3711        map.ed.insert_str_after_cursor("not empty").unwrap();
3712
3713        let res = map.handle_key(Ctrl('h'), &mut |_| {});
3714        assert_eq!(res.is_ok(), true);
3715        assert_eq!(map.ed.current_buffer().to_string(), "not empt".to_string());
3716    }
3717}