diff --git a/Cargo.toml b/Cargo.toml
index 3580e38803f536151ff7897cb3f0e33f9808e7fb..e49e3c0f1966c66c573562c4cee4b55970e69b47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,6 +15,7 @@ unicode-width = "0.1.3"
 
 [target.'cfg(unix)'.dependencies]
 nix = "0.5.0"
+term = "0.4"
 
 [target.'cfg(windows)'.dependencies]
 winapi = "0.2"
diff --git a/examples/example.rs b/examples/example.rs
index 8d49697fa64fddfeb4bf5025b3dac9b9d7cdbcc4..ff7f9b625be93d2dd0c9de5c51c4b116f938f8a9 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -19,7 +19,7 @@ fn main() {
         .completion_type(CompletionType::List)
         .build();
     let c = FilenameCompleter::new();
-    let mut rl = Editor::new(config);
+    let mut rl = Editor::new(config).expect("Cannot create line editor");
     rl.set_completer(Some(c));
     if let Err(_) = rl.load_history("history.txt") {
         println!("No previous history.");
diff --git a/rustfmt.toml b/rustfmt.toml
index 44148a2d3c3ed6bc75e28e1c55eec63f4d720698..6496add0b747be108c2a26d5848d6604179d3a12 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1 +1,3 @@
-reorder_imports = true
+reorder_imports = false
+normalise_comments = false
+write_mode = "Overwrite"
\ No newline at end of file
diff --git a/src/error.rs b/src/error.rs
index 3df6e70e3fccc3b3b098012e317d01df1760014a..1a4d92940bf872941b7acbc03efbe676acb29fad 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -6,6 +6,8 @@ use std::error;
 use std::fmt;
 #[cfg(unix)]
 use nix;
+#[cfg(unix)]
+use term;
 
 /// The error type for Rustyline errors that can arise from
 /// I/O related errors or Errno when using the nix-rust library
@@ -23,6 +25,8 @@ pub enum ReadlineError {
     /// Unix Error from syscall
     #[cfg(unix)]
     Errno(nix::Error),
+    #[cfg(unix)]
+    TermError(term::Error),
     #[cfg(windows)]
     WindowResize,
     #[cfg(windows)]
@@ -39,6 +43,8 @@ impl fmt::Display for ReadlineError {
             ReadlineError::Char(ref err) => err.fmt(f),
             #[cfg(unix)]
             ReadlineError::Errno(ref err) => write!(f, "Errno: {}", err.errno().desc()),
+            #[cfg(unix)]
+            ReadlineError::TermError(ref err) => err.fmt(f),
             #[cfg(windows)]
             ReadlineError::WindowResize => write!(f, "WindowResize"),
             #[cfg(windows)]
@@ -57,6 +63,8 @@ impl error::Error for ReadlineError {
             ReadlineError::Char(ref err) => err.description(),
             #[cfg(unix)]
             ReadlineError::Errno(ref err) => err.errno().desc(),
+            #[cfg(unix)]
+            ReadlineError::TermError(ref err) => err.description(),
             #[cfg(windows)]
             ReadlineError::WindowResize => "WindowResize",
             #[cfg(windows)]
@@ -85,6 +93,13 @@ impl From<io::CharsError> for ReadlineError {
     }
 }
 
+#[cfg(unix)]
+impl From<term::Error> for ReadlineError {
+    fn from(err: term::Error) -> ReadlineError {
+        ReadlineError::TermError(err)
+    }
+}
+
 #[cfg(windows)]
 impl From<char::DecodeUtf16Error> for ReadlineError {
     fn from(err: char::DecodeUtf16Error) -> ReadlineError {
diff --git a/src/lib.rs b/src/lib.rs
index 9971fae23502f0a987461831de843c06c8887c20..a9cc263f6b20c589ac3a16296e0640fab80d4599 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,7 +8,7 @@
 //!
 //! ```
 //! let config = rustyline::Config::default();
-//! let mut rl = rustyline::Editor::<()>::new(config);
+//! let mut rl = rustyline::Editor::<()>::new(config).expect("Cannot create line editor");
 //! let readline = rl.readline(">> ");
 //! match readline {
 //!     Ok(line) => println!("Line: {:?}",line),
@@ -22,6 +22,8 @@
 extern crate libc;
 #[cfg(unix)]
 extern crate nix;
+#[cfg(unix)]
+extern crate term;
 extern crate unicode_width;
 #[cfg(windows)]
 extern crate winapi;
@@ -38,12 +40,10 @@ pub mod config;
 
 mod tty;
 
-use std::cell::RefCell;
 use std::fmt;
 use std::io::{self, Read, Write};
 use std::mem;
 use std::path::Path;
-use std::rc::Rc;
 use std::result;
 #[cfg(unix)]
 use nix::sys::signal;
@@ -70,7 +70,7 @@ struct State<'out, 'prompt> {
     old_rows: usize, // Number of rows used so far (from start of prompt to end of input)
     history_index: usize, // The history index we are currently editing
     snapshot: LineBuffer, // Current edited line before history browsing/completion
-    term: Rc<RefCell<Terminal>>, // terminal
+    term: Terminal, // terminal
 }
 
 #[derive(Copy, Clone, Debug, Default)]
@@ -81,12 +81,12 @@ struct Position {
 
 impl<'out, 'prompt> State<'out, 'prompt> {
     fn new(out: &'out mut Write,
-           term: Rc<RefCell<Terminal>>,
+           term: Terminal,
            prompt: &'prompt str,
            history_index: usize)
            -> State<'out, 'prompt> {
         let capacity = MAX_LINE;
-        let cols = term.borrow().get_columns();
+        let cols = term.get_columns();
         let prompt_size = calculate_position(prompt, Position::default(), cols);
         State {
             out: out,
@@ -179,16 +179,15 @@ impl<'out, 'prompt> State<'out, 'prompt> {
         // calculate the desired position of the cursor
         let cursor = calculate_position(&self.line[..self.line.pos()], prompt_size, self.cols);
 
-        let mut term = self.term.borrow_mut();
         // position at the start of the prompt, clear to end of previous input
-        let mut info = try!(term.get_console_screen_buffer_info());
+        let mut info = try!(self.term.get_console_screen_buffer_info());
         info.dwCursorPosition.X = 0;
         info.dwCursorPosition.Y -= self.cursor.row as i16;
-        try!(term.set_console_cursor_position(info.dwCursorPosition));
+        try!(self.term.set_console_cursor_position(info.dwCursorPosition));
         let mut _count = 0;
-        try!(term.fill_console_output_character(
-                                                 (info.dwSize.X * (self.old_rows as i16 +1)) as u32,
-                                                 info.dwCursorPosition));
+        try!(self.term
+            .fill_console_output_character((info.dwSize.X * (self.old_rows as i16 + 1)) as u32,
+                                           info.dwCursorPosition));
         let mut ab = String::new();
         // display the prompt
         ab.push_str(prompt); // TODO handle ansi escape code (SetConsoleTextAttribute)
@@ -197,10 +196,10 @@ impl<'out, 'prompt> State<'out, 'prompt> {
         try!(write_and_flush(self.out, ab.as_bytes()));
 
         // position the cursor
-        let mut info = try!(term.get_console_screen_buffer_info());
+        let mut info = try!(self.term.get_console_screen_buffer_info());
         info.dwCursorPosition.X = cursor.col as i16;
         info.dwCursorPosition.Y -= (end_pos.row - cursor.row) as i16;
-        try!(term.set_console_cursor_position(info.dwCursorPosition));
+        try!(self.term.set_console_cursor_position(info.dwCursorPosition));
 
         self.cursor = cursor;
         self.old_rows = end_pos.row;
@@ -209,7 +208,7 @@ impl<'out, 'prompt> State<'out, 'prompt> {
     }
 
     fn update_columns(&mut self) {
-        self.cols = self.term.borrow().get_columns();
+        self.cols = self.term.get_columns();
     }
 }
 
@@ -644,7 +643,7 @@ fn page_completions<R: Read>(rdr: &mut tty::RawReader<R>,
                                  .unwrap() + min_col_pad);
     let num_cols = s.cols / max_width;
 
-    let mut pause_row = s.term.borrow().get_rows() - 1;
+    let mut pause_row = s.term.get_rows() - 1;
     let num_rows = (candidates.len() + num_cols - 1) / num_cols;
     let mut ab = String::new();
     for row in 0..num_rows {
@@ -663,7 +662,7 @@ fn page_completions<R: Read>(rdr: &mut tty::RawReader<R>,
                 KeyPress::Char('y') |
                 KeyPress::Char('Y') |
                 KeyPress::Char(' ') => {
-                    pause_row += s.term.borrow().get_rows() - 1;
+                    pause_row += s.term.get_rows() - 1;
                 }
                 KeyPress::Enter => {
                     pause_row += 1;
@@ -785,14 +784,17 @@ fn readline_edit<C: Completer>(prompt: &str,
     let mut stdout = io::stdout();
 
     editor.kill_ring.reset();
-    let mut s = State::new(&mut stdout, editor.term.clone(), prompt, editor.history.len());
+    let mut s = State::new(&mut stdout,
+                           editor.term.clone(),
+                           prompt,
+                           editor.history.len());
     try!(s.refresh_line());
 
-    let mut rdr = try!(s.term.borrow().create_reader());
+    let mut rdr = try!(s.term.create_reader());
 
     loop {
         let rk = rdr.next_key(true);
-        if rk.is_err() && s.term.borrow().sigwinch() {
+        if rk.is_err() && s.term.sigwinch() {
             s.update_columns();
             try!(s.refresh_line());
             continue;
@@ -881,7 +883,7 @@ fn readline_edit<C: Completer>(prompt: &str,
             }
             KeyPress::Ctrl('L') => {
                 // Clear the screen leaving the current line at the top of the screen.
-                try!(s.term.borrow_mut().clear_screen(&mut s.out));
+                try!(s.term.clear_screen(&mut s.out));
                 try!(s.refresh_line())
             }
             KeyPress::Ctrl('N') |
@@ -928,9 +930,9 @@ fn readline_edit<C: Completer>(prompt: &str,
             }
             #[cfg(unix)]
             KeyPress::Ctrl('Z') => {
-                try!(s.term.borrow_mut().disable_raw_mode(original_mode));
+                try!(tty::disable_raw_mode(original_mode));
                 try!(signal::raise(signal::SIGSTOP));
-                try!(s.term.borrow_mut().enable_raw_mode()); // TODO original_mode may have changed
+                try!(tty::enable_raw_mode()); // TODO original_mode may have changed
                 try!(s.refresh_line())
             }
             // TODO CTRL-_ // undo
@@ -1047,7 +1049,7 @@ fn readline_direct() -> Result<String> {
 
 /// Line editor
 pub struct Editor<C: Completer> {
-    term: Rc<RefCell<Terminal>>,
+    term: Terminal,
     history: History,
     completer: Option<C>,
     kill_ring: KillRing,
@@ -1055,26 +1057,26 @@ pub struct Editor<C: Completer> {
 }
 
 impl<C: Completer> Editor<C> {
-    pub fn new(config: Config) -> Editor<C> {
-        let term = Rc::new(RefCell::new(Terminal::new()));
-        Editor {
+    pub fn new(config: Config) -> Result<Editor<C>> {
+        let term = try!(Terminal::new());
+        Ok(Editor {
             term: term,
             history: History::new(config),
             completer: None,
             kill_ring: KillRing::new(60),
             config: config,
-        }
+        })
     }
 
     /// This method will read a line from STDIN and will display a `prompt`
     pub fn readline(&mut self, prompt: &str) -> Result<String> {
-        if self.term.borrow().is_unsupported() {
+        if self.term.is_unsupported() {
             // Write prompt and flush it to stdout
             let mut stdout = io::stdout();
             try!(write_and_flush(&mut stdout, prompt.as_bytes()));
 
             readline_direct()
-        } else if !self.term.borrow().is_stdin_tty() {
+        } else if !self.term.is_stdin_tty() {
             // Not a tty: read from file / pipe.
             readline_direct()
         } else {
@@ -1121,6 +1123,7 @@ impl<C: Completer> fmt::Debug for Editor<C> {
 #[cfg(all(unix,test))]
 mod test {
     use std::cell::RefCell;
+    use std::collections::HashMap;
     use std::io::Write;
     use std::rc::Rc;
     use line_buffer::LineBuffer;
@@ -1136,7 +1139,7 @@ mod test {
                         pos: usize,
                         cols: usize)
                         -> State<'out, 'static> {
-        let term = Rc::new(RefCell::new(Terminal::new()));
+        let term = Terminal::new().unwrap();
         State {
             out: out,
             prompt: "",
@@ -1204,7 +1207,8 @@ mod test {
         let mut out = ::std::io::sink();
         let mut s = init_state(&mut out, "rus", 3, 80);
         let input = b"\n";
-        let mut rdr = RawReader::new(&input[..]).unwrap();
+        let terminfo_keys = Rc::new(RefCell::new(HashMap::new()));
+        let mut rdr = RawReader::new(&input[..], terminfo_keys).unwrap();
         let completer = SimpleCompleter;
         let key = super::complete_line(&mut rdr, &mut s, &completer, &Config::default()).unwrap();
         assert_eq!(Some(KeyPress::Ctrl('J')), key);
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index bf84dbb7719e9fb7f44a2e8f7cf0cee4c69a817f..b4f0ac84bab2a3b06e6678f43366bf553e0e1b8e 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -1,5 +1,8 @@
 use std;
+use std::cell::RefCell;
+use std::collections::HashMap;
 use std::io::{Chars, Read, Write};
+use std::rc::Rc;
 use std::sync;
 use std::sync::atomic;
 use libc;
@@ -84,6 +87,7 @@ fn is_a_tty(fd: libc::c_int) -> bool {
     unsafe { libc::isatty(fd) != 0 }
 }
 
+/// Enable RAW mode for the terminal.
 pub fn enable_raw_mode() -> Result<Mode> {
     use nix::errno::Errno::ENOTTY;
     use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP, IXON,
@@ -107,6 +111,7 @@ pub fn enable_raw_mode() -> Result<Mode> {
     Ok(original_mode)
 }
 
+/// Disable RAW mode for the terminal.
 pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
     try!(termios::tcsetattr(STDIN_FILENO, termios::TCSAFLUSH, &original_mode));
     Ok(())
@@ -121,11 +126,17 @@ fn clear_screen(w: &mut Write) -> Result<()> {
 /// Console input reader
 pub struct RawReader<R> {
     chars: Chars<R>,
+    terminfo_keys: Rc<RefCell<HashMap<Vec<u8>, String>>>,
 }
 
 impl<R: Read> RawReader<R> {
-    pub fn new(stdin: R) -> Result<RawReader<R>> {
-        Ok(RawReader { chars: stdin.chars() })
+    pub fn new(stdin: R,
+               terminfo_keys: Rc<RefCell<HashMap<Vec<u8>, String>>>)
+               -> Result<RawReader<R>> {
+        Ok(RawReader {
+            chars: stdin.chars(),
+            terminfo_keys: terminfo_keys,
+        })
     }
 
     // As there is no read timeout to properly handle single ESC key,
@@ -230,22 +241,25 @@ extern "C" fn sigwinch_handler(_: signal::SigNum) {
 
 pub type Terminal = PosixTerminal;
 
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 pub struct PosixTerminal {
     unsupported: bool,
     stdin_isatty: bool,
+    terminfo_keys: Rc<RefCell<HashMap<Vec<u8>, String>>>,
 }
 
 impl PosixTerminal {
-    pub fn new() -> PosixTerminal {
-        let term = PosixTerminal {
+    pub fn new() -> Result<PosixTerminal> {
+        let mut term = PosixTerminal {
             unsupported: is_unsupported_term(),
             stdin_isatty: is_a_tty(STDIN_FILENO),
+            terminfo_keys: Rc::new(RefCell::new(HashMap::new())),
         };
         if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
             install_sigwinch_handler();
+            try!(term.load_capabilities());
         }
-        term
+        Ok(term)
     }
 
     // Init checks:
@@ -262,21 +276,17 @@ impl PosixTerminal {
 
     // Init if terminal-style mode:
 
-    // pub fn load_capabilities(&mut self) -> Result<()> {
-    // Ok(())
-    // }
-
-    // Interactive loop:
-
-    /// Enable RAW mode for the terminal.
-    pub fn enable_raw_mode(&mut self) -> Result<Mode> {
-        enable_raw_mode()
+    fn load_capabilities(&mut self) -> Result<()> {
+        use term::terminfo::TermInfo;
+        let term_info = try!(TermInfo::from_env());
+        let mut terminfo_keys = self.terminfo_keys.borrow_mut();
+        for (key, val) in term_info.strings.into_iter() {
+            terminfo_keys.insert(val.clone(), key.clone());
+        }
+        Ok(())
     }
 
-    /// Disable RAW mode for the terminal.
-    pub fn disable_raw_mode(&mut self, mode: Mode) -> Result<()> {
-        disable_raw_mode(mode)
-    }
+    // Interactive loop:
 
     /// Get the number of columns in the current terminal.
     pub fn get_columns(&self) -> usize {
@@ -290,7 +300,7 @@ impl PosixTerminal {
 
     /// Create a RAW reader
     pub fn create_reader(&self) -> Result<RawReader<std::io::Stdin>> {
-        RawReader::new(std::io::stdin())
+        RawReader::new(std::io::stdin(), self.terminfo_keys.clone())
     }
 
     /// Check if a SIGWINCH signal has been received
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index e0e62d04e38c97afa50ef8fecfb7b779f566e7a2..5f83d34b9f7a33dd7c175f0a467fd85fdd1acff7 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -75,6 +75,7 @@ fn is_a_tty(fd: winapi::DWORD) -> bool {
     }
 }
 
+/// Enable raw mode for the TERM
 pub fn enable_raw_mode() -> Result<Mode> {
     let handle = try!(get_std_handle(STDIN_FILENO));
     let original_mode = try!(get_console_mode(handle));
@@ -91,6 +92,7 @@ pub fn enable_raw_mode() -> Result<Mode> {
     Ok(original_mode)
 }
 
+/// Disable Raw mode for the term
 pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
     let handle = try!(get_std_handle(STDIN_FILENO));
     check!(kernel32::SetConsoleMode(handle, original_mode));
@@ -223,20 +225,20 @@ static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
 
 pub type Terminal = Console;
 
-#[derive(Debug)]
+#[derive(Clone,Debug)]
 pub struct Console {
     stdin_isatty: bool,
     stdout_handle: winapi::HANDLE,
 }
 
 impl Console {
-    pub fn new() -> Console {
+    pub fn new() -> Result<Console> {
         use std::ptr;
         let stdout_handle = get_std_handle(STDOUT_FILENO).unwrap_or(ptr::null_mut());
-        Console {
+        Ok(Console {
             stdin_isatty: is_a_tty(STDIN_FILENO),
             stdout_handle: stdout_handle,
-        }
+        })
     }
 
     /// Checking for an unsupported TERM in windows is a no-op
@@ -252,20 +254,6 @@ impl Console {
     // See ReadConsoleInputW && WINDOW_BUFFER_SIZE_EVENT
     // }
 
-    pub fn load_capabilities(&mut self) -> Result<()> {
-        Ok(())
-    }
-
-    /// Enable raw mode for the TERM
-    pub fn enable_raw_mode(&mut self) -> Result<Mode> {
-        enable_raw_mode()
-    }
-
-    /// Disable Raw mode for the term
-    pub fn disable_raw_mode(&mut self, mode: Mode) -> Result<()> {
-        disable_raw_mode(mode)
-    }
-
     /// Try to get the number of columns in the current terminal,
     /// or assume 80 if it fails.
     pub fn get_columns(&self) -> usize {
@@ -301,13 +289,16 @@ impl Console {
         Ok(())
     }
 
-    pub fn fill_console_output_character(&mut self, length: winapi::DWORD, pos: winapi::COORD) -> Result<()> {
+    pub fn fill_console_output_character(&mut self,
+                                         length: winapi::DWORD,
+                                         pos: winapi::COORD)
+                                         -> Result<()> {
         let mut _count = 0;
         check!(kernel32::FillConsoleOutputCharacterA(self.stdout_handle,
-                                                 ' ' as winapi::CHAR,
-                                                 length,
-                                                 pos,
-                                                 &mut _count));
+                                                     ' ' as winapi::CHAR,
+                                                     length,
+                                                     pos,
+                                                     &mut _count));
         Ok(())
     }
 }