Support variables/interpolation in o>, e>, o+e> redirect (#9747)

# Description
Fixes:  #8517
Fixes: #9246
Fixes: #9709
Relative: #9723


## About the change
Before the pr, nushell only parse redirection target as a string(through
`parse_string` call).
In the pr, I'm trying to make the value more generic(using `parse_value`
with `SyntaxShape::Any`)

And during eval stage, we guard it to only eval `String`,
`StringInterpolation`, `FullCellPath`, `FilePath`, so other type of
redirection target like `1ms` won't be permitted.

# User-Facing Changes

After the pr: redirection support something like the following:
1. `let a = "x"; cat toolkit.nu o> $a`
2. `let a = "x"; cat toolkit.nu o> $"($a).txt"`
3. `cat toolkit.nu out> ("~/a.txt" | path expand)`
This commit is contained in:
WindSoilder
2023-07-20 19:56:46 +08:00
committed by GitHub
parent 488002f4bc
commit ba4723cc9f
3 changed files with 82 additions and 8 deletions

View File

@ -5522,8 +5522,7 @@ pub fn parse_pipeline(
PipelineElement::Expression(*span, expr)
}
LiteElement::Redirection(span, redirection, command) => {
trace!("parsing: pipeline element: redirection");
let expr = parse_string(working_set, command.parts[0]);
let expr = parse_value(working_set, command.parts[0], &SyntaxShape::Any);
PipelineElement::Redirection(*span, redirection.clone(), expr)
}
@ -5532,9 +5531,11 @@ pub fn parse_pipeline(
err: (err_span, err_command),
} => {
trace!("parsing: pipeline element: separate redirection");
let out_expr = parse_string(working_set, out_command.parts[0]);
let out_expr =
parse_value(working_set, out_command.parts[0], &SyntaxShape::Any);
let err_expr = parse_string(working_set, err_command.parts[0]);
let err_expr =
parse_value(working_set, err_command.parts[0], &SyntaxShape::Any);
PipelineElement::SeparateRedirection {
out: (*out_span, out_expr),
@ -5547,7 +5548,8 @@ pub fn parse_pipeline(
} => {
trace!("parsing: pipeline element: same target redirection");
let expr = parse_expression(working_set, &command.parts, is_subexpression);
let redirect_expr = parse_string(working_set, redirect_command.parts[0]);
let redirect_expr =
parse_value(working_set, redirect_command.parts[0], &SyntaxShape::Any);
PipelineElement::SameTargetRedirection {
cmd: (*cmd_span, expr),
redirection: (*redirect_span, redirect_expr),
@ -5636,7 +5638,8 @@ pub fn parse_pipeline(
trace!("parsing: pipeline element: same target redirection");
let expr = parse_expression(working_set, &command.parts, is_subexpression);
let redirect_expr = parse_string(working_set, redirect_cmd.parts[0]);
let redirect_expr =
parse_value(working_set, redirect_cmd.parts[0], &SyntaxShape::Any);
Pipeline {
elements: vec![PipelineElement::SameTargetRedirection {