use nu_ansi_term::Color;
use reedline::{DefaultPrompt, DefaultPromptSegment, Reedline, Signal};
pub fn run() {
crate::host::reset_host();
let mut line_editor = Reedline::create();
let prompt = DefaultPrompt::new(
DefaultPromptSegment::Basic("> ".to_string()),
DefaultPromptSegment::Empty,
);
loop {
match line_editor.read_line(&prompt) {
Ok(Signal::Success(mut buffer)) => {
if buffer.trim().is_empty() {
continue;
}
let cont_prompt = DefaultPrompt::new(
DefaultPromptSegment::Basic("... ".to_string()),
DefaultPromptSegment::Empty,
);
while unbalanced(&buffer) {
match line_editor.read_line(&cont_prompt) {
Ok(Signal::Success(more)) => {
buffer.push('\n');
buffer.push_str(&more);
}
_ => break,
}
}
run_line(&buffer);
}
Ok(Signal::CtrlC) => continue,
Ok(Signal::CtrlD) => break,
Ok(_) => continue,
Err(_) => break,
}
}
}
fn unbalanced(s: &str) -> bool {
let mut depth: i32 = 0;
let mut quote: Option<char> = None;
let mut escaped = false;
for c in s.chars() {
if let Some(q) = quote {
if escaped {
escaped = false;
} else if c == '\\' {
escaped = true;
} else if c == q {
quote = None;
}
continue;
}
match c {
'"' | '\'' | '`' => quote = Some(c),
'{' | '(' | '[' => depth += 1,
'}' | ')' | ']' => depth -= 1,
_ => {}
}
}
depth > 0
}
fn run_line(src: &str) {
match crate::compile(src) {
Ok(prog) => match crate::run_compiled(prog) {
Ok(_) => {}
Err(e) => eprintln!("{}", Color::Red.paint(e)),
},
Err(e) => eprintln!("{}", Color::Red.paint(e)),
}
}