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