From 489819a28eaa211148c25a7e6e99168773ca1278 Mon Sep 17 00:00:00 2001 From: greg Date: Sat, 28 Sep 2019 17:31:37 -0700 Subject: [PATCH] Multiline prompt --- schala-repl/src/repl/mod.rs | 82 ++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/schala-repl/src/repl/mod.rs b/schala-repl/src/repl/mod.rs index 97946ab..4ce3070 100644 --- a/schala-repl/src/repl/mod.rs +++ b/schala-repl/src/repl/mod.rs @@ -27,6 +27,12 @@ pub struct Repl { options: ReplOptions, } +#[derive(Clone)] +enum PromptStyle { + Normal, + Multiline +} + impl Repl { pub fn new(initial_states: Vec>) -> Repl { use linefeed::Interface; @@ -62,37 +68,73 @@ impl Repl { fn handle_repl_loop(&mut self) { use linefeed::ReadResult::*; + let sigil = self.interpreter_directive_sigil; - loop { - self.update_line_reader(); - match self.line_reader.read_line() { - Err(e) => { - println!("readline IO Error: {}", e); - break; - }, - Ok(Eof) | Ok(Signal(_)) => break, - Ok(Input(ref input)) => { - self.line_reader.add_history_unique(input.to_string()); - match input.chars().nth(0) { - Some(ch) if ch == self.interpreter_directive_sigil => match self.handle_interpreter_directive(input) { - Some(directive_output) => println!("<> {}", directive_output), - None => (), + 'main: loop { + macro_rules! match_or_break { + ($line:expr) => { + match $line { + Err(e) => { + println!("readline IO Error: {}", e); + break 'main; }, - _ => { - for repl_response in self.handle_input(input) { - println!("{}", repl_response); - } - } + Ok(Eof) | Ok(Signal(_)) => break 'main, + Ok(Input(ref input)) => input, } } } + self.update_line_reader(); + let line = self.line_reader.read_line(); + let input: &str = match_or_break!(line); + + self.line_reader.add_history_unique(input.to_string()); + let mut chars = input.chars().peekable(); + let repl_responses = match chars.nth(0) { + Some(ch) if ch == sigil => { + if chars.peek() == Some(&'{') { + let mut buf = String::new(); + buf.push_str(input.get(2..).unwrap()); + 'multiline: loop { + self.set_prompt(PromptStyle::Multiline); + let new_line = self.line_reader.read_line(); + let new_input = match_or_break!(new_line); + if new_input.starts_with(":}") { + break 'multiline; + } else { + buf.push_str(new_input); + buf.push_str("\n"); + } + } + self.handle_input(&buf) + } else { + match self.handle_interpreter_directive(input) { + Some(directive_output) => println!("<> {}", directive_output), + None => (), + } + continue + } + }, + _ => self.handle_input(input) + }; + + for repl_response in repl_responses.iter() { + println!("{}", repl_response); + } } } fn update_line_reader(&mut self) { let tab_complete_handler = TabCompleteHandler::new(self.interpreter_directive_sigil, self.get_directives()); self.line_reader.set_completer(Arc::new(tab_complete_handler)); //TODO fix this here - let prompt_str = format!(">> "); + self.set_prompt(PromptStyle::Normal); + } + + fn set_prompt(&mut self, prompt_style: PromptStyle) { + let prompt_str = match prompt_style { + PromptStyle::Normal => ">> ".to_string(), + PromptStyle::Multiline => ">| ".to_string(), + }; + self.line_reader.set_prompt(&prompt_str).unwrap(); }