Fix undos
diff --git a/src/lib.rs b/src/lib.rs
index 27e246b..d17ecda 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -137,10 +137,6 @@
         // TODO swap ChangeListener ?
     }
 
-    fn backup(&mut self) {
-        self.snapshot.backup(&self.line);
-    }
-
     /// Rewrite the currently edited line accordingly to the buffer content,
     /// cursor position, and number of columns of the terminal.
     fn refresh_line(&mut self) -> Result<()> {
@@ -629,8 +625,10 @@
         try!(beep());
         Ok(None)
     } else if CompletionType::Circular == config.completion_type() {
-        // Save the current edited line before to overwrite it
-        s.backup();
+        s.changes.borrow_mut().begin();
+        // Save the current edited line before overwriting it
+        let backup = s.line.as_str().to_owned();
+        let backup_pos = s.line.pos();
         let mut cmd;
         let mut i = 0;
         loop {
@@ -640,9 +638,8 @@
                 try!(s.refresh_line());
             } else {
                 // Restore current edited line
-                s.snapshot();
+                s.line.update(&backup, backup_pos);
                 try!(s.refresh_line());
-                s.snapshot();
             }
 
             cmd = try!(s.next_cmd(rdr));
@@ -655,16 +652,15 @@
                 }
                 Cmd::Abort => {
                     // Re-show original buffer
-                    s.snapshot();
                     if i < candidates.len() {
+                        s.line.update(&backup, backup_pos);
                         try!(s.refresh_line());
                     }
+                    s.changes.borrow_mut().cancel();
                     return Ok(None);
                 }
                 _ => {
-                    if i == candidates.len() {
-                        s.snapshot();
-                    }
+                    s.changes.borrow_mut().end();
                     break;
                 }
             }
@@ -887,8 +883,9 @@
                            editor.history.len(),
                            editor.custom_bindings.clone());
 
-    s.line.bind(s.changes.clone());
     s.line.bind(editor.kill_ring.clone());
+    // must be the last
+    s.line.bind(s.changes.clone());
 
     try!(s.refresh_line());
 
@@ -1093,9 +1090,11 @@
                 editor.kill_ring.borrow_mut().stop_killing();
             }
             Cmd::Undo => {
+                s.line.unbind();
                 if s.changes.borrow_mut().undo(&mut s.line) {
                     try!(s.refresh_line());
                 }
+                s.line.bind(s.changes.clone());
             }
             Cmd::Interrupt => {
                 return Err(error::ReadlineError::Interrupted);
diff --git a/src/line_buffer.rs b/src/line_buffer.rs
index 23da995..c9f251f 100644
--- a/src/line_buffer.rs
+++ b/src/line_buffer.rs
@@ -75,6 +75,9 @@
     pub fn bind(&mut self, cl: Rc<RefCell<ChangeListener>>) {
         self.cl.push(cl);
     }
+    pub fn unbind(&mut self) {
+        self.cl.pop();
+    }
 
     /// Extracts a string slice containing the entire buffer.
     pub fn as_str(&self) -> &str {
@@ -123,14 +126,6 @@
         }
     }
 
