DEV: repl ergonomic improvements.

* Ctrl-C, Ctrl-D now do the appropriate thing
* #exit will now exit the repl
This commit is contained in:
Jeremy Wall 2019-11-09 19:27:18 -06:00
parent 2c927ed0e5
commit f067886cfa
3 changed files with 29 additions and 2 deletions

View File

@ -15,4 +15,7 @@ Currently supported commands are:
* #del <name>
- deletes a previously created named binding
* #exit
- Exits the repl.

View File

@ -24,6 +24,10 @@ impl StatementAccumulator {
Self { acc: Vec::new() }
}
pub fn reset(&mut self) {
self.acc = Vec::new();
}
pub fn next_line(&self) -> usize {
self.acc.len() + 1
}

View File

@ -27,6 +27,8 @@ use std::path::{Path, PathBuf};
use std::process;
use std::rc::Rc;
use rustyline::error::ReadlineError;
use ucglib::build;
use ucglib::build::assets::{Cache, MemoryCache};
use ucglib::build::Val;
@ -585,12 +587,28 @@ fn do_repl<C: Cache>(
build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry);
// loop
let mut lines = ucglib::io::StatementAccumulator::new();
println!("Welcome to the UCG repl. Ctrl-D to exit");
println!("Welcome to the UCG repl. Ctrl-D to exit, Ctrl-C to abort expression.");
println!("Type '#help' for help.");
println!("");
loop {
// print prompt
let line = editor.readline(&format!("{}> ", lines.next_line()))?;
let line = match editor.readline(&format!("{}> ", lines.next_line())) {
Ok(l) => l,
Err(e) => {
if let ReadlineError::Eof = e {
eprintln!("Recieved EOF Exiting...");
process::exit(0);
}
if let ReadlineError::Interrupted = e {
// Reset our lines and start over again
eprintln!("Interrupted!");
lines.reset();
continue;
}
eprintln!("Error: {}", e);
process::exit(1);
}
};
// repl commands are only valid while not accumulating a statement;
let trimmed = line.trim();
if trimmed.starts_with("#") {
@ -612,6 +630,8 @@ fn do_repl<C: Cache>(
eprintln!("No such binding {}", key.val);
}
}
} else if trimmed.starts_with("#exit") {
process::exit(0);
} else {
eprintln!("Invalid repl command...");
eprintln!("");