Simplify expressions (#3389)

* WIP: experiment with simpler expressions

* fix simple invoke

* update tests

* fix a few tests

* Make paren parsing more robust

* fix external args

* Remove old invocation

* Update tests

* Update tests
This commit is contained in:
JT 2021-05-12 13:01:48 +12:00 committed by GitHub
parent c80a9585b0
commit 25a8caa9b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 181 additions and 364 deletions

View file

@ -81,11 +81,7 @@ ptree-support = ["nu-cli/ptree", "nu-command/ptree"]
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"] rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
term-support = ["nu-cli/term", "nu-command/term"] term-support = ["nu-cli/term", "nu-command/term"]
uuid-support = ["nu-cli/uuid_crate", "nu-command/uuid_crate"] uuid-support = ["nu-cli/uuid_crate", "nu-command/uuid_crate"]
which-support = [ which-support = ["nu-cli/which", "nu-command/which", "nu-engine/which"]
"nu-cli/which",
"nu-command/which",
"nu-engine/which",
]
default = [ default = [
"nu-cli/shadow-rs", "nu-cli/shadow-rs",

View file

@ -384,7 +384,7 @@ mod tests {
#[test] #[test]
fn completes_incomplete_nested_structure() { fn completes_incomplete_nested_structure() {
let registry: VecRegistry = vec![Signature::build("sys")].into(); let registry: VecRegistry = vec![Signature::build("sys")].into();
let line = "echo $(sy"; let line = "echo (sy";
assert_eq!( assert_eq!(
completion_location(line, &registry, 8), completion_location(line, &registry, 8),

View file

@ -145,7 +145,7 @@ fn requote(orig_value: String) -> String {
if should_quote { if should_quote {
if quotes.is_empty() { if quotes.is_empty() {
// TODO we don't really have an escape character, so there isn't a great option right // TODO we don't really have an escape character, so there isn't a great option right
// now. One possibility is `{{$(char backtick)}}` // now. One possibility is `{{(char backtick)}}`
value.to_string() value.to_string()
} else { } else {
let quote = quotes[0]; let quote = quotes[0];

View file

@ -44,7 +44,7 @@ impl WholeStreamCommand for Command {
}, },
Example { Example {
description: "Check that all values are even", description: "Check that all values are even",
example: "echo [2 4 6 8] | all? $(= $it mod 2) == 0", example: "echo [2 4 6 8] | all? ($it mod 2) == 0",
result: Some(vec![Value::from(true)]), result: Some(vec![Value::from(true)]),
}, },
] ]

View file

@ -69,7 +69,7 @@ following values:
https://en.wikipedia.org/wiki/ANSI_escape_code https://en.wikipedia.org/wiki/ANSI_escape_code
OSC: '\x1b]' is not required for --osc parameter OSC: '\x1b]' is not required for --osc parameter
Example: echo [$(ansi -o '0') 'some title' $(char bel)] | str collect Example: echo [(ansi -o '0') 'some title' (char bel)] | str collect
Format: # Format: #
0 Set window title and icon name 0 Set window title and icon name
1 Set icon name 1 Set icon name
@ -96,7 +96,7 @@ Format: #
Example { Example {
description: description:
"Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)", "Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)",
example: r#"echo [$(ansi rb) Hello " " $(ansi gb) Nu " " $(ansi pb) World] | str collect"#, example: r#"echo [(ansi rb) Hello " " (ansi gb) Nu " " (ansi pb) World] | str collect"#,
result: Some(vec![Value::from( result: Some(vec![Value::from(
"\u{1b}[1;31mHello \u{1b}[1;32mNu \u{1b}[1;35mWorld", "\u{1b}[1;31mHello \u{1b}[1;32mNu \u{1b}[1;35mWorld",
)]), )]),
@ -104,7 +104,7 @@ Format: #
Example { Example {
description: description:
"Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)", "Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)",
example: r#"echo [$(ansi -e '3;93;41m') Hello $(ansi reset) " " $(ansi gb) Nu " " $(ansi pb) World] | str collect"#, example: r#"echo [(ansi -e '3;93;41m') Hello (ansi reset) " " (ansi gb) Nu " " (ansi pb) World] | str collect"#,
result: Some(vec![Value::from( result: Some(vec![Value::from(
"\u{1b}[3;93;41mHello\u{1b}[0m \u{1b}[1;32mNu \u{1b}[1;35mWorld", "\u{1b}[3;93;41mHello\u{1b}[0m \u{1b}[1;32mNu \u{1b}[1;35mWorld",
)]), )]),
@ -299,7 +299,7 @@ pub fn str_to_ansi(s: &str) -> Option<String> {
// Reference for ansi codes https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 // Reference for ansi codes https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
// Another good reference http://ascii-table.com/ansi-escape-sequences.php // Another good reference http://ascii-table.com/ansi-escape-sequences.php
// For setting title like `echo [$(char title) $(pwd) $(char bel)] | str collect` // For setting title like `echo [(char title) (pwd) (char bel)] | str collect`
"title" => Some("\x1b]2;".to_string()), // ESC]2; xterm sets window title using OSC syntax escapes "title" => Some("\x1b]2;".to_string()), // ESC]2; xterm sets window title using OSC syntax escapes
// Ansi Erase Sequences // Ansi Erase Sequences

View file

@ -31,7 +31,7 @@ impl WholeStreamCommand for SubCommand {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "strip ansi escape sequences from string", description: "strip ansi escape sequences from string",
example: "echo [$(ansi gb) 'hello' $(ansi reset)] | str collect | ansi strip", example: "echo [(ansi gb) 'hello' (ansi reset)] | str collect | ansi strip",
result: None, result: None,
}] }]
} }

View file

@ -44,7 +44,7 @@ impl WholeStreamCommand for Command {
}, },
Example { Example {
description: "Check if any of the values is odd", description: "Check if any of the values is odd",
example: "echo [2 4 1 6 8] | any? $(= $it mod 2) == 1", example: "echo [2 4 1 6 8] | any? ($it mod 2) == 1",
result: Some(vec![Value::from(true)]), result: Some(vec![Value::from(true)]),
}, },
] ]

View file

@ -35,7 +35,7 @@ impl WholeStreamCommand for Char {
}, },
Example { Example {
description: "Output prompt character, newline and a hamburger character", description: "Output prompt character, newline and a hamburger character",
example: r#"echo $(char prompt) $(char newline) $(char hamburger)"#, example: r#"echo (char prompt) (char newline) (char hamburger)"#,
result: Some(vec![ result: Some(vec![
UntaggedValue::string("\u{25b6}").into(), UntaggedValue::string("\u{25b6}").into(),
UntaggedValue::string("\n").into(), UntaggedValue::string("\n").into(),

View file

@ -42,7 +42,7 @@ impl WholeStreamCommand for Each {
}, },
Example { Example {
description: "Echo the square of each integer", description: "Echo the square of each integer",
example: "echo [1 2 3] | each { echo $(= $it * $it) }", example: "echo [1 2 3] | each { echo ($it * $it) }",
result: Some(vec![ result: Some(vec![
UntaggedValue::int(1).into(), UntaggedValue::int(1).into(),
UntaggedValue::int(4).into(), UntaggedValue::int(4).into(),

View file

@ -63,7 +63,7 @@ impl WholeStreamCommand for Command {
), ),
},Example { },Example {
description: "use a block if setting the empty cell contents is wanted", description: "use a block if setting the empty cell contents is wanted",
example: "echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { = [33 37] }", example: "echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { [33 37] }",
result: Some( result: Some(
vec![ vec![
UntaggedValue::row(indexmap! { UntaggedValue::row(indexmap! {

View file

@ -39,12 +39,12 @@ impl WholeStreamCommand for Command {
}, },
Example { Example {
description: "flatten a column having a nested table", description: "flatten a column having a nested table",
example: "echo [[origin, people]; [Ecuador, $(echo [[name, meal]; ['Andres', 'arepa']])]] | flatten | get meal", example: "echo [[origin, people]; [Ecuador, (echo [[name, meal]; ['Andres', 'arepa']])]] | flatten | get meal",
result: Some(vec![Value::from("arepa")]), result: Some(vec![Value::from("arepa")]),
}, },
Example { Example {
description: "restrict the flattening by passing column names", description: "restrict the flattening by passing column names",
example: "echo [[origin, crate, versions]; [World, $(echo [[name]; ['nu-cli']]), ['0.21', '0.22']]] | flatten versions | last | get versions", example: "echo [[origin, crate, versions]; [World, (echo [[name]; ['nu-cli']]), ['0.21', '0.22']]] | flatten versions | last | get versions",
result: Some(vec![Value::from("0.22")]), result: Some(vec![Value::from("0.22")]),
} }
] ]

View file

@ -100,7 +100,7 @@ impl WholeStreamCommand for Command {
Example { Example {
description: description:
"use the block form to generate a grouping key when each row gets processed", "use the block form to generate a grouping key when each row gets processed",
example: "echo [1 3 1 3 2 1 1] | group-by { = ($it - 1) mod 3 }", example: "echo [1 3 1 3 2 1 1] | group-by { ($it - 1) mod 3 }",
result: Some(vec![UntaggedValue::row(indexmap! { result: Some(vec![UntaggedValue::row(indexmap! {
"0".to_string() => UntaggedValue::Table(vec![ "0".to_string() => UntaggedValue::Table(vec![
UntaggedValue::int(1).into(), UntaggedValue::int(1).into(),

View file

@ -51,7 +51,7 @@ impl WholeStreamCommand for Command {
.into()]), .into()]),
},Example { },Example {
description: "Use in block form for more involved insertion logic", description: "Use in block form for more involved insertion logic",
example: "echo [[author, lucky_number]; ['Yehuda', 4]] | insert success { = $it.lucky_number * 10 }", example: "echo [[author, lucky_number]; ['Yehuda', 4]] | insert success { $it.lucky_number * 10 }",
result: Some(vec![UntaggedValue::row(indexmap! { result: Some(vec![UntaggedValue::row(indexmap! {
"author".to_string() => Value::from("Yehuda"), "author".to_string() => Value::from("Yehuda"),
"lucky_number".to_string() => UntaggedValue::int(4).into(), "lucky_number".to_string() => UntaggedValue::int(4).into(),

View file

@ -67,7 +67,7 @@ On Windows, an extra 'prefix' column is added."#
}, },
Example { Example {
description: "Replace a complex extension", description: "Replace a complex extension",
example: r"echo 'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { = txt }", example: r"echo 'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
result: None, result: None,
}, },
Example { Example {
@ -93,7 +93,7 @@ On Windows, an extra 'prefix' column is added."#
}, },
Example { Example {
description: "Replace a complex extension", description: "Replace a complex extension",
example: r"echo '/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { = txt }", example: r"echo '/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
result: None, result: None,
}, },
Example { Example {

View file

@ -57,22 +57,22 @@ impl WholeStreamCommand for Reduce {
vec![ vec![
Example { Example {
description: "Simple summation (equivalent to math sum)", description: "Simple summation (equivalent to math sum)",
example: "echo 1 2 3 4 | reduce { = $acc + $it }", example: "echo 1 2 3 4 | reduce { $acc + $it }",
result: Some(vec![UntaggedValue::int(10).into()]), result: Some(vec![UntaggedValue::int(10).into()]),
}, },
Example { Example {
description: "Summation from starting value using fold", description: "Summation from starting value using fold",
example: "echo 1 2 3 4 | reduce -f $(= -1) { = $acc + $it }", example: "echo 1 2 3 4 | reduce -f (-1) { $acc + $it }",
result: Some(vec![UntaggedValue::int(9).into()]), result: Some(vec![UntaggedValue::int(9).into()]),
}, },
Example { Example {
description: "Folding with rows", description: "Folding with rows",
example: "<table> | reduce -f 1.6 { = $acc * $(echo $it.a | str to-int) + $(echo $it.b | str to-int) }", example: "<table> | reduce -f 1.6 { $acc * (echo $it.a | str to-int) + (echo $it.b | str to-int) }",
result: None, result: None,
}, },
Example { Example {
description: "Numbered reduce to find index of longest word", description: "Numbered reduce to find index of longest word",
example: "echo one longest three bar | reduce -n { if $(echo $it.item | str length) > $(echo $acc.item | str length) {echo $it} {echo $acc}} | get index", example: "echo one longest three bar | reduce -n { if ($it.item | str length) > ($acc.item | str length) {echo $it} {echo $acc}} | get index",
result: None, result: None,
}, },
] ]

View file

@ -69,7 +69,7 @@ impl WholeStreamCommand for Command {
}, },
Example { Example {
description: "Treat each row as a markdown element", description: "Treat each row as a markdown element",
example: "echo [[H1]; [\"Welcome to Nushell\"]] | append $(ls | first 2) | to md --per-element --pretty", example: "echo [[H1]; [\"Welcome to Nushell\"]] | append (ls | first 2) | to md --per-element --pretty",
result: Some(vec![Value::from(one(r#" result: Some(vec![Value::from(one(r#"
# Welcome to Nushell # Welcome to Nushell
| name | type | chickens | modified | | name | type | chickens | modified |

View file

@ -10,7 +10,7 @@ fn filesystem_change_from_current_directory_using_relative_path() {
cwd: dirs.root(), cwd: dirs.root(),
r#" r#"
cd cd_test_1 cd cd_test_1
echo $(pwd) echo (pwd)
"# "#
); );
@ -25,7 +25,7 @@ fn filesystem_change_from_current_directory_using_absolute_path() {
cwd: dirs.test(), cwd: dirs.test(),
r#" r#"
cd "{}" cd "{}"
echo $(pwd) echo (pwd)
"#, "#,
dirs.formats() dirs.formats()
); );
@ -44,7 +44,7 @@ fn filesystem_switch_back_to_previous_working_directory() {
r#" r#"
cd {} cd {}
cd - cd -
echo $(pwd) echo (pwd)
"#, "#,
dirs.test() dirs.test()
); );
@ -62,7 +62,7 @@ fn filesytem_change_from_current_directory_using_relative_path_and_dash() {
cwd: dirs.test(), cwd: dirs.test(),
r#" r#"
cd odin/- cd odin/-
echo $(pwd) echo (pwd)
"# "#
); );
@ -80,7 +80,7 @@ fn filesystem_change_current_directory_to_parent_directory() {
cwd: dirs.test(), cwd: dirs.test(),
r#" r#"
cd .. cd ..
echo $(pwd) echo (pwd)
"# "#
); );
@ -97,7 +97,7 @@ fn filesystem_change_current_directory_to_two_parents_up_using_multiple_dots() {
cwd: dirs.test().join("foo/bar"), cwd: dirs.test().join("foo/bar"),
r#" r#"
cd ... cd ...
echo $(pwd) echo (pwd)
"# "#
); );
@ -116,7 +116,7 @@ fn filesystem_change_current_directory_to_parent_directory_after_delete_cwd() {
rm {}/foo/bar rm {}/foo/bar
echo "," echo ","
cd .. cd ..
echo $(pwd) echo (pwd)
"#, "#,
dirs.test() dirs.test()
); );
@ -135,7 +135,7 @@ fn filesystem_change_to_home_directory() {
cwd: dirs.test(), cwd: dirs.test(),
r#" r#"
cd ~ cd ~
echo $(pwd) echo (pwd)
"# "#
); );
@ -152,7 +152,7 @@ fn filesystem_change_to_a_directory_containing_spaces() {
cwd: dirs.test(), cwd: dirs.test(),
r#" r#"
cd "robalino turner katz" cd "robalino turner katz"
echo $(pwd) echo (pwd)
"# "#
); );
@ -219,7 +219,7 @@ fn filesystem_change_directory_to_symlink_relative() {
cwd: dirs.test().join("boo"), cwd: dirs.test().join("boo"),
r#" r#"
cd ../foo_link cd ../foo_link
echo $(pwd) echo (pwd)
"# "#
); );

View file

@ -17,7 +17,7 @@ fn each_group_works() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
echo [1 2 3 4 5 6] | each group 3 { echo $it } | to json echo [1 2 3 4 5 6] | each group 3 { $it } | to json
"# "#
)); ));
@ -29,7 +29,7 @@ fn each_window() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
echo [1 2 3 4] | each window 3 { echo $it } | to json echo [1 2 3 4] | each window 3 { $it } | to json
"# "#
)); ));

View file

@ -6,9 +6,9 @@ fn reports_emptiness() {
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo [[are_empty]; echo [[are_empty];
[$(= [[check]; [[]] ])] [([[check]; [[]] ])]
[$(= [[check]; [""] ])] [([[check]; [""] ])]
[$(= [[check]; [$(wrap)] ])] [([[check]; [(wrap)] ])]
] ]
| get are_empty | get are_empty
| empty? check | empty? check
@ -32,7 +32,7 @@ fn sets_block_run_value_for_an_empty_column() {
[ Jason, Gedge, 10/11/2013, 1 ] [ Jason, Gedge, 10/11/2013, 1 ]
[ Yehuda, Katz, 10/11/2013, '' ] [ Yehuda, Katz, 10/11/2013, '' ]
] ]
| empty? likes { = 1 } | empty? likes { 1 }
| get likes | get likes
| math sum | math sum
"# "#
@ -50,9 +50,9 @@ fn sets_block_run_value_for_many_empty_columns() {
[ boost check ]; [ boost check ];
[ 1, [] ] [ 1, [] ]
[ 1, "" ] [ 1, "" ]
[ 1, $(wrap) ] [ 1, (wrap) ]
] ]
| empty? boost check { = 1 } | empty? boost check { 1 }
| get boost check | get boost check
| math sum | math sum
"# "#
@ -73,9 +73,9 @@ fn passing_a_block_will_set_contents_on_empty_cells_and_leave_non_empty_ones_unt
[ Arepas, "", "" ] [ Arepas, "", "" ]
[ Jorge, 30, 3000 ] [ Jorge, 30, 3000 ]
] ]
| empty? LVL { = 9 } | empty? LVL { 9 }
| empty? HP { | empty? HP {
= $it.LVL * 1000 $it.LVL * 1000
} }
| math sum | math sum
| get HP | get HP

View file

@ -7,8 +7,8 @@ fn flatten_nested_tables_with_columns() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo [[origin, people]; [Ecuador, $(= 'Andres' | wrap name)]] echo [[origin, people]; [Ecuador, ('Andres' | wrap name)]]
[[origin, people]; [Nu, $(= 'nuno' | wrap name)]] [[origin, people]; [Nu, ('nuno' | wrap name)]]
| flatten | flatten
| get name | get name
| str collect ',' | str collect ','
@ -23,8 +23,8 @@ fn flatten_nested_tables_that_have_many_columns() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo [[origin, people]; [Ecuador, $(echo [[name, meal]; ['Andres', 'arepa']])]] echo [[origin, people]; [Ecuador, (echo [[name, meal]; ['Andres', 'arepa']])]]
[[origin, people]; [USA, $(echo [[name, meal]; ['Katz', 'nurepa']])]] [[origin, people]; [USA, (echo [[name, meal]; ['Katz', 'nurepa']])]]
| flatten | flatten
| get meal | get meal
| str collect ',' | str collect ','

View file

@ -35,7 +35,7 @@ fn sets_the_column_from_an_invocation() {
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
wrap content wrap content
| insert content $(open --raw cargo_sample.toml | lines | first 5) | insert content (open --raw cargo_sample.toml | lines | first 5)
| get content.1 | get content.1
| str contains "nu" | str contains "nu"
"# "#

View file

@ -5,7 +5,7 @@ fn into_int_filesize() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo 1kb | into int | each {= $it / 1000 } echo 1kb | into int | each { $it / 1000 }
"# "#
)); ));
@ -17,7 +17,7 @@ fn into_int_filesize2() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo 1kib | into int | each {= $it / 1024 } echo 1kib | into int | each { $it / 1024 }
"# "#
)); ));
@ -29,7 +29,7 @@ fn into_int_int() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo 1024 | into int | each {= $it / 1024 } echo 1024 | into int | each { $it / 1024 }
"# "#
)); ));

View file

@ -12,7 +12,7 @@ fn one_arg() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 1
"# "#
)); ));
@ -24,7 +24,7 @@ fn add() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 + 1 1 + 1
"# "#
)); ));
@ -36,7 +36,7 @@ fn add_compound() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 + 2 + 2 1 + 2 + 2
"# "#
)); ));
@ -48,7 +48,7 @@ fn precedence_of_operators() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 + 2 * 2 1 + 2 * 2
"# "#
)); ));
@ -60,7 +60,7 @@ fn precedence_of_operators2() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 + 2 * 2 + 1 1 + 2 * 2 + 1
"# "#
)); ));
@ -72,7 +72,7 @@ fn division_of_ints() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 4 / 2 4 / 2
"# "#
)); ));
@ -84,7 +84,7 @@ fn division_of_ints2() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 / 4 1 / 4
"# "#
)); ));
@ -96,7 +96,7 @@ fn error_zero_division_int_int() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 / 0 1 / 0
"# "#
)); ));
@ -108,7 +108,7 @@ fn error_zero_division_decimal_int() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1.0 / 0 1.0 / 0
"# "#
)); ));
@ -120,7 +120,7 @@ fn error_zero_division_int_decimal() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1 / 0.0 1 / 0.0
"# "#
)); ));
@ -132,7 +132,7 @@ fn error_zero_division_decimal_decimal() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1.0 / 0.0 1.0 / 0.0
"# "#
)); ));
@ -144,7 +144,7 @@ fn proper_precedence_history() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 2 / 2 / 2 + 1 2 / 2 / 2 + 1
"# "#
)); ));
@ -156,7 +156,7 @@ fn parens_precedence() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 4 * (6 - 3) 4 * (6 - 3)
"# "#
)); ));
@ -168,7 +168,7 @@ fn modulo() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 9 mod 2 9 mod 2
"# "#
)); ));
@ -180,7 +180,7 @@ fn duration_math() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1wk + 1day 1wk + 1day
"# "#
)); ));
@ -192,7 +192,7 @@ fn duration_decimal_math() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 5.5day + 0.5day 5.5day + 0.5day
"# "#
)); ));
@ -204,7 +204,7 @@ fn duration_math_with_nanoseconds() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1wk + 10ns 1wk + 10ns
"# "#
)); ));
@ -216,7 +216,7 @@ fn duration_decimal_math_with_nanoseconds() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1.5wk + 10ns 1.5wk + 10ns
"# "#
)); ));
@ -228,7 +228,7 @@ fn duration_math_with_negative() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 1day - 1wk 1day - 1wk
"# "#
)); ));
@ -240,7 +240,7 @@ fn compound_comparison() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 4 > 3 && 2 > 1 4 > 3 && 2 > 1
"# "#
)); ));
@ -252,7 +252,7 @@ fn compound_comparison2() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
= 4 < 3 || 2 > 1 4 < 3 || 2 > 1
"# "#
)); ));
@ -276,7 +276,7 @@ fn compound_where_paren() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where (a == 2 && b == 1) || b == 2 | to json echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where ($it.a == 2 && $it.b == 1) || $it.b == 2 | to json
"# "#
)); ));

