1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#[macro_use] extern crate error_chain; #[macro_use] extern crate nom; #[macro_use] extern crate log; #[cfg(test)] #[macro_use] extern crate nom_test_helpers; use std::io::{self, Write}; use std::default::Default; use std::collections::HashMap; use std::process; use errors::*; const DEFAULT_PROMPT: &'static str = "*"; pub struct Config { pub prompt: String, pub dirty: bool, pub show_prompt: bool, pub current_index: Option<usize>, pub default_filename: Option<String>, pub cut_buffer: Vec<String>, pub marks: HashMap<char, usize>, pub last_error: Option<String>, pub print_errors: bool, } impl Default for Config { fn default() -> Config { Config { prompt: DEFAULT_PROMPT.into(), dirty: false, show_prompt: false, current_index: None, default_filename: None, cut_buffer: vec![], marks: HashMap::new(), last_error: None, print_errors: false, } } } impl Config { pub fn update_curidx(&mut self, idx: usize) { let loc = if let Some(v) = self.current_index.as_ref() { *v + idx } else { idx }; self.current_index = Some(loc); } } pub type Buffer = Vec<String>; pub fn insert_all(buffer: &mut Buffer, index: usize, elements: &[String]) -> Result<()> { for (idx, elem) in elements.into_iter().enumerate() { buffer.insert(index + idx, elem.to_owned()); } Ok(()) } pub fn run(config: &mut Config) -> Result<()> { let mut buffer = Buffer::new(); loop { if config.show_prompt { write!(&mut io::stdout(), "{}", config.prompt) .chain_err(|| "Couldn't write prompt")?; } io::stdout().flush().chain_err(|| "Couldn't flush stdout")?; let mut inp = String::new(); io::stdin().read_line(&mut inp).chain_err(|| "Couldn't read input")?; let inp = parse::parse_line(inp.trim()); let inp = match inp { nom::IResult::Done(_, o) => o, x => { debug!("Not done, got {:?}", x); continue; }, }; debug!("Command: {:?}, current index: {:?}", &inp, config.current_index); match inp.run(&mut buffer, config) { Err(Error(ErrorKind::Unknown, _)) => { println!("?"); }, Err(Error(ErrorKind::Msg(s), _)) => { if config.print_errors { println!("{}", s); } else { println!("?"); } config.last_error = Some(s); }, Err(_) => process::exit(1), _ => (), }; } } mod errors; mod parse; mod cli; mod commands;