Commit 1832aa1e authored by Liam's avatar Liam Committed by GitHub
Browse files

Merge pull request #42 from iamcodemaker/ctrl

support detection of ctrl-c and ctrl-d key presses
parents ee95b1af 1745f757
......@@ -2,29 +2,46 @@ extern crate liner;
use liner::Context;
use liner::KeyBindings;
use std::io::ErrorKind;
fn main() {
let mut con = Context::new();
loop {
let res = con.read_line("[prompt]$ ", &mut |_| {}).unwrap();
let res = con.read_line("[prompt]$ ", &mut |_| {});
if res.is_empty() {
break;
}
match res {
Ok(res) => {
match res.as_str() {
"emacs" => {
con.key_bindings = KeyBindings::Emacs;
println!("emacs mode");
}
"vi" => {
con.key_bindings = KeyBindings::Vi;
println!("vi mode");
}
"exit" => {
println!("exiting...");
break;
}
_ => {}
}
match res.as_str() {
"emacs" => {
con.key_bindings = KeyBindings::Emacs;
println!("emacs mode");
con.history.push(res.into()).unwrap();
}
"vi" => {
con.key_bindings = KeyBindings::Vi;
println!("vi mode");
Err(e) => {
match e.kind() {
// ctrl-c pressed
ErrorKind::Interrupted => {}
// ctrl-d pressed
ErrorKind::UnexpectedEof => {
println!("exiting...");
break;
}
_ => panic!("error: {:?}", e),
}
}
_ => {}
}
con.history.push(res.into()).unwrap();
}
}
......@@ -287,6 +287,11 @@ impl Buffer {
false
}
}
/// Return true if the buffer is empty.
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
#[cfg(test)]
......
use std::io::{self, Write};
use std::io::{self, Write, ErrorKind};
use termion::event::Key;
use Editor;
use event::*;
......@@ -12,7 +12,18 @@ pub trait KeyMap<'a, W: Write, T>: From<T> {
handler(Event::new(self.editor(), EventKind::BeforeKey(key)));
let is_empty = self.editor().current_buffer().is_empty();
match key {
Key::Ctrl('c') => {
try!(self.editor().handle_newline());
return Err(io::Error::new(ErrorKind::Interrupted, "ctrl-c"));
}
// if the current buffer is empty, treat ctrl-d as eof
Key::Ctrl('d') if is_empty => {
try!(self.editor().handle_newline());
return Err(io::Error::new(ErrorKind::UnexpectedEof, "ctrl-d"));
}
Key::Char('\t') => try!(self.editor().complete(handler)),
Key::Char('\n') => {
try!(self.editor().handle_newline());
......@@ -40,3 +51,72 @@ pub use vi::Vi;
pub mod emacs;
pub use emacs::Emacs;
#[cfg(test)]
mod tests {
use super::*;
use termion::event::Key::*;
use std::io::ErrorKind;
use Context;
struct TestKeyMap<'a, W: Write> {
ed: Editor<'a, W>,
}
impl<'a, W: Write> TestKeyMap<'a, W> {
pub fn new(ed: Editor<'a, W>) -> Self {
TestKeyMap {
ed: ed,
}
}
}
impl<'a, W: Write> KeyMap<'a, W, TestKeyMap<'a, W>> for TestKeyMap<'a, W> {
fn handle_key_core(&mut self, _: Key) -> io::Result<()> {
Ok(())
}
fn editor(&mut self) -> &mut Editor<'a, W> {
&mut self.ed
}
}
#[test]
/// when the current buffer is empty, ctrl-d generates and eof error
fn ctrl_d_empty() {
let mut context = Context::new();
let out = Vec::new();
let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
let mut map = TestKeyMap::new(ed);
let res = map.handle_key(Ctrl('d'), &mut |_| {});
assert_eq!(res.is_err(), true);
assert_eq!(res.err().unwrap().kind(), ErrorKind::UnexpectedEof);
}
#[test]
/// when the current buffer is not empty, ctrl-d should be ignored
fn ctrl_d_non_empty() {
let mut context = Context::new();
let out = Vec::new();
let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
let mut map = TestKeyMap::new(ed);
map.ed.insert_str_after_cursor("not empty").unwrap();
let res = map.handle_key(Ctrl('d'), &mut |_| {});
assert_eq!(res.is_ok(), true);
}
#[test]
/// ctrl-c should generate an error
fn ctrl_c() {
let mut context = Context::new();
let out = Vec::new();
let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
let mut map = TestKeyMap::new(ed);
let res = map.handle_key(Ctrl('c'), &mut |_| {});
assert_eq!(res.is_err(), true);
assert_eq!(res.err().unwrap().kind(), ErrorKind::Interrupted);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment