simple_repl/
lib.rs

1use rustyline::error::ReadlineError;
2use rustyline::DefaultEditor;
3
4#[derive(Debug)]
5pub enum ReplError<E>{
6    ReadlineError,
7    EvaluatorError(E),
8}
9
10pub enum EvalResult<T> {
11    Continue,
12    ExitRepl,
13    Passthrough(T),
14}
15
16pub enum ReplResult<T> {
17    ExitRepl,
18    Passthrough(T)
19}
20
21impl <E> std::convert::From<ReadlineError> for ReplError<E> {
22    fn from(_: ReadlineError) -> Self {
23        ReplError::ReadlineError
24    }
25}
26
27pub fn repl<T, E> (mut evaluator: impl FnMut(&str) -> Result<EvalResult<T>, E>) -> std::result::Result<ReplResult<T>, ReplError<E>> {
28    let mut rl = DefaultEditor::new()?;
29
30    loop {
31        let input = rl.readline("> ")?;
32        let input_str = input.as_str();
33
34        rl.add_history_entry(input_str)?;
35
36        match evaluator(input_str) {
37            Ok(EvalResult::Continue) => continue,
38            Ok(EvalResult::ExitRepl) => break Ok(ReplResult::ExitRepl),
39            Ok(EvalResult::Passthrough(x)) => break Ok(ReplResult::Passthrough(x)),
40            Err(e) => break Err(ReplError::EvaluatorError(e)),
41        }
42    }
43}