From 4f57c5d56e3dc7c69f92bf3e1e9ac74930872d8b Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Mon, 23 Jan 2023 01:32:56 +0800 Subject: [PATCH] Fix multi-line redirection inside a block (#7808) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fixes: #7786 The issue is because the lite block is wrong while converting from lex tokens # What happened internally? Take the following as example: ``` ❯ def foobar [] { 'hello' out> /tmp/output.1 'world' out> /tmp/output.2 } ``` ## Before: ``` LiteBlock { block: [ LitePipeline { commands: [ Command(None, LiteCommand { comments: [], parts: [Span { start: 40900, end:40907 }] }), Redirection(Span { start: 40908, end: 40912 }, Stdout, LiteCommand { comments: [], parts: [Span { start: 40913, end: 40926 }] })] }, LitePipeline { commands: [ Redirection(Span { start: 40908, end: 40912 }, Stdout, LiteCommand { comments: [], parts: [Span { start: 40929, end: 40936 }] }), // this is wrong, should be command. Redirection(Span { start: 40937, end: 40941 }, Stdout, LiteCommand { comments: [], parts: [Span { start: 40942, end: 40955 }] })] }] } ``` ## After: ``` LiteBlock { block: [ LitePipeline { commands: [ Command(None, LiteCommand { comments: [], parts: [Span { start: 40824, end: 40831 }] }), Redirection(Span { start: 40832, end: 40836 }, Stdout, LiteCommand { comments: [], parts: [Span { start: 40837, end: 40850 }] })] }, LitePipeline { commands: [ Command(None, LiteCommand { comments: [], parts: [Span { start: 40854, end: 40861 }] }), Redirection(Span { start: 40862, end: 40866 }, Stdout, LiteCommand { comments: [], parts: [Span { start: 40867, end: 40880 }] })] } ] } ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --- .../nu-command/tests/commands/redirection.rs | 23 +++++++++++++++++-- crates/nu-parser/src/lite_parser.rs | 2 ++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/tests/commands/redirection.rs b/crates/nu-command/tests/commands/redirection.rs index 14ee683f8e..f7371d9cf7 100644 --- a/crates/nu-command/tests/commands/redirection.rs +++ b/crates/nu-command/tests/commands/redirection.rs @@ -1,3 +1,4 @@ +use nu_test_support::fs::{file_contents, Stub::FileWithContent}; use nu_test_support::nu; use nu_test_support::playground::Playground; @@ -65,10 +66,28 @@ fn redirect_out() { }) } +#[test] +fn two_lines_redirection() { + Playground::setup("redirections with two lines commands", |dirs, _| { + nu!( + cwd: dirs.test(), + r#" +def foobar [] { + 'hello' out> output1.txt + 'world' out> output2.txt +} +foobar"#); + let file_out1 = dirs.test().join("output1.txt"); + let actual = file_contents(file_out1); + assert!(actual.contains("hello")); + let file_out2 = dirs.test().join("output2.txt"); + let actual = file_contents(file_out2); + assert!(actual.contains("world")); + }) +} + #[test] fn separate_redirection() { - use nu_test_support::fs::{file_contents, Stub::FileWithContent}; - use nu_test_support::playground::Playground; Playground::setup( "external with both stdout and stderr messages, to different file", |dirs, sandbox| { diff --git a/crates/nu-parser/src/lite_parser.rs b/crates/nu-parser/src/lite_parser.rs index 0a1f97e7bf..5d017a356a 100644 --- a/crates/nu-parser/src/lite_parser.rs +++ b/crates/nu-parser/src/lite_parser.rs @@ -304,6 +304,8 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { block.push(curr_pipeline); curr_pipeline = LitePipeline::new(); + last_connector = TokenContents::Pipe; + last_connector_span = None; } }