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}