diff --git a/Cargo.lock b/Cargo.lock index 15c5d13b3d..1addaf0540 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,9 +89,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", @@ -308,9 +308,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.101" +version = "0.2.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" [[package]] name = "lock_api" @@ -339,7 +339,7 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "miette" version = "3.0.1-alpha.0" -source = "git+https://github.com/zkat/miette?branch=release/3.0.0#491ce7c0ce1f04c9b6fc09c250f188c1ec77df53" +source = "git+https://github.com/zkat/miette?branch=release/3.0.0#e02965787b5e6206dad46556a50edae578449789" dependencies = [ "atty", "backtrace", @@ -359,7 +359,7 @@ dependencies = [ [[package]] name = "miette-derive" version = "3.0.0-alpha.0" -source = "git+https://github.com/zkat/miette?branch=release/3.0.0#491ce7c0ce1f04c9b6fc09c250f188c1ec77df53" +source = "git+https://github.com/zkat/miette?branch=release/3.0.0#e02965787b5e6206dad46556a50edae578449789" dependencies = [ "proc-macro2", "quote", @@ -670,7 +670,7 @@ dependencies = [ [[package]] name = "reedline" version = "0.1.0" -source = "git+https://github.com/jntrnr/reedline?branch=main#cd87851ad9f238b491062bb854d65489ca2c4c1c" +source = "git+https://github.com/jntrnr/reedline?branch=main#22fc31c68d1da6a41a93b5cfa901143b4eca4051" dependencies = [ "chrono", "crossterm", @@ -916,9 +916,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" diff --git a/crates/nu-cli/src/lib.rs b/crates/nu-cli/src/lib.rs index f0f8a4ab54..f2643bdfbd 100644 --- a/crates/nu-cli/src/lib.rs +++ b/crates/nu-cli/src/lib.rs @@ -1,7 +1,9 @@ mod completions; mod errors; mod syntax_highlight; +mod validation; pub use completions::NuCompleter; pub use errors::report_error; pub use syntax_highlight::NuHighlighter; +pub use validation::NuValidator; diff --git a/crates/nu-cli/src/validation.rs b/crates/nu-cli/src/validation.rs new file mode 100644 index 0000000000..85bf9538ae --- /dev/null +++ b/crates/nu-cli/src/validation.rs @@ -0,0 +1,23 @@ +use std::{cell::RefCell, rc::Rc}; + +use nu_parser::{parse, ParseError}; +use nu_protocol::engine::{EngineState, StateWorkingSet}; +use reedline::{ValidationResult, Validator}; + +pub struct NuValidator { + pub engine_state: Rc>, +} + +impl Validator for NuValidator { + fn validate(&self, line: &str) -> ValidationResult { + let engine_state = self.engine_state.borrow(); + let mut working_set = StateWorkingSet::new(&*engine_state); + let (_, err) = parse(&mut working_set, None, line.as_bytes(), false); + + if matches!(err, Some(ParseError::UnexpectedEof(..))) { + ValidationResult::Incomplete + } else { + ValidationResult::Complete + } + } +} diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs index fffb3c0b06..6d400f67b4 100644 --- a/crates/nu-parser/src/errors.rs +++ b/crates/nu-parser/src/errors.rs @@ -21,7 +21,7 @@ pub enum ParseError { #[error("Unexpected end of code.")] #[diagnostic(code(nu::parser::unexpected_eof), url(docsrs))] - UnexpectedEof(String, #[label("expected {0}")] Span), + UnexpectedEof(String, #[label("expected closing {0}")] Span), #[error("Unclosed delimiter.")] #[diagnostic(code(nu::parser::unclosed_delimiter), url(docsrs))] diff --git a/crates/nu-parser/src/lex.rs b/crates/nu-parser/src/lex.rs index 5d08d2dd8b..b1b50f99be 100644 --- a/crates/nu-parser/src/lex.rs +++ b/crates/nu-parser/src/lex.rs @@ -181,7 +181,13 @@ pub fn lex_item( // correct information from the non-lite parse. return ( span, - Some(ParseError::UnexpectedEof((delim as char).to_string(), span)), + Some(ParseError::UnexpectedEof( + (delim as char).to_string(), + Span { + start: span.end, + end: span.end, + }, + )), ); } diff --git a/src/main.rs b/src/main.rs index ace8b69360..8dc8d7c6e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use miette::{IntoDiagnostic, Result}; -use nu_cli::{report_error, NuCompleter, NuHighlighter}; +use nu_cli::{report_error, NuCompleter, NuHighlighter, NuValidator}; use nu_command::create_default_context; use nu_engine::eval_block; use nu_parser::parse; @@ -71,7 +71,10 @@ fn main() -> Result<()> { })) .with_completion_action_handler(Box::new( DefaultCompletionActionHandler::default().with_completer(Box::new(completer)), - )); + )) + .with_validator(Box::new(NuValidator { + engine_state: engine_state.clone(), + })); let prompt = DefaultPrompt::new(1); let stack = nu_protocol::engine::Stack::new();