Improve $in handling (#5137)

* Simplify in logic

* Add tests

* more tests, and fixes
This commit is contained in:
JT 2022-04-09 09:41:05 +12:00 committed by GitHub
parent 0892a16a3d
commit 97eb8492a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 11 deletions

View File

@ -1,7 +1,9 @@
use nu_engine::{eval_block, CallExt}; use nu_engine::{eval_block, CallExt};
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack}; use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Value}; use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Value,
};
#[derive(Clone)] #[derive(Clone)]
pub struct Collect; pub struct Collect;
@ -42,7 +44,7 @@ impl Command for Collect {
if let Some(var) = block.signature.get_positional(0) { if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id { if let Some(var_id) = &var.var_id {
stack.add_var(*var_id, input); stack.add_var(*var_id, input.clone());
} }
} }
@ -50,7 +52,7 @@ impl Command for Collect {
engine_state, engine_state,
&mut stack, &mut stack,
&block, &block,
PipelineData::new(call.head), input.into_pipeline_data(),
call.redirect_stdout, call.redirect_stdout,
call.redirect_stderr, call.redirect_stderr,
) )

View File

@ -89,7 +89,8 @@ impl Command for FromNuon {
let (lite_block, err) = nu_parser::lite_parse(&lexed); let (lite_block, err) = nu_parser::lite_parse(&lexed);
error = error.or(err); error = error.or(err);
let (mut block, err) = nu_parser::parse_block(&mut working_set, &lite_block, true, &[]); let (mut block, err) =
nu_parser::parse_block(&mut working_set, &lite_block, true, &[], false);
error = error.or(err); error = error.or(err);
if let Some(pipeline) = block.pipelines.get(1) { if let Some(pipeline) = block.pipelines.get(1) {

View File

@ -19,7 +19,7 @@ fn quickcheck_parse(data: String) -> bool {
let mut working_set = StateWorkingSet::new(&context); let mut working_set = StateWorkingSet::new(&context);
working_set.add_file("quickcheck".into(), data.as_bytes()); working_set.add_file("quickcheck".into(), data.as_bytes());
let _ = nu_parser::parse_block(&mut working_set, &lite_block, false, &[]); let _ = nu_parser::parse_block(&mut working_set, &lite_block, false, &[], false);
} }
} }
true true

View File

@ -1776,7 +1776,8 @@ pub fn parse_full_cell_path(
let (output, err) = lite_parse(&output); let (output, err) = lite_parse(&output);
error = error.or(err); error = error.or(err);
let (output, err) = parse_block(working_set, &output, true, expand_aliases_denylist); let (output, err) =
parse_block(working_set, &output, true, expand_aliases_denylist, true);
error = error.or(err); error = error.or(err);
let block_id = working_set.add_block(output); let block_id = working_set.add_block(output);
@ -3660,7 +3661,8 @@ pub fn parse_block_expression(
} }
} }
let (mut output, err) = parse_block(working_set, &output, false, expand_aliases_denylist); let (mut output, err) =
parse_block(working_set, &output, false, expand_aliases_denylist, false);
error = error.or(err); error = error.or(err);
if let Some(signature) = signature { if let Some(signature) = signature {
@ -4570,6 +4572,7 @@ pub fn parse_block(
lite_block: &LiteBlock, lite_block: &LiteBlock,
scoped: bool, scoped: bool,
expand_aliases_denylist: &[usize], expand_aliases_denylist: &[usize],
is_subexpression: bool,
) -> (Block, Option<ParseError>) { ) -> (Block, Option<ParseError>) {
trace!("parsing block: {:?}", lite_block); trace!("parsing block: {:?}", lite_block);
@ -4614,11 +4617,19 @@ pub fn parse_block(
}) })
.collect::<Vec<Expression>>(); .collect::<Vec<Expression>>();
if is_subexpression {
for expr in output.iter_mut().skip(1) { for expr in output.iter_mut().skip(1) {
if expr.has_in_variable(working_set) { if expr.has_in_variable(working_set) {
*expr = wrap_expr_with_collect(working_set, expr); *expr = wrap_expr_with_collect(working_set, expr);
} }
} }
} else {
for expr in output.iter_mut() {
if expr.has_in_variable(working_set) {
*expr = wrap_expr_with_collect(working_set, expr);
}
}
}
Pipeline { Pipeline {
expressions: output, expressions: output,
@ -4656,7 +4667,12 @@ pub fn parse_block(
} }
} }
continue; continue;
} else if expr.has_in_variable(working_set) && !is_subexpression
{
*expr = wrap_expr_with_collect(working_set, expr);
} }
} else if expr.has_in_variable(working_set) && !is_subexpression {
*expr = wrap_expr_with_collect(working_set, expr);
} }
} }
} }
@ -5026,7 +5042,8 @@ pub fn parse(
let (output, err) = lite_parse(&output); let (output, err) = lite_parse(&output);
error = error.or(err); error = error.or(err);
let (mut output, err) = parse_block(working_set, &output, scoped, expand_aliases_denylist); let (mut output, err) =
parse_block(working_set, &output, scoped, expand_aliases_denylist, false);
error = error.or(err); error = error.or(err);
let mut seen = vec![]; let mut seen = vec![];

View File

@ -340,3 +340,29 @@ fn default_value11() -> TestResult {
fn default_value12() -> TestResult { fn default_value12() -> TestResult {
fail_test(r#"def foo [--x:int = "a"] { $x }"#, "default value not int") fail_test(r#"def foo [--x:int = "a"] { $x }"#, "default value not int")
} }
#[test]
fn loose_each() -> TestResult {
run_test(r#"[[1, 2, 3], [4, 5, 6]] | each { $in.1 } | math sum"#, "7")
}
#[test]
fn in_means_input() -> TestResult {
run_test(r#"def shl [] { $in * 2 }; 2 | shl"#, "4")
}
#[test]
fn in_iteration() -> TestResult {
run_test(
r#"[3, 4, 5] | each { echo $"hi ($in)" } | str collect"#,
"hi 3hi 4hi 5",
)
}
#[test]
fn reuseable_in() -> TestResult {
run_test(
r#"[1, 2, 3, 4] | take (($in | length) - 1) | math sum"#,
"6",
)
}