View file

@ -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}]" echo "[{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}]"
| from json | from json
| get total | get total
| reduce -f 20 { = $it + $( math eval `{{$acc}}^1.05` )} | reduce -f 20 { $it + ( math eval `{{$acc}}^1.05` )}
| str from -d 1 | str from -d 1
"# "#
) )
@ -21,7 +21,7 @@ fn reduce_table_column() {
r#" r#"
echo "[{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}]" echo "[{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}]"
| from json | from json
| reduce -f 20 { = $it.total + $( math eval `{{$acc}}^1.05` )} | reduce -f 20 { $it.total + ( math eval `{{$acc}}^1.05` )}
| str from -d 1 | str from -d 1
"# "#
) )
@ -38,7 +38,7 @@ fn reduce_rows_example() {
echo a,b 1,2 3,4 echo a,b 1,2 3,4
| split column , | split column ,
| headers | headers
| reduce -f 1.6 { = $acc * $(echo $it.a | str to-int) + $(echo $it.b | str to-int) } | reduce -f 1.6 { $acc * ($it.a | str to-int) + ($it.b | str to-int) }
"# "#
) )
); );
@ -52,7 +52,7 @@ fn reduce_numbered_example() {
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo one longest three bar echo one longest three bar
| reduce -n { if $(echo $it.item | str length) > $(echo $acc.item | str length) {echo $it} {echo $acc}} | reduce -n { if ($it.item | str length) > ($acc.item | str length) {echo $it} {echo $acc}}
| get index | get index
"# "#
) )
@ -67,7 +67,7 @@ fn reduce_numbered_integer_addition_example() {
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo [1 2 3 4] echo [1 2 3 4]
| reduce -n {= $acc.item + $it.item } | reduce -n { $acc.item + $it.item }
| get item | get item
"# "#
) )
@ -84,7 +84,7 @@ fn folding_with_tables() {
echo [10 20 30 40] echo [10 20 30 40]
| reduce -f [] { | reduce -f [] {
with-env [value $it] { with-env [value $it] {
echo $acc | append $(= 10 * $(= $nu.env.value | str to-int)) echo $acc | append (10 * ($nu.env.value | str to-int))
} }
} }
| math sum | math sum
@ -100,7 +100,7 @@ fn error_reduce_fold_type_mismatch() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
echo a b c | reduce -f 0 { = $acc + $it } echo a b c | reduce -f 0 { $acc + $it }
"# "#
) )
); );
@ -113,7 +113,7 @@ fn error_reduce_empty() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
reduce { = $acc + $it } reduce { $acc + $it }
"# "#
) )
); );

