diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-28 01:27:25 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-28 13:18:32 +0200 |
commit | 1ddda7de7458ac4bfc67936ffb129eb52f0bed72 (patch) | |
tree | e30ab890d5487c3394469eabde2c864686f9a810 | |
parent | decbf0f8318d0918d9455c2524bfc40a89cbc76c (diff) | |
download | rebel-1ddda7de7458ac4bfc67936ffb129eb52f0bed72.tar rebel-1ddda7de7458ac4bfc67936ffb129eb52f0bed72.zip |
rebel-lang: repl: add support for multiline input
Only multiline strings are supported, as the validator only checks if
the token stream is valid, not if it is a valid expression.
-rw-r--r-- | Cargo.lock | 12 | ||||
-rw-r--r-- | crates/rebel-lang/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/rebel-lang/examples/repl.rs | 35 |
3 files changed, 44 insertions, 5 deletions
@@ -691,6 +691,7 @@ dependencies = [ "memchr", "nix", "radix_trie", + "rustyline-derive", "unicode-segmentation", "unicode-width", "utf8parse", @@ -698,6 +699,17 @@ dependencies = [ ] [[package]] +name = "rustyline-derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5af959c8bf6af1aff6d2b463a57f71aae53d1332da58419e30ad8dc7011d951" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] name = "ryu" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/crates/rebel-lang/Cargo.toml b/crates/rebel-lang/Cargo.toml index 0c2f684..957d31d 100644 --- a/crates/rebel-lang/Cargo.toml +++ b/crates/rebel-lang/Cargo.toml @@ -15,4 +15,4 @@ enum-kinds = "0.5.1" [dev-dependencies] clap = { version = "4.0.0", features = ["derive"] } -rustyline = "14.0.0" +rustyline = { version = "14.0.0", features = ["derive"] } diff --git a/crates/rebel-lang/examples/repl.rs b/crates/rebel-lang/examples/repl.rs index 07c906f..e4c2550 100644 --- a/crates/rebel-lang/examples/repl.rs +++ b/crates/rebel-lang/examples/repl.rs @@ -5,6 +5,7 @@ use rebel_lang::{ value::{EvalError, Result, Value}, }; use rebel_parse::{recipe, tokenize}; +use rustyline::{error::ReadlineError, validate::ValidationResult}; fn intrinsic_array_len(params: &[Value]) -> Result<Value> { assert!(params.len() == 1); @@ -23,6 +24,24 @@ fn intrinsic_string_len(params: &[Value]) -> Result<Value> { )) } +#[derive(rustyline::Completer, rustyline::Hinter, rustyline::Highlighter, rustyline::Helper)] +struct Helper; + +impl rustyline::validate::Validator for Helper { + fn validate( + &self, + ctx: &mut rustyline::validate::ValidationContext, + ) -> rustyline::Result<rustyline::validate::ValidationResult> { + let input = ctx.input(); + let result = match tokenize::token_stream(input) { + Ok(_) => ValidationResult::Valid(None), + Err(_) => ValidationResult::Incomplete, + }; + + Ok(result) + } +} + fn main() -> rustyline::Result<()> { let mut ctx = Context::default(); @@ -47,12 +66,20 @@ fn main() -> rustyline::Result<()> { }, ); - let mut rl = rustyline::DefaultEditor::new()?; + let mut rl = rustyline::Editor::<Helper, rustyline::history::DefaultHistory>::new()?; + rl.set_helper(Some(Helper)); - while let Ok(line) = rl.readline("> ") { - rl.add_history_entry(line.as_str())?; + loop { + let input = match rl.readline("> ") { + Ok(input) => input, + Err(ReadlineError::Interrupted) => continue, + Err(ReadlineError::WindowResized) => continue, + Err(ReadlineError::Eof) => break, + Err(err) => panic!("{err}"), + }; + rl.add_history_entry(input.as_str())?; - let tokens = match tokenize::token_stream(&line) { + let tokens = match tokenize::token_stream(&input) { Ok(value) => value, Err(err) => { println!("Tokenize error: {err}"); |