From c9dcd212ba553fd7d5b84a229ee0d9809afb6118 Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Sun, 2 Jan 2022 16:27:58 +1100 Subject: [PATCH] Allow pipelines across multiple lines if end in pipe (#643) * Allow pipelines across multiple lines if end in pipe * Add validation support --- crates/nu-parser/src/lite_parse.rs | 39 +++++++++++++++++++++++++++--- src/tests/test_parser.rs | 11 +++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/crates/nu-parser/src/lite_parse.rs b/crates/nu-parser/src/lite_parse.rs index 3fabca23ee..0a28e9fc87 100644 --- a/crates/nu-parser/src/lite_parse.rs +++ b/crates/nu-parser/src/lite_parse.rs @@ -85,16 +85,37 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { let mut curr_pipeline = LiteStatement::new(); let mut curr_command = LiteCommand::new(); + let mut last_token_was_pipe = false; + for token in tokens.iter() { match &token.contents { - TokenContents::Item => curr_command.push(token.span), + TokenContents::Item => { + curr_command.push(token.span); + last_token_was_pipe = false; + } TokenContents::Pipe => { if !curr_command.is_empty() { curr_pipeline.push(curr_command); curr_command = LiteCommand::new(); } + last_token_was_pipe = true; } - TokenContents::Eol | TokenContents::Semicolon => { + TokenContents::Eol => { + if !last_token_was_pipe { + if !curr_command.is_empty() { + curr_pipeline.push(curr_command); + + curr_command = LiteCommand::new(); + } + + if !curr_pipeline.is_empty() { + block.push(curr_pipeline); + + curr_pipeline = LiteStatement::new(); + } + } + } + TokenContents::Semicolon => { if !curr_command.is_empty() { curr_pipeline.push(curr_command); @@ -106,6 +127,8 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { curr_pipeline = LiteStatement::new(); } + + last_token_was_pipe = false; } TokenContents::Comment => { curr_command.comments.push(token.span); @@ -121,5 +144,15 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { block.push(curr_pipeline); } - (block, None) + if last_token_was_pipe { + ( + block, + Some(ParseError::UnexpectedEof( + "pipeline missing end".into(), + tokens[tokens.len() - 1].span, + )), + ) + } else { + (block, None) + } } diff --git a/src/tests/test_parser.rs b/src/tests/test_parser.rs index 2bc9b10e84..53324d9c86 100644 --- a/src/tests/test_parser.rs +++ b/src/tests/test_parser.rs @@ -123,3 +123,14 @@ fn let_not_statement() -> TestResult { fn for_in_missing_var_name() -> TestResult { fail_test("for in", "missing") } + +#[test] +fn multiline_pipe_in_block() -> TestResult { + run_test( + r#"do { + echo hello | + str length + }"#, + "5", + ) +}