View file

@ -136,7 +136,7 @@ mod columns {
| get bit | get bit
| reverse | reverse
| each --numbered { | each --numbered {
= $it.item * (2 ** $it.index) $it.item * (2 ** $it.index)
} }
| math sum | math sum
"#, "#,

View file

@ -50,7 +50,7 @@ fn sets_the_column_from_an_invocation() {
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
wrap content wrap content
| update content $(open --raw cargo_sample.toml | lines | first 5) | update content (open --raw cargo_sample.toml | lines | first 5)
| get content.1 | get content.1
| str contains "nu" | str contains "nu"
"# "#

View file

@ -86,7 +86,7 @@ fn md_combined() {
}; };
title title
| append $(meals) | append (meals)
| to md --per-element --pretty | to md --per-element --pretty
"# "#
)); ));

View file

@ -293,6 +293,11 @@ pub fn compute_values(
Ok(UntaggedValue::Primitive(Primitive::Duration(result))) Ok(UntaggedValue::Primitive(Primitive::Duration(result)))
} }
(Primitive::String(x), Primitive::String(y)) => {
let mut new_string = x.clone();
new_string.push_str(y);
Ok(UntaggedValue::Primitive(Primitive::String(new_string)))
}
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),
}, },
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),

View file

@ -5,6 +5,7 @@ use log::{log_enabled, trace};
use crate::evaluation_context::EvaluationContext; use crate::evaluation_context::EvaluationContext;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::hir::SpannedExpression; use nu_protocol::hir::SpannedExpression;
use nu_protocol::{UntaggedValue, Value};
use nu_stream::{InputStream, ToInputStream}; use nu_stream::{InputStream, ToInputStream};
pub(crate) fn run_expression_block( pub(crate) fn run_expression_block(
@ -18,5 +19,11 @@ pub(crate) fn run_expression_block(
let output = evaluate_baseline_expr(expr, ctx)?; let output = evaluate_baseline_expr(expr, ctx)?;
Ok(std::iter::once(Ok(output)).to_input_stream()) match output {
Value {
value: UntaggedValue::Table(x),
..
} => Ok(InputStream::from_stream(x.into_iter())),
output => Ok(std::iter::once(Ok(output)).to_input_stream()),
}
} }

View file

@ -6,7 +6,7 @@ fn test_parse_invocation_with_range() {
cwd: ".", cwd: ".",
r#" r#"
let foo = 3 let foo = 3
echo $(echo 1..$foo | each { echo $it }) | to json echo (echo 1..$foo | each { $it }) | to json
"# "#
); );
assert_eq!(actual.out, "[1,2,3]") assert_eq!(actual.out, "[1,2,3]")

