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> * #del <name>
- deletes a previously created named binding - deletes a previously created named binding
* #exit
- Exits the repl.

View File

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

View File

@ -27,6 +27,8 @@ use std::path::{Path, PathBuf};
use std::process; use std::process;
use std::rc::Rc; use std::rc::Rc;
use rustyline::error::ReadlineError;
use ucglib::build; use ucglib::build;
use ucglib::build::assets::{Cache, MemoryCache}; use ucglib::build::assets::{Cache, MemoryCache};
use ucglib::build::Val; use ucglib::build::Val;
@ -585,12 +587,28 @@ fn do_repl<C: Cache>(
build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry); build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry);
// loop // loop
let mut lines = ucglib::io::StatementAccumulator::new(); 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!("Type '#help' for help.");
println!(""); println!("");
loop { loop {
// print prompt // 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; // repl commands are only valid while not accumulating a statement;
let trimmed = line.trim(); let trimmed = line.trim();
if trimmed.starts_with("#") { if trimmed.starts_with("#") {
@ -612,6 +630,8 @@ fn do_repl<C: Cache>(
eprintln!("No such binding {}", key.val); eprintln!("No such binding {}", key.val);
} }
} }
} else if trimmed.starts_with("#exit") {
process::exit(0);
} else { } else {
eprintln!("Invalid repl command..."); eprintln!("Invalid repl command...");
eprintln!(""); eprintln!("");