From d675d0670a213dd8a6c3b7afd93d2d9f51ede93c Mon Sep 17 00:00:00 2001
From: gwenn <gtreguier@gmail.com>
Date: Sun, 12 Feb 2017 11:26:35 +0100
Subject: [PATCH] Fix ce/de/ye/cw/cW vi commands

---
 src/keymap.rs      | 25 +++++++++++++------------
 src/line_buffer.rs | 42 +++++++++++++++++++++---------------------
 2 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/src/keymap.rs b/src/keymap.rs
index 6cdab694..3a1e8860 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -57,7 +57,8 @@ pub enum Word {
 #[derive(Debug, Clone, PartialEq, Copy)]
 pub enum At {
     Start,
-    End,
+    BeforeEnd,
+    AfterEnd
 }
 
 #[derive(Debug, Clone, PartialEq, Copy)]
@@ -208,7 +209,7 @@ impl EditState {
                 if positive {
                     Cmd::Kill(Movement::BackwardWord(n, Word::Emacs))
                 } else {
-                    Cmd::Kill(Movement::ForwardWord(n, At::End, Word::Emacs))
+                    Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
                 }
             }
             KeyPress::Meta('<') => Cmd::BeginningOfHistory,
@@ -217,20 +218,20 @@ impl EditState {
                 if positive {
                     Cmd::BackwardWord(n, Word::Emacs)
                 } else {
-                    Cmd::ForwardWord(n, At::End, Word::Emacs)
+                    Cmd::ForwardWord(n, At::AfterEnd, Word::Emacs)
                 }
             }
             KeyPress::Meta('C') => Cmd::CapitalizeWord,
             KeyPress::Meta('D') => {
                 if positive {
-                    Cmd::Kill(Movement::ForwardWord(n, At::End, Word::Emacs))
+                    Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
                 } else {
                     Cmd::Kill(Movement::BackwardWord(n, Word::Emacs))
                 }
             }
             KeyPress::Meta('F') => {
                 if positive {
-                    Cmd::ForwardWord(n, At::End, Word::Emacs)
+                    Cmd::ForwardWord(n, At::AfterEnd, Word::Emacs)
                 } else {
                     Cmd::BackwardWord(n, Word::Emacs)
                 }
@@ -307,8 +308,8 @@ impl EditState {
             }
             KeyPress::Char('D') |
             KeyPress::Ctrl('K') => Cmd::Kill(Movement::EndOfLine),
-            KeyPress::Char('e') => Cmd::ForwardWord(n, At::End, Word::Vi),
-            KeyPress::Char('E') => Cmd::ForwardWord(n, At::End, Word::Big),
+            KeyPress::Char('e') => Cmd::ForwardWord(n, At::BeforeEnd, Word::Vi),
+            KeyPress::Char('E') => Cmd::ForwardWord(n, At::BeforeEnd, Word::Big),
             KeyPress::Char('i') => {
                 // vi-insertion-mode
                 self.insert = true;
@@ -429,8 +430,8 @@ impl EditState {
             KeyPress::Char('0') => Some(Movement::BeginningOfLine), // vi-kill-line-prev: Vi cut from beginning of line to cursor.
             KeyPress::Char('b') => Some(Movement::BackwardWord(n, Word::Vi)),
             KeyPress::Char('B') => Some(Movement::BackwardWord(n, Word::Big)),
-            KeyPress::Char('e') => Some(Movement::ForwardWord(n, At::End, Word::Vi)),
-            KeyPress::Char('E') => Some(Movement::ForwardWord(n, At::End, Word::Big)),
+            KeyPress::Char('e') => Some(Movement::ForwardWord(n, At::AfterEnd, Word::Vi)),
+            KeyPress::Char('E') => Some(Movement::ForwardWord(n, At::AfterEnd, Word::Big)),
             KeyPress::Char(c) if c == 'f' || c == 'F' || c == 't' || c == 'T' => {
                 let cs = try!(self.vi_char_search(rdr, config, c));
                 match cs {
@@ -446,7 +447,7 @@ impl EditState {
             KeyPress::Char('w') => {
                 // 'cw' is 'ce'
                 if key == KeyPress::Char('c') {
-                    Some(Movement::ForwardWord(n, At::End, Word::Vi))
+                    Some(Movement::ForwardWord(n, At::AfterEnd, Word::Vi))
                 } else {
                     Some(Movement::ForwardWord(n, At::Start, Word::Vi))
                 }
@@ -454,7 +455,7 @@ impl EditState {
             KeyPress::Char('W') => {
                 // 'cW' is 'cE'
                 if key == KeyPress::Char('c') {
-                    Some(Movement::ForwardWord(n, At::End, Word::Big))
+                    Some(Movement::ForwardWord(n, At::AfterEnd, Word::Big))
                 } else {
                     Some(Movement::ForwardWord(n, At::Start, Word::Big))
                 }
@@ -530,7 +531,7 @@ impl EditState {
                 if positive {
                     Cmd::Kill(Movement::BackwardWord(n, Word::Big))
                 } else {
-                    Cmd::Kill(Movement::ForwardWord(n, At::End, Word::Big))
+                    Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Big))
                 }
             }
             KeyPress::Ctrl('Y') => {
diff --git a/src/line_buffer.rs b/src/line_buffer.rs
index 7df42a2b..5c7e76db 100644
--- a/src/line_buffer.rs
+++ b/src/line_buffer.rs
@@ -356,7 +356,7 @@ impl LineBuffer {
         let mut wp = 0;
         let mut gis = self.buf[pos..].grapheme_indices(true);
         let mut gi = None;
-        if at == At::End {
+        if at != At::Start {
             // TODO Validate
             gi = gis.next();
         }
@@ -371,8 +371,8 @@ impl LineBuffer {
                                 if at == At::Start && is_start_of_word(word_def, x, y) {
                                     wp = j;
                                     break 'inner;
-                                } else if at == At::End && is_end_of_word(word_def, x, y) {
-                                    if word_def == Word::Emacs {
+                                } else if at != At::Start && is_end_of_word(word_def, x, y) {
+                                    if word_def == Word::Emacs || at == At::AfterEnd {
                                         wp = j;
                                     } else {
                                         wp = i;
@@ -505,7 +505,7 @@ impl LineBuffer {
     /// Alter the next word.
     pub fn edit_word(&mut self, a: WordAction) -> bool {
         if let Some(start) = self.next_word_pos(self.pos, At::Start, Word::Emacs, 1) {
-            if let Some(end) = self.next_word_pos(self.pos, At::End, Word::Emacs, 1) {
+            if let Some(end) = self.next_word_pos(self.pos, At::AfterEnd, Word::Emacs, 1) {
                 if start == end {
                     return false;
                 }
@@ -530,13 +530,13 @@ impl LineBuffer {
     /// Transpose two words
     pub fn transpose_words(&mut self, n: RepeatCount) -> bool {
         let word_def = Word::Emacs;
-        self.move_to_next_word(At::End, word_def, n);
+        self.move_to_next_word(At::AfterEnd, word_def, n);
         let w2_end = self.pos;
         self.move_to_prev_word(word_def, 1);
         let w2_beg = self.pos;
         self.move_to_prev_word(word_def, n);
         let w1_beg = self.pos;
-        self.move_to_next_word(At::End, word_def, 1);
+        self.move_to_next_word(At::AfterEnd, word_def, 1);
         let w1_end = self.pos;
         if w1_beg == w2_beg || w2_beg < w1_end {
             return false;
@@ -942,7 +942,7 @@ mod test {
     #[test]
     fn move_to_next_word() {
         let mut s = LineBuffer::init("a ß  c", 1);
-        let ok = s.move_to_next_word(At::End, Word::Emacs, 1);
+        let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
         assert_eq!("a ß  c", s.buf);
         assert_eq!(4, s.pos);
         assert_eq!(true, ok);
@@ -951,7 +951,7 @@ mod test {
     #[test]
     fn move_to_end_of_word() {
         let mut s = LineBuffer::init("a ßeta  c", 1);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert_eq!("a ßeta  c", s.buf);
         assert_eq!(6, s.pos);
         assert_eq!(true, ok);
@@ -960,44 +960,44 @@ mod test {
     #[test]
     fn move_to_end_of_vi_word() {
         let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(4, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(6, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(10, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(11, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(14, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(15, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(ok);
         assert_eq!(18, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Vi, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
         assert!(!ok);
     }
 
     #[test]
     fn move_to_end_of_big_word() {
         let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0);
-        let ok = s.move_to_next_word(At::End, Word::Big, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
         assert!(ok);
         assert_eq!(4, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Big, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
         assert!(ok);
         assert_eq!(15, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Big, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
         assert!(ok);
         assert_eq!(18, s.pos);
-        let ok = s.move_to_next_word(At::End, Word::Big, 1);
+        let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
         assert!(!ok);
     }
 
@@ -1057,7 +1057,7 @@ mod test {
     #[test]
     fn delete_word() {
         let mut s = LineBuffer::init("a ß  c", 1);
-        let text = s.delete_word(At::End, Word::Emacs, 1);
+        let text = s.delete_word(At::AfterEnd, Word::Emacs, 1);
         assert_eq!("a  c", s.buf);
         assert_eq!(1, s.pos);
         assert_eq!(Some(" ß".to_string()), text);
-- 
GitLab