| extern crate log; |
| extern crate rustyline; |
| |
| use log::{Level, LevelFilter, Metadata, Record, SetLoggerError}; |
| |
| use rustyline::completion::{Completer, FilenameCompleter}; |
| use rustyline::error::ReadlineError; |
| use rustyline::hint::Hinter; |
| use rustyline::{Cmd, CompletionType, Config, EditMode, Editor, Helper, KeyPress}; |
| |
| // On unix platforms you can use ANSI escape sequences |
| #[cfg(unix)] |
| static PROMPT: &'static str = "\x1b[1;32m>>\x1b[0m "; |
| |
| // Windows consoles typically don't support ANSI escape sequences out |
| // of the box |
| #[cfg(windows)] |
| static PROMPT: &'static str = ">> "; |
| |
| struct MyHelper(FilenameCompleter); |
| |
| impl Completer for MyHelper { |
| fn complete(&self, line: &str, pos: usize) -> Result<(usize, Vec<String>), ReadlineError> { |
| self.0.complete(line, pos) |
| } |
| } |
| |
| impl Hinter for MyHelper { |
| fn hint(&self, line: &str, _pos: usize) -> Option<String> { |
| if line == "hello" { |
| if cfg!(target_os = "windows") { |
| Some(" World".to_owned()) |
| } else { |
| Some(" \x1b[1mWorld\x1b[m".to_owned()) |
| } |
| } else { |
| None |
| } |
| } |
| } |
| |
| impl Helper for MyHelper {} |
| |
| fn main() { |
| init_logger().is_ok(); |
| let config = Config::builder() |
| .history_ignore_space(true) |
| .completion_type(CompletionType::List) |
| .edit_mode(EditMode::Emacs) |
| .build(); |
| let h = MyHelper(FilenameCompleter::new()); |
| let mut rl = Editor::with_config(config); |
| rl.set_helper(Some(h)); |
| 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."); |
| } |
| loop { |
| let readline = rl.readline(PROMPT); |
| match readline { |
| Ok(line) => { |
| rl.add_history_entry(line.as_ref()); |
| println!("Line: {}", line); |
| } |
| Err(ReadlineError::Interrupted) => { |
| println!("CTRL-C"); |
| break; |
| } |
| Err(ReadlineError::Eof) => { |
| println!("CTRL-D"); |
| break; |
| } |
| Err(err) => { |
| println!("Error: {:?}", err); |
| break; |
| } |
| } |
| } |
| rl.save_history("history.txt").unwrap(); |
| } |
| |
| static LOGGER: Logger = Logger; |
| struct Logger; |
| |
| impl log::Log for Logger { |
| fn enabled(&self, metadata: &Metadata) -> bool { |
| metadata.level() <= Level::Debug |
| } |
| |
| fn log(&self, record: &Record) { |
| if self.enabled(record.metadata()) { |
| eprintln!("{} - {}", record.level(), record.args()); |
| } |
| } |
| |
| fn flush(&self) {} |
| } |
| |
| fn init_logger() -> Result<(), SetLoggerError> { |
| try!(log::set_logger(&LOGGER)); |
| log::set_max_level(LevelFilter::Info); |
| Ok(()) |
| } |