extern crate liner;
extern crate regex;
extern crate termion;
use std::env::{args, current_dir};
use std::io;
use liner::{Completer, Context, CursorPosition, Event, EventKind, FilenameCompleter, Prompt};
use regex::Regex;
use termion::color;
fn highlight_dodo(s: &str) -> String {
let reg_exp = Regex::new("(?P<k>dodo)").unwrap();
let format = format!("{}$k{}", color::Fg(color::Red), color::Fg(color::Reset));
reg_exp.replace_all(s, format.as_str()).to_string()
}
struct CommentCompleter {
inner: Option<FilenameCompleter>,
}
impl Completer for CommentCompleter {
fn completions(&mut self, start: &str) -> Vec<String> {
if let Some(inner) = &mut self.inner {
inner.completions(start)
} else {
Vec::new()
}
}
fn on_event<W: io::Write>(&mut self, event: Event<W>) {
if let EventKind::BeforeComplete = event.kind {
let (_, pos) = event.editor.get_words_and_cursor_position();
let filename = match pos {
CursorPosition::InWord(i) => i > 0,
CursorPosition::InSpace(Some(_), _) => true,
CursorPosition::InSpace(None, _) => false,
CursorPosition::OnWordLeftEdge(i) => i >= 1,
CursorPosition::OnWordRightEdge(i) => i >= 1,
};
self.inner = if filename {
let completer = FilenameCompleter::new(Some(current_dir().unwrap()));
Some(completer)
} else {
None
}
}
}
}
fn main() {
let mut con = Context::new();
let mut completer = CommentCompleter { inner: None };
let history_file = match args().nth(1) {
Some(file_name) => {
println!("History file: {}", file_name);
file_name
}
None => {
eprintln!("No history file provided. Ending example early.");
return;
}
};
con.history
.set_file_name_and_load_history(history_file)
.unwrap();
loop {
let res = con.read_line(
Prompt::from("[prompt]\n% "),
Some(Box::new(highlight_dodo)),
&mut completer,
);
match res {
Ok(res) => {
match res.as_str() {
"emacs" => {
con.key_bindings = liner::KeyBindings::Emacs;
println!("emacs mode");
}
"vi" => {
con.key_bindings = liner::KeyBindings::Vi;
println!("vi mode");
}
"exit" | "" => {
println!("exiting...");
break;
}
_ => {}
}
if res.is_empty() {
break;
}
con.history.push(res.into()).unwrap();
}
Err(e) => {
match e.kind() {
io::ErrorKind::Interrupted => {}
io::ErrorKind::UnexpectedEof => {
println!("exiting...");
break;
}
_ => {
panic!("error: {:?}", e)
}
}
}
}
}
con.history.commit_to_file();
}