Multiline prompt

This commit is contained in:
greg 2019-09-28 17:31:37 -07:00
parent c427646e75
commit 489819a28e
1 changed files with 62 additions and 20 deletions

View File

@ -27,6 +27,12 @@ pub struct Repl {
options: ReplOptions, options: ReplOptions,
} }
#[derive(Clone)]
enum PromptStyle {
Normal,
Multiline
}
impl Repl { impl Repl {
pub fn new(initial_states: Vec<Box<dyn ProgrammingLanguageInterface>>) -> Repl { pub fn new(initial_states: Vec<Box<dyn ProgrammingLanguageInterface>>) -> Repl {
use linefeed::Interface; use linefeed::Interface;
@ -62,37 +68,73 @@ impl Repl {
fn handle_repl_loop(&mut self) { fn handle_repl_loop(&mut self) {
use linefeed::ReadResult::*; use linefeed::ReadResult::*;
let sigil = self.interpreter_directive_sigil;
loop { 'main: loop {
self.update_line_reader(); macro_rules! match_or_break {
match self.line_reader.read_line() { ($line:expr) => {
Err(e) => { match $line {
println!("readline IO Error: {}", e); Err(e) => {
break; println!("readline IO Error: {}", e);
}, break 'main;
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 => (),
}, },
_ => { Ok(Eof) | Ok(Signal(_)) => break 'main,
for repl_response in self.handle_input(input) { Ok(Input(ref input)) => input,
println!("{}", repl_response);
}
}
} }
} }
} }
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) { fn update_line_reader(&mut self) {
let tab_complete_handler = TabCompleteHandler::new(self.interpreter_directive_sigil, self.get_directives()); 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 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(); self.line_reader.set_prompt(&prompt_str).unwrap();
} }