diff --git a/examples/example.rs b/examples/example.rs
index 9f047c64d9e7fd86851017cda8519e96977383c7..8f0233736d2100a2de17c52936a914597af6d584 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -6,7 +6,7 @@ use log::{LogRecord, LogLevel, LogLevelFilter, LogMetadata, SetLoggerError};
 
 use rustyline::completion::FilenameCompleter;
 use rustyline::error::ReadlineError;
-use rustyline::{Config, CompletionType, Editor, EditMode};
+use rustyline::{Cmd, Config, CompletionType, Editor, EditMode, KeyPress};
 
 // On unix platforms you can use ANSI escape sequences
 #[cfg(unix)]
@@ -27,6 +27,8 @@ fn main() {
     let c = FilenameCompleter::new();
     let mut rl = Editor::with_config(config);
     rl.set_completer(Some(c));
+    rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
+    rl.bind_sequence(KeyPress::Meta('P'), Cmd::HistorySearchBackward);
     if rl.load_history("history.txt").is_err() {
         println!("No previous history.");
     }
diff --git a/src/consts.rs b/src/consts.rs
index a1fc550b2db07b56e1d3c4fdba9b3af3ec39ca55..aadac847a23da4e52ad543f3044008963a26e2cf 100644
--- a/src/consts.rs
+++ b/src/consts.rs
@@ -53,7 +53,7 @@ pub fn char_to_key_press(c: char) -> KeyPress {
         '\x19' => KeyPress::Ctrl('Y'),
         '\x1a' => KeyPress::Ctrl('Z'),
         '\x1b' => KeyPress::Esc,
-        '\x7f' => KeyPress::Backspace, // TODO Validate
+        '\x7f' => KeyPress::Backspace,
         _ => KeyPress::Null,
     }
 }
