If the directory in which REPL history is stored does not exist, gently try to create it, but do not raise an error if it doesn't work. We may want to warn about it, but in general this sort of non-essential feature should not cause a hard failure. Change-Id: If4fe8db0c7893c39627efe72c9cd9ebf7ed63f04 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6213 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
85 lines
2.1 KiB
Rust
85 lines
2.1 KiB
Rust
use std::{
|
|
env, fs,
|
|
path::{Path, PathBuf},
|
|
process,
|
|
};
|
|
|
|
use rustyline::{error::ReadlineError, Editor};
|
|
|
|
fn main() {
|
|
let mut args = env::args();
|
|
if args.len() > 2 {
|
|
println!("Usage: tvix-eval [script]");
|
|
process::exit(1);
|
|
}
|
|
|
|
if let Some(file) = args.nth(1) {
|
|
run_file(&file);
|
|
} else {
|
|
run_prompt();
|
|
}
|
|
}
|
|
|
|
fn run_file(file: &str) {
|
|
let contents = fs::read_to_string(file).expect("failed to read the input file");
|
|
let path = Path::new(file).to_owned();
|
|
|
|
match tvix_eval::interpret(&contents, Some(path)) {
|
|
Ok(result) => println!("=> {} :: {}", result, result.type_of()),
|
|
Err(err) => eprintln!("{}", err),
|
|
}
|
|
}
|
|
|
|
fn state_dir() -> Option<PathBuf> {
|
|
let mut path = dirs::data_dir();
|
|
if let Some(p) = path.as_mut() {
|
|
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() {
|
|
// Attempt to set up these paths, but do not hard fail if it
|
|
// doesn't work.
|
|
Some(mut path) => {
|
|
std::fs::create_dir_all(&path).ok();
|
|
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, None) {
|
|
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();
|
|
}
|
|
}
|