From 6e733f49bc53990a1f2586096eccfb8b67da2856 Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Thu, 17 Feb 2022 06:40:24 -0500 Subject: [PATCH] Require block params (#4505) * Require block params * Improve errors --- crates/nu-command/src/core_commands/tutor.rs | 2 +- crates/nu-command/src/filters/each.rs | 2 +- crates/nu-command/src/filters/each_group.rs | 2 +- crates/nu-command/src/filters/each_window.rs | 2 +- crates/nu-command/src/filters/empty.rs | 2 +- crates/nu-command/src/filters/find.rs | 4 +- crates/nu-command/src/filters/par_each.rs | 2 +- crates/nu-command/src/filters/reduce.rs | 32 ++++----- crates/nu-command/tests/commands/each.rs | 10 +-- crates/nu-command/tests/commands/echo.rs | 8 +-- crates/nu-command/tests/commands/into_int.rs | 6 +- crates/nu-command/tests/commands/ls.rs | 2 +- crates/nu-command/tests/commands/parse.rs | 2 +- crates/nu-command/tests/commands/reduce.rs | 20 +++--- crates/nu-command/tests/commands/roll.rs | 4 +- .../nu-command/tests/commands/str_/collect.rs | 2 +- crates/nu-parser/src/errors.rs | 9 +++ crates/nu-parser/src/parser.rs | 69 +++++++++++++------ docs/commands/each.md | 2 +- docs/commands/par-each.md | 2 +- src/tests/test_engine.rs | 2 +- src/tests/test_iteration.rs | 8 +-- src/tests/test_parser.rs | 23 +++++-- src/tests/test_strings.rs | 6 +- tests/shell/mod.rs | 4 +- tests/shell/pipeline/commands/external.rs | 4 +- tests/shell/pipeline/commands/internal.rs | 20 +++--- 27 files changed, 149 insertions(+), 102 deletions(-) diff --git a/crates/nu-command/src/core_commands/tutor.rs b/crates/nu-command/src/core_commands/tutor.rs index 574dd53fdb..730082583b 100644 --- a/crates/nu-command/src/core_commands/tutor.rs +++ b/crates/nu-command/src/core_commands/tutor.rs @@ -303,7 +303,7 @@ The `each` command gives us a way of working with each individual row or element of a list one at a time. It reads these in from the pipeline and runs a block on each element. A block is a group of pipelines. ``` -echo 1 2 3 | each { $it + 10} +echo 1 2 3 | each { |it| $it + 10} ``` This example iterates over each element sent by `echo`, giving us three new values that are the original value + 10. Here, the `$it` is a variable that diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index 2dbddf66d1..26a967a0ef 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -46,7 +46,7 @@ impl Command for Each { ]; vec![Example { - example: "[1 2 3] | each { 2 * $it }", + example: "[1 2 3] | each { |it| 2 * $it }", description: "Multiplies elements in list", result: Some(Value::List { vals: stream_test_1, diff --git a/crates/nu-command/src/filters/each_group.rs b/crates/nu-command/src/filters/each_group.rs index f7f8153dad..2defc4f0b0 100644 --- a/crates/nu-command/src/filters/each_group.rs +++ b/crates/nu-command/src/filters/each_group.rs @@ -42,7 +42,7 @@ impl Command for EachGroup { ]; vec![Example { - example: "echo [1 2 3 4] | each group 2 { $it.0 + $it.1 }", + example: "echo [1 2 3 4] | each group 2 { |it| $it.0 + $it.1 }", description: "Echo the sum of each pair", result: Some(Value::List { vals: stream_test_1, diff --git a/crates/nu-command/src/filters/each_window.rs b/crates/nu-command/src/filters/each_window.rs index e983f8085b..1f3dd4484c 100644 --- a/crates/nu-command/src/filters/each_window.rs +++ b/crates/nu-command/src/filters/each_window.rs @@ -68,7 +68,7 @@ impl Command for EachWindow { vec![ Example { - example: "echo [1 2 3 4] | each window 2 { $it.0 + $it.1 }", + example: "echo [1 2 3 4] | each window 2 { |it| $it.0 + $it.1 }", description: "A sliding window of two elements", result: Some(Value::List { vals: stream_test_1, diff --git a/crates/nu-command/src/filters/empty.rs b/crates/nu-command/src/filters/empty.rs index 992eacc8af..9fb041c59c 100644 --- a/crates/nu-command/src/filters/empty.rs +++ b/crates/nu-command/src/filters/empty.rs @@ -72,7 +72,7 @@ impl Command for Empty { }, Example { description: "use a block if setting the empty cell contents is wanted", - example: "[[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 -b { [33 37] }", + example: "[[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 -b { |_| [33 37] }", result: Some( Value::List { vals: vec![ diff --git a/crates/nu-command/src/filters/find.rs b/crates/nu-command/src/filters/find.rs index 631e283578..b7b5676564 100644 --- a/crates/nu-command/src/filters/find.rs +++ b/crates/nu-command/src/filters/find.rs @@ -60,7 +60,7 @@ impl Command for Find { }, Example { description: "Find the first odd value", - example: "echo [2 4 3 6 5 8] | find --predicate { ($it mod 2) == 1 }", + example: "echo [2 4 3 6 5 8] | find --predicate { |it| ($it mod 2) == 1 }", result: Some(Value::List { vals: vec![Value::test_int(3), Value::test_int(5)], span: Span::test_data() @@ -68,7 +68,7 @@ impl Command for Find { }, Example { description: "Find if a service is not running", - example: "echo [[version patch]; [0.1.0 $false] [0.1.1 $true] [0.2.0 $false]] | find -p { $it.patch }", + example: "echo [[version patch]; [0.1.0 $false] [0.1.1 $true] [0.2.0 $false]] | find -p { |it| $it.patch }", result: Some(Value::List { vals: vec![Value::test_record( vec!["version", "patch"], diff --git a/crates/nu-command/src/filters/par_each.rs b/crates/nu-command/src/filters/par_each.rs index 9b634d3ac1..e15267d391 100644 --- a/crates/nu-command/src/filters/par_each.rs +++ b/crates/nu-command/src/filters/par_each.rs @@ -32,7 +32,7 @@ impl Command for ParEach { fn examples(&self) -> Vec { vec![Example { - example: "[1 2 3] | par-each { 2 * $it }", + example: "[1 2 3] | par-each { |it| 2 * $it }", description: "Multiplies elements in list", result: None, }] diff --git a/crates/nu-command/src/filters/reduce.rs b/crates/nu-command/src/filters/reduce.rs index 5451b87212..1bb9b6956e 100644 --- a/crates/nu-command/src/filters/reduce.rs +++ b/crates/nu-command/src/filters/reduce.rs @@ -24,7 +24,7 @@ impl Command for Reduce { ) .required( "block", - SyntaxShape::Block(Some(vec![SyntaxShape::Any])), + SyntaxShape::Block(Some(vec![SyntaxShape::Any, SyntaxShape::Any])), "reducing function", ) .switch("numbered", "iterate with an index", Some('n')) @@ -37,7 +37,7 @@ impl Command for Reduce { fn examples(&self) -> Vec { vec![ Example { - example: "[ 1 2 3 4 ] | reduce { $it.acc + $it.item }", + example: "[ 1 2 3 4 ] | reduce {|it, acc| $it + $acc }", description: "Sum values of a list (same as 'math sum')", result: Some(Value::Int { val: 10, @@ -45,7 +45,7 @@ impl Command for Reduce { }), }, Example { - example: "[ 1 2 3 4 ] | reduce -f 10 { $it.acc + $it.item }", + example: "[ 1 2 3 4 ] | reduce -f 10 {|it, acc| $acc + $it }", description: "Sum values with a starting value (fold)", result: Some(Value::Int { val: 20, @@ -53,7 +53,7 @@ impl Command for Reduce { }), }, Example { - example: r#"[ i o t ] | reduce -f "Arthur, King of the Britons" { $it.acc | str find-replace -a $it.item "X" }"#, + example: r#"[ i o t ] | reduce -f "Arthur, King of the Britons" {|it, acc| $acc | str find-replace -a $it "X" }"#, description: "Replace selected characters in a string with 'X'", result: Some(Value::String { val: "ArXhur, KXng Xf Xhe BrXXXns".to_string(), @@ -61,11 +61,11 @@ impl Command for Reduce { }), }, Example { - example: r#"[ one longest three bar ] | reduce -n { - if ($it.item | str length) > ($it.acc | str length) { + example: r#"[ one longest three bar ] | reduce -n { |it, acc| + if ($it.item | str length) > ($acc | str length) { $it.item } else { - $it.acc + $acc } }"#, description: "Find the longest string and its index", @@ -147,32 +147,28 @@ impl Command for Reduce { if let Some(var_id) = &var.var_id { let it = if numbered { Value::Record { - cols: vec![ - "index".to_string(), - "acc".to_string(), - "item".to_string(), - ], + cols: vec!["index".to_string(), "item".to_string()], vals: vec![ Value::Int { val: idx as i64 + off, span, }, - acc, x, ], span, } } else { - Value::Record { - cols: vec!["acc".to_string(), "item".to_string()], - vals: vec![acc, x], - span, - } + x }; stack.add_var(*var_id, it); } } + if let Some(var) = block.signature.get_positional(1) { + if let Some(var_id) = &var.var_id { + stack.add_var(*var_id, acc); + } + } let v = match eval_block(engine_state, &mut stack, block, PipelineData::new(span)) { Ok(v) => v.into_value(span), diff --git a/crates/nu-command/tests/commands/each.rs b/crates/nu-command/tests/commands/each.rs index 5b15e6626a..0be56792ae 100644 --- a/crates/nu-command/tests/commands/each.rs +++ b/crates/nu-command/tests/commands/each.rs @@ -5,7 +5,7 @@ fn each_works_separately() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo [1 2 3] | each { echo $it 10 | math sum } | to json -r + echo [1 2 3] | each { |it| echo $it 10 | math sum } | to json -r "# )); @@ -17,7 +17,7 @@ fn each_group_works() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo [1 2 3 4 5 6] | each group 3 { $it } | to json --raw + echo [1 2 3 4 5 6] | each group 3 { |it| $it } | to json --raw "# )); @@ -29,7 +29,7 @@ fn each_window() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo [1 2 3 4] | each window 3 { $it } | to json --raw + echo [1 2 3 4] | each window 3 { |it| $it } | to json --raw "# )); @@ -41,7 +41,7 @@ fn each_window_stride() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo [1 2 3 4 5 6] | each window 3 -s 2 { echo $it } | to json --raw + echo [1 2 3 4 5 6] | each window 3 -s 2 { |it| echo $it } | to json --raw "# )); @@ -65,7 +65,7 @@ fn each_implicit_it_in_block() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo [[foo bar]; [a b] [c d] [e f]] | each { nu --testbin cococo $it.foo } | str collect + echo [[foo bar]; [a b] [c d] [e f]] | each { |it| nu --testbin cococo $it.foo } | str collect "# )); diff --git a/crates/nu-command/tests/commands/echo.rs b/crates/nu-command/tests/commands/echo.rs index 4da8e2dbec..cad2a6c777 100644 --- a/crates/nu-command/tests/commands/echo.rs +++ b/crates/nu-command/tests/commands/echo.rs @@ -17,7 +17,7 @@ fn echo_range_handles_inclusive() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo 1..3 | each { $it } | to json --raw + echo 1..3 | each { |x| $x } | to json --raw "# )); @@ -29,7 +29,7 @@ fn echo_range_handles_exclusive() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo 1..<3 | each { $it } | to json --raw + echo 1..<3 | each { |x| $x } | to json --raw "# )); @@ -41,7 +41,7 @@ fn echo_range_handles_inclusive_down() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo 3..1 | each { $it } | to json --raw + echo 3..1 | each { |it| $it } | to json --raw "# )); @@ -53,7 +53,7 @@ fn echo_range_handles_exclusive_down() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#" - echo 3..<1 | each { $it } | to json --raw + echo 3..<1 | each { |it| $it } | to json --raw "# )); diff --git a/crates/nu-command/tests/commands/into_int.rs b/crates/nu-command/tests/commands/into_int.rs index dbb20a1c7d..e7f5d7c5d9 100644 --- a/crates/nu-command/tests/commands/into_int.rs +++ b/crates/nu-command/tests/commands/into_int.rs @@ -5,7 +5,7 @@ fn into_int_filesize() { let actual = nu!( cwd: ".", pipeline( r#" - echo 1kb | into int | each { $it / 1000 } + echo 1kb | into int | each { |it| $it / 1000 } "# )); @@ -17,7 +17,7 @@ fn into_int_filesize2() { let actual = nu!( cwd: ".", pipeline( r#" - echo 1kib | into int | each { $it / 1024 } + echo 1kib | into int | each { |it| $it / 1024 } "# )); @@ -29,7 +29,7 @@ fn into_int_int() { let actual = nu!( cwd: ".", pipeline( r#" - echo 1024 | into int | each { $it / 1024 } + echo 1024 | into int | each { |it| $it / 1024 } "# )); diff --git a/crates/nu-command/tests/commands/ls.rs b/crates/nu-command/tests/commands/ls.rs index 91f9a1393f..e78a982791 100644 --- a/crates/nu-command/tests/commands/ls.rs +++ b/crates/nu-command/tests/commands/ls.rs @@ -87,7 +87,7 @@ fn lists_all_files_in_directories_from_stream() { cwd: dirs.test(), pipeline( r#" echo dir_a dir_b - | each { ls $it } + | each { |it| ls $it } | flatten | length "# )); diff --git a/crates/nu-command/tests/commands/parse.rs b/crates/nu-command/tests/commands/parse.rs index bf8e6d419f..b783b97bd9 100644 --- a/crates/nu-command/tests/commands/parse.rs +++ b/crates/nu-command/tests/commands/parse.rs @@ -22,7 +22,7 @@ mod simple { r#" open key_value_separated_arepa_ingredients.txt | lines - | each { echo $it | parse "{Name}={Value}" } + | each { |it| echo $it | parse "{Name}={Value}" } | flatten | get 1 | get Value diff --git a/crates/nu-command/tests/commands/reduce.rs b/crates/nu-command/tests/commands/reduce.rs index bf5583bf5d..95d428a515 100644 --- a/crates/nu-command/tests/commands/reduce.rs +++ b/crates/nu-command/tests/commands/reduce.rs @@ -8,7 +8,7 @@ fn reduce_table_column() { echo "[{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}]" | from json | get total - | reduce -f 20 { $it.item + (math eval $"($it.acc)^1.05")} + | reduce -f 20 { |it, acc| $it + (math eval $"($acc)^1.05")} | into string -d 1 "# ) @@ -23,7 +23,7 @@ fn reduce_table_column_with_path() { cwd: ".", pipeline( r#" [{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}] - | reduce -f 20 { $it.item.total + (math eval $"($it.acc)^1.05")} + | reduce -f 20 { |it, acc| $it.total + (math eval $"($acc)^1.05")} | into string -d 1 "# ) @@ -38,7 +38,7 @@ fn reduce_rows_example() { cwd: ".", pipeline( r#" [[a,b]; [1,2] [3,4]] - | reduce -f 1.6 { $it.acc * ($it.item.a | into int) + ($it.item.b | into int) } + | reduce -f 1.6 { |it, acc| $acc * ($it.a | into int) + ($it.b | into int) } "# ) ); @@ -54,7 +54,7 @@ fn reduce_numbered_example() { cwd: ".", pipeline( r#" echo one longest three bar - reduce -n { if ($it.item | str length) > ($acc.item | str length) {echo $it} {echo $acc}} + reduce -n { |it, acc| if ($it | str length) > ($acc | str length) {echo $it} else {echo $acc}} | get index "# ) @@ -69,7 +69,7 @@ fn reduce_numbered_integer_addition_example() { cwd: ".", pipeline( r#" echo [1 2 3 4] - | reduce -n { $it.acc + $it.item } + | reduce -n { |it, acc| $acc + $it.item } | get item "# ) @@ -84,9 +84,9 @@ fn folding_with_tables() { cwd: ".", pipeline( r#" echo [10 20 30 40] - | reduce -f [] { - with-env [value $it.item] { - echo $it.acc | append (10 * ($env.value | into int)) + | reduce -f [] { |it, acc| + with-env [value $it] { + echo $acc | append (10 * ($env.value | into int)) } } | math sum @@ -102,7 +102,7 @@ fn error_reduce_fold_type_mismatch() { let actual = nu!( cwd: ".", pipeline( r#" - echo a b c | reduce -f 0 { $it.acc + $it.item } + echo a b c | reduce -f 0 { |it, acc| $acc + $it } "# ) ); @@ -115,7 +115,7 @@ fn error_reduce_empty() { let actual = nu!( cwd: ".", pipeline( r#" - reduce { $it.$acc + $it.item } + reduce { |it, acc| $acc + $it } "# ) ); diff --git a/crates/nu-command/tests/commands/roll.rs b/crates/nu-command/tests/commands/roll.rs index 81fd72d091..f238be3591 100644 --- a/crates/nu-command/tests/commands/roll.rs +++ b/crates/nu-command/tests/commands/roll.rs @@ -135,7 +135,7 @@ mod columns { transpose bit --ignore-titles | get bit | reverse - | each --numbered { + | each --numbered { |it| $it.item * (2 ** $it.index) } | math sum @@ -155,7 +155,7 @@ mod columns { pipeline( r#" split chars - | each { $it | into int } + | each { |it| $it | into int } | rotate --ccw | rename bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8 "# diff --git a/crates/nu-command/tests/commands/str_/collect.rs b/crates/nu-command/tests/commands/str_/collect.rs index 73db93cf13..4a4a93c1dd 100644 --- a/crates/nu-command/tests/commands/str_/collect.rs +++ b/crates/nu-command/tests/commands/str_/collect.rs @@ -44,7 +44,7 @@ fn sum_one_to_four() { let actual = nu!( cwd: ".", pipeline( r#" - 1..4 | each { $it } | into string | str collect "+" | math eval + 1..4 | each { |it| $it } | into string | str collect "+" | math eval "# ) ); diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs index 6dcab36cfd..274bec72ab 100644 --- a/crates/nu-parser/src/errors.rs +++ b/crates/nu-parser/src/errors.rs @@ -175,6 +175,15 @@ pub enum ParseError { #[diagnostic(code(nu::parser::rest_needs_name), url(docsrs))] RestNeedsName(#[label = "needs a parameter name"] Span), + #[error("Parameter not correct type.")] + #[diagnostic(code(nu::parser::parameter_mismatch_type), url(docsrs))] + ParameterMismatchType( + String, + String, + String, + #[label = "parameter {0} needs to be '{1}' instead of '{2}'"] Span, + ), + #[error("Extra columns.")] #[diagnostic(code(nu::parser::extra_columns), url(docsrs))] ExtraColumns( diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 07c493cc7b..1afaf57151 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2894,7 +2894,7 @@ pub fn parse_block_expression( working_set.enter_scope(); // Check to see if we have parameters - let (mut signature, amt_to_skip): (Option>, usize) = match output.first() { + let (signature, amt_to_skip): (Option<(Box, Span)>, usize) = match output.first() { Some(Token { contents: TokenContents::Pipe, span, @@ -2923,16 +2923,14 @@ pub fn parse_block_expression( end }; - let (signature, err) = parse_signature_helper( - working_set, - Span { - start: start_point, - end: end_point, - }, - ); + let signature_span = Span { + start: start_point, + end: end_point, + }; + let (signature, err) = parse_signature_helper(working_set, signature_span); error = error.or(err); - (Some(signature), amt_to_skip) + (Some((signature, signature_span)), amt_to_skip) } _ => (None, 0), }; @@ -2942,19 +2940,48 @@ pub fn parse_block_expression( // TODO: Finish this if let SyntaxShape::Block(Some(v)) = shape { - if signature.is_none() && v.len() == 1 { - // We'll assume there's an `$it` present - let var_id = working_set.add_variable(b"$it".to_vec(), Type::Unknown); + if let Some((sig, sig_span)) = &signature { + if sig.num_positionals() != v.len() { + error = error.or_else(|| { + Some(ParseError::Expected( + format!( + "{} block parameter{}", + v.len(), + if v.len() > 1 { "s" } else { "" } + ), + *sig_span, + )) + }); + } - let mut new_sigature = Signature::new(""); - new_sigature.required_positional.push(PositionalArg { - var_id: Some(var_id), - name: "$it".into(), - desc: String::new(), - shape: SyntaxShape::Any, + for (expected, PositionalArg { name, shape, .. }) in + v.iter().zip(sig.required_positional.iter()) + { + if expected != shape && *shape != SyntaxShape::Any { + error = error.or_else(|| { + Some(ParseError::ParameterMismatchType( + name.to_owned(), + expected.to_string(), + shape.to_string(), + *sig_span, + )) + }); + } + } + } else if !v.is_empty() { + error = error.or_else(|| { + Some(ParseError::Expected( + format!( + "{} block parameter{}", + v.len(), + if v.len() > 1 { "s" } else { "" } + ), + Span { + start: span.start + 1, + end: span.start + 1, + }, + )) }); - - signature = Some(Box::new(new_sigature)); } } @@ -2962,7 +2989,7 @@ pub fn parse_block_expression( error = error.or(err); if let Some(signature) = signature { - output.signature = signature; + output.signature = signature.0; } else if let Some(last) = working_set.delta.scope.last() { // FIXME: this only supports the top $it. Is this sufficient? diff --git a/docs/commands/each.md b/docs/commands/each.md index 62e25b05fc..2f9056a54e 100644 --- a/docs/commands/each.md +++ b/docs/commands/each.md @@ -19,6 +19,6 @@ Run a block on each element of input Multiplies elements in list ```shell -> [1 2 3] | each { 2 * $it } +> [1 2 3] | each { |it| 2 * $it } ``` diff --git a/docs/commands/par-each.md b/docs/commands/par-each.md index 477ac0c41b..9e58ce7ab7 100644 --- a/docs/commands/par-each.md +++ b/docs/commands/par-each.md @@ -19,6 +19,6 @@ Run a block on each element of input in parallel Multiplies elements in list ```shell -> [1 2 3] | par-each { 2 * $it } +> [1 2 3] | par-each { |it| 2 * $it } ``` diff --git a/src/tests/test_engine.rs b/src/tests/test_engine.rs index f569e32868..95d95f3f69 100644 --- a/src/tests/test_engine.rs +++ b/src/tests/test_engine.rs @@ -86,7 +86,7 @@ fn scope_variable() -> TestResult { #[test] fn earlier_errors() -> TestResult { fail_test( - r#"[1, "bob"] | each { $it + 3 } | each { $it / $it } | table"#, + r#"[1, "bob"] | each { |it| $it + 3 } | each { |it| $it / $it } | table"#, "int", ) } diff --git a/src/tests/test_iteration.rs b/src/tests/test_iteration.rs index 14824bb0c5..ec1544b52f 100644 --- a/src/tests/test_iteration.rs +++ b/src/tests/test_iteration.rs @@ -3,7 +3,7 @@ use crate::tests::{run_test, TestResult}; #[test] fn better_block_types() -> TestResult { run_test( - r#"([1, 2, 3] | each -n { $"($it.index) is ($it.item)" }).1"#, + r#"([1, 2, 3] | each -n { |it| $"($it.index) is ($it.item)" }).1"#, "1 is 2", ) } @@ -11,14 +11,14 @@ fn better_block_types() -> TestResult { #[test] fn row_iteration() -> TestResult { run_test( - "[[name, size]; [tj, 100], [rl, 200]] | each { $it.size * 8 } | get 1", + "[[name, size]; [tj, 100], [rl, 200]] | each { |it| $it.size * 8 } | get 1", "1600", ) } #[test] fn record_iteration() -> TestResult { - run_test("([[name, level]; [aa, 100], [bb, 200]] | each { $it | each { |x| if $x.column == \"level\" { $x.value + 100 } else { $x.value } } }).level | get 1", "300") + run_test("([[name, level]; [aa, 100], [bb, 200]] | each { |it| $it | each { |x| if $x.column == \"level\" { $x.value + 100 } else { $x.value } } }).level | get 1", "300") } #[test] @@ -45,7 +45,7 @@ fn for_loops() -> TestResult { #[test] fn par_each() -> TestResult { run_test( - r#"1..10 | par-each --numbered { ([[index, item]; [$it.index, ($it.item > 5)]]).0 } | where index == 4 | get item.0"#, + r#"1..10 | par-each --numbered { |it| ([[index, item]; [$it.index, ($it.item > 5)]]).0 } | where index == 4 | get item.0"#, "false", ) } diff --git a/src/tests/test_parser.rs b/src/tests/test_parser.rs index dac9593a9f..2bee06e100 100644 --- a/src/tests/test_parser.rs +++ b/src/tests/test_parser.rs @@ -40,7 +40,7 @@ fn alias_recursion() -> TestResult { #[test] fn block_param1() -> TestResult { - run_test("[3] | each { $it + 10 } | get 0", "13") + run_test("[3] | each { |it| $it + 10 } | get 0", "13") } #[test] @@ -50,7 +50,7 @@ fn block_param2() -> TestResult { #[test] fn block_param3_list_iteration() -> TestResult { - run_test("[1,2,3] | each { $it + 10 } | get 1", "12") + run_test("[1,2,3] | each { |it| $it + 10 } | get 1", "12") } #[test] @@ -70,7 +70,7 @@ fn range_iteration2() -> TestResult { #[test] fn simple_value_iteration() -> TestResult { - run_test("4 | each { $it + 10 }", "14") + run_test("4 | each { |it| $it + 10 }", "14") } #[test] @@ -116,7 +116,7 @@ fn bad_var_name() -> TestResult { #[test] fn long_flag() -> TestResult { run_test( - r#"([a, b, c] | each --numbered { if $it.index == 1 { 100 } else { 0 } }).1"#, + r#"([a, b, c] | each --numbered { |it| if $it.index == 1 { 100 } else { 0 } }).1"#, "100", ) } @@ -314,3 +314,18 @@ fn capture_row_condition() -> TestResult { fn proper_missing_param() -> TestResult { fail_test(r#"def foo [x y z w] { }; foo a b c"#, "missing w") } + +#[test] +fn block_arity_check1() -> TestResult { + fail_test(r#"ls | each { 1 }"#, "expected 1 block parameter") +} + +#[test] +fn block_arity_check2() -> TestResult { + fail_test(r#"ls | reduce { 1 }"#, "expected 2 block parameters") +} + +#[test] +fn block_arity_check3() -> TestResult { + fail_test(r#"ls | each { |x, y| 1}"#, "expected 1 block parameter") +} diff --git a/src/tests/test_strings.rs b/src/tests/test_strings.rs index 4e95c48947..160fab8288 100644 --- a/src/tests/test_strings.rs +++ b/src/tests/test_strings.rs @@ -7,13 +7,13 @@ fn build_string1() -> TestResult { #[test] fn build_string2() -> TestResult { - run_test("'nu' | each {build-string $it 'shell'}", "nushell") + run_test("'nu' | each { |it| build-string $it 'shell'}", "nushell") } #[test] fn build_string3() -> TestResult { run_test( - "build-string 'nu' 'shell' | each {build-string $it ' rocks'}", + "build-string 'nu' 'shell' | each { |it| build-string $it ' rocks'}", "nushell rocks", ) } @@ -21,7 +21,7 @@ fn build_string3() -> TestResult { #[test] fn build_string4() -> TestResult { run_test( - "['sam','rick','pete'] | each { build-string $it ' is studying'} | get 2", + "['sam','rick','pete'] | each { |it| build-string $it ' is studying'} | get 2", "pete is studying", ) } diff --git a/tests/shell/mod.rs b/tests/shell/mod.rs index 0fff95de05..bdb5ef006a 100644 --- a/tests/shell/mod.rs +++ b/tests/shell/mod.rs @@ -23,7 +23,7 @@ fn plugins_are_declared_with_wix() { | where Directory.attributes.Id == "$(var.PlatformProgramFilesFolder)" | get Directory.children.Directory.children.0 | last | get Directory.children.Component.children - | each { echo $it | first } + | each { |it| echo $it | first } | skip | where File.attributes.Name =~ "nu_plugin" | str substring [_, -4] File.attributes.Name @@ -32,7 +32,7 @@ fn plugins_are_declared_with_wix() { | wrap wix } | default wix _ - | each { if $it.wix != $it.cargo { 1 } { 0 } } + | each { |it| if $it.wix != $it.cargo { 1 } { 0 } } | math sum "# )); diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index f811e02ab1..489e810b01 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -111,7 +111,7 @@ mod it_evaluation { ls | sort-by name | get name - | each { nu --testbin cococo $it } + | each { |it| nu --testbin cococo $it } | get 1 "# )); @@ -136,7 +136,7 @@ mod it_evaluation { r#" open nu_candies.txt | lines - | each { nu --testbin chop $it} + | each { |it| nu --testbin chop $it} | get 1 "# )); diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 51191b56c0..0548798e87 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -22,7 +22,7 @@ fn takes_rows_of_nu_value_strings_and_pipes_it_to_stdin_of_external() { r#" open nu_times.csv | get origin - | each { ^echo $it | nu --testbin chop } + | each { |it| ^echo $it | nu --testbin chop } | get 2 "# )); @@ -76,7 +76,7 @@ fn argument_subexpression() { let actual = nu!( cwd: ".", r#" - echo "foo" | each { echo (echo $it) } + echo "foo" | each { |it| echo (echo $it) } "# ); @@ -102,7 +102,7 @@ fn subexpression_handles_dot() { r#" echo (open nu_times.csv) | get name - | each { nu --testbin chop $it } + | each { |it| nu --testbin chop $it } | get 3 "# )); @@ -116,7 +116,7 @@ fn string_interpolation_with_it() { let actual = nu!( cwd: ".", r#" - echo "foo" | each { echo $"($it)" } + echo "foo" | each { |it| echo $"($it)" } "# ); @@ -128,7 +128,7 @@ fn string_interpolation_with_it_column_path() { let actual = nu!( cwd: ".", r#" - echo [[name]; [sammie]] | each { echo $"($it.name)" } | get 0 + echo [[name]; [sammie]] | each { |it| echo $"($it.name)" } | get 0 "# ); @@ -1048,7 +1048,7 @@ fn duration_overflow() { let actual = nu!( cwd: ".", pipeline( r#" - ls | get modified | each { $it + 10000000000000000day } + ls | get modified | each { |it| $it + 10000000000000000day } "#) ); @@ -1060,7 +1060,7 @@ fn date_and_duration_overflow() { let actual = nu!( cwd: ".", pipeline( r#" - ls | get modified | each { $it + 1000000000day } + ls | get modified | each { |it| $it + 1000000000day } "#) ); @@ -1336,17 +1336,17 @@ mod variable_scoping { == "ZZZ" ); test_variable_scope_list!( - r#" def test [input] { echo [0 1 2] | each { echo $input } } + r#" def test [input] { echo [0 1 2] | each { |_| echo $input } } test ZZZ "# == ["ZZZ", "ZZZ", "ZZZ"] ); test_variable_scope_list!( - r#" def test [input] { echo [0 1 2] | each { if $it > 0 {echo $input} else {echo $input}} } + r#" def test [input] { echo [0 1 2] | each { |it| if $it > 0 {echo $input} else {echo $input}} } test ZZZ "# == ["ZZZ", "ZZZ", "ZZZ"] ); test_variable_scope_list!( - r#" def test [input] { echo [0 1 2] | each { if $input == $input {echo $input} else {echo $input}} } + r#" def test [input] { echo [0 1 2] | each { |_| if $input == $input {echo $input} else {echo $input}} } test ZZZ "# == ["ZZZ", "ZZZ", "ZZZ"] );