diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/repl.rs | 40 | ||||
-rw-r--r-- | cli/tests/integration_tests.rs | 34 |
2 files changed, 70 insertions, 4 deletions
diff --git a/cli/repl.rs b/cli/repl.rs index 1bb5df096..3d22f8156 100644 --- a/cli/repl.rs +++ b/cli/repl.rs @@ -12,7 +12,6 @@ use regex::Captures; use regex::Regex; use rustyline::error::ReadlineError; use rustyline::highlight::Highlighter; -use rustyline::validate::MatchingBracketValidator; use rustyline::validate::ValidationContext; use rustyline::validate::ValidationResult; use rustyline::validate::Validator; @@ -26,7 +25,6 @@ use std::sync::Mutex; #[derive(Completer, Helper, Hinter)] struct Helper { highlighter: LineHighlighter, - validator: MatchingBracketValidator, } impl Validator for Helper { @@ -34,7 +32,42 @@ impl Validator for Helper { &self, ctx: &mut ValidationContext, ) -> Result<ValidationResult, ReadlineError> { - self.validator.validate(ctx) + let mut stack: Vec<char> = Vec::new(); + for c in ctx.input().chars() { + match c { + '(' | '[' | '{' => stack.push(c), + ')' | ']' | '}' => match (stack.pop(), c) { + (Some('('), ')') | (Some('['), ']') | (Some('{'), '}') => {} + (Some(left), _) => { + return Ok(ValidationResult::Invalid(Some(format!( + "Mismatched pairs: {:?} is not properly closed", + left + )))) + } + (None, c) => { + return Ok(ValidationResult::Invalid(Some(format!( + "Mismatched pairs: {:?} is unpaired", + c + )))) + } + }, + '`' => { + if stack.is_empty() || stack.last().unwrap() != &c { + stack.push(c); + } else { + stack.pop(); + } + } + + _ => {} + } + } + + if !stack.is_empty() { + return Ok(ValidationResult::Incomplete); + } + + Ok(ValidationResult::Valid(None)) } } @@ -274,7 +307,6 @@ pub async fn run( let helper = Helper { highlighter: LineHighlighter::new(), - validator: MatchingBracketValidator::new(), }; let editor = Arc::new(Mutex::new(Editor::new())); diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 5bf1a5a85..fdf2425cd 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -1127,6 +1127,40 @@ fn run_watch() { drop(t); } +#[cfg(unix)] +#[test] +fn repl_test_pty_multiline() { + use std::io::Read; + use util::pty::fork::*; + + let tests_path = util::tests_path(); + let fork = Fork::from_ptmx().unwrap(); + if let Ok(mut master) = fork.is_parent() { + master.write_all(b"(\n1 + 2\n)\n").unwrap(); + master.write_all(b"{\nfoo: \"foo\"\n}\n").unwrap(); + master.write_all(b"`\nfoo\n`\n").unwrap(); + master.write_all(b"close();\n").unwrap(); + + let mut output = String::new(); + master.read_to_string(&mut output).unwrap(); + + assert!(output.contains('3')); + assert!(output.contains("{ foo: \"foo\" }")); + assert!(output.contains("\"\\nfoo\\n\"")); + + fork.wait().unwrap(); + } else { + util::deno_cmd() + .current_dir(tests_path) + .env("NO_COLOR", "1") + .arg("repl") + .spawn() + .unwrap() + .wait() + .unwrap(); + } +} + #[test] fn repl_test_console_log() { let (out, err) = util::run_and_collect_output( |