diff --git a/.gitignore b/.gitignore index 9b226ad0..2d64e220 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Cargo.lock benches/results before* after* +.rhai-repl-history.txt diff --git a/Cargo.toml b/Cargo.toml index 4ad7a8c4..36facb9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,22 @@ include = ["**/*.rs", "scripts/*.rhai", "**/*.md", "Cargo.toml"] keywords = ["scripting", "scripting-engine", "scripting-language", "embedded"] categories = ["no-std", "embedded", "wasm", "parser-implementations"] +[lib] +name = "rhai" +path = "src/lib.rs" + +[[bin]] +name = "rhai-repl" +path = "src/bin/rhai-repl.rs" +required-features = ["rustyline"] + [dependencies] smallvec = { version = "1.7", default-features = false, features = ["union", "const_new" ] } ahash = { version = "0.7", default-features = false } num-traits = { version = "0.2", default-features = false } smartstring = { version = "0.2.8", default-features = false } rhai_codegen = { version = "1.2", path = "codegen", default-features = false } +rustyline = { versoin = "9", optional = true } [dev-dependencies] serde_bytes = "0.11" diff --git a/src/bin/rhai-repl.rs b/src/bin/rhai-repl.rs index 6af84a55..6ddc128b 100644 --- a/src/bin/rhai-repl.rs +++ b/src/bin/rhai-repl.rs @@ -1,3 +1,5 @@ +use rustyline::error::ReadlineError; +use rustyline::Editor; use rhai::{Dynamic, Engine, EvalAltResult, Module, Scope, AST, INT}; use std::{ @@ -191,6 +193,12 @@ fn main() { // Create scope let mut scope = Scope::new(); + // REPL line editor setup + let mut rl = Editor::<()>::new(); + if rl.load_history(".rhai-repl-history.txt").is_err() { + println!("No previous history."); + } + // REPL loop let mut input = String::new(); let mut main_ast = AST::empty(); @@ -200,33 +208,48 @@ fn main() { print_help(); 'main_loop: loop { - print!("rhai-repl> "); - stdout().flush().expect("couldn't flush stdout"); - input.clear(); - loop { - match stdin().read_line(&mut input) { - Ok(0) => break 'main_loop, - Ok(_) => (), - Err(err) => panic!("input error: {}", err), + let readline = rl.readline("rhai-repl> "); + + match readline { + Ok(line) => { + rl.add_history_entry(line.as_str()); + input = line; + }, + + Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => { + break 'main_loop + }, + + Err(err) => { + eprintln!("Error: {:?}", err); + break 'main_loop } - - let line = input.as_str().trim_end(); - - // Allow line continuation - if line.ends_with('\\') { - let len = line.len(); - input.truncate(len - 1); - input.push('\n'); - } else { - break; - } - - print!("> "); - stdout().flush().expect("couldn't flush stdout"); } + //loop { + // match stdin().read_line(&mut input) { + // Ok(0) => break 'main_loop, + // Ok(_) => (), + // Err(err) => panic!("input error: {}", err), + // } + + // let line = input.as_str().trim_end(); + + // // Allow line continuation + // if line.ends_with('\\') { + // let len = line.len(); + // input.truncate(len - 1); + // input.push('\n'); + // } else { + // break; + // } + + // print!("> "); + // stdout().flush().expect("couldn't flush stdout"); + //} + let script = input.trim(); if script.is_empty() { @@ -341,4 +364,6 @@ fn main() { // Throw away all the statements, leaving only the functions main_ast.clear_statements(); } + + rl.save_history(".rhai-repl-history.txt").unwrap(); }