Repository: kkawakam/rustyline
Pull request #571 (2021-11-01 16:21:29)

Misc


Patch:
diff --git a/BUGS.md b/BUGS.md
index fe75517..f6ac7d8 100644
--- a/BUGS.md
+++ b/BUGS.md
@@ -16,9 +16,10 @@ Currently, performance is poor because, most of the time, we refresh the whole l
 We would like to transform events on prompt/line/hint into partial repaint.
 
 See `termwiz` design (`Surface`).
-See `replxx` refresh delay (`_lastRefreshTime`)
+See `replxx` refresh delay (`_lastRefreshTime`) or `python-prompt-toolkit` max_render_postpone_time.
 https://docs.rs/xi-unicode/0.3.0/xi_unicode/struct.LineBreakIterator.html
 https://github.com/xi-editor/xi-editor/blob/master/rust/core-lib/src/linewrap.rs
+[vt100](https://docs.rs/vt100/0.12.0/vt100/struct.Screen.html#method.contents_diff)
 
 ## Action / Command
 
diff --git a/Cargo.toml b/Cargo.toml
index c2e240a..cfa0432 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,7 +2,7 @@
 name = "rustyline"
 version = "9.0.0"
 authors = ["Katsu Kawakami <kkawa1570@gmail.com>"]
-edition = "2021"
+edition = "2018"
 description = "Rustyline, a readline implementation based on Antirez's Linenoise"
 documentation = "http://docs.rs/rustyline"
 repository = "https://github.com/kkawakam/rustyline"
diff --git a/History.md b/History.md
index 0e9d6f6..bbb6efd 100644
--- a/History.md
+++ b/History.md
@@ -17,14 +17,17 @@
     - if path used to save history is the same:
         + if timestamp is still the same => we can append only new lines if history has not been truncated.
 
+```
 HistoryInfo
   first_add_index: Option<usize>, // first line inserted by this session
   truncated: bool //
   path_info: Option<PathInfo>,
-
+```
+```
 PathInfo
   path: Path,
   modified: SystemTime,
+```
 
 ---
 With `termwiz`, you can define your own `History` backend.
diff --git a/TODO.md b/TODO.md
index 0223526..c56198d 100644
--- a/TODO.md
+++ b/TODO.md
@@ -42,6 +42,7 @@ History
 each line input session.
 - [X] append_history
 - [ ] history_truncate_file
+- [ ] custom persistent storage
 
 Input
 - [ ] Password input (#58) (https://github.com/conradkdotcom/rpassword) (https://github.com/antirez/linenoise/issues/125)
diff --git a/examples/example.rs b/examples/example.rs
index f937b8f..7b3ccc8 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -113,11 +113,11 @@ fn main() -> rustyline::Result<()> {
                 println!("Line: {}", line);
             }
             Err(ReadlineError::Interrupted) => {
-                println!("Interrupted");
+                println!("CTRL-C");
                 break;
             }
             Err(ReadlineError::Eof) => {
-                println!("Encountered Eof");
+                println!("CTRL-D");
                 break;
             }
             Err(err) => {
diff --git a/src/completion.rs b/src/completion.rs
index 7cf2794..c31d5a9 100644
--- a/src/completion.rs
+++ b/src/completion.rs
@@ -7,11 +7,6 @@ use crate::line_buffer::LineBuffer;
 use crate::{Context, Result};
 use memchr::memchr;
 
-// TODO: let the implementers choose/find word boundaries ???
-// (line, pos) is like (rl_line_buffer, rl_point) to make contextual completion
-// ("select t.na| from tbl as t")
-// TODO: make &self &mut self ???
-
 /// A completion candidate.
 pub trait Candidate {
     /// Text to display when listing alternatives.
@@ -69,18 +64,23 @@ impl Candidate for Pair {
     }
 }
 
+// TODO: let the implementers customize how the candidate(s) are displayed
+// https://github.com/kkawakam/rustyline/issues/302
+
 /// To be called for tab-completion.
 pub trait Completer {
     /// Specific completion candidate.
     type Candidate: Candidate;
 
+    // TODO: let the implementers choose/find word boundaries ??? => Lexer
+
     /// Takes the currently edited `line` with the cursor `pos`ition and
     /// returns the start position and the completion candidates for the
     /// partial word to be completed.
     ///
     /// ("ls /usr/loc", 11) => Ok((3, vec!["/usr/local/"]))
     fn complete(
-        &self,
+        &self, // FIXME should be `&mut self`
         line: &str,
         pos: usize,
         ctx: &Context<'_>,
diff --git a/src/error.rs b/src/error.rs
index 3ef771a..b4d365f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -14,9 +14,9 @@ use std::io;
 pub enum ReadlineError {
     /// I/O Error
     Io(io::Error),
-    /// EOF (VEOF / Ctrl-D)
+    /// EOF (Ctrl-D)
     Eof,
-    /// Interrupt signal (VINTR / VQUIT / Ctrl-C)
+    /// Ctrl-C
     Interrupted,
     /// Chars Error
     #[cfg(unix)]
diff --git a/src/highlight.rs b/src/highlight.rs
index c46401b..95577fc 100644
--- a/src/highlight.rs
+++ b/src/highlight.rs
@@ -42,7 +42,7 @@ pub trait Highlighter {
     /// Currently, used only with `CompletionType::List`.
     fn highlight_candidate<'c>(
         &self,
-        candidate: &'c str,
+        candidate: &'c str, // FIXME should be Completer::Candidate
         completion: CompletionType,
     ) -> Cow<'c, str> {
         let _ = completion;
@@ -94,6 +94,8 @@ impl<'r, H: ?Sized + Highlighter> Highlighter for &'r H {
 const OPENS: &[u8; 3] = b"{[(";
 const CLOSES: &[u8; 3] = b"}])";
 
+/// TODO versus https://python-prompt-toolkit.readthedocs.io/en/master/pages/reference.html?highlight=HighlightMatchingBracketProcessor#prompt_toolkit.layout.processors.HighlightMatchingBracketProcessor
+
 /// Highlight matching bracket when typed or cursor moved on.
 #[derive(Default)]
 pub struct MatchingBracketHighlighter {
diff --git a/src/history.rs b/src/history.rs
index 4d521d5..1bde437 100644
--- a/src/history.rs
+++ b/src/history.rs
@@ -34,6 +34,12 @@ pub struct SearchResult<'a> {
     pub pos: usize,
 }
 
+/// HistoryEntry: text + timestamp
+/// TODO Make possible to customize how history is stored / loaded.
+/// https://github.com/kkawakam/rustyline/issues/442
+/// https://github.com/kkawakam/rustyline/issues/127
+/// See https://python-prompt-toolkit.readthedocs.io/en/master/pages/reference.html#prompt_toolkit.history.History abstract methods
+
 /// Current state of the history.
 #[derive(Default)]
 pub struct History {
diff --git a/src/keymap.rs b/src/keymap.rs
index 2abeaf0..80fe6af 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -45,11 +45,11 @@ pub enum Cmd {
     EndOfFile,
     /// end-of-history
     EndOfHistory,
-    /// forward-search-history
+    /// forward-search-history (incremental search)
     ForwardSearchHistory,
-    /// history-search-backward
+    /// history-search-backward (common prefix search)
     HistorySearchBackward,
-    /// history-search-forward
+    /// history-search-forward (common prefix search)
     HistorySearchForward,
     /// Indent current line
     Indent(Movement),
@@ -79,7 +79,7 @@ pub enum Cmd {
     ReplaceChar(RepeatCount, char),
     /// vi-change-to, vi-substitute
     Replace(Movement, Option<String>),
-    /// reverse-search-history
+    /// reverse-search-history (incremental search)
     ReverseSearchHistory,
     /// self-insert
     SelfInsert(RepeatCount, char),
@@ -434,7 +434,6 @@ impl InputState {
         }
     }
 
-    /// Application customized binding
     fn custom_binding(
         &self,
         wrt: &mut dyn Refresher,
@@ -457,20 +456,6 @@ impl InputState {
         }
     }
 
-    /// Terminal peculiar binding
-    fn term_binding<R: RawReader>(
-        rdr: &mut R,
-        wrt: &mut dyn Refresher,
-        key: &KeyEvent,
-    ) -> Option<Cmd> {
-        let cmd = rdr.find_binding(key);
-        if cmd == Some(Cmd::EndOfFile) && !wrt.line().is_empty() {
-            None // ReadlineError::Eof only if line is empty
-        } else {
-            cmd
-        }
-    }
-
     fn custom_seq_binding<R: RawReader>(
         &self,
         rdr: &mut R,
@@ -565,8 +550,6 @@ impl InputState {
             } else {
                 cmd
             });
-        } else if let Some(cmd) = InputState::term_binding(rdr, wrt, &key) {
-            return Ok(cmd);
         }
         let cmd = match key {
             E(K::Char(c), M::NONE) => {
@@ -742,8 +725,6 @@ impl InputState {
             } else {
                 cmd
             });
-        } else if let Some(cmd) = InputState::term_binding(rdr, wrt, &key) {
-            return Ok(cmd);
         }
         let cmd = match key {
             E(K::Char('$'), M::NONE) | E(K::End, M::NONE) => Cmd::Move(Movement::EndOfLine),
@@ -915,8 +896,6 @@ impl InputState {
             } else {
                 cmd
             });
-        } else if let Some(cmd) = InputState::term_binding(rdr, wrt, &key) {
-            return Ok(cmd);
         }
         let cmd = match key {
             E(K::Char(c), M::NONE) => {
@@ -1059,7 +1038,6 @@ impl InputState {
             } else {
                 Movement::ForwardChar(n)
             }),
-            #[cfg(any(windows, test))]
             E(K::Char('C'), M::CTRL) => Cmd::Interrupt,
             E(K::Char('D'), M::CTRL) => {
                 if self.is_emacs_mode() && !wrt.line().is_empty() {
@@ -1068,10 +1046,8 @@ impl InputState {
                     } else {
                         Movement::BackwardChar(n)
                     })
-                } else if cfg!(window) || cfg!(test) || !wrt.line().is_empty() {
-                    Cmd::EndOfFile
                 } else {
-                    Cmd::Unknown
+                    Cmd::EndOfFile
                 }
             }
             E(K::Delete, M::NONE) => Cmd::Kill(if positive {
@@ -1119,6 +1095,7 @@ impl InputState {
                     Cmd::Unknown // TODO Validate
                 }
             }
+            E(K::Char('Z'), M::CTRL) => Cmd::Suspend,
             E(K::Char('_'), M::CTRL) => Cmd::Undo(n),
             E(K::UnknownEscSeq, M::NONE) => Cmd::Noop,
             E(K::BracketedPasteStart, M::NONE) => {
diff --git a/src/lib.rs b/src/lib.rs
index 3f13d38..e189e77 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -440,7 +440,6 @@ fn readline_edit<H: Helper>(
     initial: Option<(&str, &str)>,
     editor: &mut Editor<H>,
     original_mode: &tty::Mode,
-    term_key_map: tty::KeyMap,
 ) -> Result<String> {
     let mut stdout = editor.term.create_writer();
 
@@ -458,7 +457,7 @@ fn readline_edit<H: Helper>(
             .update((left.to_owned() + right).as_ref(), left.len());
     }
 
-    let mut rdr = editor.term.create_reader(&editor.config, term_key_map)?;
+    let mut rdr = editor.term.create_reader(&editor.config)?;
     if editor.term.is_output_tty() && editor.config.check_cursor_position() {
         if let Err(e) = s.move_cursor_at_leftmost(&mut rdr) {
             if s.out.sigwinch() {
@@ -567,9 +566,9 @@ fn readline_raw<H: Helper>(
     initial: Option<(&str, &str)>,
     editor: &mut Editor<H>,
 ) -> Result<String> {
-    let (original_mode, term_key_map) = editor.term.enable_raw_mode()?;
+    let original_mode = editor.term.enable_raw_mode()?;
     let guard = Guard(&original_mode);
-    let user_input = readline_edit(prompt, initial, editor, &original_mode, term_key_map);
+    let user_input = readline_edit(prompt, initial, editor, &original_mode);
     if editor.config.auto_add_history() {
         if let Ok(ref line) = user_input {
             editor.add_history_entry(line.as_str());
diff --git a/src/line_buffer.rs b/src/line_buffer.rs
index 9c99bc3..f14abba 100644
--- a/src/line_buffer.rs
+++ b/src/line_buffer.rs
@@ -52,6 +52,8 @@ pub(crate) trait ChangeListener: DeleteListener {
     fn replace(&mut self, idx: usize, old: &str, new: &str);
 }
 
+// TODO split / cache lines ?
+
 /// Represent the current input (text and cursor position).
 ///
 /// The methods do text manipulations or/and cursor movements.
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index 96bcf8f..3b511bb 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -7,7 +7,7 @@ use crate::highlight::Highlighter;
 use crate::keys::KeyEvent;
 use crate::layout::{Layout, Position};
 use crate::line_buffer::LineBuffer;
-use crate::{Cmd, Result};
+use crate::Result;
 
 /// Terminal state
 pub trait RawMode: Sized {
@@ -24,8 +24,6 @@ pub trait RawReader {
     fn next_char(&mut self) -> Result<char>;
     /// Bracketed paste
     fn read_pasted_text(&mut self) -> Result<String>;
-    /// Check if `key` is bound to a peculiar command
-    fn find_binding(&self, key: &KeyEvent) -> Option<Cmd>;
 }
 
 /// Display prompt, line and cursor in terminal output
@@ -201,7 +199,6 @@ fn width(s: &str, esc_seq: &mut u8) -> usize {
 
 /// Terminal contract
 pub trait Term {
-    type KeyMap;
     type Reader: RawReader; // rl_instream
     type Writer: Renderer<Reader = Self::Reader>; // rl_outstream
     type Mode: RawMode;
@@ -221,9 +218,9 @@ pub trait Term {
     /// check if output stream is connected to a terminal.
     fn is_output_tty(&self) -> bool;
     /// Enable RAW mode for the terminal.
-    fn enable_raw_mode(&mut self) -> Result<(Self::Mode, Self::KeyMap)>;
+    fn enable_raw_mode(&mut self) -> Result<Self::Mode>;
     /// Create a RAW reader
-    fn create_reader(&self, config: &Config, key_map: Self::KeyMap) -> Result<Self::Reader>;
+    fn create_reader(&self, config: &Config) -> Result<Self::Reader>;
     /// Create a writer
     fn create_writer(&self) -> Self::Writer;
 }
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 8e97bc4..00fa7b8 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -9,18 +9,18 @@ use log::{debug, warn};
 use nix::poll::{self, PollFlags};
 use nix::sys::signal;
 use nix::sys::termios;
-use nix::sys::termios::{SetArg, SpecialCharacterIndices as SCI, Termios};
+use nix::sys::termios::SetArg;
 use unicode_segmentation::UnicodeSegmentation;
 use utf8parse::{Parser, Receiver};
 
 use super::{width, RawMode, RawReader, Renderer, Term};
 use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
+use crate::error;
 use crate::highlight::Highlighter;
 use crate::keys::{KeyCode as K, KeyEvent, KeyEvent as E, Modifiers as M};
 use crate::layout::{Layout, Position};
 use crate::line_buffer::LineBuffer;
-use crate::{error, Cmd, Result};
-use std::collections::HashMap;
+use crate::Result;
 
 const STDIN_FILENO: RawFd = libc::STDIN_FILENO;
 
@@ -95,10 +95,6 @@ fn is_a_tty(fd: RawFd) -> bool {
     unsafe { libc::isatty(fd) != 0 }
 }
 
-pub type PosixKeyMap = HashMap<KeyEvent, Cmd>;
-#[cfg(not(test))]
-pub type KeyMap = PosixKeyMap;
-
 #[must_use = "You must restore default mode (disable_raw_mode)"]
 pub struct PosixMode {
     termios: termios::Termios,
@@ -154,7 +150,6 @@ pub struct PosixRawReader {
     buf: [u8; 1],
     parser: Parser,
     receiver: Utf8,
-    key_map: PosixKeyMap,
 }
 
 struct Utf8 {
@@ -189,7 +184,7 @@ const RXVT_CTRL: char = '\x1e';
 const RXVT_CTRL_SHIFT: char = '@';
 
 impl PosixRawReader {
-    fn new(config: &Config, key_map: PosixKeyMap) -> Self {
+    fn new(config: &Config) -> Self {
         Self {
             stdin: StdinRaw {},
             timeout_ms: config.keyseq_timeout(),
@@ -199,7 +194,6 @@ impl PosixRawReader {
                 c: None,
                 valid: true,
             },
-            key_map,
         }
     }
 
@@ -722,14 +716,6 @@ impl RawReader for PosixRawReader {
         let buffer = buffer.replace("\r", "\n");
         Ok(buffer)
     }
-
-    fn find_binding(&self, key: &KeyEvent) -> Option<Cmd> {
-        let cmd = self.key_map.get(key).cloned();
-        if let Some(ref cmd) = cmd {
-            debug!(target: "rustyline", "terminal key binding: {:?} => {:?}", key, cmd);
-        }
-        cmd
-    }
 }
 
 impl Receiver for Utf8 {
@@ -1000,7 +986,7 @@ impl Renderer for PosixRenderer {
         }
         let col = read_digits_until(rdr, 'R')?;
         debug!(target: "rustyline", "initial cursor location: {:?}", col);
-        if col.is_some() && col != Some(1) {
+        if col != Some(1) {
             self.write_and_flush(b"\n")?;
         }
         Ok(())
@@ -1043,13 +1029,6 @@ extern "C" fn sigwinch_handler(_: libc::c_int) {
     debug!(target: "rustyline", "SIGWINCH");
 }
 
-fn map_key(key_map: &mut HashMap<KeyEvent, Cmd>, raw: &Termios, index: SCI, name: &str, cmd: Cmd) {
-    let cc = char::from(raw.control_chars[index as usize]);
-    let key = KeyEvent::new(cc, M::NONE);
-    debug!(target: "rustyline", "{}: {:?}", name, key);
-    key_map.insert(key, cmd);
-}
-
 #[cfg(not(test))]
 pub type Terminal = PosixTerminal;
 
@@ -1076,7 +1055,6 @@ impl PosixTerminal {
 }
 
 impl Term for PosixTerminal {
-    type KeyMap = PosixKeyMap;
     type Mode = PosixMode;
     type Reader = PosixRawReader;
     type Writer = PosixRenderer;
@@ -1123,9 +1101,9 @@ impl Term for PosixTerminal {
 
     // Interactive loop:
 
-    fn enable_raw_mode(&mut self) -> Result<(Self::Mode, PosixKeyMap)> {
+    fn enable_raw_mode(&mut self) -> Result<Self::Mode> {
         use nix::errno::Errno::ENOTTY;
-        use nix::sys::termios::{ControlFlags, InputFlags, LocalFlags};
+        use nix::sys::termios::{ControlFlags, InputFlags, LocalFlags, SpecialCharacterIndices};
         if !self.stdin_isatty {
             return Err(ENOTTY.into());
         }
@@ -1147,15 +1125,8 @@ impl Term for PosixTerminal {
         // disable echoing, canonical mode, extended input processing and signals
         raw.local_flags &=
             !(LocalFlags::ECHO | LocalFlags::ICANON | LocalFlags::IEXTEN | LocalFlags::ISIG);
-        raw.control_chars[SCI::VMIN as usize] = 1; // One character-at-a-time input
-        raw.control_chars[SCI::VTIME as usize] = 0; // with blocking read
-
-        let mut key_map: HashMap<KeyEvent, Cmd> = HashMap::with_capacity(3);
-        map_key(&mut key_map, &raw, SCI::VEOF, "VEOF", Cmd::EndOfFile);
-        map_key(&mut key_map, &raw, SCI::VINTR, "VINTR", Cmd::Interrupt);
-        map_key(&mut key_map, &raw, SCI::VQUIT, "VQUIT", Cmd::Interrupt);
-        map_key(&mut key_map, &raw, SCI::VSUSP, "VSUSP", Cmd::Suspend);
-
+        raw.control_chars[SpecialCharacterIndices::VMIN as usize] = 1; // One character-at-a-time input
+        raw.control_chars[SpecialCharacterIndices::VTIME as usize] = 0; // with blocking read
         termios::tcsetattr(STDIN_FILENO, SetArg::TCSADRAIN, &raw)?;
 
         // enable bracketed paste
@@ -1167,18 +1138,15 @@ impl Term for PosixTerminal {
         } else {
             Some(self.stream_type)
         };
-        Ok((
-            PosixMode {
-                termios: original_mode,
-                out,
-            },
-            key_map,
-        ))
+        Ok(PosixMode {
+            termios: original_mode,
+            out,
+        })
     }
 
     /// Create a RAW reader
-    fn create_reader(&self, config: &Config, key_map: PosixKeyMap) -> Result<PosixRawReader> {
-        Ok(PosixRawReader::new(config, key_map))
+    fn create_reader(&self, config: &Config) -> Result<PosixRawReader> {
+        Ok(PosixRawReader::new(config))
     }
 
     fn create_writer(&self) -> PosixRenderer {
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index 62732d0..76645cd 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -17,11 +17,12 @@ use winapi::um::{consoleapi, processenv, winbase, winuser};
 
 use super::{width, RawMode, RawReader, Renderer, Term};
 use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
+use crate::error;
 use crate::highlight::Highlighter;
 use crate::keys::{KeyCode as K, KeyEvent, Modifiers as M};
 use crate::layout::{Layout, Position};
 use crate::line_buffer::LineBuffer;
-use crate::{error, Cmd, Result};
+use crate::Result;
 
 const STDIN_FILENO: DWORD = winbase::STD_INPUT_HANDLE;
 const STDOUT_FILENO: DWORD = winbase::STD_OUTPUT_HANDLE;
@@ -65,10 +66,6 @@ fn get_console_mode(handle: HANDLE) -> Result<DWORD> {
     Ok(original_mode)
 }
 
-type ConsoleKeyMap = ();
-#[cfg(not(test))]
-pub type KeyMap = ConsoleKeyMap;
-
 #[must_use = "You must restore default mode (disable_raw_mode)"]
 #[cfg(not(test))]
 pub type Mode = ConsoleMode;
@@ -227,10 +224,6 @@ impl RawReader for ConsoleRawReader {
     fn read_pasted_text(&mut self) -> Result<String> {
         Ok(clipboard_win::get_clipboard_string()?)
     }
-
-    fn find_binding(&self, _: &KeyEvent) -> Option<Cmd> {
-        None
-    }
 }
 
 pub struct ConsoleRenderer {
@@ -543,7 +536,6 @@ impl Console {
 }
 
 impl Term for Console {
-    type KeyMap = ConsoleKeyMap;
     type Mode = ConsoleMode;
     type Reader = ConsoleRawReader;
     type Writer = ConsoleRenderer;
@@ -608,7 +600,7 @@ impl Term for Console {
     // }
 
     /// Enable RAW mode for the terminal.
-    fn enable_raw_mode(&mut self) -> Result<(ConsoleMode, ConsoleKeyMap)> {
+    fn enable_raw_mode(&mut self) -> Result<Self::Mode> {
         if !self.stdin_isatty {
             Err(io::Error::new(
                 io::ErrorKind::Other,
@@ -663,18 +655,15 @@ impl Term for Console {
             None
         };
 
-        Ok((
-            ConsoleMode {
-                original_stdin_mode,
-                stdin_handle: self.stdin_handle,
-                original_stdstream_mode,
-                stdstream_handle: self.stdstream_handle,
-            },
-            (),
-        ))
+        Ok(ConsoleMode {
+            original_stdin_mode,
+            stdin_handle: self.stdin_handle,
+            original_stdstream_mode,
+            stdstream_handle: self.stdstream_handle,
+        })
     }
 
-    fn create_reader(&self, _: &Config, _: ConsoleKeyMap) -> Result<ConsoleRawReader> {
+    fn create_reader(&self, _: &Config) -> Result<ConsoleRawReader> {
         ConsoleRawReader::create()
     }
 


Test patch:
diff --git a/src/tty/test.rs b/src/tty/test.rs
index 0b362f4..d8bed91 100644
--- a/src/tty/test.rs
+++ b/src/tty/test.rs
@@ -10,9 +10,8 @@ use crate::highlight::Highlighter;
 use crate::keys::KeyEvent;
 use crate::layout::{Layout, Position};
 use crate::line_buffer::LineBuffer;
-use crate::{Cmd, Result};
+use crate::Result;
 
-pub type KeyMap = ();
 pub type Mode = ();
 
 impl RawMode for Mode {
@@ -37,10 +36,6 @@ impl<'a> RawReader for Iter<'a, KeyEvent> {
     fn read_pasted_text(&mut self) -> Result<String> {
         unimplemented!()
     }
-
-    fn find_binding(&self, _: &KeyEvent) -> Option<Cmd> {
-        None
-    }
 }
 
 impl RawReader for IntoIter<KeyEvent> {
@@ -64,10 +59,6 @@ impl RawReader for IntoIter<KeyEvent> {
     fn read_pasted_text(&mut self) -> Result<String> {
         unimplemented!()
     }
-
-    fn find_binding(&self, _: &KeyEvent) -> Option<Cmd> {
-        None
-    }
 }
 
 pub struct Sink {}
@@ -149,7 +140,6 @@ pub struct DummyTerminal {
 }
 
 impl Term for DummyTerminal {
-    type KeyMap = KeyMap;
     type Mode = Mode;
     type Reader = IntoIter<KeyEvent>;
     type Writer = Sink;
@@ -191,11 +181,11 @@ impl Term for DummyTerminal {
 
     // Interactive loop:
 
-    fn enable_raw_mode(&mut self) -> Result<(Mode, KeyMap)> {
-        Ok(((), ()))
+    fn enable_raw_mode(&mut self) -> Result<Mode> {
+        Ok(())
     }
 
-    fn create_reader(&self, _: &Config, _: KeyMap) -> Result<Self::Reader> {
+    fn create_reader(&self, _: &Config) -> Result<IntoIter<KeyEvent>> {
         Ok(self.keys.clone().into_iter())
     }