View file

@ -1,5 +1,6 @@
use std::{path::Path, sync::Arc}; use std::{path::Path, sync::Arc};
use bigdecimal::BigDecimal;
use indexmap::IndexMap; use indexmap::IndexMap;
use log::trace; use log::trace;
use nu_errors::{ArgumentError, ParseError}; use nu_errors::{ArgumentError, ParseError};
@ -12,11 +13,12 @@ use nu_protocol::{NamedType, PositionalType, Signature, SyntaxShape, UnspannedPa
use nu_source::{HasSpan, Span, Spanned, SpannedItem}; use nu_source::{HasSpan, Span, Spanned, SpannedItem};
use num_bigint::BigInt; use num_bigint::BigInt;
use crate::lex::lexer::{lex, parse_block};
use crate::lex::tokens::{LiteBlock, LiteCommand, LitePipeline}; use crate::lex::tokens::{LiteBlock, LiteCommand, LitePipeline};
use crate::path::expand_path; use crate::path::expand_path;
use crate::scope::ParserScope; use crate::{
use bigdecimal::BigDecimal; lex::lexer::{lex, parse_block},
ParserScope,
};
use self::{ use self::{
def::{parse_definition, parse_definition_prototype}, def::{parse_definition, parse_definition_prototype},
@ -94,8 +96,7 @@ pub fn parse_full_column_path(
lite_arg: &Spanned<String>, lite_arg: &Spanned<String>,
scope: &dyn ParserScope, scope: &dyn ParserScope,
) -> (SpannedExpression, Option<ParseError>) { ) -> (SpannedExpression, Option<ParseError>) {
let mut delimiter = '.'; let mut inside_delimiter = vec![];
let mut inside_delimiter = false;
let mut output = vec![]; let mut output = vec![];
let mut current_part = String::new(); let mut current_part = String::new();
let mut start_index = 0; let mut start_index = 0;
@ -106,23 +107,21 @@ pub fn parse_full_column_path(
for (idx, c) in lite_arg.item.char_indices() { for (idx, c) in lite_arg.item.char_indices() {
last_index = idx; last_index = idx;
if inside_delimiter { if c == '(' {
if c == delimiter { inside_delimiter.push(')');
inside_delimiter = false; } else if let Some(delimiter) = inside_delimiter.last() {
if c == *delimiter {
inside_delimiter.pop();
} }
} else if c == '(' {
inside_delimiter = true;
delimiter = ')';
} else if c == '\'' || c == '"' { } else if c == '\'' || c == '"' {
inside_delimiter = true; inside_delimiter.push(c);
delimiter = c;
} else if c == '.' { } else if c == '.' {
let part_span = Span::new( let part_span = Span::new(
lite_arg.span.start() + start_index, lite_arg.span.start() + start_index,
lite_arg.span.start() + idx, lite_arg.span.start() + idx,
); );
if head.is_none() && current_part.starts_with("$(") && current_part.ends_with(')') { if head.is_none() && current_part.starts_with('(') && current_part.ends_with(')') {
let (invoc, err) = let (invoc, err) =
parse_invocation(&current_part.clone().spanned(part_span), scope); parse_invocation(&current_part.clone().spanned(part_span), scope);
if error.is_none() { if error.is_none() {
@ -158,7 +157,7 @@ pub fn parse_full_column_path(
); );
if head.is_none() { if head.is_none() {
if current_part.starts_with("$(") && current_part.ends_with(')') { if current_part.starts_with('(') && current_part.ends_with(')') {
let (invoc, err) = parse_invocation(&current_part.spanned(part_span), scope); let (invoc, err) = parse_invocation(&current_part.spanned(part_span), scope);
if error.is_none() { if error.is_none() {
error = err; error = err;
@ -419,12 +418,12 @@ fn parse_invocation(
let string: String = lite_arg let string: String = lite_arg
.item .item
.chars() .chars()
.skip(2) .skip(1)
.take(lite_arg.item.chars().count() - 3) .take(lite_arg.item.chars().count() - 2)
.collect(); .collect();
// We haven't done much with the inner string, so let's go ahead and work with it // We haven't done much with the inner string, so let's go ahead and work with it
let (tokens, err) = lex(&string, lite_arg.span.start() + 2); let (tokens, err) = lex(&string, lite_arg.span.start() + 1);
if err.is_some() { if err.is_some() {
return (garbage(lite_arg.span), err); return (garbage(lite_arg.span), err);
}; };
@ -468,21 +467,7 @@ fn parse_dollar_expr(
scope: &dyn ParserScope, scope: &dyn ParserScope,
) -> (SpannedExpression, Option<ParseError>) { ) -> (SpannedExpression, Option<ParseError>) {
trace!("Parsing dollar expression: {:?}", lite_arg.item); trace!("Parsing dollar expression: {:?}", lite_arg.item);
if lite_arg.item == "$true" { if let (expr, None) = parse_range(lite_arg, scope) {
(
SpannedExpression::new(Expression::boolean(true), lite_arg.span),
None,
)
} else if lite_arg.item == "$false" {
(
SpannedExpression::new(Expression::boolean(false), lite_arg.span),
None,
)
} else if lite_arg.item.ends_with(')') {
//Return invocation
trace!("Parsing invocation expression");
parse_invocation(lite_arg, scope)
} else if let (expr, None) = parse_range(lite_arg, scope) {
(expr, None) (expr, None)
} else if let (expr, None) = parse_full_column_path(lite_arg, scope) { } else if let (expr, None) = parse_full_column_path(lite_arg, scope) {
(expr, None) (expr, None)
@ -661,10 +646,13 @@ fn parse_external_arg(
scope: &dyn ParserScope, scope: &dyn ParserScope,
) -> (SpannedExpression, Option<ParseError>) { ) -> (SpannedExpression, Option<ParseError>) {
if lite_arg.item.starts_with('$') { if lite_arg.item.starts_with('$') {
return parse_dollar_expr(&lite_arg, scope); parse_dollar_expr(&lite_arg, scope)
} } else if lite_arg.item.starts_with('(') {
parse_invocation(&lite_arg, scope)
if lite_arg.item.starts_with('`') && lite_arg.item.len() > 1 && lite_arg.item.ends_with('`') { } else if lite_arg.item.starts_with('`')
&& lite_arg.item.len() > 1
&& lite_arg.item.ends_with('`')
{
// This is an interpolated string // This is an interpolated string
parse_interpolated_string(&lite_arg, scope) parse_interpolated_string(&lite_arg, scope)
} else { } else {
@ -772,65 +760,6 @@ fn parse_table(
) )
} }
/// Tries to parse a number in a paranthesis, e.g., (123) or (-123)
fn try_parse_number_in_paranthesis(
lite_arg: &Spanned<String>,
) -> (SpannedExpression, Option<ParseError>) {
let mut chars = lite_arg.item.chars();
match (chars.next(), chars.next_back()) {
(Some('('), Some(')')) => {
match chars.as_str().trim().parse::<BigInt>() {
Ok(parsed_integer) => (
SpannedExpression::new(Expression::integer(parsed_integer), lite_arg.span),
None,
),
// we don't care if it does not manage to parse it, because then likely it is not a number
Err(_) => {
match chars.as_str().trim().parse::<BigDecimal>() {
Ok(parsed_decimal) => (
SpannedExpression::new(
Expression::decimal(parsed_decimal),
lite_arg.span,
),
None,
),
// we don't care if it does not manage to parse it, because then likely it is not a number
Err(_) => (
garbage(lite_arg.span),
Some(ParseError::mismatch(
"cannot parse number",
lite_arg.clone(),
)),
),
}
}
}
}
(Some('('), _) => (
garbage(lite_arg.span),
Some(ParseError::mismatch(
"missing closing bracket",
lite_arg.clone(),
)),
),
(_, Some(')')) => (
garbage(lite_arg.span),
Some(ParseError::mismatch(
"missing starting bracket",
lite_arg.clone(),
)),
),
(_, _) => (
garbage(lite_arg.span),
Some(ParseError::mismatch(
"number in paranthesis",
lite_arg.clone(),
)),
),
}
}
/// Parses the given argument using the shape as a guide for how to correctly parse the argument /// Parses the given argument using the shape as a guide for how to correctly parse the argument
fn parse_arg( fn parse_arg(
expected_type: SyntaxShape, expected_type: SyntaxShape,
@ -843,7 +772,7 @@ fn parse_arg(
// before anything else, try to see if this is a number in paranthesis // before anything else, try to see if this is a number in paranthesis
if lite_arg.item.starts_with('(') { if lite_arg.item.starts_with('(') {
let (expr, err) = try_parse_number_in_paranthesis(lite_arg); let (expr, err) = parse_full_column_path(&lite_arg, scope);
if err.is_none() { if err.is_none() {
return (expr, None); return (expr, None);
} }
@ -1117,69 +1046,15 @@ fn shorthand_reparse(
} }
} }
fn parse_parenthesized_expression(
lite_arg: &Spanned<String>,
scope: &dyn ParserScope,
shorthand_mode: bool,
) -> (SpannedExpression, Option<ParseError>) {
let mut chars = lite_arg.item.chars();
match (chars.next(), chars.next_back()) {
(Some('('), Some(')')) => {
// We have a literal row
let string: String = chars.collect();
// We haven't done much with the inner string, so let's go ahead and work with it
let (tokens, err) = lex(&string, lite_arg.span.start() + 1);
if err.is_some() {
return (garbage(lite_arg.span), err);
}
let (lite_block, err) = parse_block(tokens);
if err.is_some() {
return (garbage(lite_arg.span), err);
}
if lite_block.block.len() != 1 {
return (
garbage(lite_arg.span),
Some(ParseError::mismatch("math expression", lite_arg.clone())),
);
}
let mut lite_pipeline = lite_block.block[0].clone();
let mut collection = vec![];
for lite_pipeline in lite_pipeline.pipelines.iter_mut() {
for lite_cmd in lite_pipeline.commands.iter_mut() {
collection.append(&mut lite_cmd.parts);
}
}
let (_, expr, err) = parse_math_expression(0, &collection[..], scope, shorthand_mode);
(expr, err)
}
_ => (
garbage(lite_arg.span),
Some(ParseError::mismatch("table", lite_arg.clone())),
),
}
}
fn parse_possibly_parenthesized( fn parse_possibly_parenthesized(
lite_arg: &Spanned<String>, lite_arg: &Spanned<String>,
scope: &dyn ParserScope, scope: &dyn ParserScope,
shorthand_mode: bool,
) -> ( ) -> (
(Option<Spanned<String>>, SpannedExpression), (Option<Spanned<String>>, SpannedExpression),
Option<ParseError>, Option<ParseError>,
) { ) {
if lite_arg.item.starts_with('(') {
let (lhs, err) = parse_parenthesized_expression(lite_arg, scope, shorthand_mode);
((None, lhs), err)
} else {
let (lhs, err) = parse_arg(SyntaxShape::Any, scope, lite_arg); let (lhs, err) = parse_arg(SyntaxShape::Any, scope, lite_arg);
((Some(lite_arg.clone()), lhs), err) ((Some(lite_arg.clone()), lhs), err)
}
} }
/// Handle parsing math expressions, complete with working with the precedence of the operators /// Handle parsing math expressions, complete with working with the precedence of the operators
@ -1200,8 +1075,7 @@ pub fn parse_math_expression(
let mut working_exprs = vec![]; let mut working_exprs = vec![];
let mut prec = vec![]; let mut prec = vec![];
let (lhs_working_expr, err) = let (lhs_working_expr, err) = parse_possibly_parenthesized(&lite_args[idx], scope);
parse_possibly_parenthesized(&lite_args[idx], scope, shorthand_mode);
if error.is_none() { if error.is_none() {
error = err; error = err;
@ -1239,8 +1113,7 @@ pub fn parse_math_expression(
prec prec
); );
let (rhs_working_expr, err) = let (rhs_working_expr, err) = parse_possibly_parenthesized(&lite_args[idx], scope);
parse_possibly_parenthesized(&lite_args[idx], scope, shorthand_mode);
if error.is_none() { if error.is_none() {
error = err; error = err;
@ -1740,22 +1613,32 @@ fn parse_call(
})), })),
error, error,
); );
} else if lite_cmd.parts[0].item.starts_with('$') || lite_cmd.parts[0].item.starts_with('{') { // } else if lite_cmd.parts[0].item.starts_with('(') {
// let (expr, err) = parse_simple_invocation(&lite_cmd.parts[0], scope);
// error = error.or(err);
// return (Some(ClassifiedCommand::Expr(Box::new(expr))), error);
} else if lite_cmd.parts[0].item.starts_with('{') {
return parse_value_call(lite_cmd, scope); return parse_value_call(lite_cmd, scope);
} else if lite_cmd.parts[0].item == "=" { } else if lite_cmd.parts[0].item.starts_with('$')
let expr = if lite_cmd.parts.len() > 1 { || lite_cmd.parts[0].item.starts_with('\"')
let (_, expr, err) = parse_math_expression(0, &lite_cmd.parts[1..], scope, false); || lite_cmd.parts[0].item.starts_with('\'')
|| lite_cmd.parts[0].item.starts_with('`')
|| lite_cmd.parts[0].item.starts_with('-')
|| lite_cmd.parts[0].item.starts_with('0')
|| lite_cmd.parts[0].item.starts_with('1')
|| lite_cmd.parts[0].item.starts_with('2')
|| lite_cmd.parts[0].item.starts_with('3')
|| lite_cmd.parts[0].item.starts_with('4')
|| lite_cmd.parts[0].item.starts_with('5')
|| lite_cmd.parts[0].item.starts_with('6')
|| lite_cmd.parts[0].item.starts_with('7')
|| lite_cmd.parts[0].item.starts_with('8')
|| lite_cmd.parts[0].item.starts_with('9')
|| lite_cmd.parts[0].item.starts_with('[')
|| lite_cmd.parts[0].item.starts_with('(')
{
let (_, expr, err) = parse_math_expression(0, &lite_cmd.parts[..], scope, false);
error = error.or(err); error = error.or(err);
expr
} else {
error = error.or_else(|| {
Some(ParseError::argument_error(
lite_cmd.parts[0].clone(),
ArgumentError::MissingMandatoryPositional("an expression".into()),
))
});
garbage(lite_cmd.span())
};
return (Some(ClassifiedCommand::Expr(Box::new(expr))), error); return (Some(ClassifiedCommand::Expr(Box::new(expr))), error);
} else if lite_cmd.parts[0].item == "alias" { } else if lite_cmd.parts[0].item == "alias" {
let error = parse_alias(&lite_cmd, scope); let error = parse_alias(&lite_cmd, scope);
@ -1925,77 +1808,6 @@ fn expand_shorthand_forms(
} }
} }
// pub fn parse_block(lite_block: &LiteBlock, scope: &dyn ParserScope) -> ClassifiedBlock {
// let mut block = vec![];
// let mut error = None;
// for lite_group in &lite_block.block {
// let mut command_list = vec![];
// for lite_pipeline in &lite_group.pipelines {
// let (lite_pipeline, vars, err) = expand_shorthand_forms(lite_pipeline);
// if error.is_none() {
// error = err;
// }
// let (pipeline, err) = parse_pipeline(&lite_pipeline, scope);
// let pipeline = if let Some(vars) = vars {
// let span = pipeline.commands.span;
// let group = Group::new(vec![pipeline.commands.clone()], span);
// let block = hir::Block::new(vec![], vec![group], span);
// let mut call = hir::Call::new(
// Box::new(SpannedExpression {
// expr: Expression::string("with-env".to_string()),
// span,
// }),
// span,
// );
// call.positional = Some(vec![
// SpannedExpression {
// expr: Expression::List(vec![
// SpannedExpression {
// expr: Expression::string(vars.0.item),
// span: vars.0.span,
// },
// SpannedExpression {
// expr: Expression::string(vars.1.item),
// span: vars.1.span,
// },
// ]),
// span: Span::new(vars.0.span.start(), vars.1.span.end()),
// },
// SpannedExpression {
// expr: Expression::Block(block),
// span,
// },
// ]);
// let classified_with_env = ClassifiedCommand::Internal(InternalCommand {
// name: "with-env".to_string(),
// name_span: Span::unknown(),
// args: call,
// });
// ClassifiedPipeline {
// commands: Pipeline {
// list: vec![classified_with_env],
// span,
// },
// }
// } else {
// pipeline
// };
// command_list.push(pipeline.commands);
// if error.is_none() {
// error = err;
// }
// }
// let group = Group::new(command_list, lite_block.span());
// block.push(group);
// }
// let block = Block::new(vec![], block, lite_block.span());
// ClassifiedBlock::new(block, error)
// }
fn parse_alias(call: &LiteCommand, scope: &dyn ParserScope) -> Option<ParseError> { fn parse_alias(call: &LiteCommand, scope: &dyn ParserScope) -> Option<ParseError> {
if call.parts.len() < 4 { if call.parts.len() < 4 {
return Some(ParseError::mismatch("alias", call.parts[0].clone())); return Some(ParseError::mismatch("alias", call.parts[0].clone()));

View file

@ -1,8 +1,5 @@
[package] [package]
authors = [ authors = ["Andrei Volnin <wolandr@gmail.com>", "The Nu Project Contributors"]
"Andrei Volnin <wolandr@gmail.com>",
"The Nu Project Contributors"
]
description = "Pretty hex dump of bytes slice in the common style." description = "Pretty hex dump of bytes slice in the common style."
edition = "2018" edition = "2018"
license = "MIT" license = "MIT"

View file

@ -48,7 +48,7 @@ Some text
The style used by `textview` can be configured in `config.toml`. The style used by `textview` can be configured in `config.toml`.
```shell ```shell
> open --raw $(which nu | get path) | autoview > open --raw (which nu | get path) | autoview
... ...
126d1c0: 64 31 66 37 62 30 31 63 36 2e 31 31 38 2e 6c 6c d1f7b01c6.118.ll 126d1c0: 64 31 66 37 62 30 31 63 36 2e 31 31 38 2e 6c 6c d1f7b01c6.118.ll
126d1d0: 76 6d 2e 34 34 38 37 35 37 31 32 34 39 35 33 39 vm.4487571249539 126d1d0: 76 6d 2e 34 34 38 37 35 37 31 32 34 39 35 33 39 vm.4487571249539

View file

@ -56,7 +56,7 @@ We want to add two totals (numbers `33` and `37`) for the day `2020/04/16`
Set a table with two numbers for the empty column Set a table with two numbers for the empty column
```shell ```shell
> echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { = [33 37] } > echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { [33 37] }
═══╦════════════════╦════════════════╦════════════════ ═══╦════════════════╦════════════════╦════════════════
# ║ 2020/04/16 ║ 2020/07/10 ║ 2020/11/16 # ║ 2020/04/16 ║ 2020/07/10 ║ 2020/11/16
═══╬════════════════╬════════════════╬════════════════ ═══╬════════════════╬════════════════╬════════════════
@ -66,7 +66,7 @@ Set a table with two numbers for the empty column
Checking all the numbers Checking all the numbers
```shell ```shell
> echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { = [33 37] } | pivot _ totals | get totals > echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { [33 37] } | pivot _ totals | get totals
═══╦════ ═══╦════
0 ║ 33 0 ║ 33
1 ║ 37 1 ║ 37

View file

@ -14,7 +14,7 @@ pivot_mode = "auto" # auto, always, never
ctrlc_exit = false ctrlc_exit = false
complete_from_path = true complete_from_path = true
rm_always_trash = true rm_always_trash = true
prompt = "build-string $(ansi gb) $(pwd) $(ansi reset) '(' $(ansi cb) $(do -i { git rev-parse --abbrev-ref HEAD } | str trim ) $(ansi reset) ')' $(ansi yb) $(date format '%m/%d/%Y %I:%M:%S%.3f %p' ) $(ansi reset) '> ' " prompt = "build-string (ansi gb) (pwd) (ansi reset) '(' (ansi cb) (do -i { git rev-parse --abbrev-ref HEAD } | str trim ) (ansi reset) ')' (ansi yb) (date format '%m/%d/%Y %I:%M:%S%.3f %p' ) (ansi reset) '> ' "
# for each of the options in the color_config section, you are able to set # for each of the options in the color_config section, you are able to set
# the color alone or with one of the following attributes. # the color alone or with one of the following attributes.

View file

@ -47,7 +47,7 @@ fn plugins_are_declared_with_wix() {
| wrap wix | wrap wix
} }
| default wix _ | default wix _
| each { if $it.wix != $it.cargo { = 1 } { = 0 } } | each { if $it.wix != $it.cargo { 1 } { 0 } }
| math sum | math sum
"# "#
)); ));

View file

@ -34,7 +34,7 @@ fn automatically_change_directory() {
cwd: dirs.test(), cwd: dirs.test(),
r#" r#"
autodir autodir
echo $(pwd) echo (pwd)
"# "#
); );
@ -300,7 +300,7 @@ mod external_command_arguments {
let actual = nu!( let actual = nu!(
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
nu --testbin cococo $(ls | get name) nu --testbin cococo (ls | get name)
"# "#
)); ));

View file

@ -50,7 +50,7 @@ fn treats_dot_dot_as_path_not_range() {
r#" r#"
mkdir temp; mkdir temp;
cd temp; cd temp;
echo $(open ../nu_times.csv).name | autoview; echo (open ../nu_times.csv).name | autoview;
cd ..; cd ..;
rmdir temp rmdir temp
"# "#
@ -66,7 +66,7 @@ fn invocation_properly_redirects() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
echo $(nu --testbin cococo "hello") | str collect echo (nu --testbin cococo "hello") | str collect
"# "#
); );
@ -78,7 +78,7 @@ fn argument_invocation() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
echo "foo" | each { echo $(echo $it) } echo "foo" | each { echo (echo $it) }
"# "#
); );
@ -102,7 +102,7 @@ fn invocation_handles_dot() {
let actual = nu!( let actual = nu!(
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
echo $(open nu_times.csv) echo (open nu_times.csv)
| get name | get name
| each { nu --testbin chop $it | lines } | each { nu --testbin chop $it | lines }
| nth 3 | nth 3
@ -202,7 +202,7 @@ fn run_custom_command() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
def add-me [x y] { = $x + $y}; add-me 10 5 def add-me [x y] { $x + $y}; add-me 10 5
"# "#
); );
@ -214,7 +214,7 @@ fn run_custom_command_with_flag() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
def foo [--bar:number] { if $(echo $bar | empty?) { echo "empty" } { echo $bar } }; foo --bar 10 def foo [--bar:number] { if ($bar | empty?) { echo "empty" } { echo $bar } }; foo --bar 10
"# "#
); );
@ -226,7 +226,7 @@ fn run_custom_command_with_flag_missing() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
def foo [--bar:number] { if $(echo $bar | empty?) { echo "empty" } { echo $bar } }; foo def foo [--bar:number] { if ($bar | empty?) { echo "empty" } { echo $bar } }; foo
"# "#
); );
@ -325,7 +325,7 @@ fn set_variable() {
r#" r#"
let x = 5 let x = 5
let y = 12 let y = 12
= $x + $y $x + $y
"# "#
); );
@ -396,7 +396,7 @@ fn run_dynamic_blocks() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
let block = { echo "holaaaa" }; $block let block = { echo "holaaaa" }; do $block
"# "#
); );
assert_eq!(actual.out, "holaaaa"); assert_eq!(actual.out, "holaaaa");
@ -407,7 +407,7 @@ fn run_dynamic_blocks() {
fn argument_invocation_reports_errors() { fn argument_invocation_reports_errors() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
"echo $(ferris_is_not_here.exe)" "echo (ferris_is_not_here.exe)"
); );
assert!(actual.err.contains("Command not found")); assert!(actual.err.contains("Command not found"));
@ -644,7 +644,7 @@ fn filesize_math() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 100 * 10kb 100 * 10kb
"# "#
); );
@ -658,7 +658,7 @@ fn filesize_math2() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 100 / 10kb 100 / 10kb
"# "#
); );
@ -670,7 +670,7 @@ fn filesize_math3() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 100kb / 10 100kb / 10
"# "#
); );
@ -681,7 +681,7 @@ fn filesize_math4() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 100kb * 5 100kb * 5
"# "#
); );
@ -693,7 +693,7 @@ fn filesize_math5() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 1001 * 1kb 1001 * 1kb
"# "#
); );
@ -705,7 +705,7 @@ fn filesize_math6() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 1001 * 1mb 1001 * 1mb
"# "#
); );
@ -717,7 +717,7 @@ fn filesize_math7() {
let actual = nu!( let actual = nu!(
cwd: ".", cwd: ".",
r#" r#"
= 1001 * 1gb 1001 * 1gb
"# "#
); );
@ -753,7 +753,7 @@ fn duration_overflow() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
ls | get modified | each { = $it + 10000000000000000day } ls | get modified | each { $it + 10000000000000000day }
"#) "#)
); );
@ -765,7 +765,7 @@ fn date_and_duration_overflow() {
let actual = nu!( let actual = nu!(
cwd: ".", pipeline( cwd: ".", pipeline(
r#" r#"
ls | get modified | each { = $it + 1000000000day } ls | get modified | each { $it + 1000000000day }
"#) "#)
); );