From a8eef9af334e73f463db99dc8eb16f5318abfbdb Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Fri, 17 Mar 2023 20:36:28 +0800 Subject: [PATCH] Restrict closure expression to be something like `{|| ...}` (#8290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description As title, closes: #7921 closes: #8273 # User-Facing Changes when define a closure without pipe, nushell will raise error for now: ``` ❯ let x = {ss ss} Error: nu::parser::closure_missing_pipe × Missing || inside closure ╭─[entry #2:1:1] 1 │ let x = {ss ss} · ───┬─── · ╰── Parsing as a closure, but || is missing ╰──── help: Try add || to the beginning of closure ``` `any`, `each`, `all`, `where` command accepts closure, it forces user input closure like `{||`, or parse error will returned. ``` ❯ {major:2, minor:1, patch:4} | values | each { into string } Error: nu::parser::closure_missing_pipe × Missing || inside closure ╭─[entry #4:1:1] 1 │ {major:2, minor:1, patch:4} | values | each { into string } · ───────┬─────── · ╰── Parsing as a closure, but || is missing ╰──── help: Try add || to the beginning of closure ``` `with-env`, `do`, `def`, `try` are special, they still remain the same, although it says that it accepts a closure, but they don't need to be written like `{||`, it's more likely a block but can capture variable outside of scope: ``` ❯ def test [input] { echo [0 1 2] | do { do { echo $input } } }; test aaa aaa ``` Just realize that It's a big breaking change, we need to update config and scripts... # 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. --- crates/nu-cmd-lang/src/core_commands/do_.rs | 6 +++- crates/nu-cmd-lang/src/core_commands/try_.rs | 5 +++- crates/nu-command/src/debug/timeit.rs | 2 +- crates/nu-command/src/filters/all.rs | 2 +- crates/nu-command/src/filters/any.rs | 2 +- crates/nu-command/src/filters/each.rs | 2 +- crates/nu-command/tests/commands/all.rs | 6 ++-- crates/nu-command/tests/commands/any.rs | 6 ++-- .../tests/commands/bytes/starts_with.rs | 14 ++++----- crates/nu-command/tests/commands/empty.rs | 8 ++--- crates/nu-command/tests/commands/group_by.rs | 2 +- crates/nu-command/tests/commands/ls.rs | 2 +- crates/nu-command/tests/commands/update.rs | 2 +- crates/nu-command/tests/commands/upsert.rs | 2 +- crates/nu-command/tests/commands/where_.rs | 4 +-- crates/nu-parser/src/errors.rs | 8 +++++ crates/nu-parser/src/parser.rs | 25 ++++++++++++---- crates/nu-parser/tests/test_parser.rs | 8 ++++- .../src/sample_config/default_config.nu | 14 ++++----- .../nu-utils/src/sample_config/default_env.nu | 12 ++++---- .../src/sample_config/sample_login.nu | 2 +- src/tests/test_engine.rs | 9 ++++-- tests/hooks/mod.rs | 30 +++++++++---------- tests/shell/pipeline/commands/internal.rs | 6 ++-- 24 files changed, 108 insertions(+), 71 deletions(-) diff --git a/crates/nu-cmd-lang/src/core_commands/do_.rs b/crates/nu-cmd-lang/src/core_commands/do_.rs index 330d906de1..65ed6a4f70 100644 --- a/crates/nu-cmd-lang/src/core_commands/do_.rs +++ b/crates/nu-cmd-lang/src/core_commands/do_.rs @@ -22,7 +22,11 @@ impl Command for Do { fn signature(&self) -> Signature { Signature::build("do") - .required("closure", SyntaxShape::Any, "the closure to run") + .required( + "closure", + SyntaxShape::OneOf(vec![SyntaxShape::Closure(None), SyntaxShape::Any]), + "the closure to run", + ) .input_output_types(vec![(Type::Any, Type::Any)]) .switch( "ignore-errors", diff --git a/crates/nu-cmd-lang/src/core_commands/try_.rs b/crates/nu-cmd-lang/src/core_commands/try_.rs index 778aa3822b..37feac1224 100644 --- a/crates/nu-cmd-lang/src/core_commands/try_.rs +++ b/crates/nu-cmd-lang/src/core_commands/try_.rs @@ -26,7 +26,10 @@ impl Command for Try { "catch_block", SyntaxShape::Keyword( b"catch".to_vec(), - Box::new(SyntaxShape::Closure(Some(vec![SyntaxShape::Any]))), + Box::new(SyntaxShape::OneOf(vec![ + SyntaxShape::Closure(None), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), + ])), ), "block to run if try block fails", ) diff --git a/crates/nu-command/src/debug/timeit.rs b/crates/nu-command/src/debug/timeit.rs index 1430b2e635..a70056f3ef 100644 --- a/crates/nu-command/src/debug/timeit.rs +++ b/crates/nu-command/src/debug/timeit.rs @@ -111,7 +111,7 @@ fn test_time_closure() { use nu_test_support::{nu, nu_repl_code, playground::Playground}; Playground::setup("test_time_closure", |dirs, _| { let inp = [ - r#"[2 3 4] | timeit { to nuon | save foo.txt }"#, + r#"[2 3 4] | timeit {|_| to nuon | save foo.txt }"#, "open foo.txt", ]; let actual_repl = nu!(cwd: dirs.test(), nu_repl_code(&inp)); diff --git a/crates/nu-command/src/filters/all.rs b/crates/nu-command/src/filters/all.rs index 13abfdd511..2651ac1b66 100644 --- a/crates/nu-command/src/filters/all.rs +++ b/crates/nu-command/src/filters/all.rs @@ -45,7 +45,7 @@ impl Command for All { }, Example { description: "Check that each item is a string", - example: "[foo bar 2 baz] | all { ($in | describe) == 'string' }", + example: "[foo bar 2 baz] | all {|| ($in | describe) == 'string' }", result: Some(Value::test_bool(false)), }, Example { diff --git a/crates/nu-command/src/filters/any.rs b/crates/nu-command/src/filters/any.rs index 654a551d54..5651a925f2 100644 --- a/crates/nu-command/src/filters/any.rs +++ b/crates/nu-command/src/filters/any.rs @@ -45,7 +45,7 @@ impl Command for Any { }, Example { description: "Check that any item is a string", - example: "[1 2 3 4] | any { ($in | describe) == 'string' }", + example: "[1 2 3 4] | any {|| ($in | describe) == 'string' }", result: Some(Value::test_bool(false)), }, Example { diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index 29b6663bbb..7200be565e 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -74,7 +74,7 @@ with 'transpose' first."# }), }, Example { - example: "{major:2, minor:1, patch:4} | values | each { into string }", + example: "{major:2, minor:1, patch:4} | values | each {|| into string }", description: "Produce a list of values in the record, converted to string", result: Some(Value::List { vals: vec![ diff --git a/crates/nu-command/tests/commands/all.rs b/crates/nu-command/tests/commands/all.rs index b5ab229bae..89c446829e 100644 --- a/crates/nu-command/tests/commands/all.rs +++ b/crates/nu-command/tests/commands/all.rs @@ -85,7 +85,7 @@ fn works_with_1_param_blocks() { fn works_with_0_param_blocks() { let actual = nu!( cwd: ".", pipeline( - r#"[1 2 3] | all { print $in | true }"# + r#"[1 2 3] | all {|| print $in | true }"# )); assert_eq!(actual.out, "123true"); @@ -105,7 +105,7 @@ fn early_exits_with_1_param_blocks() { fn early_exits_with_0_param_blocks() { let actual = nu!( cwd: ".", pipeline( - r#"[1 2 3] | all { print $in | false }"# + r#"[1 2 3] | all {|| print $in | false }"# )); assert_eq!(actual.out, "1false"); @@ -125,7 +125,7 @@ fn all_uses_enumerate_index() { fn unique_env_each_iteration() { let actual = nu!( cwd: "tests/fixtures/formats", - "[1 2] | all { print ($env.PWD | str ends-with 'formats') | cd '/' | true } | to nuon" + "[1 2] | all {|| print ($env.PWD | str ends-with 'formats') | cd '/' | true } | to nuon" ); assert_eq!(actual.out, "truetruetrue"); diff --git a/crates/nu-command/tests/commands/any.rs b/crates/nu-command/tests/commands/any.rs index c4c24fc255..c61f6c5384 100644 --- a/crates/nu-command/tests/commands/any.rs +++ b/crates/nu-command/tests/commands/any.rs @@ -61,7 +61,7 @@ fn works_with_1_param_blocks() { fn works_with_0_param_blocks() { let actual = nu!( cwd: ".", pipeline( - r#"[1 2 3] | any { print $in | false }"# + r#"[1 2 3] | any {|| print $in | false }"# )); assert_eq!(actual.out, "123false"); @@ -81,7 +81,7 @@ fn early_exits_with_1_param_blocks() { fn early_exits_with_0_param_blocks() { let actual = nu!( cwd: ".", pipeline( - r#"[1 2 3] | any { print $in | true }"# + r#"[1 2 3] | any {|| print $in | true }"# )); assert_eq!(actual.out, "1true"); @@ -101,7 +101,7 @@ fn any_uses_enumerate_index() { fn unique_env_each_iteration() { let actual = nu!( cwd: "tests/fixtures/formats", - "[1 2] | any { print ($env.PWD | str ends-with 'formats') | cd '/' | false } | to nuon" + "[1 2] | any {|| print ($env.PWD | str ends-with 'formats') | cd '/' | false } | to nuon" ); assert_eq!(actual.out, "truetruefalse"); diff --git a/crates/nu-command/tests/commands/bytes/starts_with.rs b/crates/nu-command/tests/commands/bytes/starts_with.rs index 7e80ce15ef..797d5766e7 100644 --- a/crates/nu-command/tests/commands/bytes/starts_with.rs +++ b/crates/nu-command/tests/commands/bytes/starts_with.rs @@ -79,7 +79,7 @@ fn long_stream_binary_overflow() { let actual = nu!( cwd: ".", r#" - nu --testbin repeater (0x[01]) 32768 | bytes starts-with (0..32768 | each { 0x[01] } | bytes collect) + nu --testbin repeater (0x[01]) 32768 | bytes starts-with (0..32768 | each {|| 0x[01] } | bytes collect) "# ); @@ -92,7 +92,7 @@ fn long_stream_binary_exact() { let actual = nu!( cwd: ".", r#" - nu --testbin repeater (0x[01020304]) 8192 | bytes starts-with (0..<8192 | each { 0x[01020304] } | bytes collect) + nu --testbin repeater (0x[01020304]) 8192 | bytes starts-with (0..<8192 | each {|| 0x[01020304] } | bytes collect) "# ); @@ -105,7 +105,7 @@ fn long_stream_string_exact() { let actual = nu!( cwd: ".", r#" - nu --testbin repeater hell 8192 | bytes starts-with (0..<8192 | each { "hell" | into binary } | bytes collect) + nu --testbin repeater hell 8192 | bytes starts-with (0..<8192 | each {|| "hell" | into binary } | bytes collect) "# ); @@ -118,8 +118,8 @@ fn long_stream_mixed_exact() { let actual = nu!( cwd: ".", r#" - let binseg = (0..<2048 | each { 0x[003d9fbf] } | bytes collect) - let strseg = (0..<2048 | each { "hell" | into binary } | bytes collect) + let binseg = (0..<2048 | each {|| 0x[003d9fbf] } | bytes collect) + let strseg = (0..<2048 | each {|| "hell" | into binary } | bytes collect) nu --testbin repeat_bytes 003d9fbf 2048 68656c6c 2048 | bytes starts-with (bytes build $binseg $strseg) "# @@ -138,8 +138,8 @@ fn long_stream_mixed_overflow() { let actual = nu!( cwd: ".", r#" - let binseg = (0..<2048 | each { 0x[003d9fbf] } | bytes collect) - let strseg = (0..<2048 | each { "hell" | into binary } | bytes collect) + let binseg = (0..<2048 | each {|| 0x[003d9fbf] } | bytes collect) + let strseg = (0..<2048 | each {|| "hell" | into binary } | bytes collect) nu --testbin repeat_bytes 003d9fbf 2048 68656c6c 2048 | bytes starts-with (bytes build $binseg $strseg 0x[01]) "# diff --git a/crates/nu-command/tests/commands/empty.rs b/crates/nu-command/tests/commands/empty.rs index 45b4bbf9bf..9ba4567ad7 100644 --- a/crates/nu-command/tests/commands/empty.rs +++ b/crates/nu-command/tests/commands/empty.rs @@ -6,7 +6,7 @@ fn reports_emptiness() { cwd: ".", pipeline( r#" [[] '' {} null] - | all { + | all {|| is-empty } "# @@ -21,7 +21,7 @@ fn reports_nonemptiness() { cwd: ".", pipeline( r#" [[1] ' ' {a:1} 0] - | any { + | any {|| is-empty } "# @@ -36,7 +36,7 @@ fn reports_emptiness_by_columns() { cwd: ".", pipeline( r#" [{a:1 b:null c:null} {a:2 b:null c:null}] - | any { + | any {|| is-empty b c } "# @@ -51,7 +51,7 @@ fn reports_nonemptiness_by_columns() { cwd: ".", pipeline( r#" [{a:1 b:null c:3} {a:null b:5 c:2}] - | any { + | any {|| is-empty a b } "# diff --git a/crates/nu-command/tests/commands/group_by.rs b/crates/nu-command/tests/commands/group_by.rs index 87371db486..0765ce2931 100644 --- a/crates/nu-command/tests/commands/group_by.rs +++ b/crates/nu-command/tests/commands/group_by.rs @@ -61,7 +61,7 @@ fn errors_if_given_unknown_column_name() { cwd: dirs.test(), pipeline( r#" open los_tres_caballeros.json - | group-by { get nu.releases.version } + | group-by {|| get nu.releases.version } "# )); diff --git a/crates/nu-command/tests/commands/ls.rs b/crates/nu-command/tests/commands/ls.rs index 37c328349f..a8fbea48f5 100644 --- a/crates/nu-command/tests/commands/ls.rs +++ b/crates/nu-command/tests/commands/ls.rs @@ -548,7 +548,7 @@ fn list_ignores_ansi() { let actual = nu!( cwd: dirs.test(), pipeline( r#" - ls | find .txt | each { ls $in.name } + ls | find .txt | each {|| ls $in.name } "# )); diff --git a/crates/nu-command/tests/commands/update.rs b/crates/nu-command/tests/commands/update.rs index 86d43aa6a1..0795fa2769 100644 --- a/crates/nu-command/tests/commands/update.rs +++ b/crates/nu-command/tests/commands/update.rs @@ -44,7 +44,7 @@ fn sets_the_column_from_a_block_full_stream_output() { cwd: "tests/fixtures/formats", pipeline( r#" {content: null} - | update content { open --raw cargo_sample.toml | lines | first 5 } + | update content {|| open --raw cargo_sample.toml | lines | first 5 } | get content.1 | str contains "nu" "# diff --git a/crates/nu-command/tests/commands/upsert.rs b/crates/nu-command/tests/commands/upsert.rs index 73197e3d57..fc80d11279 100644 --- a/crates/nu-command/tests/commands/upsert.rs +++ b/crates/nu-command/tests/commands/upsert.rs @@ -44,7 +44,7 @@ fn sets_the_column_from_a_block_full_stream_output() { cwd: "tests/fixtures/formats", pipeline( r#" {content: null} - | upsert content { open --raw cargo_sample.toml | lines | first 5 } + | upsert content {|| open --raw cargo_sample.toml | lines | first 5 } | get content.1 | str contains "nu" "# diff --git a/crates/nu-command/tests/commands/where_.rs b/crates/nu-command/tests/commands/where_.rs index 68fec34461..cd57f0b5ac 100644 --- a/crates/nu-command/tests/commands/where_.rs +++ b/crates/nu-command/tests/commands/where_.rs @@ -35,7 +35,7 @@ fn where_inside_block_works() { fn filters_with_0_arity_block() { let actual = nu!( cwd: ".", - "[1 2 3 4] | where { $in < 3 } | to nuon" + "[1 2 3 4] | where {|| $in < 3 } | to nuon" ); assert_eq!(actual.out, "[1, 2]"); @@ -55,7 +55,7 @@ fn filters_with_1_arity_block() { fn unique_env_each_iteration() { let actual = nu!( cwd: "tests/fixtures/formats", - "[1 2] | where { print ($env.PWD | str ends-with 'formats') | cd '/' | true } | to nuon" + "[1 2] | where {|| print ($env.PWD | str ends-with 'formats') | cd '/' | true } | to nuon" ); assert_eq!(actual.out, "truetrue[1, 2]"); diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs index ec9f394507..ea67015570 100644 --- a/crates/nu-parser/src/errors.rs +++ b/crates/nu-parser/src/errors.rs @@ -38,6 +38,13 @@ pub enum ParseError { #[diagnostic(code(nu::parser::parse_mismatch))] Expected(String, #[label("expected {0}")] Span), + #[error("Missing || inside closure")] + #[diagnostic( + code(nu::parser::closure_missing_pipe), + help("Try add || to the beginning of closure") + )] + ClosureMissingPipe(#[label("Parsing as a closure, but || is missing")] Span), + #[error("Type mismatch during operation.")] #[diagnostic(code(nu::parser::type_mismatch))] Mismatch(String, String, #[label("expected {0}, found {1}")] Span), // expected, found, span @@ -487,6 +494,7 @@ impl ParseError { ParseError::UnknownOperator(_, _, s) => *s, ParseError::InvalidLiteral(_, _, s) => *s, ParseError::NotAConstant(s) => *s, + ParseError::ClosureMissingPipe(s) => *s, } } } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index f7844be964..37e6cacc83 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1779,8 +1779,10 @@ pub fn parse_brace_expr( if matches!(second_token, None) { // If we're empty, that means an empty record or closure - if matches!(shape, SyntaxShape::Closure(_)) { - parse_closure_expression(working_set, shape, span, expand_aliases_denylist) + if matches!(shape, SyntaxShape::Closure(None)) { + parse_closure_expression(working_set, shape, span, expand_aliases_denylist, false) + } else if matches!(shape, SyntaxShape::Closure(Some(_))) { + parse_closure_expression(working_set, shape, span, expand_aliases_denylist, true) } else if matches!(shape, SyntaxShape::Block) { parse_block_expression(working_set, span, expand_aliases_denylist) } else { @@ -1789,11 +1791,13 @@ pub fn parse_brace_expr( } else if matches!(second_token_contents, Some(TokenContents::Pipe)) || matches!(second_token_contents, Some(TokenContents::PipePipe)) { - parse_closure_expression(working_set, shape, span, expand_aliases_denylist) + parse_closure_expression(working_set, shape, span, expand_aliases_denylist, true) } else if matches!(third_token, Some(b":")) { parse_full_cell_path(working_set, None, span, expand_aliases_denylist) - } else if matches!(shape, SyntaxShape::Closure(_)) || matches!(shape, SyntaxShape::Any) { - parse_closure_expression(working_set, shape, span, expand_aliases_denylist) + } else if matches!(shape, SyntaxShape::Closure(None)) { + parse_closure_expression(working_set, shape, span, expand_aliases_denylist, false) + } else if matches!(shape, SyntaxShape::Closure(Some(_))) || matches!(shape, SyntaxShape::Any) { + parse_closure_expression(working_set, shape, span, expand_aliases_denylist, true) } else if matches!(shape, SyntaxShape::Block) { parse_block_expression(working_set, span, expand_aliases_denylist) } else { @@ -4414,6 +4418,7 @@ pub fn parse_closure_expression( shape: &SyntaxShape, span: Span, expand_aliases_denylist: &[usize], + require_pipe: bool, ) -> (Expression, Option) { trace!("parsing: closure expression"); @@ -4490,7 +4495,15 @@ pub fn parse_closure_expression( Some((Box::new(Signature::new("closure".to_string())), *span)), 1, ), - _ => (None, 0), + _ => { + if require_pipe { + error = error.or(Some(ParseError::ClosureMissingPipe(span))); + working_set.exit_scope(); + return (garbage(span), error); + } else { + (None, 0) + } + } }; // TODO: Finish this diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 1f03bf78c9..b2c125b477 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -1563,7 +1563,13 @@ mod input_types { ) .optional( "else_expression", - SyntaxShape::Keyword(b"else".to_vec(), Box::new(SyntaxShape::Expression)), + SyntaxShape::Keyword( + b"else".to_vec(), + Box::new(SyntaxShape::OneOf(vec![ + SyntaxShape::Block, + SyntaxShape::Expression, + ])), + ), "expression or block to run if check fails", ) .category(Category::Core) diff --git a/crates/nu-utils/src/sample_config/default_config.nu b/crates/nu-utils/src/sample_config/default_config.nu index 60b8f43f97..575c6395a6 100644 --- a/crates/nu-utils/src/sample_config/default_config.nu +++ b/crates/nu-utils/src/sample_config/default_config.nu @@ -12,7 +12,7 @@ let dark_theme = { empty: blue # Closures can be used to choose colors for specific values. # The value (in this case, a bool) is piped into the closure. - bool: { if $in { 'light_cyan' } else { 'light_gray' } } + bool: {|| if $in { 'light_cyan' } else { 'light_gray' } } int: white filesize: {|e| if $e == 0b { @@ -22,7 +22,7 @@ let dark_theme = { } else { 'blue' } } duration: white - date: { (date now) - $in | + date: {|| (date now) - $in | if $in < 1hr { 'red3b' } else if $in < 6hr { @@ -93,7 +93,7 @@ let light_theme = { empty: blue # Closures can be used to choose colors for specific values. # The value (in this case, a bool) is piped into the closure. - bool: { if $in { 'dark_cyan' } else { 'dark_gray' } } + bool: {|| if $in { 'dark_cyan' } else { 'dark_gray' } } int: dark_gray filesize: {|e| if $e == 0b { @@ -103,7 +103,7 @@ let light_theme = { } else { 'blue_bold' } } duration: dark_gray - date: { (date now) - $in | + date: {|| (date now) - $in | if $in < 1hr { 'red3b' } else if $in < 6hr { @@ -289,10 +289,10 @@ let-env config = { render_right_prompt_on_last_line: false # true or false to enable or disable right prompt to be rendered on last line of the prompt. hooks: { - pre_prompt: [{ + pre_prompt: [{|| null # replace with source code to run before the prompt is shown }] - pre_execution: [{ + pre_execution: [{|| null # replace with source code to run before the repl input is run }] env_change: { @@ -300,7 +300,7 @@ let-env config = { null # replace with source code to run if the PWD environment is different since the last repl input }] } - display_output: { + display_output: {|| if (term size).columns >= 100 { table -e } else { table } } } diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index 0b3cc32a48..bd453fcf82 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -33,15 +33,15 @@ def create_right_prompt [] { } # Use nushell functions to define your right and left prompt -let-env PROMPT_COMMAND = { create_left_prompt } -let-env PROMPT_COMMAND_RIGHT = { create_right_prompt } +let-env PROMPT_COMMAND = {|| create_left_prompt } +let-env PROMPT_COMMAND_RIGHT = {|| create_right_prompt } # The prompt indicators are environmental variables that represent # the state of the prompt -let-env PROMPT_INDICATOR = { "> " } -let-env PROMPT_INDICATOR_VI_INSERT = { ": " } -let-env PROMPT_INDICATOR_VI_NORMAL = { "> " } -let-env PROMPT_MULTILINE_INDICATOR = { "::: " } +let-env PROMPT_INDICATOR = {|| "> " } +let-env PROMPT_INDICATOR_VI_INSERT = {|| ": " } +let-env PROMPT_INDICATOR_VI_NORMAL = {|| "> " } +let-env PROMPT_MULTILINE_INDICATOR = {|| "::: " } # Specifies how environment variables are: # - converted from a string to a value on Nushell startup (from_string) diff --git a/crates/nu-utils/src/sample_config/sample_login.nu b/crates/nu-utils/src/sample_config/sample_login.nu index 26539c8eaf..ff5d62d78f 100644 --- a/crates/nu-utils/src/sample_config/sample_login.nu +++ b/crates/nu-utils/src/sample_config/sample_login.nu @@ -3,7 +3,7 @@ # - will be sourced after config.nu and env.nu in case of nushell started as login shell # just as an example for overwriting of an environment variable of env.nu -let-env PROMPT_INDICATOR = { "(LS)> " } +let-env PROMPT_INDICATOR = {|| "(LS)> " } # Similar to env-path and config-path there is a variable containing the path to login.nu echo $nu.loginshell-path \ No newline at end of file diff --git a/src/tests/test_engine.rs b/src/tests/test_engine.rs index c47d559821..b61399ee6e 100644 --- a/src/tests/test_engine.rs +++ b/src/tests/test_engine.rs @@ -115,7 +115,7 @@ fn proper_variable_captures() -> TestResult { #[test] fn proper_variable_captures_with_calls() -> TestResult { run_test( - r#"def foo [] { let y = 60; def bar [] { $y }; { bar } }; do (foo)"#, + r#"def foo [] { let y = 60; def bar [] { $y }; {|| bar } }; do (foo)"#, "60", ) } @@ -329,7 +329,10 @@ fn default_value_expression() -> TestResult { #[test] fn loose_each() -> TestResult { - run_test(r#"[[1, 2, 3], [4, 5, 6]] | each { $in.1 } | math sum"#, "7") + run_test( + r#"[[1, 2, 3], [4, 5, 6]] | each {|| $in.1 } | math sum"#, + "7", + ) } #[test] @@ -340,7 +343,7 @@ fn in_means_input() -> TestResult { #[test] fn in_iteration() -> TestResult { run_test( - r#"[3, 4, 5] | each { echo $"hi ($in)" } | str join"#, + r#"[3, 4, 5] | each {|| echo $"hi ($in)" } | str join"#, "hi 3hi 4hi 5", ) } diff --git a/tests/hooks/mod.rs b/tests/hooks/mod.rs index 93b1bbdd7a..0ef82e9d1f 100644 --- a/tests/hooks/mod.rs +++ b/tests/hooks/mod.rs @@ -166,7 +166,7 @@ fn env_change_define_alias() { #[test] fn env_change_simple_block_preserve_env_var() { let inp = &[ - &env_change_hook("FOO", r#"{ let-env SPAM = "spam" }"#), + &env_change_hook("FOO", r#"{|| let-env SPAM = "spam" }"#), "let-env FOO = 1", "$env.SPAM", ]; @@ -183,8 +183,8 @@ fn env_change_simple_block_list_shadow_env_var() { &env_change_hook( "FOO", r#"[ - { let-env SPAM = "foo" } - { let-env SPAM = "spam" } + {|| let-env SPAM = "foo" } + {|| let-env SPAM = "spam" } ]"#, ), "let-env FOO = 1", @@ -200,7 +200,7 @@ fn env_change_simple_block_list_shadow_env_var() { #[test] fn env_change_block_preserve_env_var() { let inp = &[ - &env_change_hook_code("FOO", r#"{ let-env SPAM = "spam" }"#), + &env_change_hook_code("FOO", r#"{|| let-env SPAM = "spam" }"#), "let-env FOO = 1", "$env.SPAM", ]; @@ -227,7 +227,7 @@ fn pre_prompt_define_command() { #[test] fn pre_prompt_simple_block_preserve_env_var() { let inp = &[ - &pre_prompt_hook(r#"{ let-env SPAM = "spam" }"#), + &pre_prompt_hook(r#"{|| let-env SPAM = "spam" }"#), "$env.SPAM", ]; @@ -242,8 +242,8 @@ fn pre_prompt_simple_block_list_shadow_env_var() { let inp = &[ &pre_prompt_hook( r#"[ - { let-env SPAM = "foo" } - { let-env SPAM = "spam" } + {|| let-env SPAM = "foo" } + {|| let-env SPAM = "spam" } ]"#, ), "$env.SPAM", @@ -258,7 +258,7 @@ fn pre_prompt_simple_block_list_shadow_env_var() { #[test] fn pre_prompt_block_preserve_env_var() { let inp = &[ - &pre_prompt_hook_code(r#"{ let-env SPAM = "spam" }"#), + &pre_prompt_hook_code(r#"{|| let-env SPAM = "spam" }"#), "$env.SPAM", ]; @@ -284,7 +284,7 @@ fn pre_execution_define_command() { #[test] fn pre_execution_simple_block_preserve_env_var() { let inp = &[ - &pre_execution_hook(r#"{ let-env SPAM = "spam" }"#), + &pre_execution_hook(r#"{|| let-env SPAM = "spam" }"#), "$env.SPAM", ]; @@ -299,8 +299,8 @@ fn pre_execution_simple_block_list_shadow_env_var() { let inp = &[ &pre_execution_hook( r#"[ - { let-env SPAM = "foo" } - { let-env SPAM = "spam" } + {|| let-env SPAM = "foo" } + {|| let-env SPAM = "spam" } ]"#, ), "$env.SPAM", @@ -315,7 +315,7 @@ fn pre_execution_simple_block_list_shadow_env_var() { #[test] fn pre_execution_block_preserve_env_var() { let inp = &[ - &pre_execution_hook_code(r#"{ let-env SPAM = "spam" }"#), + &pre_execution_hook_code(r#"{|| let-env SPAM = "spam" }"#), "$env.SPAM", ]; @@ -328,7 +328,7 @@ fn pre_execution_block_preserve_env_var() { #[test] fn pre_execution_commandline() { let inp = &[ - &pre_execution_hook_code(r#"{ let-env repl_commandline = (commandline) }"#), + &pre_execution_hook_code(r#"{|| let-env repl_commandline = (commandline) }"#), "$env.repl_commandline", ]; @@ -361,7 +361,7 @@ fn env_change_shadow_command() { #[test] fn env_change_block_dont_preserve_command() { let inp = &[ - &env_change_hook_code("FOO", r#"{ def foo [] { "foo" } }"#), + &env_change_hook_code("FOO", r#"{|| def foo [] { "foo" } }"#), "let-env FOO = 1", "foo", ]; @@ -493,7 +493,7 @@ fn err_hook_non_boolean_condition_output() { hooks: { env_change: { FOO : { - condition: { "foo" } + condition: {|| "foo" } code: "print spam" } } diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index bfb2701682..73cebd9232 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -649,11 +649,11 @@ fn octal_number() { } #[test] -fn run_dynamic_blocks() { +fn run_dynamic_closures() { let actual = nu!( cwd: ".", r#" - let block = { echo "holaaaa" }; do $block + let closure = {|| echo "holaaaa" }; do $closure "# ); assert_eq!(actual.out, "holaaaa"); @@ -1176,7 +1176,7 @@ fn hide_alias_shadowing() { r#" def test-shadowing [] { alias greet = echo hello; - let xyz = { greet }; + let xyz = {|| greet }; hide greet; do $xyz };