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