-    /// Backup `src`
-    pub fn backup(&mut self, src: &LineBuffer) {
-        let end = self.len();
-        self.drain(0..end, Direction::default());
-        self.insert_str(0, &src.buf);
-        self.pos = src.pos;
-    }
-
     /// Returns the character at current cursor position.
     fn grapheme_at_cursor(&self) -> Option<&str> {
         if self.pos == self.buf.len() {
diff --git a/src/undo.rs b/src/undo.rs
index d8f52e9..5fe4d25 100644
--- a/src/undo.rs
+++ b/src/undo.rs
@@ -1,4 +1,6 @@
 //! Undo API
+use std::fmt::Debug;
+
 use line_buffer::{ChangeListener, Direction, LineBuffer};
 use std_unicode::str::UnicodeStr;
 use unicode_segmentation::UnicodeSegmentation;
@@ -69,7 +71,6 @@
 pub struct Changeset {
     undos: Vec<Change>, // undoable changes
     redos: Vec<Change>, // undone changes, redoable
-    undoing: bool,
 }
 
 impl Changeset {
@@ -77,16 +78,17 @@
         Changeset {
             undos: Vec::new(),
             redos: Vec::new(),
-            undoing: false,
         }
     }
 
     pub fn begin(&mut self) {
+        debug!(target: "rustyline", "Changeset::begin");
         self.redos.clear();
         self.undos.push(Change::Begin);
     }
 
     pub fn end(&mut self) {
+        debug!(target: "rustyline", "Changeset::end");
         self.redos.clear();
         if let Some(&Change::Begin) = self.undos.last() {
             // emtpy Begin..End
@@ -106,6 +108,7 @@
     }
 
     pub fn insert(&mut self, idx: usize, c: char) {
+        debug!(target: "rustyline", "Changeset::insert({:?}, {:?})", idx, c);
         self.redos.clear();
         if !c.is_alphanumeric() {
             self.undos.push(Self::insert_char(idx, c));
@@ -134,7 +137,8 @@
         };
     }
 
-    pub fn insert_str<S: Into<String>>(&mut self, idx: usize, string: S) {
+    pub fn insert_str<S: Into<String> + Debug>(&mut self, idx: usize, string: S) {
+        debug!(target: "rustyline", "Changeset::insert_str({:?}, {:?})", idx, string);
         self.redos.clear();
         self.undos
             .push(Change::Insert {
@@ -143,7 +147,8 @@
                   });
     }
 
-    pub fn delete<S: AsRef<str> + Into<String>>(&mut self, indx: usize, string: S) {
+    pub fn delete<S: AsRef<str> + Into<String> + Debug>(&mut self, indx: usize, string: S) {
+        debug!(target: "rustyline", "Changeset::delete({:?}, {:?})", indx, string);
         self.redos.clear();
 
         if !Self::single_char(string.as_ref()) {
@@ -211,7 +216,7 @@
     }*/
 
     pub fn undo(&mut self, line: &mut LineBuffer) -> bool {
-        self.undoing = true;
+        debug!(target: "rustyline", "Changeset::undo");
         let mut waiting_for_begin = 0;
         let mut undone = false;
         loop {
@@ -236,13 +241,34 @@
                 break;
             }
         }
-        self.undoing = false;
         undone
     }
 
+    pub fn cancel(&mut self) {
+        debug!(target: "rustyline", "Changeset::cancel");
+        let mut waiting_for_begin = 1;
+        loop {
+            if let Some(change) = self.undos.pop() {
+                match change {
+                    Change::Begin => {
+                        waiting_for_begin -= 1;
+                    }
+                    Change::End => {
+                        waiting_for_begin += 1;
+                    }
+                    _ => {}
+                };
+            } else {
+                break;
+            }
+            if waiting_for_begin <= 0 {
+                break;
+            }
+        }
+    }
+
     #[cfg(test)]
     pub fn redo(&mut self, line: &mut LineBuffer) -> bool {
-        self.undoing = true;
         let mut waiting_for_end = 0;
         let mut redone = false;
         loop {
@@ -267,28 +293,18 @@
                 break;
             }
         }
-        self.undoing = false;
         redone
     }
 }
 
 impl ChangeListener for Changeset {
     fn insert_char(&mut self, idx: usize, c: char) {
-        if self.undoing {
-            return;
-        }
         self.insert(idx, c);
     }
     fn insert_str(&mut self, idx: usize, string: &str) {
-        if self.undoing {
-            return;
-        }
         self.insert_str(idx, string);
     }
     fn delete(&mut self, idx: usize, string: &str, _: Direction) {
-        if self.undoing {
-            return;
-        }
         self.delete(idx, string);
     }
 }