nushell/src/tests/test_engine.rs

446 lines
10 KiB
Rust
Raw Normal View History

use crate::tests::{fail_test, run_test, TestResult};
Parameter defaults to $nu.scope.commands (#9152) (*third* try at posting this PR, #9104, like #9084, got polluted with unrelated commits. I'm never going to pull from the github feature branch again!) # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Show parameter defaults in scope command signature, where they're available for display by help. per https://github.com/nushell/nushell/issues/8928. I found unexpected ramifications in one completer (NuHelpCompleter) and plugins, which both use the flag-formatting routine from builtin help. For the moment I made the minimum necessary changes to get the mainline scenario to pass tests and run. But we should circle back on what to do with plugins and help completer.. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> 1. New `parameter_default` column to `signatures` table in `$nu.scope.commands` It is populated with whatever parameters can be defaulted: currently positional args and named flags. 2. Built in help (both `help <command>` and `<command> --help` will display the defaults 3. Help completer will display defaults for flags, but not for positionals. Example: A custom command with some default parameters: ``` 〉cat ~/work/dflts.nu # sample function to show defaults in help export def main [ arg1: string # mandatory positional arg2:string=abc # optional positional --switch # no default here --named:int # named flag, no default --other:string=def # flag --hard:record<foo:int bar:string, bas:bool> # default can be compound type = {foo:22, bar:"other worlds", bas:false} ] { {arg1: $arg1, arg2: $arg2, switch: $switch, named: $named, other: $other, hard: $hard, } } 〉use ~/work/dflts.nu 〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion ╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮ │ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │ ├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤ │ 0 │ │ input │ any │ false │ │ │ 1 │ arg1 │ positional │ string │ false │ │ │ 2 │ arg2 │ positional │ string │ true │ abc │ │ 3 │ switch │ switch │ │ true │ │ │ 4 │ named │ named │ int │ true │ │ │ 5 │ other │ named │ string │ true │ def │ │ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │ │ │ │ │ │ │ │ foo │ 22 │ │ │ │ │ │ │ │ │ bar │ other worlds │ │ │ │ │ │ │ │ │ bas │ false │ │ │ │ │ │ │ │ ╰───────┴───────────────╯ │ │ 7 │ │ output │ any │ false │ │ ╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯ 〉help dflts sample function to show defaults in help Usage: > dflts {flags} <arg1> (arg2) Flags: --switch - switch -- no default here --named <Int> - named flag, typed, but no default --other <String> - flag with default (default: 'def') --hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false}) -h, --help - Display the help message for this command Parameters: arg1 <string>: mandatory positional arg2 <string>: optional positional (optional, default: 'abc') ``` Compared to (relevant bits of) help output previously: ``` Flags: -h, --help - Display the help message for this command -, --switch - no default here -, --named <int> - named flag, no default -, --other <string> - flag -, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type Signatures: <any> | dflts <string> <string> -> <any> Parameters: arg1 <string>: mandatory positional (optional) arg2 <string>: optional positional ``` # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > [x] toolkit check pr > ``` --> # 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. -->
2023-05-11 18:59:56 +00:00
use rstest::rstest;
#[test]
fn concrete_variable_assignment() -> TestResult {
run_test(
"let x = (1..100 | each { |y| $y + 100 }); let y = ($x | length); $x | length",
"100",
)
}
#[test]
fn proper_shadow() -> TestResult {
run_test("let x = 10; let x = $x + 9; $x", "19")
}
#[test]
fn in_variable_1() -> TestResult {
run_test(r#"[3] | if $in.0 > 4 { "yay!" } else { "boo" }"#, "boo")
}
#[test]
fn in_variable_2() -> TestResult {
run_test(r#"3 | if $in > 2 { "yay!" } else { "boo" }"#, "yay!")
}
#[test]
fn in_variable_3() -> TestResult {
run_test(r#"3 | if $in > 4 { "yay!" } else { $in }"#, "3")
}
#[test]
fn in_variable_4() -> TestResult {
run_test(r#"3 | do { $in }"#, "3")
}
#[test]
fn in_variable_5() -> TestResult {
run_test(r#"3 | if $in > 2 { $in - 10 } else { $in * 10 }"#, "-7")
}
#[test]
fn in_variable_6() -> TestResult {
run_test(r#"3 | if $in > 6 { $in - 10 } else { $in * 10 }"#, "30")
}
2022-04-30 21:13:21 +00:00
#[test]
fn in_and_if_else() -> TestResult {
run_test(
r#"[1, 2, 3] | if false {} else if true { $in | length }"#,
"3",
)
}
#[test]
fn help_works_with_missing_requirements() -> TestResult {
REFACTOR: move the 0% commands to `nu-cmd-extra` (#9404) requires - https://github.com/nushell/nushell/pull/9455 # :gear: Description in this PR i move the commands we've all agreed, in the core team, to move out of the core Nushell to the `extra` feature. > **Warning** > in the first commits here, i've > - moved the implementations to `nu-cmd-extra` > - removed the declaration of all the commands below from `nu-command` > - made sure the commands were not available anymore with `cargo run -- -n` ## the list of commands to move with the current command table downloaded as `commands.csv`, i've run ```bash let commands = ( open commands.csv | where is_plugin == "FALSE" and category != "deprecated" | select name category "approv. %" | rename name category approval | insert treated {|it| ( ($it.approval == 100) or # all the core team agreed on them ($it.name | str starts-with "bits") or # see https://github.com/nushell/nushell/pull/9241 ($it.name | str starts-with "dfr") # see https://github.com/nushell/nushell/pull/9327 )} ) ``` to preprocess them and then ```bash $commands | where {|it| (not $it.treated) and ($it.approval == 0)} ``` to get all untreated commands with no approval, which gives ``` ╭────┬───────────────┬─────────┬─────────────┬──────────╮ │ # │ name │ treated │ category │ approval │ ├────┼───────────────┼─────────┼─────────────┼──────────┤ │ 0 │ fmt │ false │ conversions │ 0 │ │ 1 │ each while │ false │ filters │ 0 │ │ 2 │ roll │ false │ filters │ 0 │ │ 3 │ roll down │ false │ filters │ 0 │ │ 4 │ roll left │ false │ filters │ 0 │ │ 5 │ roll right │ false │ filters │ 0 │ │ 6 │ roll up │ false │ filters │ 0 │ │ 7 │ rotate │ false │ filters │ 0 │ │ 8 │ update cells │ false │ filters │ 0 │ │ 9 │ decode hex │ false │ formats │ 0 │ │ 10 │ encode hex │ false │ formats │ 0 │ │ 11 │ from url │ false │ formats │ 0 │ │ 12 │ to html │ false │ formats │ 0 │ │ 13 │ ansi gradient │ false │ platform │ 0 │ │ 14 │ ansi link │ false │ platform │ 0 │ │ 15 │ format │ false │ strings │ 0 │ ╰────┴───────────────┴─────────┴─────────────┴──────────╯ ``` # :paintbrush: User-Facing Changes ``` $nothing ``` # :test_tube: Tests + Formatting - :black_circle: `toolkit fmt` - :black_circle: `toolkit clippy` - :black_circle: `toolkit test` - :black_circle: `toolkit test stdlib` # :book: After Submitting ``` $nothing ``` # :mag: For reviewers ```bash $commands | where {|it| (not $it.treated) and ($it.approval == 0)} | each {|command| try { help $command.name | ignore } catch {|e| $"($command.name): ($e.msg)" } } ``` should give no output in `cargo run --features extra -- -n` and a table with 16 lines in `cargo run -- -n`
2023-07-06 15:31:31 +00:00
// `each while` is part of the *extra* feature and adds 3 lines
Input output checking (#9680) # Description This PR tights input/output type-checking a bit more. There are a lot of commands that don't have correct input/output types, so part of the effort is updating them. This PR now contains updates to commands that had wrong input/output signatures. It doesn't add examples for these new signatures, but that can be follow-up work. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This work enforces many more checks on pipeline type correctness than previous nushell versions. This strictness may uncover incompatibilities in existing scripts or shortcomings in the type information for internal commands. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # 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. -->
2023-07-14 03:20:35 +00:00
let expected_length = if cfg!(feature = "extra") { "66" } else { "63" };
REFACTOR: move the 0% commands to `nu-cmd-extra` (#9404) requires - https://github.com/nushell/nushell/pull/9455 # :gear: Description in this PR i move the commands we've all agreed, in the core team, to move out of the core Nushell to the `extra` feature. > **Warning** > in the first commits here, i've > - moved the implementations to `nu-cmd-extra` > - removed the declaration of all the commands below from `nu-command` > - made sure the commands were not available anymore with `cargo run -- -n` ## the list of commands to move with the current command table downloaded as `commands.csv`, i've run ```bash let commands = ( open commands.csv | where is_plugin == "FALSE" and category != "deprecated" | select name category "approv. %" | rename name category approval | insert treated {|it| ( ($it.approval == 100) or # all the core team agreed on them ($it.name | str starts-with "bits") or # see https://github.com/nushell/nushell/pull/9241 ($it.name | str starts-with "dfr") # see https://github.com/nushell/nushell/pull/9327 )} ) ``` to preprocess them and then ```bash $commands | where {|it| (not $it.treated) and ($it.approval == 0)} ``` to get all untreated commands with no approval, which gives ``` ╭────┬───────────────┬─────────┬─────────────┬──────────╮ │ # │ name │ treated │ category │ approval │ ├────┼───────────────┼─────────┼─────────────┼──────────┤ │ 0 │ fmt │ false │ conversions │ 0 │ │ 1 │ each while │ false │ filters │ 0 │ │ 2 │ roll │ false │ filters │ 0 │ │ 3 │ roll down │ false │ filters │ 0 │ │ 4 │ roll left │ false │ filters │ 0 │ │ 5 │ roll right │ false │ filters │ 0 │ │ 6 │ roll up │ false │ filters │ 0 │ │ 7 │ rotate │ false │ filters │ 0 │ │ 8 │ update cells │ false │ filters │ 0 │ │ 9 │ decode hex │ false │ formats │ 0 │ │ 10 │ encode hex │ false │ formats │ 0 │ │ 11 │ from url │ false │ formats │ 0 │ │ 12 │ to html │ false │ formats │ 0 │ │ 13 │ ansi gradient │ false │ platform │ 0 │ │ 14 │ ansi link │ false │ platform │ 0 │ │ 15 │ format │ false │ strings │ 0 │ ╰────┴───────────────┴─────────┴─────────────┴──────────╯ ``` # :paintbrush: User-Facing Changes ``` $nothing ``` # :test_tube: Tests + Formatting - :black_circle: `toolkit fmt` - :black_circle: `toolkit clippy` - :black_circle: `toolkit test` - :black_circle: `toolkit test stdlib` # :book: After Submitting ``` $nothing ``` # :mag: For reviewers ```bash $commands | where {|it| (not $it.treated) and ($it.approval == 0)} | each {|command| try { help $command.name | ignore } catch {|e| $"($command.name): ($e.msg)" } } ``` should give no output in `cargo run --features extra -- -n` and a table with 16 lines in `cargo run -- -n`
2023-07-06 15:31:31 +00:00
run_test(r#"each --help | lines | length"#, expected_length)
}
#[test]
fn scope_variable() -> TestResult {
run_test(
r#"let x = 3; scope variables | where name == "$x" | get type.0"#,
"int",
)
}
Parameter defaults to $nu.scope.commands (#9152) (*third* try at posting this PR, #9104, like #9084, got polluted with unrelated commits. I'm never going to pull from the github feature branch again!) # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Show parameter defaults in scope command signature, where they're available for display by help. per https://github.com/nushell/nushell/issues/8928. I found unexpected ramifications in one completer (NuHelpCompleter) and plugins, which both use the flag-formatting routine from builtin help. For the moment I made the minimum necessary changes to get the mainline scenario to pass tests and run. But we should circle back on what to do with plugins and help completer.. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> 1. New `parameter_default` column to `signatures` table in `$nu.scope.commands` It is populated with whatever parameters can be defaulted: currently positional args and named flags. 2. Built in help (both `help <command>` and `<command> --help` will display the defaults 3. Help completer will display defaults for flags, but not for positionals. Example: A custom command with some default parameters: ``` 〉cat ~/work/dflts.nu # sample function to show defaults in help export def main [ arg1: string # mandatory positional arg2:string=abc # optional positional --switch # no default here --named:int # named flag, no default --other:string=def # flag --hard:record<foo:int bar:string, bas:bool> # default can be compound type = {foo:22, bar:"other worlds", bas:false} ] { {arg1: $arg1, arg2: $arg2, switch: $switch, named: $named, other: $other, hard: $hard, } } 〉use ~/work/dflts.nu 〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion ╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮ │ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │ ├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤ │ 0 │ │ input │ any │ false │ │ │ 1 │ arg1 │ positional │ string │ false │ │ │ 2 │ arg2 │ positional │ string │ true │ abc │ │ 3 │ switch │ switch │ │ true │ │ │ 4 │ named │ named │ int │ true │ │ │ 5 │ other │ named │ string │ true │ def │ │ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │ │ │ │ │ │ │ │ foo │ 22 │ │ │ │ │ │ │ │ │ bar │ other worlds │ │ │ │ │ │ │ │ │ bas │ false │ │ │ │ │ │ │ │ ╰───────┴───────────────╯ │ │ 7 │ │ output │ any │ false │ │ ╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯ 〉help dflts sample function to show defaults in help Usage: > dflts {flags} <arg1> (arg2) Flags: --switch - switch -- no default here --named <Int> - named flag, typed, but no default --other <String> - flag with default (default: 'def') --hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false}) -h, --help - Display the help message for this command Parameters: arg1 <string>: mandatory positional arg2 <string>: optional positional (optional, default: 'abc') ``` Compared to (relevant bits of) help output previously: ``` Flags: -h, --help - Display the help message for this command -, --switch - no default here -, --named <int> - named flag, no default -, --other <string> - flag -, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type Signatures: <any> | dflts <string> <string> -> <any> Parameters: arg1 <string>: mandatory positional (optional) arg2 <string>: optional positional ``` # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > [x] toolkit check pr > ``` --> # 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. -->
2023-05-11 18:59:56 +00:00
#[rstest]
#[case("a", "<> nothing")]
#[case("b", "<1.23> float")]
#[case("flag1", "<> nothing")]
#[case("flag2", "<4.56> float")]
fn scope_command_defaults(#[case] var: &str, #[case] exp_result: &str) -> TestResult {
run_test(
&format!(
r#"def t1 [a:int b?:float=1.23 --flag1:string --flag2:float=4.56] {{ true }};
let rslt = (scope commands | where name == 't1' | get signatures.0.any | where parameter_name == '{var}' | get parameter_default.0);
Parameter defaults to $nu.scope.commands (#9152) (*third* try at posting this PR, #9104, like #9084, got polluted with unrelated commits. I'm never going to pull from the github feature branch again!) # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Show parameter defaults in scope command signature, where they're available for display by help. per https://github.com/nushell/nushell/issues/8928. I found unexpected ramifications in one completer (NuHelpCompleter) and plugins, which both use the flag-formatting routine from builtin help. For the moment I made the minimum necessary changes to get the mainline scenario to pass tests and run. But we should circle back on what to do with plugins and help completer.. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> 1. New `parameter_default` column to `signatures` table in `$nu.scope.commands` It is populated with whatever parameters can be defaulted: currently positional args and named flags. 2. Built in help (both `help <command>` and `<command> --help` will display the defaults 3. Help completer will display defaults for flags, but not for positionals. Example: A custom command with some default parameters: ``` 〉cat ~/work/dflts.nu # sample function to show defaults in help export def main [ arg1: string # mandatory positional arg2:string=abc # optional positional --switch # no default here --named:int # named flag, no default --other:string=def # flag --hard:record<foo:int bar:string, bas:bool> # default can be compound type = {foo:22, bar:"other worlds", bas:false} ] { {arg1: $arg1, arg2: $arg2, switch: $switch, named: $named, other: $other, hard: $hard, } } 〉use ~/work/dflts.nu 〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion ╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮ │ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │ ├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤ │ 0 │ │ input │ any │ false │ │ │ 1 │ arg1 │ positional │ string │ false │ │ │ 2 │ arg2 │ positional │ string │ true │ abc │ │ 3 │ switch │ switch │ │ true │ │ │ 4 │ named │ named │ int │ true │ │ │ 5 │ other │ named │ string │ true │ def │ │ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │ │ │ │ │ │ │ │ foo │ 22 │ │ │ │ │ │ │ │ │ bar │ other worlds │ │ │ │ │ │ │ │ │ bas │ false │ │ │ │ │ │ │ │ ╰───────┴───────────────╯ │ │ 7 │ │ output │ any │ false │ │ ╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯ 〉help dflts sample function to show defaults in help Usage: > dflts {flags} <arg1> (arg2) Flags: --switch - switch -- no default here --named <Int> - named flag, typed, but no default --other <String> - flag with default (default: 'def') --hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false}) -h, --help - Display the help message for this command Parameters: arg1 <string>: mandatory positional arg2 <string>: optional positional (optional, default: 'abc') ``` Compared to (relevant bits of) help output previously: ``` Flags: -h, --help - Display the help message for this command -, --switch - no default here -, --named <int> - named flag, no default -, --other <string> - flag -, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type Signatures: <any> | dflts <string> <string> -> <any> Parameters: arg1 <string>: mandatory positional (optional) arg2 <string>: optional positional ``` # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > [x] toolkit check pr > ``` --> # 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. -->
2023-05-11 18:59:56 +00:00
$"<($rslt)> ($rslt | describe)""#
),
exp_result,
Parameter defaults to $nu.scope.commands (#9152) (*third* try at posting this PR, #9104, like #9084, got polluted with unrelated commits. I'm never going to pull from the github feature branch again!) # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Show parameter defaults in scope command signature, where they're available for display by help. per https://github.com/nushell/nushell/issues/8928. I found unexpected ramifications in one completer (NuHelpCompleter) and plugins, which both use the flag-formatting routine from builtin help. For the moment I made the minimum necessary changes to get the mainline scenario to pass tests and run. But we should circle back on what to do with plugins and help completer.. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> 1. New `parameter_default` column to `signatures` table in `$nu.scope.commands` It is populated with whatever parameters can be defaulted: currently positional args and named flags. 2. Built in help (both `help <command>` and `<command> --help` will display the defaults 3. Help completer will display defaults for flags, but not for positionals. Example: A custom command with some default parameters: ``` 〉cat ~/work/dflts.nu # sample function to show defaults in help export def main [ arg1: string # mandatory positional arg2:string=abc # optional positional --switch # no default here --named:int # named flag, no default --other:string=def # flag --hard:record<foo:int bar:string, bas:bool> # default can be compound type = {foo:22, bar:"other worlds", bas:false} ] { {arg1: $arg1, arg2: $arg2, switch: $switch, named: $named, other: $other, hard: $hard, } } 〉use ~/work/dflts.nu 〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion ╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮ │ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │ ├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤ │ 0 │ │ input │ any │ false │ │ │ 1 │ arg1 │ positional │ string │ false │ │ │ 2 │ arg2 │ positional │ string │ true │ abc │ │ 3 │ switch │ switch │ │ true │ │ │ 4 │ named │ named │ int │ true │ │ │ 5 │ other │ named │ string │ true │ def │ │ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │ │ │ │ │ │ │ │ foo │ 22 │ │ │ │ │ │ │ │ │ bar │ other worlds │ │ │ │ │ │ │ │ │ bas │ false │ │ │ │ │ │ │ │ ╰───────┴───────────────╯ │ │ 7 │ │ output │ any │ false │ │ ╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯ 〉help dflts sample function to show defaults in help Usage: > dflts {flags} <arg1> (arg2) Flags: --switch - switch -- no default here --named <Int> - named flag, typed, but no default --other <String> - flag with default (default: 'def') --hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false}) -h, --help - Display the help message for this command Parameters: arg1 <string>: mandatory positional arg2 <string>: optional positional (optional, default: 'abc') ``` Compared to (relevant bits of) help output previously: ``` Flags: -h, --help - Display the help message for this command -, --switch - no default here -, --named <int> - named flag, no default -, --other <string> - flag -, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type Signatures: <any> | dflts <string> <string> -> <any> Parameters: arg1 <string>: mandatory positional (optional) arg2 <string>: optional positional ``` # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > [x] toolkit check pr > ``` --> # 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. -->
2023-05-11 18:59:56 +00:00
)
}
#[test]
fn earlier_errors() -> TestResult {
fail_test(
r#"[1, "bob"] | each { |it| $it + 3 } | each { |it| $it / $it } | table"#,
"int",
)
}
#[test]
fn missing_flags_are_nothing() -> TestResult {
run_test(
r#"def foo [--aaa(-a): int, --bbb(-b): int] { (if $aaa == null { 10 } else { $aaa }) + (if $bbb == null { 100 } else { $bbb }) }; foo"#,
"110",
)
}
#[test]
fn missing_flags_are_nothing2() -> TestResult {
run_test(
r#"def foo [--aaa(-a): int, --bbb(-b): int] { (if $aaa == null { 10 } else { $aaa }) + (if $bbb == null { 100 } else { $bbb }) }; foo -a 90"#,
"190",
)
}
#[test]
fn missing_flags_are_nothing3() -> TestResult {
run_test(
r#"def foo [--aaa(-a): int, --bbb(-b): int] { (if $aaa == null { 10 } else { $aaa }) + (if $bbb == null { 100 } else { $bbb }) }; foo -b 45"#,
"55",
)
}
#[test]
fn missing_flags_are_nothing4() -> TestResult {
run_test(
r#"def foo [--aaa(-a): int, --bbb(-b): int] { (if $aaa == null { 10 } else { $aaa }) + (if $bbb == null { 100 } else { $bbb }) }; foo -a 3 -b 10000"#,
"10003",
)
}
#[test]
fn proper_variable_captures() -> TestResult {
run_test(
r#"def foo [x] { let y = 100; { || $y + $x } }; do (foo 23)"#,
"123",
)
}
#[test]
fn proper_variable_captures_with_calls() -> TestResult {
run_test(
Restrict closure expression to be something like `{|| ...}` (#8290) # 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.
2023-03-17 12:36:28 +00:00
r#"def foo [] { let y = 60; def bar [] { $y }; {|| bar } }; do (foo)"#,
"60",
)
}
#[test]
fn proper_variable_captures_with_nesting() -> TestResult {
run_test(
r#"def foo [x] { let z = 100; def bar [y] { $y - $x + $z } ; { |z| bar $z } }; do (foo 11) 13"#,
"102",
)
}
#[test]
fn divide_duration() -> TestResult {
run_test(r#"4ms / 4ms"#, "1")
}
#[test]
fn divide_filesize() -> TestResult {
run_test(r#"4mb / 4mb"#, "1")
}
2022-01-24 21:55:45 +00:00
#[test]
fn date_comparison() -> TestResult {
run_test(r#"(date now) < ((date now) + 2min)"#, "true")
}
#[test]
fn let_sees_input() -> TestResult {
run_test(
r#"def c [] { let x = (str length); $x }; "hello world" | c"#,
"11",
)
}
#[test]
fn let_sees_in_variable() -> TestResult {
run_test(
r#"def c [] { let x = $in.name; $x | str length }; {name: bob, size: 100 } | c"#,
"3",
)
}
#[test]
fn let_sees_in_variable2() -> TestResult {
run_test(
r#"def c [] { let x = ($in | str length); $x }; 'bob' | c"#,
"3",
)
}
#[test]
fn def_env() -> TestResult {
run_test(
remove let-env, focus on mutating $env (#9574) # Description For years, Nushell has used `let-env` to set a single environment variable. As our work on scoping continued, we refined what it meant for a variable to be in scope using `let` but never updated how `let-env` would work. Instead, `let-env` confusingly created mutations to the command's copy of `$env`. So, to help fix the mental model and point people to the right way of thinking about what changing the environment means, this PR removes `let-env` to encourage people to think of it as updating the command's environment variable via mutation. Before: ``` let-env FOO = "BAR" ``` Now: ``` $env.FOO = "BAR" ``` It's also a good reminder that the environment owned by the command is in the `$env` variable rather than global like it is in other shells. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This completely removes `let-env FOO = "BAR"` so that we can focus on `$env.FOO = "BAR"`. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After / Before Submitting integration scripts to update: - :heavy_check_mark: [starship](https://github.com/starship/starship/blob/master/src/init/starship.nu) - :heavy_check_mark: [virtualenv](https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/nushell/activate.nu) - :heavy_check_mark: [atuin](https://github.com/ellie/atuin/blob/main/atuin/src/shell/atuin.nu) (PR: https://github.com/ellie/atuin/pull/1080) - :x: [zoxide](https://github.com/ajeetdsouza/zoxide/blob/main/templates/nushell.txt) (PR: https://github.com/ajeetdsouza/zoxide/pull/587) - :heavy_check_mark: [oh-my-posh](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/shell/scripts/omp.nu) (pr: https://github.com/JanDeDobbeleer/oh-my-posh/pull/4011)
2023-06-30 19:57:51 +00:00
r#"def-env bob [] { $env.BAR = "BAZ" }; bob; $env.BAR"#,
"BAZ",
)
}
#[test]
fn not_def_env() -> TestResult {
remove let-env, focus on mutating $env (#9574) # Description For years, Nushell has used `let-env` to set a single environment variable. As our work on scoping continued, we refined what it meant for a variable to be in scope using `let` but never updated how `let-env` would work. Instead, `let-env` confusingly created mutations to the command's copy of `$env`. So, to help fix the mental model and point people to the right way of thinking about what changing the environment means, this PR removes `let-env` to encourage people to think of it as updating the command's environment variable via mutation. Before: ``` let-env FOO = "BAR" ``` Now: ``` $env.FOO = "BAR" ``` It's also a good reminder that the environment owned by the command is in the `$env` variable rather than global like it is in other shells. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This completely removes `let-env FOO = "BAR"` so that we can focus on `$env.FOO = "BAR"`. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After / Before Submitting integration scripts to update: - :heavy_check_mark: [starship](https://github.com/starship/starship/blob/master/src/init/starship.nu) - :heavy_check_mark: [virtualenv](https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/nushell/activate.nu) - :heavy_check_mark: [atuin](https://github.com/ellie/atuin/blob/main/atuin/src/shell/atuin.nu) (PR: https://github.com/ellie/atuin/pull/1080) - :x: [zoxide](https://github.com/ajeetdsouza/zoxide/blob/main/templates/nushell.txt) (PR: https://github.com/ajeetdsouza/zoxide/pull/587) - :heavy_check_mark: [oh-my-posh](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/shell/scripts/omp.nu) (pr: https://github.com/JanDeDobbeleer/oh-my-posh/pull/4011)
2023-06-30 19:57:51 +00:00
fail_test(r#"def bob [] { $env.BAR = "BAZ" }; bob; $env.BAR"#, "")
}
#[test]
fn def_env_hiding_something() -> TestResult {
fail_test(
remove let-env, focus on mutating $env (#9574) # Description For years, Nushell has used `let-env` to set a single environment variable. As our work on scoping continued, we refined what it meant for a variable to be in scope using `let` but never updated how `let-env` would work. Instead, `let-env` confusingly created mutations to the command's copy of `$env`. So, to help fix the mental model and point people to the right way of thinking about what changing the environment means, this PR removes `let-env` to encourage people to think of it as updating the command's environment variable via mutation. Before: ``` let-env FOO = "BAR" ``` Now: ``` $env.FOO = "BAR" ``` It's also a good reminder that the environment owned by the command is in the `$env` variable rather than global like it is in other shells. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This completely removes `let-env FOO = "BAR"` so that we can focus on `$env.FOO = "BAR"`. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After / Before Submitting integration scripts to update: - :heavy_check_mark: [starship](https://github.com/starship/starship/blob/master/src/init/starship.nu) - :heavy_check_mark: [virtualenv](https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/nushell/activate.nu) - :heavy_check_mark: [atuin](https://github.com/ellie/atuin/blob/main/atuin/src/shell/atuin.nu) (PR: https://github.com/ellie/atuin/pull/1080) - :x: [zoxide](https://github.com/ajeetdsouza/zoxide/blob/main/templates/nushell.txt) (PR: https://github.com/ajeetdsouza/zoxide/pull/587) - :heavy_check_mark: [oh-my-posh](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/shell/scripts/omp.nu) (pr: https://github.com/JanDeDobbeleer/oh-my-posh/pull/4011)
2023-06-30 19:57:51 +00:00
r#"$env.FOO = "foo"; def-env bob [] { hide-env FOO }; bob; $env.FOO"#,
"",
)
}
#[test]
fn def_env_then_hide() -> TestResult {
fail_test(
remove let-env, focus on mutating $env (#9574) # Description For years, Nushell has used `let-env` to set a single environment variable. As our work on scoping continued, we refined what it meant for a variable to be in scope using `let` but never updated how `let-env` would work. Instead, `let-env` confusingly created mutations to the command's copy of `$env`. So, to help fix the mental model and point people to the right way of thinking about what changing the environment means, this PR removes `let-env` to encourage people to think of it as updating the command's environment variable via mutation. Before: ``` let-env FOO = "BAR" ``` Now: ``` $env.FOO = "BAR" ``` It's also a good reminder that the environment owned by the command is in the `$env` variable rather than global like it is in other shells. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This completely removes `let-env FOO = "BAR"` so that we can focus on `$env.FOO = "BAR"`. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After / Before Submitting integration scripts to update: - :heavy_check_mark: [starship](https://github.com/starship/starship/blob/master/src/init/starship.nu) - :heavy_check_mark: [virtualenv](https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/nushell/activate.nu) - :heavy_check_mark: [atuin](https://github.com/ellie/atuin/blob/main/atuin/src/shell/atuin.nu) (PR: https://github.com/ellie/atuin/pull/1080) - :x: [zoxide](https://github.com/ajeetdsouza/zoxide/blob/main/templates/nushell.txt) (PR: https://github.com/ajeetdsouza/zoxide/pull/587) - :heavy_check_mark: [oh-my-posh](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/shell/scripts/omp.nu) (pr: https://github.com/JanDeDobbeleer/oh-my-posh/pull/4011)
2023-06-30 19:57:51 +00:00
r#"def-env bob [] { $env.BOB = "bob" }; def-env un-bob [] { hide-env BOB }; bob; un-bob; $env.BOB"#,
"",
)
}
#[test]
fn export_def_env() -> TestResult {
run_test(
remove let-env, focus on mutating $env (#9574) # Description For years, Nushell has used `let-env` to set a single environment variable. As our work on scoping continued, we refined what it meant for a variable to be in scope using `let` but never updated how `let-env` would work. Instead, `let-env` confusingly created mutations to the command's copy of `$env`. So, to help fix the mental model and point people to the right way of thinking about what changing the environment means, this PR removes `let-env` to encourage people to think of it as updating the command's environment variable via mutation. Before: ``` let-env FOO = "BAR" ``` Now: ``` $env.FOO = "BAR" ``` It's also a good reminder that the environment owned by the command is in the `$env` variable rather than global like it is in other shells. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This completely removes `let-env FOO = "BAR"` so that we can focus on `$env.FOO = "BAR"`. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After / Before Submitting integration scripts to update: - :heavy_check_mark: [starship](https://github.com/starship/starship/blob/master/src/init/starship.nu) - :heavy_check_mark: [virtualenv](https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/nushell/activate.nu) - :heavy_check_mark: [atuin](https://github.com/ellie/atuin/blob/main/atuin/src/shell/atuin.nu) (PR: https://github.com/ellie/atuin/pull/1080) - :x: [zoxide](https://github.com/ajeetdsouza/zoxide/blob/main/templates/nushell.txt) (PR: https://github.com/ajeetdsouza/zoxide/pull/587) - :heavy_check_mark: [oh-my-posh](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/shell/scripts/omp.nu) (pr: https://github.com/JanDeDobbeleer/oh-my-posh/pull/4011)
2023-06-30 19:57:51 +00:00
r#"module foo { export def-env bob [] { $env.BAR = "BAZ" } }; use foo bob; bob; $env.BAR"#,
"BAZ",
)
}
2022-02-04 21:19:13 +00:00
#[test]
remove let-env, focus on mutating $env (#9574) # Description For years, Nushell has used `let-env` to set a single environment variable. As our work on scoping continued, we refined what it meant for a variable to be in scope using `let` but never updated how `let-env` would work. Instead, `let-env` confusingly created mutations to the command's copy of `$env`. So, to help fix the mental model and point people to the right way of thinking about what changing the environment means, this PR removes `let-env` to encourage people to think of it as updating the command's environment variable via mutation. Before: ``` let-env FOO = "BAR" ``` Now: ``` $env.FOO = "BAR" ``` It's also a good reminder that the environment owned by the command is in the `$env` variable rather than global like it is in other shells. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE This completely removes `let-env FOO = "BAR"` so that we can focus on `$env.FOO = "BAR"`. # 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 -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After / Before Submitting integration scripts to update: - :heavy_check_mark: [starship](https://github.com/starship/starship/blob/master/src/init/starship.nu) - :heavy_check_mark: [virtualenv](https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/nushell/activate.nu) - :heavy_check_mark: [atuin](https://github.com/ellie/atuin/blob/main/atuin/src/shell/atuin.nu) (PR: https://github.com/ellie/atuin/pull/1080) - :x: [zoxide](https://github.com/ajeetdsouza/zoxide/blob/main/templates/nushell.txt) (PR: https://github.com/ajeetdsouza/zoxide/pull/587) - :heavy_check_mark: [oh-my-posh](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/shell/scripts/omp.nu) (pr: https://github.com/JanDeDobbeleer/oh-my-posh/pull/4011)
2023-06-30 19:57:51 +00:00
fn dynamic_load_env() -> TestResult {
run_test(r#"let x = "FOO"; load-env {$x: "BAZ"}; $env.FOO"#, "BAZ")
2022-02-04 21:19:13 +00:00
}
#[test]
fn reduce_spans() -> TestResult {
fail_test(
r#"let x = ([1, 2, 3] | reduce -f 0 { $it.item + 2 * $it.acc }); error make {msg: "oh that hurts", label: {text: "right here", start: (metadata $x).span.start, end: (metadata $x).span.end } }"#,
"right here",
)
}
2022-02-16 09:59:44 +00:00
#[test]
fn with_env_shorthand_nested_quotes() -> TestResult {
run_test(
r#"FOO='-arg "hello world"' echo $env | get FOO"#,
"-arg \"hello world\"",
)
}
#[test]
fn test_redirection_stderr() -> TestResult {
// try a nonsense binary
run_test(r#"do -i { asdjw4j5cnaabw44rd }; echo done"#, "done")
}
#[test]
fn datetime_literal() -> TestResult {
run_test(r#"(date now) - 2019-08-23 > 1hr"#, "true")
}
#[test]
fn shortcircuiting_and() -> TestResult {
Better errors when bash-like operators are used (#7241) # Description Adds improved errors for when a user uses a bashism that nu doesn't support. fixes #7237 Examples: ``` Error: nu::parser::shell_andand (link) × The '&&' operator is not supported in Nushell ╭─[entry #1:1:1] 1 │ ls && ls · ─┬ · ╰── instead of '&&', use ';' or 'and' ╰──── help: use ';' instead of the shell '&&', or 'and' instead of the boolean '&&' ``` ``` Error: nu::parser::shell_oror (link) × The '||' operator is not supported in Nushell ╭─[entry #8:1:1] 1 │ ls || ls · ─┬ · ╰── instead of '||', use 'try' or 'or' ╰──── help: use 'try' instead of the shell '||', or 'or' instead of the boolean '||' ``` ``` Error: nu::parser::shell_err (link) × The '2>' shell operation is 'err>' in Nushell. ╭─[entry #9:1:1] 1 │ foo 2> bar.txt · ─┬ · ╰── use 'err>' instead of '2>' in Nushell ╰──── ``` ``` Error: nu::parser::shell_outerr (link) × The '2>&1' shell operation is 'out+err>' in Nushell. ╭─[entry #10:1:1] 1 │ foo 2>&1 bar.txt · ──┬─ · ╰── use 'out+err>' instead of '2>&1' in Nushell ╰──── help: Nushell redirection will write all of stdout before stderr. ``` # User-Facing Changes **BREAKING CHANGES** This removes the `&&` and `||` operators. We previously supported by `&&`/`and` and `||`/`or`. With this change, only `and` and `or` are valid boolean operators. # 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.
2022-12-07 23:02:11 +00:00
run_test(r#"false and (5 / 0; false)"#, "false")
}
#[test]
fn shortcircuiting_or() -> TestResult {
Better errors when bash-like operators are used (#7241) # Description Adds improved errors for when a user uses a bashism that nu doesn't support. fixes #7237 Examples: ``` Error: nu::parser::shell_andand (link) × The '&&' operator is not supported in Nushell ╭─[entry #1:1:1] 1 │ ls && ls · ─┬ · ╰── instead of '&&', use ';' or 'and' ╰──── help: use ';' instead of the shell '&&', or 'and' instead of the boolean '&&' ``` ``` Error: nu::parser::shell_oror (link) × The '||' operator is not supported in Nushell ╭─[entry #8:1:1] 1 │ ls || ls · ─┬ · ╰── instead of '||', use 'try' or 'or' ╰──── help: use 'try' instead of the shell '||', or 'or' instead of the boolean '||' ``` ``` Error: nu::parser::shell_err (link) × The '2>' shell operation is 'err>' in Nushell. ╭─[entry #9:1:1] 1 │ foo 2> bar.txt · ─┬ · ╰── use 'err>' instead of '2>' in Nushell ╰──── ``` ``` Error: nu::parser::shell_outerr (link) × The '2>&1' shell operation is 'out+err>' in Nushell. ╭─[entry #10:1:1] 1 │ foo 2>&1 bar.txt · ──┬─ · ╰── use 'out+err>' instead of '2>&1' in Nushell ╰──── help: Nushell redirection will write all of stdout before stderr. ``` # User-Facing Changes **BREAKING CHANGES** This removes the `&&` and `||` operators. We previously supported by `&&`/`and` and `||`/`or`. With this change, only `and` and `or` are valid boolean operators. # 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.
2022-12-07 23:02:11 +00:00
run_test(r#"true or (5 / 0; false)"#, "true")
}
#[test]
fn nonshortcircuiting_xor() -> TestResult {
run_test(r#"true xor (print "hello"; false) | ignore"#, "hello")
}
#[test]
fn open_ended_range() -> TestResult {
run_test(r#"1.. | first 100000 | length"#, "100000")
}
2022-03-07 20:08:56 +00:00
#[test]
fn default_value1() -> TestResult {
run_test(r#"def foo [x = 3] { $x }; foo"#, "3")
}
#[test]
fn default_value2() -> TestResult {
run_test(r#"def foo [x: int = 3] { $x }; foo"#, "3")
}
#[test]
fn default_value3() -> TestResult {
run_test(r#"def foo [--x = 3] { $x }; foo"#, "3")
}
#[test]
fn default_value4() -> TestResult {
run_test(r#"def foo [--x: int = 3] { $x }; foo"#, "3")
}
#[test]
fn default_value5() -> TestResult {
run_test(r#"def foo [x = 3] { $x }; foo 10"#, "10")
}
#[test]
fn default_value6() -> TestResult {
run_test(r#"def foo [x: int = 3] { $x }; foo 10"#, "10")
}
#[test]
fn default_value7() -> TestResult {
run_test(r#"def foo [--x = 3] { $x }; foo --x 10"#, "10")
}
#[test]
fn default_value8() -> TestResult {
run_test(r#"def foo [--x: int = 3] { $x }; foo --x 10"#, "10")
}
#[test]
fn default_value9() -> TestResult {
fail_test(r#"def foo [--x = 3] { $x }; foo --x a"#, "expected int")
}
#[test]
fn default_value10() -> TestResult {
fail_test(r#"def foo [x = 3] { $x }; foo a"#, "expected int")
}
#[test]
fn default_value11() -> TestResult {
fail_test(
r#"def foo [x = 3, y] { $x }; foo a"#,
"after optional parameter",
)
}
#[test]
fn default_value12() -> TestResult {
fail_test(
r#"def foo [--x:int = "a"] { $x }"#,
allow records to have type annotations (#8914) # Description follow up to #8529 cleaned up version of #8892 - the original syntax is okay ```nu def okay [rec: record] {} ``` - you can now add type annotations for fields if you know them before hand ```nu def okay [rec: record<name: string>] {} ``` - you can specify multiple fields ```nu def okay [person: record<name: string age: int>] {} # an optional comma is allowed def okay [person: record<name: string, age: int>] {} ``` - if annotations are specified, any use of the command will be type checked against the specified type ```nu def unwrap [result: record<ok: bool, value: any>] {} unwrap {ok: 2, value: "value"} # errors with Error: nu::parser::type_mismatch × Type mismatch. ╭─[entry #4:1:1] 1 │ unwrap {ok: 2, value: "value"} · ───────┬───── · ╰── expected record<ok: bool, value: any>, found record<ok: int, value: string> ╰──── ``` > here the error is in the `ok` field, since `any` is coerced into any type > as a result `unwrap {ok: true, value: "value"}` is okay - the key must be a string, either quoted or unquoted ```nu def err [rec: record<{}: list>] {} # errors with Error: × `record` type annotations key not string ╭─[entry #7:1:1] 1 │ def unwrap [result: record<{}: bool, value: any>] {} · ─┬ · ╰── must be a string ╰──── ``` - a key doesn't have to have a type in which case it is assumed to be `any` ```nu def okay [person: record<name age>] {} def okay [person: record<name: string age>] {} ``` - however, if you put a colon, you have to specify a type ```nu def err [person: record<name: >] {} # errors with Error: nu::parser::parse_mismatch × Parse mismatch during operation. ╭─[entry #12:1:1] 1 │ def unwrap [res: record<name: >] { $res } · ┬ · ╰── expected type after colon ╰──── ``` # User-Facing Changes **[BREAKING CHANGES]** - this change adds a field to `SyntaxShape::Record` so any plugins that used it will have to update and include the field. though if you are unsure of the type the record expects, `SyntaxShape::Record(vec![])` will suffice
2023-04-26 13:16:55 +00:00
"expected default value to be `int`",
)
2022-03-07 20:08:56 +00:00
}
#[test]
fn default_value_constant1() -> TestResult {
run_test(r#"def foo [x = "foo"] { $x }; foo"#, "foo")
}
#[test]
fn default_value_constant2() -> TestResult {
run_test(r#"def foo [secs = 1sec] { $secs }; foo"#, "1sec")
}
#[test]
fn default_value_not_constant1() -> TestResult {
fail_test(
r#"def foo [x = ("foo" | str length)] { $x }; foo"#,
"expected a constant",
)
}
#[test]
fn default_value_not_constant2() -> TestResult {
fail_test(
r#"def foo [--x = ("foo" | str length)] { $x }; foo"#,
"expected a constant",
)
}
#[test]
fn loose_each() -> TestResult {
Restrict closure expression to be something like `{|| ...}` (#8290) # 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.
2023-03-17 12:36:28 +00:00
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(
Restrict closure expression to be something like `{|| ...}` (#8290) # 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.
2023-03-17 12:36:28 +00:00
r#"[3, 4, 5] | each {|| echo $"hi ($in)" } | str join"#,
"hi 3hi 4hi 5",
)
}
#[test]
fn reusable_in() -> TestResult {
run_test(
r#"[1, 2, 3, 4] | take (($in | length) - 1) | math sum"#,
"6",
)
}
#[test]
fn better_operator_spans() -> TestResult {
run_test(
r#"metadata ({foo: 10} | (20 - $in.foo)) | get span | $in.start < $in.end"#,
"true",
)
}
2022-04-26 18:39:38 +00:00
#[test]
fn range_right_exclusive() -> TestResult {
run_test(r#"[1, 4, 5, 8, 9] | range 1..<3 | math sum"#, "9")
}
/// Issue #7872
#[test]
fn assignment_to_in_var_no_panic() -> TestResult {
fail_test(r#"$in = 3"#, "needs to be a mutable variable")
}
#[test]
fn assignment_to_env_no_panic() -> TestResult {
fail_test(r#"$env = 3"#, "cannot_replace_env")
}
#[test]
fn short_flags() -> TestResult {
run_test(
r#"def foobar [-a: int, -b: string, -c: string] { echo $'($a) ($c) ($b)' }; foobar -b "balh balh" -a 1543 -c "FALSE123""#,
"1543 FALSE123 balh balh",
)
}
#[test]
fn short_flags_1() -> TestResult {
run_test(
r#"def foobar [-a: string, -b: string, -s: int] { if ( $s == 0 ) { echo $'($b)($a)' }}; foobar -a test -b case -s 0 "#,
"casetest",
)
}
#[test]
fn short_flags_2() -> TestResult {
run_test(
r#"def foobar [-a: int, -b: string, -c: int] { $a + $c };foobar -b "balh balh" -a 10 -c 1 "#,
"11",
)
}