diff --git a/src/keymap.rs b/src/keymap.rs
index 87bb37b5e428297d47376a617597af260e70b6f2..203e79bcf69f1e9803e6a5f27a761aa4ce463916 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -46,6 +46,16 @@ pub enum Cmd {
 }
 
 impl Cmd {
+    pub fn should_reset_kill_ring(&self) -> bool {
+        match *self {
+            Cmd::Kill(Movement::BackwardChar(_)) |
+            Cmd::Kill(Movement::ForwardChar(_)) => true,
+            Cmd::ClearScreen | Cmd::Kill(_) | Cmd::Noop | Cmd::Suspend | Cmd::Yank(_, _) |
+            Cmd::YankPop => false,
+            _ => true,
+        }
+    }
+
     fn is_repeatable_change(&self) -> bool {
         match *self {
             Cmd::Insert(_, _) |
diff --git a/src/kill_ring.rs b/src/kill_ring.rs
index b6342f6f05ab0f8257ce59e6a02cae853c4b991e..d28f92036e0ccdc105eb7fba785be8c95c23c15c 100644
--- a/src/kill_ring.rs
+++ b/src/kill_ring.rs
@@ -16,7 +16,9 @@ pub enum Mode {
 
 pub struct KillRing {
     slots: Vec<String>,
+    // where we are in the kill ring
     index: usize,
+    // whether or not the last command was a kill or a yank
     last_action: Action,
 }
 
@@ -45,9 +47,7 @@ impl KillRing {
                 }
                 match dir {
                     Mode::Append => self.slots[self.index].push_str(text),
-                    Mode::Prepend => {
-                        self.slots[self.index] = String::from(text) + &self.slots[self.index]
-                    }
+                    Mode::Prepend => self.slots[self.index].insert_str(0, text),
                 };
             }
             _ => {
diff --git a/src/lib.rs b/src/lib.rs
index 420d2b6ebff4991a39765b6c8e2b2a7db31831fb..35a939cb498c1e81bd9bf339df50cb2743460423 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -866,11 +866,14 @@ fn readline_edit<C: Completer>(prompt: &str,
         let rc = s.next_cmd(&mut rdr);
         let mut cmd = try!(rc);
 
+        if cmd.should_reset_kill_ring() {
+            editor.reset_kill_ring();
+        }
+
         // autocomplete
         if cmd == Cmd::Complete && completer.is_some() {
             let next = try!(complete_line(&mut rdr, &mut s, completer.unwrap(), &editor.config));
             if next.is_some() {
-                editor.reset_kill_ring();
                 cmd = next.unwrap();
             } else {
                 continue;
@@ -878,11 +881,9 @@ fn readline_edit<C: Completer>(prompt: &str,
         }
 
         if let Cmd::SelfInsert(n, c) = cmd {
-            editor.reset_kill_ring();
             try!(edit_insert(&mut s, c, n));
             continue;
         } else if let Cmd::Insert(n, text) = cmd {
-            editor.reset_kill_ring();
             try!(edit_yank(&mut s, &text, Anchor::Before, n));
             continue;
         }
@@ -899,31 +900,25 @@ fn readline_edit<C: Completer>(prompt: &str,
 
         match cmd {
             Cmd::Move(Movement::BeginningOfLine) => {
-                editor.reset_kill_ring();
                 // Move to the beginning of line.
                 try!(edit_move_home(&mut s))
             }
             Cmd::Move(Movement::ViFirstPrint) => {
-                editor.reset_kill_ring();
                 try!(edit_move_home(&mut s));
                 try!(edit_move_to_next_word(&mut s, At::Start, Word::Big, 1))
             }
             Cmd::Move(Movement::BackwardChar(n)) => {
-                editor.reset_kill_ring();
                 // Move back a character.
                 try!(edit_move_backward(&mut s, n))
             }
             Cmd::Kill(Movement::ForwardChar(n)) => {
-                editor.reset_kill_ring();
                 // Delete (forward) one character at point.
                 try!(edit_delete(&mut s, n))
             }
             Cmd::Replace(n, c) => {
-                editor.reset_kill_ring();
                 try!(edit_replace_char(&mut s, c, n));
             }
             Cmd::EndOfFile => {
-                editor.reset_kill_ring();
                 if !s.edit_state.is_emacs_mode() && !s.line.is_empty() {
                     try!(edit_move_end(&mut s));
                     break;
@@ -934,17 +929,14 @@ fn readline_edit<C: Completer>(prompt: &str,
                 }
             }
             Cmd::Move(Movement::EndOfLine) => {
-                editor.reset_kill_ring();
                 // Move to the end of line.
                 try!(edit_move_end(&mut s))
             }
             Cmd::Move(Movement::ForwardChar(n)) => {
-                editor.reset_kill_ring();
                 // Move forward a character.
                 try!(edit_move_forward(&mut s, n))
             }
             Cmd::Kill(Movement::BackwardChar(n)) => {
-                editor.reset_kill_ring();
                 // Delete one character backward.
                 try!(edit_backspace(&mut s, n))
             }
@@ -966,17 +958,14 @@ fn readline_edit<C: Completer>(prompt: &str,
                 try!(s.refresh_line())
             }
             Cmd::NextHistory => {
-                editor.reset_kill_ring();
                 // Fetch the next command from the history list.
                 try!(edit_history_next(&mut s, &editor.history, false))
             }
             Cmd::PreviousHistory => {
-                editor.reset_kill_ring();
                 // Fetch the previous command from the history list.
                 try!(edit_history_next(&mut s, &editor.history, true))
             }
             Cmd::TransposeChars => {
-                editor.reset_kill_ring();
                 // Exchange the char before cursor with the character at cursor.
                 try!(edit_transpose_chars(&mut s))
             }
@@ -989,7 +978,6 @@ fn readline_edit<C: Completer>(prompt: &str,
             #[cfg(unix)]
             Cmd::QuotedInsert => {
                 // Quoted insert
-                editor.reset_kill_ring();
                 let c = try!(rdr.next_char());
                 try!(edit_insert(&mut s, c, 1)) // FIXME
             }
@@ -1000,7 +988,6 @@ fn readline_edit<C: Completer>(prompt: &str,
                 }
             }
             Cmd::ViYankTo(mvt) => {
-                editor.reset_kill_ring();
                 if let Some(text) = s.line.copy(mvt) {
                     editor.kill_ring.borrow_mut().kill(&text, Mode::Append)
                 }
@@ -1008,7 +995,6 @@ fn readline_edit<C: Completer>(prompt: &str,
             // TODO CTRL-_ // undo
             Cmd::AcceptLine => {
                 // Accept the line regardless of where the cursor is.
-                editor.reset_kill_ring();
                 try!(edit_move_end(&mut s));
                 break;
             }
@@ -1020,22 +1006,18 @@ fn readline_edit<C: Completer>(prompt: &str,
             }
             Cmd::BeginningOfHistory => {
                 // move to first entry in history
-                editor.reset_kill_ring();
                 try!(edit_history(&mut s, &editor.history, true))
             }
             Cmd::EndOfHistory => {
                 // move to last entry in history
-                editor.reset_kill_ring();
                 try!(edit_history(&mut s, &editor.history, false))
             }
             Cmd::Move(Movement::BackwardWord(n, word_def)) => {
                 // move backwards one word
-                editor.reset_kill_ring();
                 try!(edit_move_to_prev_word(&mut s, word_def, n))
             }
             Cmd::CapitalizeWord => {
                 // capitalize word after point
-                editor.reset_kill_ring();
                 try!(edit_word(&mut s, WordAction::CAPITALIZE))
             }
             Cmd::Kill(Movement::ForwardWord(n, at, word_def)) => {
@@ -1046,22 +1028,18 @@ fn readline_edit<C: Completer>(prompt: &str,
             }
             Cmd::Move(Movement::ForwardWord(n, at, word_def)) => {
                 // move forwards one word
-                editor.reset_kill_ring();
                 try!(edit_move_to_next_word(&mut s, at, word_def, n))
             }
             Cmd::DowncaseWord => {
                 // lowercase word after point
-                editor.reset_kill_ring();
                 try!(edit_word(&mut s, WordAction::LOWERCASE))
             }
             Cmd::TransposeWords(n) => {
                 // transpose words
-                editor.reset_kill_ring();
                 try!(edit_transpose_words(&mut s, n))
             }
             Cmd::UpcaseWord => {
                 // uppercase word after point
-                editor.reset_kill_ring();
                 try!(edit_word(&mut s, WordAction::UPPERCASE))
             }
             Cmd::YankPop => {
@@ -1070,10 +1048,7 @@ fn readline_edit<C: Completer>(prompt: &str,
                     try!(edit_yank_pop(&mut s, yank_size, text))
                 }
             }
-            Cmd::Move(Movement::ViCharSearch(n, cs)) => {
-                editor.reset_kill_ring();
-                try!(edit_move_to(&mut s, cs, n))
-            }
+            Cmd::Move(Movement::ViCharSearch(n, cs)) => try!(edit_move_to(&mut s, cs, n)),
             Cmd::Kill(Movement::ViCharSearch(n, cs)) => {
                 s.line.bind(KILL_RING_NAME, editor.kill_ring.clone());
                 try!(edit_delete_to(&mut s, cs, n));
@@ -1087,7 +1062,6 @@ fn readline_edit<C: Completer>(prompt: &str,
                 s.line.bind(UNDOS_NAME, s.changes.clone());
             }
             Cmd::Interrupt => {
-                editor.reset_kill_ring();
                 return Err(error::ReadlineError::Interrupted);
             }
             #[cfg(unix)]
@@ -1100,7 +1074,6 @@ fn readline_edit<C: Completer>(prompt: &str,
             }
             Cmd::Noop => {}
             _ => {
-                editor.reset_kill_ring();
                 // Ignore the character typed.
             }
         }