mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 22:50:14 +02:00
Support redirect stderr and stdout+stderr with a pipe (#11708)
# Description Close: #9673 Close: #8277 Close: #10944 This pr introduces the following syntax: 1. `e>|`, pipe stderr to next command. Example: `$env.FOO=bar nu --testbin echo_env_stderr FOO e>| str length` 2. `o+e>|` and `e+o>|`, pipe both stdout and stderr to next command, example: `$env.FOO=bar nu --testbin echo_env_mixed out-err FOO FOO e+o>| str length` Note: it only works for external commands. ~There is no different for internal commands, that is, the following three commands do the same things:~ Edit: it raises errors if we want to pipes for internal commands ``` ❯ ls e>| str length Error: × `e>|` only works with external streams ╭─[entry #1:1:1] 1 │ ls e>| str length · ─┬─ · ╰── `e>|` only works on external streams ╰──── ❯ ls e+o>| str length Error: × `o+e>|` only works with external streams ╭─[entry #2:1:1] 1 │ ls e+o>| str length · ──┬── · ╰── `o+e>|` only works on external streams ╰──── ``` This can help us to avoid some strange issues like the following: `$env.FOO=bar (nu --testbin echo_env_stderr FOO) e>| str length` Which is hard to understand and hard to explain to users. # User-Facing Changes Nan # Tests + Formatting To be done # After Submitting Maybe update documentation about these syntax.
This commit is contained in:
@ -1299,7 +1299,9 @@ fn parse_binary_with_base(
|
||||
}
|
||||
TokenContents::Pipe
|
||||
| TokenContents::PipePipe
|
||||
| TokenContents::ErrGreaterPipe
|
||||
| TokenContents::OutGreaterThan
|
||||
| TokenContents::OutErrGreaterPipe
|
||||
| TokenContents::OutGreaterGreaterThan
|
||||
| TokenContents::ErrGreaterThan
|
||||
| TokenContents::ErrGreaterGreaterThan
|
||||
@ -5479,7 +5481,9 @@ pub fn parse_pipeline(
|
||||
|
||||
for command in &pipeline.commands[1..] {
|
||||
match command {
|
||||
LiteElement::Command(Some(pipe_span), command) => {
|
||||
LiteElement::Command(Some(pipe_span), command)
|
||||
| LiteElement::ErrPipedCommand(Some(pipe_span), command)
|
||||
| LiteElement::OutErrPipedCommand(Some(pipe_span), command) => {
|
||||
new_command.parts.push(*pipe_span);
|
||||
|
||||
new_command.comments.extend_from_slice(&command.comments);
|
||||
@ -5584,6 +5588,18 @@ pub fn parse_pipeline(
|
||||
|
||||
PipelineElement::Expression(*span, expr)
|
||||
}
|
||||
LiteElement::ErrPipedCommand(span, command) => {
|
||||
trace!("parsing: pipeline element: err piped command");
|
||||
let expr = parse_expression(working_set, &command.parts, is_subexpression);
|
||||
|
||||
PipelineElement::ErrPipedExpression(*span, expr)
|
||||
}
|
||||
LiteElement::OutErrPipedCommand(span, command) => {
|
||||
trace!("parsing: pipeline element: err piped command");
|
||||
let expr = parse_expression(working_set, &command.parts, is_subexpression);
|
||||
|
||||
PipelineElement::OutErrPipedExpression(*span, expr)
|
||||
}
|
||||
LiteElement::Redirection(span, redirection, command, is_append_mode) => {
|
||||
let expr = parse_value(working_set, command.parts[0], &SyntaxShape::Any);
|
||||
|
||||
@ -5639,6 +5655,8 @@ pub fn parse_pipeline(
|
||||
} else {
|
||||
match &pipeline.commands[0] {
|
||||
LiteElement::Command(_, command)
|
||||
| LiteElement::ErrPipedCommand(_, command)
|
||||
| LiteElement::OutErrPipedCommand(_, command)
|
||||
| LiteElement::Redirection(_, _, command, _)
|
||||
| LiteElement::SeparateRedirection {
|
||||
out: (_, command, _),
|
||||
@ -5743,6 +5761,8 @@ pub fn parse_block(
|
||||
if pipeline.commands.len() == 1 {
|
||||
match &pipeline.commands[0] {
|
||||
LiteElement::Command(_, command)
|
||||
| LiteElement::ErrPipedCommand(_, command)
|
||||
| LiteElement::OutErrPipedCommand(_, command)
|
||||
| LiteElement::Redirection(_, _, command, _)
|
||||
| LiteElement::SeparateRedirection {
|
||||
out: (_, command, _),
|
||||
@ -5836,6 +5856,8 @@ pub fn discover_captures_in_pipeline_element(
|
||||
) -> Result<(), ParseError> {
|
||||
match element {
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::ErrPipedExpression(_, expression)
|
||||
| PipelineElement::OutErrPipedExpression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression, _)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression) => {
|
||||
@ -6181,6 +6203,18 @@ fn wrap_element_with_collect(
|
||||
PipelineElement::Expression(span, expression) => {
|
||||
PipelineElement::Expression(*span, wrap_expr_with_collect(working_set, expression))
|
||||
}
|
||||
PipelineElement::ErrPipedExpression(span, expression) => {
|
||||
PipelineElement::ErrPipedExpression(
|
||||
*span,
|
||||
wrap_expr_with_collect(working_set, expression),
|
||||
)
|
||||
}
|
||||
PipelineElement::OutErrPipedExpression(span, expression) => {
|
||||
PipelineElement::OutErrPipedExpression(
|
||||
*span,
|
||||
wrap_expr_with_collect(working_set, expression),
|
||||
)
|
||||
}
|
||||
PipelineElement::Redirection(span, redirection, expression, is_append_mode) => {
|
||||
PipelineElement::Redirection(
|
||||
*span,
|
||||
|
Reference in New Issue
Block a user