From 1ddda7de7458ac4bfc67936ffb129eb52f0bed72 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 28 Apr 2024 01:27:25 +0200 Subject: 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. --- crates/rebel-lang/Cargo.toml | 2 +- crates/rebel-lang/examples/repl.rs | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'crates') 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 { assert!(params.len() == 1); @@ -23,6 +24,24 @@ fn intrinsic_string_len(params: &[Value]) -> Result { )) } +#[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 { + 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::::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}"); -- cgit v1.2.3