feat(tvix/eval): use rustyline crate for REPL
This is a substantially nicer experience, immediately granting us history, proper exiting and so on. Change-Id: Iba4cb1713b9ac53d0799722bdbe2cd0e94a2f527 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6171 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
This commit is contained in:
parent
d14db8dcaa
commit
7c803a7e72
1 changed files with 54 additions and 24 deletions
|
@ -1,8 +1,6 @@
|
||||||
use std::{
|
use std::{env, fs, path::PathBuf, process};
|
||||||
env, fs,
|
|
||||||
io::{self, Write},
|
use rustyline::{error::ReadlineError, Editor};
|
||||||
mem, process,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut args = env::args();
|
let mut args = env::args();
|
||||||
|
@ -21,26 +19,58 @@ fn main() {
|
||||||
fn run_file(file: &str) {
|
fn run_file(file: &str) {
|
||||||
let contents = fs::read_to_string(file).expect("failed to read the input file");
|
let contents = fs::read_to_string(file).expect("failed to read the input file");
|
||||||
|
|
||||||
run(contents);
|
match tvix_eval::interpret(&contents) {
|
||||||
}
|
|
||||||
|
|
||||||
fn run_prompt() {
|
|
||||||
let mut line = String::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
print!("> ");
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut line)
|
|
||||||
.expect("failed to read user input");
|
|
||||||
run(mem::take(&mut line));
|
|
||||||
line.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(code: String) {
|
|
||||||
match tvix_eval::interpret(&code) {
|
|
||||||
Ok(result) => println!("=> {} :: {}", result, result.type_of()),
|
Ok(result) => println!("=> {} :: {}", result, result.type_of()),
|
||||||
Err(err) => eprintln!("{}", err),
|
Err(err) => eprintln!("{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state_dir() -> Option<PathBuf> {
|
||||||
|
let mut path = dirs::data_dir();
|
||||||
|
path.as_mut().map(|p| p.push("tvix"));
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_prompt() {
|
||||||
|
let mut rl = Editor::<()>::new().expect("should be able to launch rustyline");
|
||||||
|
|
||||||
|
let history_path = match state_dir() {
|
||||||
|
Some(mut path) => {
|
||||||
|
path.push("history.txt");
|
||||||
|
rl.load_history(&path).ok();
|
||||||
|
|
||||||
|
Some(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let readline = rl.readline("tvix-repl> ");
|
||||||
|
match readline {
|
||||||
|
Ok(line) => {
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match tvix_eval::interpret(&line) {
|
||||||
|
Ok(result) => {
|
||||||
|
println!("=> {} :: {}", result, result.type_of());
|
||||||
|
rl.add_history_entry(line);
|
||||||
|
}
|
||||||
|
Err(err) => println!("{}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break,
|
||||||
|
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("error: {}", err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(path) = history_path {
|
||||||
|
rl.save_history(&path).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue