1use nu_ansi_term::Color;
11use reedline::{DefaultPrompt, DefaultPromptSegment, Reedline, Signal};
12
13pub fn run() {
15 crate::host::reset_host();
16 let mut line_editor = Reedline::create();
17 let prompt = DefaultPrompt::new(
18 DefaultPromptSegment::Basic("> ".to_string()),
19 DefaultPromptSegment::Empty,
20 );
21
22 loop {
23 match line_editor.read_line(&prompt) {
24 Ok(Signal::Success(mut buffer)) => {
25 if buffer.trim().is_empty() {
26 continue;
27 }
28 let cont_prompt = DefaultPrompt::new(
30 DefaultPromptSegment::Basic("... ".to_string()),
31 DefaultPromptSegment::Empty,
32 );
33 while unbalanced(&buffer) {
34 match line_editor.read_line(&cont_prompt) {
35 Ok(Signal::Success(more)) => {
36 buffer.push('\n');
37 buffer.push_str(&more);
38 }
39 _ => break,
40 }
41 }
42 run_line(&buffer);
43 }
44 Ok(Signal::CtrlC) => continue,
45 Ok(Signal::CtrlD) => break,
46 Ok(_) => continue,
47 Err(_) => break,
48 }
49 }
50}
51
52fn unbalanced(s: &str) -> bool {
56 let mut depth: i32 = 0;
57 let mut quote: Option<char> = None;
58 let mut escaped = false;
59 for c in s.chars() {
60 if let Some(q) = quote {
61 if escaped {
62 escaped = false;
63 } else if c == '\\' {
64 escaped = true;
65 } else if c == q {
66 quote = None;
67 }
68 continue;
69 }
70 match c {
71 '"' | '\'' | '`' => quote = Some(c),
72 '{' | '(' | '[' => depth += 1,
73 '}' | ')' | ']' => depth -= 1,
74 _ => {}
75 }
76 }
77 depth > 0
78}
79
80fn run_line(src: &str) {
81 match crate::compile(src) {
82 Ok(prog) => match crate::run_compiled(prog) {
83 Ok(_) => {}
84 Err(e) => eprintln!("{}", Color::Red.paint(e)),
85 },
86 Err(e) => eprintln!("{}", Color::Red.paint(e)),
87 }
88}