From e4f64d95bb29bbcfada415a115e0375fde3e1f22 Mon Sep 17 00:00:00 2001
From: gwenn <gtreguier@gmail.com>
Date: Fri, 31 Mar 2017 19:19:15 +0200
Subject: [PATCH] Use undo group

---
 src/lib.rs  | 43 +++++++++++++++++++++++--------------------
 src/undo.rs | 15 ++++++++++++---
 2 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 35a939cb..b4cdbda0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -347,14 +347,17 @@ fn edit_insert(s: &mut State, ch: char, n: RepeatCount) -> Result<()> {
 
 /// Replace a single (or n) character(s) under the cursor (Vi mode)
 fn edit_replace_char(s: &mut State, ch: char, n: RepeatCount) -> Result<()> {
-    if let Some(chars) = s.line.delete(n) {
+    s.changes.borrow_mut().begin();
+    let succeed = if let Some(chars) = s.line.delete(n) {
         let count = chars.graphemes(true).count();
         s.line.insert(ch, count);
         s.line.move_backward(1);
-        s.refresh_line()
+        true
     } else {
-        Ok(())
-    }
+        false
+    };
+    s.changes.borrow_mut().end();
+    if succeed { s.refresh_line() } else { Ok(()) }
 }
 
 // Yank/paste `text` at current position.
@@ -374,8 +377,11 @@ fn edit_yank(s: &mut State, text: &str, anchor: Anchor, n: RepeatCount) -> Resul
 
 // Delete previously yanked text and yank/paste `text` at current position.
 fn edit_yank_pop(s: &mut State, yank_size: usize, text: &str) -> Result<()> {
+    s.changes.borrow_mut().begin();
     s.line.yank_pop(yank_size, text);
-    edit_yank(s, text, Anchor::Before, 1)
+    let result = edit_yank(s, text, Anchor::Before, 1);
+    s.changes.borrow_mut().end();
+    result
 }
 
 /// Move cursor on the left.
@@ -453,11 +459,10 @@ fn edit_discard_line(s: &mut State) -> Result<()> {
 
 /// Exchange the char before cursor with the character at cursor.
 fn edit_transpose_chars(s: &mut State) -> Result<()> {
-    if s.line.transpose_chars() {
-        s.refresh_line()
-    } else {
-        Ok(())
-    }
+    s.changes.borrow_mut().begin();
+    let succeed = s.line.transpose_chars();
+    s.changes.borrow_mut().end();
+    if succeed { s.refresh_line() } else { Ok(()) }
 }
 
 fn edit_move_to_prev_word(s: &mut State, word_def: Word, n: RepeatCount) -> Result<()> {
@@ -512,19 +517,17 @@ fn edit_delete_to(s: &mut State, cs: CharSearch, n: RepeatCount) -> Result<()> {
 }
 
 fn edit_word(s: &mut State, a: WordAction) -> Result<()> {
-    if s.line.edit_word(a) {
-        s.refresh_line()
-    } else {
-        Ok(())
-    }
+    s.changes.borrow_mut().begin();
+    let succeed = s.line.edit_word(a);
+    s.changes.borrow_mut().end();
+    if succeed { s.refresh_line() } else { Ok(()) }
 }
 
 fn edit_transpose_words(s: &mut State, n: RepeatCount) -> Result<()> {
-    if s.line.transpose_words(n) {
-        s.refresh_line()
-    } else {
-        Ok(())
-    }
+    s.changes.borrow_mut().begin();
+    let succeed = s.line.transpose_words(n);
+    s.changes.borrow_mut().end();
+    if succeed { s.refresh_line() } else { Ok(()) }
 }
 
 /// Substitute the currently edited line with the next or previous history
diff --git a/src/undo.rs b/src/undo.rs
index fd68df1d..fce9e75a 100644
--- a/src/undo.rs
+++ b/src/undo.rs
@@ -86,7 +86,12 @@ impl Changeset {
 
     pub fn end(&mut self) {
         self.redos.clear();
-        self.undos.push(Change::End);
+        if let Some(&Change::Begin) = self.undos.last() {
+            // emtpy Begin..End
+            self.undos.pop();
+        } else {
+            self.undos.push(Change::End);
+        }
     }
 
     fn insert_char(idx: usize, c: char) -> Change {
@@ -212,8 +217,10 @@ impl Changeset {
                         undone = true;
                     }
                 };
+            } else {
+                break;
             }
-            if waiting_for_begin == 0 {
+            if waiting_for_begin <= 0 {
                 break;
             }
         }
@@ -239,8 +246,10 @@ impl Changeset {
                         redone = true;
                     }
                 };
+            } else {
+                break;
             }
-            if waiting_for_end == 0 {
+            if waiting_for_end <= 0 {
                 break;
             }
         }
-- 
GitLab