diff --git a/src/history.rs b/src/history.rs
index 5bb46d7e4c102db436d03e0a0872e7fcf9a25a0a..e283cb4ab94629fc1717711b2ab541a03079866e 100644
--- a/src/history.rs
+++ b/src/history.rs
@@ -118,7 +118,7 @@ impl History {
         fix_perm(&file);
         let mut wtr = BufWriter::new(file);
         for entry in &self.entries {
-            try!(wtr.write_all(&entry.as_bytes()));
+            try!(wtr.write_all(entry.as_bytes()));
             try!(wtr.write_all(b"\n"));
         }
         Ok(())
@@ -149,6 +149,18 @@ impl History {
     /// Return None if no entry contains `term` between [start, len -1] for forward search
     /// or between [0, start] for reverse search.
     pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
+        let test = |entry: &String| entry.contains(term);
+        self.search_match(term, start, dir, test)
+    }
+
+    pub fn starts_with(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
+        let test = |entry: &String| entry.starts_with(term);
+        self.search_match(term, start, dir, test)
+    }
+
+    fn search_match<F>(&self, term: &str, start: usize, dir: Direction, test: F) -> Option<usize>
+        where F: Fn(&String) -> bool
+    {
         if term.is_empty() || start >= self.len() {
             return None;
         }
@@ -158,14 +170,11 @@ impl History {
                     .iter()
                     .rev()
                     .skip(self.entries.len() - 1 - start)
-                    .position(|entry| entry.contains(term));
+                    .position(test);
                 index.and_then(|index| Some(start - index))
             }
             Direction::Forward => {
-                let index = self.entries
-                    .iter()
-                    .skip(start)
-                    .position(|entry| entry.contains(term));
+                let index = self.entries.iter().skip(start).position(test);
                 index.and_then(|index| Some(index + start))
             }
         }
diff --git a/src/keymap.rs b/src/keymap.rs
index 0a180ee26b384f364423634b39bcb95b11e25309..e158bb518d939457e31fa9cd806918bd51b53cca 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -23,6 +23,8 @@ pub enum Cmd {
     EndOfFile,
     EndOfHistory,
     ForwardSearchHistory,
+    HistorySearchBackward,
+    HistorySearchForward,
     Insert(RepeatCount, String),
     Interrupt,
     Kill(Movement),
diff --git a/src/lib.rs b/src/lib.rs
index cb69b2d299d4bd0a96356f6733b4c39bd3e38961..19c0baba93f2b78490f294e14da8cb4d7316a25c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -562,6 +562,36 @@ fn edit_history_next(s: &mut State, history: &History, prev: bool) -> Result<()>
     s.refresh_line()
 }
 
+fn edit_history_search(s: &mut State, history: &History, dir: Direction) -> Result<()> {
+    if history.is_empty() {
+        return Ok(());
+    }
+    if s.history_index == history.len() {
+        if dir == Direction::Reverse {
+            // Save the current edited line before to overwrite it
+            s.snapshot();
+        } else {
+            return Ok(());
+        }
+    } else if s.history_index == 0 && dir == Direction::Reverse {
+        return Ok(());
+    }
+    if dir == Direction::Reverse {
+        s.history_index -= 1;
+    } else {
+        s.history_index += 1;
+    }
+    if let Some(history_index) =
+        history.starts_with(&s.line.as_str()[..s.line.pos()], s.history_index, dir) {
+        s.history_index = history_index;
+        let buf = history.get(history_index).unwrap();
+        s.line.update(buf, buf.len());
+        s.refresh_line()
+    } else {
+        Ok(())
+    }
+}
+
 /// Substitute the currently edited line with the first/last history entry.
 fn edit_history(s: &mut State, history: &History, first: bool) -> Result<()> {
     if history.is_empty() {
@@ -966,6 +996,12 @@ fn readline_edit<C: Completer>(prompt: &str,
                 // Fetch the previous command from the history list.
                 try!(edit_history_next(&mut s, &editor.history, true))
             }
+            Cmd::HistorySearchBackward => {
+                try!(edit_history_search(&mut s, &editor.history, Direction::Reverse))
+            }
+            Cmd::HistorySearchForward => {
+                try!(edit_history_search(&mut s, &editor.history, Direction::Forward))
+            }
             Cmd::TransposeChars => {
                 // Exchange the char before cursor with the character at cursor.
                 try!(edit_transpose_chars(&mut s))
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index a91ad9f6a53564375c2990b789b01da18fe846bc..17a439e9511ad5b830973522fa66aece8780aa47 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -161,8 +161,6 @@ impl PosixRawReader {
             }
                })
         } else {
-            // TODO ESC-N (n): search history forward not interactively
-            // TODO ESC-P (p): search history backward not interactively
             // TODO ESC-R (r): Undo all changes made to this line.
             Ok(match seq1 {
                    '\x08' => KeyPress::Meta('\x08'), // Backspace
@@ -175,6 +173,8 @@ impl PosixRawReader {
                    'd' | 'D' => KeyPress::Meta('D'),
                    'f' | 'F' => KeyPress::Meta('F'),
                    'l' | 'L' => KeyPress::Meta('L'),
+                   'n' | 'N' => KeyPress::Meta('N'),
+                   'p' | 'P' => KeyPress::Meta('P'),
                    't' | 'T' => KeyPress::Meta('T'),
                    'u' | 'U' => KeyPress::Meta('U'),
                    'y' | 'Y' => KeyPress::Meta('Y'),
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index d9a14e16078b38f834b24f70b8a911cfefde4644..7b73e2ff58d31b63477bb33def2885a744f18d31 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -154,6 +154,8 @@ impl RawReader for ConsoleRawReader {
                                   'd' | 'D' => KeyPress::Meta('D'),
                                   'f' | 'F' => KeyPress::Meta('F'),
                                   'l' | 'L' => KeyPress::Meta('L'),
+                                  'n' | 'N' => KeyPress::Meta('N'),
+                                  'p' | 'P' => KeyPress::Meta('P'),
                                   't' | 'T' => KeyPress::Meta('T'),
                                   'u' | 'U' => KeyPress::Meta('U'),
                                   'y' | 'Y' => KeyPress::Meta('Y'),