diff --git a/book/3rdpartyprompts.md b/book/3rdpartyprompts.md index aa47d4befc..13146f0821 100644 --- a/book/3rdpartyprompts.md +++ b/book/3rdpartyprompts.md @@ -25,10 +25,10 @@ If you like [oh-my-posh](https://ohmyposh.dev/), you can use oh-my-posh with Nus ```nu # Generate the .oh-my-posh.nu file -> oh-my-posh init nu --config ~/.poshthemes/M365Princess.omp.json +oh-my-posh init nu --config ~/.poshthemes/M365Princess.omp.json # Initialize oh-my-posh.nu at shell startup by adding this line in your config.nu file -> source ~/.oh-my-posh.nu +source ~/.oh-my-posh.nu ``` For MacOS users: diff --git a/book/aliases.md b/book/aliases.md index f74f2cc5d9..798261d452 100644 --- a/book/aliases.md +++ b/book/aliases.md @@ -5,19 +5,19 @@ Aliases in Nushell offer a way of doing a simple replacement of command calls (b For example, let's create an alias called `ll` which will expand to `ls -l`. ```nu -> alias ll = ls -l +alias ll = ls -l ``` We can now call this alias: ```nu -> ll +ll ``` Once we do, it's as if we typed `ls -l`. This also allows us to pass in flags or positional parameters. For example, we can now also write: ```nu -> ll -a +ll -a ``` And get the equivalent to having typed `ls -l -a`. diff --git a/book/cheat_sheet.md b/book/cheat_sheet.md index 175ba9eed5..c325620f98 100644 --- a/book/cheat_sheet.md +++ b/book/cheat_sheet.md @@ -46,72 +46,72 @@ select two named columns from the table and print their values: interpolate text: ```nu -> let name = "Alice" -> $"greetings, ($name)!" -greetings, Alice! +let name = "Alice" +$"greetings, ($name)!" +# => greetings, Alice! ``` split text on comma delimiter and save the list to `string_list` variable: ```nu -> let string_list = "one,two,three" | split row "," -> $string_list -╭───┬───────╮ -│ 0 │ one │ -│ 1 │ two │ -│ 2 │ three │ -╰───┴───────╯ +let string_list = "one,two,three" | split row "," +$string_list +# => ╭───┬───────╮ +# => │ 0 │ one │ +# => │ 1 │ two │ +# => │ 2 │ three │ +# => ╰───┴───────╯ ``` check if a string contains a substring: ```nu -> "Hello, world!" | str contains "o, w" -true +"Hello, world!" | str contains "o, w" +# => true ``` join multiple strings with delimiter: ```nu -> let str_list = [zero one two] -> $str_list | str join ',' -zero,one,two +let str_list = [zero one two] +$str_list | str join ',' +# => zero,one,two ``` slice text by indices: ```nu -> 'Hello World!' | str substring 4..8 -o Wor +'Hello World!' | str substring 4..8 +# => o Wor ``` parse string into named columns: ```nu -> 'Nushell 0.80' | parse '{shell} {version}' -╭───┬─────────┬─────────╮ -│ # │ shell │ version │ -├───┼─────────┼─────────┤ -│ 0 │ Nushell │ 0.80 │ -╰───┴─────────┴─────────╯ +'Nushell 0.80' | parse '{shell} {version}' +# => ╭───┬─────────┬─────────╮ +# => │ # │ shell │ version │ +# => ├───┼─────────┼─────────┤ +# => │ 0 │ Nushell │ 0.80 │ +# => ╰───┴─────────┴─────────╯ ``` parse comma separated values (csv): ```nu -> "acronym,long\nAPL,A Programming Language" | from csv -╭───┬─────────┬────────────────────────╮ -│ # │ acronym │ long │ -├───┼─────────┼────────────────────────┤ -│ 0 │ APL │ A Programming Language │ -╰───┴─────────┴────────────────────────╯ +"acronym,long\nAPL,A Programming Language" | from csv +# => ╭───┬─────────┬────────────────────────╮ +# => │ # │ acronym │ long │ +# => ├───┼─────────┼────────────────────────┤ +# => │ 0 │ APL │ A Programming Language │ +# => ╰───┴─────────┴────────────────────────╯ ``` color text in command-line terminal: ```nu -> $'(ansi purple_bold)This text is a bold purple!(ansi reset)' -This text is a bold purple! +$'(ansi purple_bold)This text is a bold purple!(ansi reset)' +# => This text is a bold purple! ``` ## Lists @@ -119,136 +119,136 @@ This text is a bold purple! insert list value at index: ```nu -> [foo bar baz] | insert 1 'beeze' -╭───┬───────╮ -│ 0 │ foo │ -│ 1 │ beeze │ -│ 2 │ bar │ -│ 3 │ baz │ -╰───┴───────╯ +[foo bar baz] | insert 1 'beeze' +# => ╭───┬───────╮ +# => │ 0 │ foo │ +# => │ 1 │ beeze │ +# => │ 2 │ bar │ +# => │ 3 │ baz │ +# => ╰───┴───────╯ ``` update list value by index: ```nu -> [1, 2, 3, 4] | update 1 10 -╭───┬────╮ -│ 0 │ 1 │ -│ 1 │ 10 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -╰───┴────╯ +[1, 2, 3, 4] | update 1 10 +# => ╭───┬────╮ +# => │ 0 │ 1 │ +# => │ 1 │ 10 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => ╰───┴────╯ ``` prepend list value: ```nu -> let numbers = [1, 2, 3] -> $numbers | prepend 0 -╭───┬───╮ -│ 0 │ 0 │ -│ 1 │ 1 │ -│ 2 │ 2 │ -│ 3 │ 3 │ -╰───┴───╯ +let numbers = [1, 2, 3] +$numbers | prepend 0 +# => ╭───┬───╮ +# => │ 0 │ 0 │ +# => │ 1 │ 1 │ +# => │ 2 │ 2 │ +# => │ 3 │ 3 │ +# => ╰───┴───╯ ``` append list value: ```nu -> let numbers = [1, 2, 3] -> $numbers | append 4 -╭───┬───╮ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -╰───┴───╯ +let numbers = [1, 2, 3] +$numbers | append 4 +# => ╭───┬───╮ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => ╰───┴───╯ ``` slice first list values: ```nu -> [cammomile marigold rose forget-me-not] | first 2 -╭───┬───────────╮ -│ 0 │ cammomile │ -│ 1 │ marigold │ -╰───┴───────────╯ +[cammomile marigold rose forget-me-not] | first 2 +# => ╭───┬───────────╮ +# => │ 0 │ cammomile │ +# => │ 1 │ marigold │ +# => ╰───┴───────────╯ ``` iterate over a list; `elt` is current list value: ```nu -> let planets = [Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune] -> $planets | each { |elt| $"($elt) is a planet of the solar system" } -╭───┬─────────────────────────────────────────╮ -│ 0 │ Mercury is a planet of the solar system │ -│ 1 │ Venus is a planet of the solar system │ -│ 2 │ Earth is a planet of the solar system │ -│ 3 │ Mars is a planet of the solar system │ -│ 4 │ Jupiter is a planet of the solar system │ -│ 5 │ Saturn is a planet of the solar system │ -│ 6 │ Uranus is a planet of the solar system │ -│ 7 │ Neptune is a planet of the solar system │ -╰───┴─────────────────────────────────────────╯ +let planets = [Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune] +$planets | each { |elt| $"($elt) is a planet of the solar system" } +# => ╭───┬─────────────────────────────────────────╮ +# => │ 0 │ Mercury is a planet of the solar system │ +# => │ 1 │ Venus is a planet of the solar system │ +# => │ 2 │ Earth is a planet of the solar system │ +# => │ 3 │ Mars is a planet of the solar system │ +# => │ 4 │ Jupiter is a planet of the solar system │ +# => │ 5 │ Saturn is a planet of the solar system │ +# => │ 6 │ Uranus is a planet of the solar system │ +# => │ 7 │ Neptune is a planet of the solar system │ +# => ╰───┴─────────────────────────────────────────╯ ``` iterate over a list with an index and value: ```nu -> $planets | enumerate | each { |elt| $"($elt.index + 1) - ($elt.item)" } -╭───┬─────────────╮ -│ 0 │ 1 - Mercury │ -│ 1 │ 2 - Venus │ -│ 2 │ 3 - Earth │ -│ 3 │ 4 - Mars │ -│ 4 │ 5 - Jupiter │ -│ 5 │ 6 - Saturn │ -│ 6 │ 7 - Uranus │ -│ 7 │ 8 - Neptune │ -╰───┴─────────────╯ +$planets | enumerate | each { |elt| $"($elt.index + 1) - ($elt.item)" } +# => ╭───┬─────────────╮ +# => │ 0 │ 1 - Mercury │ +# => │ 1 │ 2 - Venus │ +# => │ 2 │ 3 - Earth │ +# => │ 3 │ 4 - Mars │ +# => │ 4 │ 5 - Jupiter │ +# => │ 5 │ 6 - Saturn │ +# => │ 6 │ 7 - Uranus │ +# => │ 7 │ 8 - Neptune │ +# => ╰───┴─────────────╯ ``` reduce the list to a single value; `reduce` gives access to accumulator that is applied to each element in the list: ```nu -> let scores = [3 8 4] -> $"total = ($scores | reduce { |elt, acc| $acc + $elt })" -total = 15 +let scores = [3 8 4] +$"total = ($scores | reduce { |elt, acc| $acc + $elt })" +# => total = 15 ``` reduce with an initial value (`--fold`): ```nu -> let scores = [3 8 4] -> $"total = ($scores | reduce --fold 1 { |elt, acc| $acc * $elt })" -total = 96 +let scores = [3 8 4] +$"total = ($scores | reduce --fold 1 { |elt, acc| $acc * $elt })" +# => total = 96 ``` give access to the 3rd item in the list: ```nu -> let planets = [Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune] -> $planets.2 -Earth +let planets = [Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune] +$planets.2 +# => Earth ``` check if any string in the list starts with `E`: ```nu -> let planets = [Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune] -> $planets | any {|elt| $elt | str starts-with "E" } -true +let planets = [Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune] +$planets | any {|elt| $elt | str starts-with "E" } +# => true ``` slice items that satisfy provided condition: ```nu -> let cond = {|x| $x < 0 }; [-1 -2 9 1] | take while $cond -╭───┬────╮ -│ 0 │ -1 │ -│ 1 │ -2 │ -╰───┴────╯ +let cond = {|x| $x < 0 }; [-1 -2 9 1] | take while $cond +# => ╭───┬────╮ +# => │ 0 │ -1 │ +# => │ 1 │ -2 │ +# => ╰───┴────╯ ``` ## Tables @@ -268,30 +268,28 @@ ls | sort-by size | first 5 concatenate two tables with same columns: ```nu -> let $a = [[first_column second_column third_column]; [foo bar snooze]] -> let $b = [[first_column second_column third_column]; [hex seeze feeze]] -> $a | append $b - -╭───┬──────────────┬───────────────┬──────────────╮ -│ # │ first_column │ second_column │ third_column │ -├───┼──────────────┼───────────────┼──────────────┤ -│ 0 │ foo │ bar │ snooze │ -│ 1 │ hex │ seeze │ feeze │ -╰───┴──────────────┴───────────────┴──────────────╯ +let $a = [[first_column second_column third_column]; [foo bar snooze]] +let $b = [[first_column second_column third_column]; [hex seeze feeze]] +$a | append $b +# => ╭───┬──────────────┬───────────────┬──────────────╮ +# => │ # │ first_column │ second_column │ third_column │ +# => ├───┼──────────────┼───────────────┼──────────────┤ +# => │ 0 │ foo │ bar │ snooze │ +# => │ 1 │ hex │ seeze │ feeze │ +# => ╰───┴──────────────┴───────────────┴──────────────╯ ``` remove the last column of a table: ```nu -> let teams_scores = [[team score plays]; ['Boston Celtics' 311 3] ['Golden State Warriors', 245 2]] -> $teams_scores | drop column - -╭───┬───────────────────────┬───────╮ -│ # │ team │ score │ -├───┼───────────────────────┼───────┤ -│ 0 │ Boston Celtics │ 311 │ -│ 1 │ Golden State Warriors │ 245 │ -╰───┴───────────────────────┴───────╯ +let teams_scores = [[team score plays]; ['Boston Celtics' 311 3] ['Golden State Warriors', 245 2]] +$teams_scores | drop column +# => ╭───┬───────────────────────┬───────╮ +# => │ # │ team │ score │ +# => ├───┼───────────────────────┼───────┤ +# => │ 0 │ Boston Celtics │ 311 │ +# => │ 1 │ Golden State Warriors │ 245 │ +# => ╰───┴───────────────────────┴───────╯ ``` ## Files and Filesystem @@ -337,7 +335,7 @@ watch . --glob=**/*.rs {|| cargo test } custom command with parameter type set to string: ```nu -> def greet [name: string] { +def greet [name: string] { $"hello ($name)" } ``` @@ -345,7 +343,7 @@ custom command with parameter type set to string: custom command with default parameter set to nushell: ```nu -> def greet [name = "nushell"] { +def greet [name = "nushell"] { $"hello ($name)" } ``` @@ -353,20 +351,20 @@ custom command with default parameter set to nushell: passing named parameter by defining flag for custom commands: ```nu -> def greet [ +def greet [ name: string --age: int ] { [$name $age] } -> greet world --age 10 +greet world --age 10 ``` using flag as a switch with a shorthand flag (-a) for the age: ```nu -> def greet [ +def greet [ name: string --age (-a): int --twice @@ -377,24 +375,24 @@ using flag as a switch with a shorthand flag (-a) for the age: [$name $age] } } -> greet -a 10 --twice hello +greet -a 10 --twice hello ``` custom command which takes any number of positional arguments using rest params: ```nu -> def greet [...name: string] { +def greet [...name: string] { print "hello all:" for $n in $name { print $n } } -> greet earth mars jupiter venus -hello all: -earth -mars -jupiter -venus +greet earth mars jupiter venus +# => hello all: +# => earth +# => mars +# => jupiter +# => venus ``` ## Variables @@ -402,64 +400,64 @@ venus an immutable variable cannot change its value after declaration: ```nu -> let val = 42 -> print $val -42 +let val = 42 +print $val +# => 42 ``` shadowing variable (declaring variable with the same name in a different scope): ```nu -> let val = 42 -> do { let val = 101; $val } -101 -> $val -42 +let val = 42 +do { let val = 101; $val } +# => 101 +$val +# => 42 ``` declaring a mutable variable with mut key word: ```nu -> mut val = 42 -> $val += 27 -> $val -69 +mut val = 42 +$val += 27 +$val +# => 69 ``` closures and nested defs cannot capture mutable variables from their environment (errors): ```nu -> mut x = 0 -> [1 2 3] | each { $x += 1 } -Error: nu::parser::expected_keyword - - × Capture of mutable variable. - ╭─[entry #83:1:18] - 1 │ [1 2 3] | each { $x += 1 } - · ─┬ - · ╰── capture of mutable variable - ╰──── +mut x = 0 +[1 2 3] | each { $x += 1 } +# => Error: nu::parser::expected_keyword +# => +# => × Capture of mutable variable. +# => ╭─[entry #83:1:18] +# => 1 │ [1 2 3] | each { $x += 1 } +# => · ─┬ +# => · ╰── capture of mutable variable +# => ╰──── ``` a constant variable is immutable and is fully evaluated at parse-time: ```nu -> const file = 'path/to/file.nu' -> source $file +const file = 'path/to/file.nu' +source $file ``` use question mark operator `?` to return null instead of error if provided path is incorrect: ```nu -> let files = (ls) -> $files.name?.0? +let files = (ls) +$files.name?.0? ``` assign the result of a pipeline to a variable: ```nu -> let big_files = (ls | where size > 10kb) -> $big_files +let big_files = (ls | where size > 10kb) +$big_files ``` ## Modules @@ -467,7 +465,7 @@ assign the result of a pipeline to a variable: use an inline module: ```nu -> module greetings { +module greetings { export def hello [name: string] { $"hello ($name)!" } @@ -476,8 +474,8 @@ use an inline module: $"hi ($where)!" } } -> use greetings hello -> hello "world" +use greetings hello +hello "world" ``` import module from file and use its environment in current scope: @@ -491,11 +489,11 @@ export def hello [] { $"hello ($env.MYNAME)" } -> use greetings.nu -> $env.MYNAME -Arthur, King of the Britons -> greetings hello -hello Arthur, King of the Britons! +use greetings.nu +$env.MYNAME +# => Arthur, King of the Britons +greetings hello +# => hello Arthur, King of the Britons! ``` use main command in module: @@ -514,9 +512,9 @@ export def main [] { "greetings and salutations!" } -> use greetings.nu -> greetings -greetings and salutations! -> greetings hello world -hello world! +use greetings.nu +greetings +# => greetings and salutations! +greetings hello world +# => hello world! ``` diff --git a/book/coloring_and_theming.md b/book/coloring_and_theming.md index c1763b7a57..a7b25ced8a 100644 --- a/book/coloring_and_theming.md +++ b/book/coloring_and_theming.md @@ -13,7 +13,7 @@ Many parts of Nushell's interface can have their color customized. All of these Table borders are controlled by the `$env.config.table.mode` setting in `config.nu`. Here is an example: ```nu -> $env.config = { +$env.config = { table: { mode: rounded } @@ -269,7 +269,7 @@ This is the current list of primitives. Not all of these are configurable. The c Here's a small example of changing some of these values. ```nu -> let config = { +let config = { color_config: { separator: purple leading_trailing_space_bg: "#ffffff" @@ -294,7 +294,7 @@ Here's a small example of changing some of these values. Here's another small example using multiple color syntaxes with some comments. ```nu -> let config = { +let config = { color_config: { separator: "#88b719" # this sets only the foreground color like PR #486 leading_trailing_space_bg: white # this sets only the foreground color in the original style @@ -348,7 +348,7 @@ Here's the current list of flat shapes. Here's a small example of how to apply color to these items. Anything not specified will receive the default color. ```nu -> $env.config = { +$env.config = { color_config: { shape_garbage: { fg: "#FFFFFF" bg: "#FF0000" attr: b} shape_bool: green @@ -372,13 +372,13 @@ The Nushell prompt is configurable through these environment variables and confi Example: For a simple prompt one could do this. Note that `PROMPT_COMMAND` requires a `block` whereas the others require a `string`. ```nu -> $env.PROMPT_COMMAND = { build-string (date now | format date '%m/%d/%Y %I:%M:%S%.3f') ': ' (pwd | path basename) } +$env.PROMPT_COMMAND = { build-string (date now | format date '%m/%d/%Y %I:%M:%S%.3f') ': ' (pwd | path basename) } ``` If you don't like the default `PROMPT_INDICATOR` you could change it like this. ```nu -> $env.PROMPT_INDICATOR = "> " +$env.PROMPT_INDICATOR = "> " ``` If you're using `starship`, you'll most likely want to show the right prompt on the last line of the prompt, just like zsh or fish. You could modify the `config.nu` file, just set `render_right_prompt_on_last_line` to true: @@ -401,13 +401,13 @@ Each of the `PROMPT_*` variables has a corresponding `TRANSIENT_PROMPT_*` variab For example, if you want to make past prompts show up without a left prompt entirely and leave only the indicator, you can use: ```nu -> $env.TRANSIENT_PROMPT_COMMAND = "" +$env.TRANSIENT_PROMPT_COMMAND = "" ``` If you want to go back to the normal left prompt, you'll have to unset `TRANSIENT_PROMPT_COMMAND`: ```nu -> hide-env TRANSIENT_PROMPT_COMMAND +hide-env TRANSIENT_PROMPT_COMMAND ``` ## `LS_COLORS` Colors for the [`ls`](/commands/docs/ls.md) Command diff --git a/book/configuration.md b/book/configuration.md index 4b6b48e67e..b31ef39c97 100644 --- a/book/configuration.md +++ b/book/configuration.md @@ -10,8 +10,8 @@ Nushell uses a configuration system that loads and runs two Nushell script files Check where Nushell is reading these config files from by calling `$nu.env-path` and `$nu.config-path`. ```nu -> $nu.env-path -/Users/FirstNameLastName/Library/Application Support/nushell/env.nu +$nu.env-path +# => /Users/FirstNameLastName/Library/Application Support/nushell/env.nu ``` _(You can think of the Nushell config loading sequence as executing two [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) lines on startup: `source /path/to/env.nu` and `source /path/to/config.nu`. Therefore, using `env.nu` for environment and `config.nu` for other config is just a convention.)_ @@ -22,8 +22,8 @@ When you launch Nushell without these files set up, Nushell will prompt you to d The default config files aren't required. If you prefer to start with an empty `env.nu` and `config.nu` then Nu applies identical defaults in internal Rust code. You can still browse the default files for default values of environment variables and a list of all configurable settings using the [`config`](#configurations-with-built-in-commands) commands: ```nu -> config env --default | nu-highlight | lines -> config nu --default | nu-highlight | lines +config env --default | nu-highlight | lines +config nu --default | nu-highlight | lines ``` ::: diff --git a/book/control_flow.md b/book/control_flow.md index e9e4625cc3..e2c3c5e5ef 100644 --- a/book/control_flow.md +++ b/book/control_flow.md @@ -25,8 +25,8 @@ The following commands execute code based on some given condition. The choice/conditional commands are expressions so they return values, unlike the other commands on this page. This means the following works. ```nu -> 'foo' | if $in == 'foo' { 1 } else { 0 } | $in + 2 -3 +'foo' | if $in == 'foo' { 1 } else { 0 } | $in + 2 +# => 3 ``` ::: @@ -36,7 +36,7 @@ The choice/conditional commands are expressions so they return values, unlike th [`if`](/commands/docs/if.html) evaluates branching [blocks](/book/types_of_data.html#blocks) of code based on the results of one or more conditions similar to the "if" functionality in other programming languages. For example: ```nu -> if $x > 0 { 'positive' } +if $x > 0 { 'positive' } ``` Returns `'positive`' when the condition is `true` (`$x` is greater than zero) and `null` when the condition is `false` (`$x` is less than or equal to zero). @@ -44,7 +44,7 @@ Returns `'positive`' when the condition is `true` (`$x` is greater than zero) an We can add an `else` branch to the `if` after the first block which executes and returns the resulting value from the `else` block when the condition is `false`. For example: ```nu -> if $x > 0 { 'positive' } else { 'non-positive' } +if $x > 0 { 'positive' } else { 'non-positive' } ``` This time it returns `'positive'` when the condition is `true` (`$x` is greater than zero) and `'non-positive`' when the condition is `false` (`$x` is less than or equal to zero). @@ -52,7 +52,7 @@ This time it returns `'positive'` when the condition is `true` (`$x` is greater We can also chain multiple `if`s together like the following: ```nu -> if $x > 0 { 'positive' } else if $x == 0 { 'zero' } else { "negative" } +if $x > 0 { 'positive' } else if $x == 0 { 'zero' } else { "negative" } ``` When the first condition is `true` (`$x` is greater than zero) it will return `'positive'`, when the first condition is `false` and the next condition is `true` (`$x` equals zero) it will return `'zero'`, otherwise it will return `'negative'` (when `$x` is less than zero). @@ -64,7 +64,7 @@ When the first condition is `true` (`$x` is greater than zero) it will return `' Basic usage of [`match`](/commands/docs/match.html) can conditionally run different code like a "switch" statement common in other languages. [`match`](/commands/docs/match.html) checks if the value after the word [`match`](/commands/docs/match.html) is equal to the value at the start of each branch before the `=>` and if it does, it executes the code after that branch's `=>`. ```nu -> match 3 { +match 3 { 1 => 'one', 2 => { let w = 'w' @@ -73,7 +73,7 @@ Basic usage of [`match`](/commands/docs/match.html) can conditionally run differ 3 => 'three', 4 => 'four' } -three +# => three ``` The branches can either return a single value or, as shown in the second branch, can return the results of a [block](/book/types_of_data.html#blocks). @@ -83,14 +83,14 @@ The branches can either return a single value or, as shown in the second branch, You can also have a catch all condition for when the given value doesn't match any of the other conditions by having a branch whose matching value is `_`. ```nu -> let foo = match 7 { +let foo = match 7 { 1 => 'one', 2 => 'two', 3 => 'three', _ => 'other number' } -> $foo -other number +$foo +# => other number ``` (Reminder, [`match`](/commands/docs/match.html) is an expression which is why we can assign the result to `$foo` here). @@ -100,13 +100,13 @@ other number You can "unpack" values from types like lists and records with [pattern matching](/cookbook/pattern_matching.html). You can then assign variables to the parts you want to unpack and use them in the matched expressions. ```nu -> let foo = { name: 'bar', count: 7 } -> match $foo { +let foo = { name: 'bar', count: 7 } +match $foo { { name: 'bar', count: $it } => ($it + 3), { name: _, count: $it } => ($it + 7), _ => 1 } -10 +# => 10 ``` The `_` in the second branch means it matches any record with field `name` and `count`, not just ones where `name` is `'bar'`. @@ -116,13 +116,13 @@ The `_` in the second branch means it matches any record with field `name` and ` You can also add an additional condition to each branch called a "guard" to determine if the branch should be matched. To do so, after the matched pattern put `if` and then the condition before the `=>`. ```nu -> let foo = { name: 'bar', count: 7 } -> match $foo { +let foo = { name: 'bar', count: 7 } +match $foo { { name: 'bar', count: $it } if $it < 5 => ($it + 3), { name: 'bar', count: $it } if $it >= 5 => ($it + 7), _ => 1 } -14 +# => 14 ``` --- @@ -138,22 +138,22 @@ The loop commands allow you to repeat a block of code multiple times. The functionality of the loop commands is similar to commands that apply a closure over elements in a list or table like [`each`](/commands/docs/each.html) or [`where`](/commands/docs/where.html) and many times you can accomplish the same thing with either. For example: ```nu -> mut result = [] -> for $it in [1 2 3] { $result = ($result | append ($it + 1)) } -> $result -╭───┬───╮ -│ 0 │ 2 │ -│ 1 │ 3 │ -│ 2 │ 4 │ -╰───┴───╯ - - -> [1 2 3] | each { $in + 1 } -╭───┬───╮ -│ 0 │ 2 │ -│ 1 │ 3 │ -│ 2 │ 4 │ -╰───┴───╯ +mut result = [] +for $it in [1 2 3] { $result = ($result | append ($it + 1)) } +$result +# => ╭───┬───╮ +# => │ 0 │ 2 │ +# => │ 1 │ 3 │ +# => │ 2 │ 4 │ +# => ╰───┴───╯ + + +[1 2 3] | each { $in + 1 } +# => ╭───┬───╮ +# => │ 0 │ 2 │ +# => │ 1 │ 3 │ +# => │ 2 │ 4 │ +# => ╰───┴───╯ ``` While it may be tempting to use loops if you're familiar with them in other languages, it is considered more in the [Nushell-style](book/thinking_in_nu.html) (idiomatic) to use commands that apply closures when you can solve a problem either way. The reason for this is because of a pretty big downside with using loops. @@ -167,16 +167,16 @@ This means that they don't work well with immutable variables and using immutabl Statements also don't work in Nushell pipelines which require some output. In fact Nushell will give an error if you try: ```nu -> [1 2 3] | for x in $in { $x + 1 } | $in ++ [5 6 7] -Error: nu::parser::unexpected_keyword - - × Statement used in pipeline. - ╭─[entry #5:1:1] - 1 │ [1 2 3] | for x in $in { $x + 1 } | $in ++ [5 6 7] - · ─┬─ - · ╰── not allowed in pipeline - ╰──── - help: 'for' keyword is not allowed in pipeline. Use 'for' by itself, outside of a pipeline. +[1 2 3] | for x in $in { $x + 1 } | $in ++ [5 6 7] +# => Error: nu::parser::unexpected_keyword +# => +# => × Statement used in pipeline. +# => ╭─[entry #5:1:1] +# => 1 │ [1 2 3] | for x in $in { $x + 1 } | $in ++ [5 6 7] +# => · ─┬─ +# => · ╰── not allowed in pipeline +# => ╰──── +# => help: 'for' keyword is not allowed in pipeline. Use 'for' by itself, outside of a pipeline. ``` Because Nushell is very pipeline oriented, this means using expression commands like [`each`](/commands/docs/each.html) is typically more natural than loop statements. @@ -186,29 +186,29 @@ Because Nushell is very pipeline oriented, this means using expression commands If loops have such a big disadvantage, why do they exist? Well, one reason is that closures, like [`each`](/commands/docs/each.html) uses, can't modify mutable variables in the surrounding environment. If you try to modify a mutable variable in a closure you will get an error: ```nu -> mut foo = [] -> [1 2 3] | each { $foo = ($foo | append ($in + 1)) } -Error: nu::parser::expected_keyword - - × Capture of mutable variable. - ╭─[entry #8:1:1] - 1 │ [1 2 3] | each { $foo = ($foo | append ($in + 1)) } - · ──┬─ - · ╰── capture of mutable variable - ╰──── +mut foo = [] +[1 2 3] | each { $foo = ($foo | append ($in + 1)) } +# => Error: nu::parser::expected_keyword +# => +# => × Capture of mutable variable. +# => ╭─[entry #8:1:1] +# => 1 │ [1 2 3] | each { $foo = ($foo | append ($in + 1)) } +# => · ──┬─ +# => · ╰── capture of mutable variable +# => ╰──── ``` If you modify an environmental variable in a closure, you can, but it will only modify it within the scope of the closure, leaving it unchanged everywhere else. Loops, however, use [blocks](/book/types_of_data.html#blocks) which means they can modify a regular mutable variable or an environmental variable within the larger scope. ```nu -> mut result = [] -> for $it in [1 2 3] { $result = ($result | append ($it + 1)) } -> $result -╭───┬───╮ -│ 0 │ 2 │ -│ 1 │ 3 │ -│ 2 │ 4 │ -╰───┴───╯ +mut result = [] +for $it in [1 2 3] { $result = ($result | append ($it + 1)) } +$result +# => ╭───┬───╮ +# => │ 0 │ 2 │ +# => │ 1 │ 3 │ +# => │ 2 │ 4 │ +# => ╰───┴───╯ ``` ### `for` @@ -216,10 +216,10 @@ If you modify an environmental variable in a closure, you can, but it will only [`for`](/commands/docs/for.html) loops over a range or collection like a list or a table. ```nu -> for x in [1 2 3] { $x * $x | print } -1 -4 -9 +for x in [1 2 3] { $x * $x | print } +# => 1 +# => 4 +# => 9 ``` #### Expression Command Alternatives @@ -234,8 +234,8 @@ If you modify an environmental variable in a closure, you can, but it will only [`while`](/commands/docs/while.html) loops the same block of code until the given condition is `false`. ```nu -> mut x = 0; while $x < 10 { $x = $x + 1 }; $x -10 +mut x = 0; while $x < 10 { $x = $x + 1 }; $x +# => 10 ``` #### Expression Command Alternatives @@ -252,8 +252,8 @@ The "until" and other "while" commands [`loop`](/commands/docs/loop.html) loops a block infinitely. You can use [`break`](/commands/docs/break.html) (as described in the next section) to limit how many times it loops. It can also be handy for continuously running scripts, like an interactive prompt. ```nu -> mut x = 0; loop { if $x > 10 { break }; $x = $x + 1 }; $x -11 +mut x = 0; loop { if $x > 10 { break }; $x = $x + 1 }; $x +# => 11 ``` ### `break` @@ -261,10 +261,10 @@ The "until" and other "while" commands [`break`](/commands/docs/break.html) will stop executing the code in a loop and resume execution after the loop. Effectively "break"ing out of the loop. ```nu -> for x in 1..10 { if $x > 3 { break }; print $x } -1 -2 -3 +for x in 1..10 { if $x > 3 { break }; print $x } +# => 1 +# => 2 +# => 3 ``` ### `continue` @@ -272,12 +272,12 @@ The "until" and other "while" commands [`continue`](/commands/docs/continue.html) will stop execution of the current loop, skipping the rest of the code in the loop, and will go to the next loop. If the loop would normally end, like if [`for`](/commands/docs/for.html) has iterated through all the given elements, or if [`while`](/commands/docs/while.html)'s condition is now false, it won't loop again and execution will continue after the loop block. ```nu -> mut x = -1; while $x <= 6 { $x = $x + 1; if $x mod 3 == 0 { continue }; print $x } -1 -2 -4 -5 -7 +mut x = -1; while $x <= 6 { $x = $x + 1; if $x mod 3 == 0 { continue }; print $x } +# => 1 +# => 2 +# => 4 +# => 5 +# => 7 ``` ## Errors @@ -287,14 +287,14 @@ The "until" and other "while" commands [`error make`](/commands/docs/error_make.html) creates an error that stops execution of the code and any code that called it, until either it is handled by a [`try`](/commands/docs/try.html) block, or it ends the script and outputs the error message. This functionality is the same as "exceptions" in other languages. ```nu -> print 'printed'; error make { msg: 'Some error info' }; print 'unprinted' -printed -Error: × Some error info - ╭─[entry #9:1:1] - 1 │ print 'printed'; error make { msg: 'Some error info' }; print 'unprinted' - · ─────┬──── - · ╰── originates from here - ╰──── +print 'printed'; error make { msg: 'Some error info' }; print 'unprinted' +# => printed +# => Error: × Some error info +# => ╭─[entry #9:1:1] +# => 1 │ print 'printed'; error make { msg: 'Some error info' }; print 'unprinted' +# => · ─────┬──── +# => · ╰── originates from here +# => ╰──── ``` The record passed to it provides some information to the code that catches it or the resulting error message. @@ -306,15 +306,15 @@ You can find more information about [`error make`](/commands/docs/error_make.htm [`try`](/commands/docs/try.html) will catch errors created anywhere in the [`try`](/commands/docs/try.html)'s code block and resume execution of the code after the block. ```nu -> try { error make { msg: 'Some error info' }}; print 'Resuming' -Resuming +try { error make { msg: 'Some error info' }}; print 'Resuming' +# => Resuming ``` This includes catching built in errors. ```nu -> try { 1 / 0 }; print 'Resuming' -Resuming +try { 1 / 0 }; print 'Resuming' +# => Resuming ``` The resulting value will be `nothing` if an error occurs and the returned value of the block if an error did not occur. @@ -322,8 +322,8 @@ The resulting value will be `nothing` if an error occurs and the returned value If you include a `catch` block after the [`try`](/commands/docs/try.html) block, it will execute the code in the `catch` block if an error occurred in the [`try`](/commands/docs/try.html) block. ```nu -> try { 1 / 0 } catch { 'An error happened!' } | $in ++ ' And now I am resuming.' -An error happened! And now I am resuming. +try { 1 / 0 } catch { 'An error happened!' } | $in ++ ' And now I am resuming.' +# => An error happened! And now I am resuming. ``` It will not execute the `catch` block if an error did not occur. @@ -345,17 +345,17 @@ def 'positive-check' [it] { ``` ```nu -> positive-check 3 -positive +positive-check 3 +# => positive -> positive-check (-3) -non-positive +positive-check (-3) +# => non-positive -> let positive_check = {|elt| if $elt > 0 { return 'positive' }; 'non-positive' } +let positive_check = {|elt| if $elt > 0 { return 'positive' }; 'non-positive' } -> do $positive_check 3 -positive +do $positive_check 3 +# => positive -> do $positive_check (-3) -non-positive +do $positive_check (-3) +# => non-positive ``` diff --git a/book/creating_errors.md b/book/creating_errors.md index b3f1d8b296..48ebbc44b1 100644 --- a/book/creating_errors.md +++ b/book/creating_errors.md @@ -37,13 +37,12 @@ def my-command [x] { When called with a value, we'll now see an error message returned: ```nu -> my-command 100 - -Error: - × this is fishy - ╭─[entry #5:1:1] - 1 │ my-command 100 - · ─┬─ - · ╰── fish right here - ╰──── +my-command 100 +# => Error: +# => × this is fishy +# => ╭─[entry #5:1:1] +# => 1 │ my-command 100 +# => · ─┬─ +# => · ╰── fish right here +# => ╰──── ``` diff --git a/book/custom_commands.md b/book/custom_commands.md index c5aa0448d4..4e85902edd 100644 --- a/book/custom_commands.md +++ b/book/custom_commands.md @@ -166,7 +166,7 @@ See also: [Pipelines](./pipelines.html) ### Pipeline Output ```nu -> ls | get name +ls | get name ``` Let's move [`ls`](/commands/docs/ls.md) into a command that we've written: @@ -178,7 +178,7 @@ def my-ls [] { ls } We can use the output from this command just as we would [`ls`](/commands/docs/ls.md). ```nu -> my-ls | get name +my-ls | get name # => ╭───┬───────────────────────╮ # => │ 0 │ myscript.nu │ # => │ 1 │ myscript2.nu │ @@ -286,7 +286,7 @@ def "str mycommand" [] { Now we can call our custom command as if it were a built-in subcommand of [`str`](/commands/docs/str.md): ```nu -> str mycommand +str mycommand ``` Of course, commands with spaces in their names are defined in the same way: diff --git a/book/custom_completions.md b/book/custom_completions.md index ea16067101..f006afc034 100644 --- a/book/custom_completions.md +++ b/book/custom_completions.md @@ -11,11 +11,11 @@ Here's a simple example: ```nu # Completion command -> def animals [] { ["cat", "dog", "eel" ] } +def animals [] { ["cat", "dog", "eel" ] } # Command to be completed -> def my-command [animal: string@animals] { print $animal } ->| my-command -cat dog eel +def my-command [animal: string@animals] { print $animal } +my-command +# => cat dog eel ``` The first line defines a custom command which returns a list of three different animals. These are the possible values for the completion. diff --git a/book/dataframes.md b/book/dataframes.md index 3d090ffe7f..b93c6babdc 100644 --- a/book/dataframes.md +++ b/book/dataframes.md @@ -51,13 +51,13 @@ The dataset has 5 columns and 5,429,252 rows. We can check that by using the `polars store-ls` command: ```nu -> let df_0 = polars open --eager Data7602DescendingYearOrder.csv -> polars store-ls | select key type columns rows estimated_size -╭──────────────────────────────────────┬───────────┬─────────┬─────────┬────────────────╮ -│ key │ type │ columns │ rows │ estimated_size │ -├──────────────────────────────────────┼───────────┼─────────┼─────────┼────────────────┤ -│ b2519dac-3b64-4e5d-a0d7-24bde9052dc7 │ DataFrame │ 5 │ 5429252 │ 184.5 MB │ -╰──────────────────────────────────────┴───────────┴─────────┴─────────┴────────────────╯ +let df_0 = polars open --eager Data7602DescendingYearOrder.csv +polars store-ls | select key type columns rows estimated_size +# => ╭──────────────────────────────────────┬───────────┬─────────┬─────────┬────────────────╮ +# => │ key │ type │ columns │ rows │ estimated_size │ +# => ├──────────────────────────────────────┼───────────┼─────────┼─────────┼────────────────┤ +# => │ b2519dac-3b64-4e5d-a0d7-24bde9052dc7 │ DataFrame │ 5 │ 5429252 │ 184.5 MB │ +# => ╰──────────────────────────────────────┴───────────┴─────────┴─────────┴────────────────╯ ``` ::: tip @@ -68,25 +68,25 @@ To open as an eager dataframe, use the `--eager` flag. We can have a look at the first lines of the file using [`first`](/commands/docs/first.md): ```nu -> $df_0 | polars first -╭───┬──────────┬─────────┬──────┬───────────┬──────────╮ -│ # │ anzsic06 │ Area │ year │ geo_count │ ec_count │ -├───┼──────────┼─────────┼──────┼───────────┼──────────┤ -│ 0 │ A │ A100100 │ 2000 │ 96 │ 130 │ -╰───┴──────────┴─────────┴──────┴───────────┴──────────╯ +$df_0 | polars first +# => ╭───┬──────────┬─────────┬──────┬───────────┬──────────╮ +# => │ # │ anzsic06 │ Area │ year │ geo_count │ ec_count │ +# => ├───┼──────────┼─────────┼──────┼───────────┼──────────┤ +# => │ 0 │ A │ A100100 │ 2000 │ 96 │ 130 │ +# => ╰───┴──────────┴─────────┴──────┴───────────┴──────────╯ ``` ...and finally, we can get an idea of the inferred data types: ```nu -> $df_0 | polars schema -╭───────────┬─────╮ -│ anzsic06 │ str │ -│ Area │ str │ -│ year │ i64 │ -│ geo_count │ i64 │ -│ ec_count │ i64 │ -╰───────────┴─────╯ +$df_0 | polars schema +# => ╭───────────┬─────╮ +# => │ anzsic06 │ str │ +# => │ Area │ str │ +# => │ year │ i64 │ +# => │ geo_count │ i64 │ +# => │ ec_count │ i64 │ +# => ╰───────────┴─────╯ ``` ### Group-by Comparison @@ -94,7 +94,7 @@ We can have a look at the first lines of the file using [`first`](/commands/docs To output more statistically correct timings, let's load and use the `std bench` command. ```nu -> use std bench +use std bench ``` We are going to group the data by year, and sum the column `geo_count`. @@ -187,7 +187,7 @@ To do that, let's stop the `polars`. When we execute our next commands, we will start a new instance of plugin. ```nu -> plugin stop polars +plugin stop polars ``` ## Working with Dataframes @@ -220,7 +220,7 @@ Now, to read that file as a dataframe use the `polars open` command like this: ```nu -> let df_1 = polars open --eager test_small.csv +let df_1 = polars open --eager test_small.csv ``` This should create the value `$df_1` in memory which holds the data we just @@ -233,12 +233,12 @@ The `polars open` command can read files in formats: **csv**, **tsv**, **parquet To see all the dataframes that are stored in memory you can use ```nu -> polars store-ls | select key type columns rows estimated_size -╭──────────────────────────────────────┬───────────┬─────────┬──────┬────────────────╮ -│ key │ type │ columns │ rows │ estimated_size │ -├──────────────────────────────────────┼───────────┼─────────┼──────┼────────────────┤ -│ e780af47-c106-49eb-b38d-d42d3946d66e │ DataFrame │ 8 │ 10 │ 403 B │ -╰──────────────────────────────────────┴───────────┴─────────┴──────┴────────────────╯ +polars store-ls | select key type columns rows estimated_size +# => ╭──────────────────────────────────────┬───────────┬─────────┬──────┬────────────────╮ +# => │ key │ type │ columns │ rows │ estimated_size │ +# => ├──────────────────────────────────────┼───────────┼─────────┼──────┼────────────────┤ +# => │ e780af47-c106-49eb-b38d-d42d3946d66e │ DataFrame │ 8 │ 10 │ 403 B │ +# => ╰──────────────────────────────────────┴───────────┴─────────┴──────┴────────────────╯ ``` As you can see, the command shows the created dataframes together with basic @@ -248,21 +248,21 @@ And if you want to see a preview of the loaded dataframe you can send the dataframe variable to the stream ```nu -> $df_1 -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ -│ 0 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │ -│ 1 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │ -│ 2 │ 3 │ 13 │ 0.30 │ 2.00 │ a │ b │ c │ third │ -│ 3 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ -│ 4 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ -│ 5 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ -│ 6 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ -│ 7 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ -│ 8 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ -│ 9 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ +$df_1 +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ +# => │ 0 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │ +# => │ 1 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │ +# => │ 2 │ 3 │ 13 │ 0.30 │ 2.00 │ a │ b │ c │ third │ +# => │ 3 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ +# => │ 4 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ +# => │ 5 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ +# => │ 6 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ +# => │ 7 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ +# => │ 8 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ +# => │ 9 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ ``` With the dataframe in memory we can start doing column operations with the @@ -279,12 +279,12 @@ Let's start with basic aggregations on the dataframe. Let's sum all the columns that exist in `df` by using the `aggregate` command ```nu -> $df_1 | polars sum -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬──────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼──────┤ -│ 0 │ 40 │ 145 │ 4.50 │ 46.00 │ │ │ │ │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴──────╯ +$df_1 | polars sum +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬──────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼──────┤ +# => │ 0 │ 40 │ 145 │ 4.50 │ 46.00 │ │ │ │ │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴──────╯ ``` As you can see, the aggregate function computes the sum for those columns where @@ -292,19 +292,19 @@ a sum makes sense. If you want to filter out the text column, you can select the columns you want by using the [`polars select`](/commands/docs/polars_select.md) command ```nu -> $df_1 | polars sum | polars select int_1 int_2 float_1 float_2 -╭───┬───────┬───────┬─────────┬─────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ -├───┼───────┼───────┼─────────┼─────────┤ -│ 0 │ 40 │ 145 │ 4.50 │ 46.00 │ -╰───┴───────┴───────┴─────────┴─────────╯ +$df_1 | polars sum | polars select int_1 int_2 float_1 float_2 +# => ╭───┬───────┬───────┬─────────┬─────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ +# => ├───┼───────┼───────┼─────────┼─────────┤ +# => │ 0 │ 40 │ 145 │ 4.50 │ 46.00 │ +# => ╰───┴───────┴───────┴─────────┴─────────╯ ``` You can even store the result from this aggregation as you would store any other Nushell variable ```nu -> let res = $df_1 | polars sum | polars select int_1 int_2 float_1 float_2 +let res = $df_1 | polars sum | polars select int_1 int_2 float_1 float_2 ``` ::: tip @@ -315,7 +315,7 @@ executed command. Note the space between `=` and `!!`. And now we have two dataframes stored in memory ```nu -> polars store-ls | select key type columns rows estimated_size +polars store-ls | select key type columns rows estimated_size ╭──────────────────────────────────────┬───────────┬─────────┬──────┬────────────────╮ │ key │ type │ columns │ rows │ estimated_size │ ├──────────────────────────────────────┼───────────┼─────────┼──────┼────────────────┤ @@ -349,7 +349,7 @@ are going to call it `test_small_a.csv`) We use the `polars open` command to create the new variable ```nu -> let df_2 = polars open --eager test_small_a.csv +let df_2 = polars open --eager test_small_a.csv ``` Now, with the second dataframe loaded in memory we can join them using the @@ -357,15 +357,15 @@ column called `int_1` from the left dataframe and the column `int_1` from the right dataframe ```nu -> $df_1 | polars join $df_2 int_1 int_1 -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────┬─────────┬───────────┬───────────┬─────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ int_2_x │ float_1_x │ float_2_x │ first_x │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┼─────────┼───────────┼───────────┼─────────┤ -│ 0 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ 11 │ 0.10 │ 0.00 │ b │ -│ 1 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ 12 │ 0.20 │ 1.00 │ a │ -│ 2 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ 13 │ 0.30 │ 2.00 │ a │ -│ 3 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ 14 │ 0.40 │ 3.00 │ a │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────┴─────────┴───────────┴───────────┴─────────╯ +$df_1 | polars join $df_2 int_1 int_1 +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────┬─────────┬───────────┬───────────┬─────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ int_2_x │ float_1_x │ float_2_x │ first_x │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┼─────────┼───────────┼───────────┼─────────┤ +# => │ 0 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ 11 │ 0.10 │ 0.00 │ b │ +# => │ 1 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ 12 │ 0.20 │ 1.00 │ a │ +# => │ 2 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ 13 │ 0.30 │ 2.00 │ a │ +# => │ 3 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ 14 │ 0.40 │ 3.00 │ a │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────┴─────────┴───────────┴───────────┴─────────╯ ``` ::: tip @@ -378,12 +378,12 @@ as long as they have the same type. For example: ```nu -> $df_1 | polars join $df_2 [int_1 first] [int_1 first] -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────┬─────────┬───────────┬───────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ int_2_x │ float_1_x │ float_2_x │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┼─────────┼───────────┼───────────┤ -│ 0 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ 11 │ 0.10 │ 0.00 │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────┴─────────┴───────────┴───────────╯ +$df_1 | polars join $df_2 [int_1 first] [int_1 first] +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────┬─────────┬───────────┬───────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ int_2_x │ float_1_x │ float_2_x │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┼─────────┼───────────┼───────────┤ +# => │ 0 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ 11 │ 0.10 │ 0.00 │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────┴─────────┴───────────┴───────────╯ ``` By default, the join command does an inner join, meaning that it will keep the @@ -404,11 +404,11 @@ operations with the same group condition. To create a `GroupBy` object you only need to use the [`polars_group-by`](/commands/docs/polars_group-by.md) command ```nu -> let group = $df_1 | polars group-by first -> $group -╭─────────────┬──────────────────────────────────────────────╮ -│ LazyGroupBy │ apply aggregation to complete execution plan │ -╰─────────────┴──────────────────────────────────────────────╯ +let group = $df_1 | polars group-by first +$group +# => ╭─────────────┬──────────────────────────────────────────────╮ +# => │ LazyGroupBy │ apply aggregation to complete execution plan │ +# => ╰─────────────┴──────────────────────────────────────────────╯ ``` When printing the `GroupBy` object we can see that it is in the background a @@ -416,15 +416,15 @@ lazy operation waiting to be completed by adding an aggregation. Using the `GroupBy` we can create aggregations on a column ```nu -> $group | polars agg (polars col int_1 | polars sum) -╭────────────────┬───────────────────────────────────────────────────────────────────────────────────────╮ -│ plan │ AGGREGATE │ -│ │ [col("int_1").sum()] BY [col("first")] FROM │ -│ │ DF ["int_1", "int_2", "float_1", "float_2"]; PROJECT */8 COLUMNS; SELECTION: "None" │ -│ optimized_plan │ AGGREGATE │ -│ │ [col("int_1").sum()] BY [col("first")] FROM │ -│ │ DF ["int_1", "int_2", "float_1", "float_2"]; PROJECT 2/8 COLUMNS; SELECTION: "None" │ -╰────────────────┴───────────────────────────────────────────────────────────────────────────────────────╯ +$group | polars agg (polars col int_1 | polars sum) +# => ╭────────────────┬───────────────────────────────────────────────────────────────────────────────────────╮ +# => │ plan │ AGGREGATE │ +# => │ │ [col("int_1").sum()] BY [col("first")] FROM │ +# => │ │ DF ["int_1", "int_2", "float_1", "float_2"]; PROJECT */8 COLUMNS; SELECTION: "None" │ +# => │ optimized_plan │ AGGREGATE │ +# => │ │ [col("int_1").sum()] BY [col("first")] FROM │ +# => │ │ DF ["int_1", "int_2", "float_1", "float_2"]; PROJECT 2/8 COLUMNS; SELECTION: "None" │ +# => ╰────────────────┴───────────────────────────────────────────────────────────────────────────────────────╯ ``` or we can define multiple aggregations on the same or different columns @@ -468,15 +468,15 @@ as integers, decimals, or strings. Let's create a small dataframe using the command `polars into-df`. ```nu -> let df_3 = [[a b]; [1 2] [3 4] [5 6]] | polars into-df -> $df_3 -╭───┬───┬───╮ -│ # │ a │ b │ -├───┼───┼───┤ -│ 0 │ 1 │ 2 │ -│ 1 │ 3 │ 4 │ -│ 2 │ 5 │ 6 │ -╰───┴───┴───╯ +let df_3 = [[a b]; [1 2] [3 4] [5 6]] | polars into-df +$df_3 +# => ╭───┬───┬───╮ +# => │ # │ a │ b │ +# => ├───┼───┼───┤ +# => │ 0 │ 1 │ 2 │ +# => │ 1 │ 3 │ 4 │ +# => │ 2 │ 5 │ 6 │ +# => ╰───┴───┴───╯ ``` ::: tip @@ -488,15 +488,15 @@ We can append columns to a dataframe in order to create a new variable. As an example, let's append two columns to our mini dataframe `$df_3` ```nu -> let df_4 = $df_3 | polars with-column $df_3.a --name a2 | polars with-column $df_3.a --name a3 -> $df_4 -╭───┬───┬───┬────┬────╮ -│ # │ a │ b │ a2 │ a3 │ -├───┼───┼───┼────┼────┤ -│ 0 │ 1 │ 2 │ 1 │ 1 │ -│ 1 │ 3 │ 4 │ 3 │ 3 │ -│ 2 │ 5 │ 6 │ 5 │ 5 │ -╰───┴───┴───┴────┴────╯ +let df_4 = $df_3 | polars with-column $df_3.a --name a2 | polars with-column $df_3.a --name a3 +$df_4 +# => ╭───┬───┬───┬────┬────╮ +# => │ # │ a │ b │ a2 │ a3 │ +# => ├───┼───┼───┼────┼────┤ +# => │ 0 │ 1 │ 2 │ 1 │ 1 │ +# => │ 1 │ 3 │ 4 │ 3 │ 3 │ +# => │ 2 │ 5 │ 6 │ 5 │ 5 │ +# => ╰───┴───┴───┴────┴────╯ ``` Nushell's powerful piping syntax allows us to create new dataframes by @@ -504,17 +504,17 @@ taking data from other dataframes and appending it to them. Now, if you list you dataframes you will see in total five dataframes ```nu -> polars store-ls | select key type columns rows estimated_size -╭──────────────────────────────────────┬─────────────┬─────────┬──────┬────────────────╮ -│ key │ type │ columns │ rows │ estimated_size │ -├──────────────────────────────────────┼─────────────┼─────────┼──────┼────────────────┤ -│ e780af47-c106-49eb-b38d-d42d3946d66e │ DataFrame │ 8 │ 10 │ 403 B │ -│ 3146f4c1-f2a0-475b-a623-7375c1fdb4a7 │ DataFrame │ 4 │ 1 │ 32 B │ -│ 455a1483-e328-43e2-a354-35afa32803b9 │ DataFrame │ 5 │ 4 │ 132 B │ -│ 0d8532a5-083b-4f78-8f66-b5e6b59dc449 │ LazyGroupBy │ │ │ │ -│ 9504dfaf-4782-42d4-9110-9dae7c8fb95b │ DataFrame │ 2 │ 3 │ 48 B │ -│ 37ab1bdc-e1fb-426d-8006-c3f974764a3d │ DataFrame │ 4 │ 3 │ 96 B │ -╰──────────────────────────────────────┴─────────────┴─────────┴──────┴────────────────╯ +polars store-ls | select key type columns rows estimated_size +# => ╭──────────────────────────────────────┬─────────────┬─────────┬──────┬────────────────╮ +# => │ key │ type │ columns │ rows │ estimated_size │ +# => ├──────────────────────────────────────┼─────────────┼─────────┼──────┼────────────────┤ +# => │ e780af47-c106-49eb-b38d-d42d3946d66e │ DataFrame │ 8 │ 10 │ 403 B │ +# => │ 3146f4c1-f2a0-475b-a623-7375c1fdb4a7 │ DataFrame │ 4 │ 1 │ 32 B │ +# => │ 455a1483-e328-43e2-a354-35afa32803b9 │ DataFrame │ 5 │ 4 │ 132 B │ +# => │ 0d8532a5-083b-4f78-8f66-b5e6b59dc449 │ LazyGroupBy │ │ │ │ +# => │ 9504dfaf-4782-42d4-9110-9dae7c8fb95b │ DataFrame │ 2 │ 3 │ 48 B │ +# => │ 37ab1bdc-e1fb-426d-8006-c3f974764a3d │ DataFrame │ 4 │ 3 │ 96 B │ +# => ╰──────────────────────────────────────┴─────────────┴─────────┴──────┴────────────────╯ ``` One thing that is important to mention is how the memory is being optimized @@ -540,15 +540,15 @@ Let's start our exploration with Series by creating one using the `polars into-d command: ```nu -> let df_5 = [9 8 4] | polars into-df -> $df_5 -╭───┬───╮ -│ # │ 0 │ -├───┼───┤ -│ 0 │ 9 │ -│ 1 │ 8 │ -│ 2 │ 4 │ -╰───┴───╯ +let df_5 = [9 8 4] | polars into-df +$df_5 +# => ╭───┬───╮ +# => │ # │ 0 │ +# => ├───┼───┤ +# => │ 0 │ 9 │ +# => │ 1 │ 8 │ +# => │ 2 │ 4 │ +# => ╰───┴───╯ ``` We have created a new series from a list of integers (we could have done the @@ -559,15 +559,15 @@ other Series. Let's create a new Series by doing some arithmetic on the previously created column. ```nu -> let df_6 = $df_5 * 3 + 10 -> $df_6 -╭───┬────╮ -│ # │ 0 │ -├───┼────┤ -│ 0 │ 37 │ -│ 1 │ 34 │ -│ 2 │ 22 │ -╰───┴────╯ +let df_6 = $df_5 * 3 + 10 +$df_6 +# => ╭───┬────╮ +# => │ # │ 0 │ +# => ├───┼────┤ +# => │ 0 │ 37 │ +# => │ 1 │ 34 │ +# => │ 2 │ 22 │ +# => ╰───┴────╯ ``` Now we have a new Series that was constructed by doing basic operations on the @@ -581,71 +581,71 @@ use `scope variables` Let's rename our previous Series so it has a memorable name ```nu -> let df_7 = $df_6 | polars rename "0" memorable -> $df_7 -╭───┬───────────╮ -│ # │ memorable │ -├───┼───────────┤ -│ 0 │ 37 │ -│ 1 │ 34 │ -│ 2 │ 22 │ -╰───┴───────────╯ +let df_7 = $df_6 | polars rename "0" memorable +$df_7 +# => ╭───┬───────────╮ +# => │ # │ memorable │ +# => ├───┼───────────┤ +# => │ 0 │ 37 │ +# => │ 1 │ 34 │ +# => │ 2 │ 22 │ +# => ╰───┴───────────╯ ``` We can also do basic operations with two Series as long as they have the same data type ```nu -> $df_5 - $df_7 -╭───┬─────────────────╮ -│ # │ sub_0_memorable │ -├───┼─────────────────┤ -│ 0 │ -28 │ -│ 1 │ -26 │ -│ 2 │ -18 │ -╰───┴─────────────────╯ +$df_5 - $df_7 +# => ╭───┬─────────────────╮ +# => │ # │ sub_0_memorable │ +# => ├───┼─────────────────┤ +# => │ 0 │ -28 │ +# => │ 1 │ -26 │ +# => │ 2 │ -18 │ +# => ╰───┴─────────────────╯ ``` And we can add them to previously defined dataframes ```nu -> let df_8 = $df_3 | polars with-column $df_5 --name new_col -> $df_8 -╭───┬───┬───┬─────────╮ -│ # │ a │ b │ new_col │ -├───┼───┼───┼─────────┤ -│ 0 │ 1 │ 2 │ 9 │ -│ 1 │ 3 │ 4 │ 8 │ -│ 2 │ 5 │ 6 │ 4 │ -╰───┴───┴───┴─────────╯ +let df_8 = $df_3 | polars with-column $df_5 --name new_col +$df_8 +# => ╭───┬───┬───┬─────────╮ +# => │ # │ a │ b │ new_col │ +# => ├───┼───┼───┼─────────┤ +# => │ 0 │ 1 │ 2 │ 9 │ +# => │ 1 │ 3 │ 4 │ 8 │ +# => │ 2 │ 5 │ 6 │ 4 │ +# => ╰───┴───┴───┴─────────╯ ``` The Series stored in a Dataframe can also be used directly, for example, we can multiply columns `a` and `b` to create a new Series ```nu -> $df_8.a * $df_8.b -╭───┬─────────╮ -│ # │ mul_a_b │ -├───┼─────────┤ -│ 0 │ 2 │ -│ 1 │ 12 │ -│ 2 │ 30 │ -╰───┴─────────╯ +$df_8.a * $df_8.b +# => ╭───┬─────────╮ +# => │ # │ mul_a_b │ +# => ├───┼─────────┤ +# => │ 0 │ 2 │ +# => │ 1 │ 12 │ +# => │ 2 │ 30 │ +# => ╰───┴─────────╯ ``` and we can start piping things in order to create new columns and dataframes ```nu -> let df_9 = $df_8 | polars with-column ($df_8.a * $df_8.b / $df_8.new_col) --name my_sum -> $df_9 -╭───┬───┬───┬─────────┬────────╮ -│ # │ a │ b │ new_col │ my_sum │ -├───┼───┼───┼─────────┼────────┤ -│ 0 │ 1 │ 2 │ 9 │ 0 │ -│ 1 │ 3 │ 4 │ 8 │ 1 │ -│ 2 │ 5 │ 6 │ 4 │ 7 │ -╰───┴───┴───┴─────────┴────────╯ +let df_9 = $df_8 | polars with-column ($df_8.a * $df_8.b / $df_8.new_col) --name my_sum +$df_9 +# => ╭───┬───┬───┬─────────┬────────╮ +# => │ # │ a │ b │ new_col │ my_sum │ +# => ├───┼───┼───┼─────────┼────────┤ +# => │ 0 │ 1 │ 2 │ 9 │ 0 │ +# => │ 1 │ 3 │ 4 │ 8 │ 1 │ +# => │ 2 │ 5 │ 6 │ 4 │ 7 │ +# => ╰───┴───┴───┴─────────┴────────╯ ``` Nushell's piping system can help you create very interesting workflows. @@ -657,26 +657,26 @@ that we can build boolean masks out of them. Let's start by creating a simple mask using the equality operator ```nu -> let mask_0 = $df_5 == 8 -> $mask_0 -╭───┬───────╮ -│ # │ 0 │ -├───┼───────┤ -│ 0 │ false │ -│ 1 │ true │ -│ 2 │ false │ -╰───┴───────╯ +let mask_0 = $df_5 == 8 +$mask_0 +# => ╭───┬───────╮ +# => │ # │ 0 │ +# => ├───┼───────┤ +# => │ 0 │ false │ +# => │ 1 │ true │ +# => │ 2 │ false │ +# => ╰───┴───────╯ ``` and with this mask we can now filter a dataframe, like this ```nu -> $df_9 | polars filter-with $mask_0 -╭───┬───┬───┬─────────┬────────╮ -│ # │ a │ b │ new_col │ my_sum │ -├───┼───┼───┼─────────┼────────┤ -│ 0 │ 3 │ 4 │ 8 │ 1 │ -╰───┴───┴───┴─────────┴────────╯ +$df_9 | polars filter-with $mask_0 +# => ╭───┬───┬───┬─────────┬────────╮ +# => │ # │ a │ b │ new_col │ my_sum │ +# => ├───┼───┼───┼─────────┼────────┤ +# => │ 0 │ 3 │ 4 │ 8 │ 1 │ +# => ╰───┴───┴───┴─────────┴────────╯ ``` Now we have a new dataframe with only the values where the mask was true. @@ -684,70 +684,70 @@ Now we have a new dataframe with only the values where the mask was true. The masks can also be created from Nushell lists, for example: ```nu -> let mask_1 = [true true false] | polars into-df -> $df_9 | polars filter-with $mask_1 -╭───┬───┬───┬─────────┬────────╮ -│ # │ a │ b │ new_col │ my_sum │ -├───┼───┼───┼─────────┼────────┤ -│ 0 │ 1 │ 2 │ 9 │ 0 │ -│ 1 │ 3 │ 4 │ 8 │ 1 │ -╰───┴───┴───┴─────────┴────────╯ +let mask_1 = [true true false] | polars into-df +$df_9 | polars filter-with $mask_1 +# => ╭───┬───┬───┬─────────┬────────╮ +# => │ # │ a │ b │ new_col │ my_sum │ +# => ├───┼───┼───┼─────────┼────────┤ +# => │ 0 │ 1 │ 2 │ 9 │ 0 │ +# => │ 1 │ 3 │ 4 │ 8 │ 1 │ +# => ╰───┴───┴───┴─────────┴────────╯ ``` To create complex masks, we have the `AND` ```nu -> $mask_0 and $mask_1 -╭───┬─────────╮ -│ # │ and_0_0 │ -├───┼─────────┤ -│ 0 │ false │ -│ 1 │ true │ -│ 2 │ false │ -╰───┴─────────╯ +$mask_0 and $mask_1 +# => ╭───┬─────────╮ +# => │ # │ and_0_0 │ +# => ├───┼─────────┤ +# => │ 0 │ false │ +# => │ 1 │ true │ +# => │ 2 │ false │ +# => ╰───┴─────────╯ ``` and `OR` operations ```nu -> $mask_0 or $mask_1 -╭───┬────────╮ -│ # │ or_0_0 │ -├───┼────────┤ -│ 0 │ true │ -│ 1 │ true │ -│ 2 │ false │ -╰───┴────────╯ +$mask_0 or $mask_1 +# => ╭───┬────────╮ +# => │ # │ or_0_0 │ +# => ├───┼────────┤ +# => │ 0 │ true │ +# => │ 1 │ true │ +# => │ 2 │ false │ +# => ╰───┴────────╯ ``` We can also create a mask by checking if some values exist in other Series. Using the first dataframe that we created we can do something like this ```nu -> let mask_2 = $df_1 | polars col first | polars is-in [b c] -> $mask_2 -╭──────────┬─────────────────────────╮ -│ input │ [table 2 rows] │ -│ function │ Boolean(IsIn) │ -│ options │ FunctionOptions { ... } │ -╰──────────┴─────────────────────────╯ +let mask_2 = $df_1 | polars col first | polars is-in [b c] +$mask_2 +# => ╭──────────┬─────────────────────────╮ +# => │ input │ [table 2 rows] │ +# => │ function │ Boolean(IsIn) │ +# => │ options │ FunctionOptions { ... } │ +# => ╰──────────┴─────────────────────────╯ ``` and this new mask can be used to filter the dataframe ```nu -> $df_1 | polars filter-with $mask_2 -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ -│ 0 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ -│ 1 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ -│ 2 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ -│ 3 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ -│ 4 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ -│ 5 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ -│ 6 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ +$df_1 | polars filter-with $mask_2 +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ +# => │ 0 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ +# => │ 1 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ +# => │ 2 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ +# => │ 3 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ +# => │ 4 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ +# => │ 5 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ +# => │ 6 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ ``` Another operation that can be done with masks is setting or replacing a value @@ -755,21 +755,21 @@ from a series. For example, we can change the value in the column `first` where the value is equal to `a` ```nu -> $df_1 | polars get first | polars set new --mask ($df_1.first =~ a) -╭───┬────────╮ -│ # │ string │ -├───┼────────┤ -│ 0 │ new │ -│ 1 │ new │ -│ 2 │ new │ -│ 3 │ b │ -│ 4 │ b │ -│ 5 │ b │ -│ 6 │ b │ -│ 7 │ c │ -│ 8 │ c │ -│ 9 │ c │ -╰───┴────────╯ +$df_1 | polars get first | polars set new --mask ($df_1.first =~ a) +# => ╭───┬────────╮ +# => │ # │ string │ +# => ├───┼────────┤ +# => │ 0 │ new │ +# => │ 1 │ new │ +# => │ 2 │ new │ +# => │ 3 │ b │ +# => │ 4 │ b │ +# => │ 5 │ b │ +# => │ 6 │ b │ +# => │ 7 │ c │ +# => │ 8 │ c │ +# => │ 9 │ c │ +# => ╰───┴────────╯ ``` ## Series as Indices @@ -780,15 +780,15 @@ from our original dataframe. With that in mind, we can use the next command to extract that information ```nu -> let indices_0 = [1 4 6] | polars into-df -> $df_1 | polars take $indices_0 -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ -│ 0 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │ -│ 1 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ -│ 2 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ +let indices_0 = [1 4 6] | polars into-df +$df_1 | polars take $indices_0 +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ +# => │ 0 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │ +# => │ 1 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ +# => │ 2 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ ``` The command [`polars take`](/commands/docs/polars_take.md) is very handy, especially if we mix it with other commands. @@ -797,15 +797,15 @@ column `first`. In order to do that, we can use the command `polars arg-unique` shown in the next example ```nu -> let indices_1 = $df_1 | polars get first | polars arg-unique -> $df_1 | polars take $indices_1 -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ -│ 0 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │ -│ 1 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ -│ 2 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ +let indices_1 = $df_1 | polars get first | polars arg-unique +$df_1 | polars take $indices_1 +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ +# => │ 0 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │ +# => │ 1 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ +# => │ 2 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ ``` Or what if we want to create a new sorted dataframe using a column in specific. @@ -817,44 +817,44 @@ The same result could be accomplished using the command [`sort`](/commands/docs/ ::: ```nu -> let indices_2 = $df_1 | polars get word | polars arg-sort -> $df_1 | polars take $indices_2 -╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ -│ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ -├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ -│ 0 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ -│ 1 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │ -│ 2 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ -│ 3 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │ -│ 4 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │ -│ 5 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ -│ 6 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ -│ 7 │ 3 │ 13 │ 0.30 │ 2.00 │ a │ b │ c │ third │ -│ 8 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ -│ 9 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ -╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ +let indices_2 = $df_1 | polars get word | polars arg-sort +$df_1 | polars take $indices_2 +# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮ +# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │ +# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤ +# => │ 0 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │ +# => │ 1 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │ +# => │ 2 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │ +# => │ 3 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │ +# => │ 4 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │ +# => │ 5 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │ +# => │ 6 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │ +# => │ 7 │ 3 │ 13 │ 0.30 │ 2.00 │ a │ b │ c │ third │ +# => │ 8 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │ +# => │ 9 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │ +# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯ ``` And finally, we can create new Series by setting a new value in the marked indices. Have a look at the next command ```nu -> let indices_3 = [0 2] | polars into-df -> $df_1 | polars get int_1 | polars set-with-idx 123 --indices $indices_3 -╭───┬───────╮ -│ # │ int_1 │ -├───┼───────┤ -│ 0 │ 123 │ -│ 1 │ 2 │ -│ 2 │ 123 │ -│ 3 │ 4 │ -│ 4 │ 0 │ -│ 5 │ 6 │ -│ 6 │ 7 │ -│ 7 │ 8 │ -│ 8 │ 9 │ -│ 9 │ 0 │ -╰───┴───────╯ +let indices_3 = [0 2] | polars into-df +$df_1 | polars get int_1 | polars set-with-idx 123 --indices $indices_3 +# => ╭───┬───────╮ +# => │ # │ int_1 │ +# => ├───┼───────┤ +# => │ 0 │ 123 │ +# => │ 1 │ 2 │ +# => │ 2 │ 123 │ +# => │ 3 │ 4 │ +# => │ 4 │ 0 │ +# => │ 5 │ 6 │ +# => │ 6 │ 7 │ +# => │ 7 │ 8 │ +# => │ 8 │ 9 │ +# => │ 9 │ 0 │ +# => ╰───┴───────╯ ``` ## Unique Values @@ -869,14 +869,14 @@ example, we can use it to count how many occurrences we have in the column `first` ```nu -> $df_1 | polars get first | polars value-counts -╭───┬───────┬───────╮ -│ # │ first │ count │ -├───┼───────┼───────┤ -│ 0 │ a │ 3 │ -│ 1 │ b │ 4 │ -│ 2 │ c │ 3 │ -╰───┴───────┴───────╯ +$df_1 | polars get first | polars value-counts +# => ╭───┬───────┬───────╮ +# => │ # │ first │ count │ +# => ├───┼───────┼───────┤ +# => │ 0 │ a │ 3 │ +# => │ 1 │ b │ 4 │ +# => │ 2 │ c │ 3 │ +# => ╰───┴───────┴───────╯ ``` As expected, the command returns a new dataframe that can be used to do more @@ -886,14 +886,14 @@ Continuing with our exploration of `Series`, the next thing that we can do is to only get the unique unique values from a series, like this ```nu -> $df_1 | polars get first | polars unique -╭───┬───────╮ -│ # │ first │ -├───┼───────┤ -│ 0 │ a │ -│ 1 │ b │ -│ 2 │ c │ -╰───┴───────╯ +$df_1 | polars get first | polars unique +# => ╭───┬───────╮ +# => │ # │ first │ +# => ├───┼───────┤ +# => │ 0 │ a │ +# => │ 1 │ b │ +# => │ 2 │ c │ +# => ╰───┴───────╯ ``` Or we can get a mask that we can use to filter out the rows where data is @@ -949,12 +949,12 @@ operations. Let's create a small example of a lazy dataframe ```nu -> let lf_0 = [[a b]; [1 a] [2 b] [3 c] [4 d]] | polars into-lazy -> $lf_0 -╭────────────────┬───────────────────────────────────────────────────────╮ -│ plan │ DF ["a", "b"]; PROJECT */2 COLUMNS; SELECTION: "None" │ -│ optimized_plan │ DF ["a", "b"]; PROJECT */2 COLUMNS; SELECTION: "None" │ -╰────────────────┴───────────────────────────────────────────────────────╯ +let lf_0 = [[a b]; [1 a] [2 b] [3 c] [4 d]] | polars into-lazy +$lf_0 +# => ╭────────────────┬───────────────────────────────────────────────────────╮ +# => │ plan │ DF ["a", "b"]; PROJECT */2 COLUMNS; SELECTION: "None" │ +# => │ optimized_plan │ DF ["a", "b"]; PROJECT */2 COLUMNS; SELECTION: "None" │ +# => ╰────────────────┴───────────────────────────────────────────────────────╯ ``` As you can see, the resulting dataframe is not yet evaluated, it stays as a @@ -962,15 +962,15 @@ set of instructions that can be done on the data. If you were to collect that dataframe you would get the next result ```nu -> $lf_0 | polars collect -╭───┬───┬───╮ -│ # │ a │ b │ -├───┼───┼───┤ -│ 0 │ 1 │ a │ -│ 1 │ 2 │ b │ -│ 2 │ 3 │ c │ -│ 3 │ 4 │ d │ -╰───┴───┴───╯ +$lf_0 | polars collect +# => ╭───┬───┬───╮ +# => │ # │ a │ b │ +# => ├───┼───┼───┤ +# => │ 0 │ 1 │ a │ +# => │ 1 │ 2 │ b │ +# => │ 2 │ 3 │ c │ +# => │ 3 │ 4 │ d │ +# => ╰───┴───┴───╯ ``` as you can see, the collect command executes the plan and creates a nushell @@ -1034,29 +1034,29 @@ In some cases the use of the `polars col` command can be inferred. For example, using the `polars select` command we can use only a string ```nu -> $lf_0 | polars select a | polars collect -╭───┬───╮ -│ # │ a │ -├───┼───┤ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -╰───┴───╯ +$lf_0 | polars select a | polars collect +# => ╭───┬───╮ +# => │ # │ a │ +# => ├───┼───┤ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => ╰───┴───╯ ``` or the `polars col` command ```nu -> $lf_0 | polars select (polars col a) | polars collect -╭───┬───╮ -│ # │ a │ -├───┼───┤ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -╰───┴───╯ +$lf_0 | polars select (polars col a) | polars collect +# => ╭───┬───╮ +# => │ # │ a │ +# => ├───┼───┤ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => ╰───┴───╯ ``` Let's try something more complicated and create aggregations from a lazy diff --git a/book/environment.md b/book/environment.md index 30bed7c099..e590d580ba 100644 --- a/book/environment.md +++ b/book/environment.md @@ -5,22 +5,22 @@ A common task in a shell is to control the environment that external application You can see the current environment variables in the $env variable: ```nu -~> $env | table -e -╭──────────────────────────────────┬───────────────────────────────────────────╮ -│ │ ╭──────┬────────────────────────────────╮ │ -│ ENV_CONVERSIONS │ │ │ ╭─────────────┬──────────────╮ │ │ -│ │ │ PATH │ │ from_string │ │ │ │ -│ │ │ │ │ to_string │ │ │ │ -│ │ │ │ ╰─────────────┴──────────────╯ │ │ -│ │ │ │ ╭─────────────┬──────────────╮ │ │ -│ │ │ Path │ │ from_string │ │ │ │ -│ │ │ │ │ to_string │ │ │ │ -│ │ │ │ ╰─────────────┴──────────────╯ │ │ -│ │ ╰──────┴────────────────────────────────╯ │ -│ HOME │ /Users/jelle │ -│ LSCOLORS │ GxFxCxDxBxegedabagaced │ -| ... | ... | -╰──────────────────────────────────┴───────────────────────────────────────────╯ +$env | table -e +# => ╭──────────────────────────────────┬───────────────────────────────────────────╮ +# => │ │ ╭──────┬────────────────────────────────╮ │ +# => │ ENV_CONVERSIONS │ │ │ ╭─────────────┬──────────────╮ │ │ +# => │ │ │ PATH │ │ from_string │ │ │ │ +# => │ │ │ │ │ to_string │ │ │ │ +# => │ │ │ │ ╰─────────────┴──────────────╯ │ │ +# => │ │ │ │ ╭─────────────┬──────────────╮ │ │ +# => │ │ │ Path │ │ from_string │ │ │ │ +# => │ │ │ │ │ to_string │ │ │ │ +# => │ │ │ │ ╰─────────────┴──────────────╯ │ │ +# => │ │ ╰──────┴────────────────────────────────╯ │ +# => │ HOME │ /Users/jelle │ +# => │ LSCOLORS │ GxFxCxDxBxegedabagaced │ +# => | ... | ... | +# => ╰──────────────────────────────────┴───────────────────────────────────────────╯ ``` In Nushell, environment variables can be any value and have any type. You can see the type of an env variable with the describe command, for example: `$env.PROMPT_COMMAND | describe`. @@ -38,7 +38,7 @@ There are several ways to set an environment variable: Using the `$env.VAR = "val"` is the most straightforward method ```nu -> $env.FOO = 'BAR' +$env.FOO = 'BAR' ``` So, if you want to extend the Windows `Path` variable, for example, you could do that as follows. @@ -55,7 +55,7 @@ If you want to give it the lowest priority instead, you can use the [`append`](/ If you have more than one environment variable you'd like to set, you can use [`load-env`](/commands/docs/load-env.md) to create a table of name/value pairs and load multiple variables at the same time: ```nu -> load-env { "BOB": "FOO", "JAY": "BAR" } +load-env { "BOB": "FOO", "JAY": "BAR" } ``` ### One-shot Environment Variables @@ -76,41 +76,41 @@ See [Modules](modules.md) for details. Individual environment variables are fields of a record that is stored in the `$env` variable and can be read with `$env.VARIABLE`: ```nu -> $env.FOO -BAR +$env.FOO +# => BAR ``` Sometimes, you may want to access an environmental variable which might be unset. Consider using the [question mark operator](types_of_data.md#optional-cell-paths) to avoid an error: ```nu -> $env.FOO | describe -Error: nu::shell::column_not_found - - × Cannot find column - ╭─[entry #1:1:1] - 1 │ $env.FOO - · ──┬─ ─┬─ - · │ ╰── cannot find column 'FOO' - · ╰── value originates here - ╰──── +$env.FOO | describe +# => Error: nu::shell::column_not_found +# => +# => × Cannot find column +# => ╭─[entry #1:1:1] +# => 1 │ $env.FOO +# => · ──┬─ ─┬─ +# => · │ ╰── cannot find column 'FOO' +# => · ╰── value originates here +# => ╰──── -> $env.FOO? | describe -nothing +$env.FOO? | describe +# => nothing -> $env.FOO? | default "BAR" -BAR +$env.FOO? | default "BAR" +# => BAR ``` Alternatively, you can check for the presence of an environmental variable with `in`: ``` -> $env.FOO -BAR +$env.FOO +# => BAR -> if "FOO" in $env { -> echo $env.FOO -> } -BAR +if "FOO" in $env { +echo $env.FOO +} +# => BAR ``` ### Case sensitivity @@ -126,14 +126,14 @@ When you set an environment variable, it will be available only in the current s Here is a small example to demonstrate the environment scoping: ```nu -> $env.FOO = "BAR" -> do { +$env.FOO = "BAR" +do { $env.FOO = "BAZ" $env.FOO == "BAZ" } -true -> $env.FOO == "BAR" -true +# => true +$env.FOO == "BAR" +# => true ``` See also: [Changing the Environment in a Custom Command](./custom_commands.html#changing-the-environment-in-a-custom-command). @@ -147,15 +147,15 @@ A common task in a shell is to change the directory using the [`cd`](/commands/d A common shorthand to set an environment variable once is available, inspired by Bash and others: ```nu -> FOO=BAR $env.FOO -BAR +FOO=BAR $env.FOO +# => BAR ``` You can also use [`with-env`](/commands/docs/with-env.md) to do the same thing more explicitly: ```nu -> with-env { FOO: BAR } { $env.FOO } -BAR +with-env { FOO: BAR } { $env.FOO } +# => BAR ``` The [`with-env`](/commands/docs/with-env.md) command will temporarily set the environment variable to the value given (here: the variable "FOO" is given the value "BAR"). Once this is done, the [block](types_of_data.md#blocks) will run with this new environment variable set. @@ -195,26 +195,26 @@ $env.ENV_CONVERSIONS = { Now, within a Nushell instance: ```nu -> with-env { FOO : 'a-b-c' } { nu } # runs Nushell with FOO env. var. set to 'a-b-c' +with-env { FOO : 'a-b-c' } { nu } # runs Nushell with FOO env. var. set to 'a-b-c' -> $env.FOO - 0 a - 1 b - 2 c +$env.FOO +# => 0 a +# => 1 b +# => 2 c ``` You can see the `$env.FOO` is now a list in a new Nushell instance with the updated config. You can also test the conversion manually by ```nu -> do $env.ENV_CONVERSIONS.FOO.from_string 'a-b-c' +do $env.ENV_CONVERSIONS.FOO.from_string 'a-b-c' ``` Now, to test the conversion list -> string, run: ```nu -> nu -c '$env.FOO' -a-b-c +nu -c '$env.FOO' +# => a-b-c ``` Because `nu` is an external program, Nushell translated the `[ a b c ]` list according to `ENV_CONVERSIONS.FOO.to_string` and passed it to the `nu` process. @@ -228,19 +228,19 @@ _(Important! The environment conversion string -> value happens **after** the en You can remove an environment variable only if it was set in the current scope via [`hide-env`](/commands/docs/hide-env.md): ```nu -> $env.FOO = 'BAR' -... -> hide-env FOO +$env.FOO = 'BAR' +# => ... +hide-env FOO ``` The hiding is also scoped which both allows you to remove an environment variable temporarily and prevents you from modifying a parent environment from within a child scope: ```nu -> $env.FOO = 'BAR' -> do { +$env.FOO = 'BAR' +do { hide-env FOO # $env.FOO does not exist } -> $env.FOO -BAR +$env.FOO +# => BAR ``` diff --git a/book/hooks.md b/book/hooks.md index 55b655bef8..1210ada256 100644 --- a/book/hooks.md +++ b/book/hooks.md @@ -88,12 +88,12 @@ Environment variables defined inside the hook **block** will be preserved in a s You can test it with the following example: ```nu -> $env.config = ($env.config | upsert hooks { +$env.config = ($env.config | upsert hooks { pre_prompt: { $env.SPAM = "eggs" } }) -> $env.SPAM -eggs +$env.SPAM +# => eggs ``` The hook blocks otherwise follow the general scoping rules, i.e., commands, aliases, etc. defined within the block will be thrown away once the block ends. @@ -150,12 +150,12 @@ You can think of it as if you typed the string into the REPL and hit Enter. So, the hook from the previous section can be also written as ```nu -> $env.config = ($env.config | upsert hooks { +$env.config = ($env.config | upsert hooks { pre_prompt: '$env.SPAM = "eggs"' }) -> $env.SPAM -eggs +$env.SPAM +# => eggs ``` This feature can be used, for example, to conditionally bring in definitions based on the current directory: diff --git a/book/loading_data.md b/book/loading_data.md index e38a4b6d9a..9c3fab8936 100644 --- a/book/loading_data.md +++ b/book/loading_data.md @@ -13,8 +13,8 @@ In a similar way to [`ls`](/commands/docs/ls.md), opening a file type that Nu un If we wanted to check the version of the project we were looking at, we can use the [`get`](/commands/docs/get.md) command. ```nu -> open editors/vscode/package.json | get version -1.0.0 +open editors/vscode/package.json | get version +# => 1.0.0 ``` Nu currently supports the following formats for loading data directly into tables: @@ -44,7 +44,7 @@ You can thus simply extend the set of supported file types of `open` by creating But what happens if you load a text file that isn't one of these? Let's try it: ```nu -> open README.md +open README.md ``` We're shown the contents of the file. @@ -98,10 +98,10 @@ An important part of working with data coming from outside Nu is that it's not a Let's imagine that we're given this data file: ```nu -> open people.txt -Octavia | Butler | Writer -Bob | Ross | Painter -Antonio | Vivaldi | Composer +open people.txt +# => Octavia | Butler | Writer +# => Bob | Ross | Painter +# => Antonio | Vivaldi | Composer ``` Each bit of data we want is separated by the pipe ('|') symbol, and each person is on a separate line. Nu doesn't have a pipe-delimited file format by default, so we'll have to parse this ourselves. @@ -109,75 +109,75 @@ Each bit of data we want is separated by the pipe ('|') symbol, and each person The first thing we want to do when bringing in the file is to work with it a line at a time: ```nu -> open people.txt | lines -───┬────────────────────────────── - 0 │ Octavia | Butler | Writer - 1 │ Bob | Ross | Painter - 2 │ Antonio | Vivaldi | Composer -───┴────────────────────────────── +open people.txt | lines +# => ───┬────────────────────────────── +# => 0 │ Octavia | Butler | Writer +# => 1 │ Bob | Ross | Painter +# => 2 │ Antonio | Vivaldi | Composer +# => ───┴────────────────────────────── ``` We can see that we're working with the lines because we're back into a list. Our next step is to see if we can split up the rows into something a little more useful. For that, we'll use the [`split`](/commands/docs/split.md) command. [`split`](/commands/docs/split.md), as the name implies, gives us a way to split a delimited string. We will use [`split`](/commands/docs/split.md)'s `column` subcommand to split the contents across multiple columns. We tell it what the delimiter is, and it does the rest: ```nu -> open people.txt | lines | split column "|" -───┬──────────┬───────────┬─────────── - # │ column1 │ column2 │ column3 -───┼──────────┼───────────┼─────────── - 0 │ Octavia │ Butler │ Writer - 1 │ Bob │ Ross │ Painter - 2 │ Antonio │ Vivaldi │ Composer -───┴──────────┴───────────┴─────────── +open people.txt | lines | split column "|" +# => ───┬──────────┬───────────┬─────────── +# => # │ column1 │ column2 │ column3 +# => ───┼──────────┼───────────┼─────────── +# => 0 │ Octavia │ Butler │ Writer +# => 1 │ Bob │ Ross │ Painter +# => 2 │ Antonio │ Vivaldi │ Composer +# => ───┴──────────┴───────────┴─────────── ``` That _almost_ looks correct. It looks like there's an extra space there. Let's [`trim`](/commands/docs/str_trim.md) that extra space: ```nu -> open people.txt | lines | split column "|" | str trim -───┬─────────┬─────────┬────────── - # │ column1 │ column2 │ column3 -───┼─────────┼─────────┼────────── - 0 │ Octavia │ Butler │ Writer - 1 │ Bob │ Ross │ Painter - 2 │ Antonio │ Vivaldi │ Composer -───┴─────────┴─────────┴────────── +open people.txt | lines | split column "|" | str trim +# => ───┬─────────┬─────────┬────────── +# => # │ column1 │ column2 │ column3 +# => ───┼─────────┼─────────┼────────── +# => 0 │ Octavia │ Butler │ Writer +# => 1 │ Bob │ Ross │ Painter +# => 2 │ Antonio │ Vivaldi │ Composer +# => ───┴─────────┴─────────┴────────── ``` Not bad. The [`split`](/commands/docs/split.md) command gives us data we can use. It also goes ahead and gives us default column names: ```nu -> open people.txt | lines | split column "|" | str trim | get column1 -───┬───────── - 0 │ Octavia - 1 │ Bob - 2 │ Antonio -───┴───────── +open people.txt | lines | split column "|" | str trim | get column1 +# => ───┬───────── +# => 0 │ Octavia +# => 1 │ Bob +# => 2 │ Antonio +# => ───┴───────── ``` We can also name our columns instead of using the default names: ```nu -> open people.txt | lines | split column "|" first_name last_name job | str trim -───┬────────────┬───────────┬────────── - # │ first_name │ last_name │ job -───┼────────────┼───────────┼────────── - 0 │ Octavia │ Butler │ Writer - 1 │ Bob │ Ross │ Painter - 2 │ Antonio │ Vivaldi │ Composer -───┴────────────┴───────────┴────────── +open people.txt | lines | split column "|" first_name last_name job | str trim +# => ───┬────────────┬───────────┬────────── +# => # │ first_name │ last_name │ job +# => ───┼────────────┼───────────┼────────── +# => 0 │ Octavia │ Butler │ Writer +# => 1 │ Bob │ Ross │ Painter +# => 2 │ Antonio │ Vivaldi │ Composer +# => ───┴────────────┴───────────┴────────── ``` Now that our data is in a table, we can use all the commands we've used on tables before: ```nu -> open people.txt | lines | split column "|" first_name last_name job | str trim | sort-by first_name -───┬────────────┬───────────┬────────── - # │ first_name │ last_name │ job -───┼────────────┼───────────┼────────── - 0 │ Antonio │ Vivaldi │ Composer - 1 │ Bob │ Ross │ Painter - 2 │ Octavia │ Butler │ Writer -───┴────────────┴───────────┴────────── +open people.txt | lines | split column "|" first_name last_name job | str trim | sort-by first_name +# => ───┬────────────┬───────────┬────────── +# => # │ first_name │ last_name │ job +# => ───┼────────────┼───────────┼────────── +# => 0 │ Antonio │ Vivaldi │ Composer +# => 1 │ Bob │ Ross │ Painter +# => 2 │ Octavia │ Butler │ Writer +# => ───┴────────────┴───────────┴────────── ``` There are other commands you can use to work with strings: @@ -188,12 +188,12 @@ There are other commands you can use to work with strings: There is also a set of helper commands we can call if we know the data has a structure that Nu should be able to understand. For example, let's open a Rust lock file: ```nu -> open Cargo.lock -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "adhoc_derive" -version = "0.1.2" +open Cargo.lock +# => # This file is automatically @generated by Cargo. +# => # It is not intended for manual editing. +# => [[package]] +# => name = "adhoc_derive" +# => version = "0.1.2" ``` The "Cargo.lock" file is actually a .toml file, but the file extension isn't .toml. That's okay, we can use the [`from`](/commands/docs/from.md) command using the `toml` subcommand: @@ -207,12 +207,12 @@ The [`from`](/commands/docs/from.md) command can be used for each of the structu While it's helpful to be able to open a file and immediately work with a table of its data, this is not always what you want to do. To get to the underlying text, the [`open`](/commands/docs/open.md) command can take an optional `--raw` flag: ```nu -> open Cargo.toml --raw -[package] name = "nu" -version = "0.1.3" -authors = ["Yehuda Katz ", "Sophia Turner <547158+sophiajt@users.noreply.github.com>"] -description = "A shell for the GitHub era" -license = "MIT" +open Cargo.toml --raw +# => [package] name = "nu" +# => version = "0.1.3" +# => authors = ["Yehuda Katz ", "Sophia Turner <547158+sophiajt@users.noreply.github.com>"] +# => description = "A shell for the GitHub era" +# => license = "MIT" ``` ## SQLite @@ -220,19 +220,19 @@ license = "MIT" SQLite databases are automatically detected by [`open`](/commands/docs/open.md), no matter what their file extension is. You can open a whole database: ```nu -> open foo.db +open foo.db ``` Or [`get`](/commands/docs/get.md) a specific table: ```nu -> open foo.db | get some_table +open foo.db | get some_table ``` Or run any SQL query you like: ```nu -> open foo.db | query db "select * from some_table" +open foo.db | query db "select * from some_table" ``` (Note: some older versions of Nu use `into db | query` instead of `query db` ) diff --git a/book/metadata.md b/book/metadata.md index 24f711cdeb..950a050e7e 100644 --- a/book/metadata.md +++ b/book/metadata.md @@ -3,14 +3,14 @@ In using Nu, you may have come across times where you felt like there was something extra going on behind the scenes. For example, let's say that you try to open a file that Nu supports only to forget and try to convert again: ```nu -> open Cargo.toml | from toml -error: Expected a string from pipeline -- shell:1:18 -1 | open Cargo.toml | from toml - | ^^^^^^^^^ requires string input -- shell:1:5 -1 | open Cargo.toml | from toml - | ---------- object originates from here +open Cargo.toml | from toml +# => error: Expected a string from pipeline +# => - shell:1:18 +# => 1 | open Cargo.toml | from toml +# => | ^^^^^^^^^ requires string input +# => - shell:1:5 +# => 1 | open Cargo.toml | from toml +# => | ---------- object originates from here ``` The error message tells us not only that what we gave [`from toml`](/commands/docs/from_toml.md) wasn't a string, but also where the value originally came from. How would it know that? @@ -20,20 +20,20 @@ Values that flow through a pipeline in Nu often have a set of additional informa Let's run the [`open`](/commands/docs/open.md) command again, but this time, we'll look at the tags it gives back: ```nu -> metadata (open Cargo.toml) -╭──────┬───────────────────╮ -│ span │ {record 2 fields} │ -╰──────┴───────────────────╯ +metadata (open Cargo.toml) +# => ╭──────┬───────────────────╮ +# => │ span │ {record 2 fields} │ +# => ╰──────┴───────────────────╯ ``` Currently, we track only the span of where values come from. Let's take a closer look at that: ```nu -> metadata (open Cargo.toml) | get span -╭───────┬────────╮ -│ start │ 212970 │ -│ end │ 212987 │ -╰───────┴────────╯ +metadata (open Cargo.toml) | get span +# => ╭───────┬────────╮ +# => │ start │ 212970 │ +# => │ end │ 212987 │ +# => ╰───────┴────────╯ ``` The span "start" and "end" here refer to where the underline will be in the line. If you count over 5, and then count up to 15, you'll see it lines up with the "Cargo.toml" filename. This is how the error we saw earlier knew what to underline. diff --git a/book/navigating_structured_data.md b/book/navigating_structured_data.md index 82da7978c7..2567444e8f 100644 --- a/book/navigating_structured_data.md +++ b/book/navigating_structured_data.md @@ -47,12 +47,12 @@ For a record, the cell-path specifies the name of a key, which is a `string`. #### Example - Access a Record Value: ```nu -> let my_record = { +let my_record = { a: 5 b: 42 } -> $my_record.b + 5 -47 +$my_record.b + 5 +# => 47 ``` ### Lists @@ -64,9 +64,9 @@ For a list, the cell-path specifies the position (index) of the value in the lis Remember, list indices are 0-based. ```nu -> let scoobies_list = [ Velma Fred Daphne Shaggy Scooby ] -> $scoobies_list.2 -Daphne +let scoobies_list = [ Velma Fred Daphne Shaggy Scooby ] +$scoobies_list.2 +# => Daphne ``` ### Tables @@ -137,30 +137,30 @@ This represents weather data in the form of a table with three columns: Access the second day's data as a record: ```nu -> $data.1 -╭───────────┬───────────────╮ -│ date │ 2 years ago │ -│ │ ╭───┬───────╮ │ -│ temps │ │ 0 │ 35.24 │ │ -│ │ │ 1 │ 35.94 │ │ -│ │ │ 2 │ 34.91 │ │ -│ │ │ 3 │ 35.24 │ │ -│ │ │ 4 │ 36.65 │ │ -│ │ ╰───┴───────╯ │ -│ condition │ sunny │ -╰───────────┴───────────────╯ +$data.1 +# => ╭───────────┬───────────────╮ +# => │ date │ 2 years ago │ +# => │ │ ╭───┬───────╮ │ +# => │ temps │ │ 0 │ 35.24 │ │ +# => │ │ │ 1 │ 35.94 │ │ +# => │ │ │ 2 │ 34.91 │ │ +# => │ │ │ 3 │ 35.24 │ │ +# => │ │ │ 4 │ 36.65 │ │ +# => │ │ ╰───┴───────╯ │ +# => │ condition │ sunny │ +# => ╰───────────┴───────────────╯ ``` #### Example - Access a Table Column (List) ```nu -> $data.condition -╭───┬────────╮ -│ 0 │ sunny │ -│ 1 │ sunny │ -│ 2 │ cloudy │ -│ 3 │ rain │ -╰───┴────────╯ +$data.condition +# => ╭───┬────────╮ +# => │ 0 │ sunny │ +# => │ 1 │ sunny │ +# => │ 2 │ cloudy │ +# => │ 3 │ rain │ +# => ╰───┴────────╯ ``` #### Example - Access a Table Cell (Value) @@ -168,8 +168,8 @@ Access the second day's data as a record: The condition for the fourth day: ```nu -> $data.condition.3 -rain +$data.condition.3 +# => rain ``` ### Nested Data @@ -181,8 +181,8 @@ Since data can be nested, a cell-path can contain references to multiple names o To obtain the temperature at the second weather station on the third day: ```nu -> $data.temps.2.1 -36.67 +$data.temps.2.1 +# => 36.67 ``` The first index `2` accesses the third day, then the next index `1` accesses the second weather station's temperature reading. @@ -202,31 +202,31 @@ Continuing with the sample table above: ### Example - `get` vs. `select` a table row ```nu -> $data | get 1 -╭───────────┬───────────────╮ -│ date │ 2 years ago │ -│ │ ╭───┬───────╮ │ -│ temps │ │ 0 │ 35.24 │ │ -│ │ │ 1 │ 35.94 │ │ -│ │ │ 2 │ 34.91 │ │ -│ │ │ 3 │ 35.24 │ │ -│ │ │ 4 │ 36.65 │ │ -│ │ ╰───┴───────╯ │ -│ condition │ sunny │ -╰───────────┴───────────────╯ - -> $data | select 1 -╭───┬─────────────┬───────────────┬───────────╮ -│ # │ date │ temps │ condition │ -├───┼─────────────┼───────────────┼───────────┤ -│ 0 │ 2 years ago │ ╭───┬───────╮ │ sunny │ -│ │ │ │ 0 │ 35.24 │ │ │ -│ │ │ │ 1 │ 35.94 │ │ │ -│ │ │ │ 2 │ 34.91 │ │ │ -│ │ │ │ 3 │ 35.24 │ │ │ -│ │ │ │ 4 │ 36.65 │ │ │ -│ │ │ ╰───┴───────╯ │ │ -╰───┴─────────────┴───────────────┴───────────╯ +$data | get 1 +# => ╭───────────┬───────────────╮ +# => │ date │ 2 years ago │ +# => │ │ ╭───┬───────╮ │ +# => │ temps │ │ 0 │ 35.24 │ │ +# => │ │ │ 1 │ 35.94 │ │ +# => │ │ │ 2 │ 34.91 │ │ +# => │ │ │ 3 │ 35.24 │ │ +# => │ │ │ 4 │ 36.65 │ │ +# => │ │ ╰───┴───────╯ │ +# => │ condition │ sunny │ +# => ╰───────────┴───────────────╯ + +$data | select 1 +# => ╭───┬─────────────┬───────────────┬───────────╮ +# => │ # │ date │ temps │ condition │ +# => ├───┼─────────────┼───────────────┼───────────┤ +# => │ 0 │ 2 years ago │ ╭───┬───────╮ │ sunny │ +# => │ │ │ │ 0 │ 35.24 │ │ │ +# => │ │ │ │ 1 │ 35.94 │ │ │ +# => │ │ │ │ 2 │ 34.91 │ │ │ +# => │ │ │ │ 3 │ 35.24 │ │ │ +# => │ │ │ │ 4 │ 36.65 │ │ │ +# => │ │ │ ╰───┴───────╯ │ │ +# => ╰───┴─────────────┴───────────────┴───────────╯ ``` Notice that: @@ -240,7 +240,7 @@ The row indices of the table resulting from `select` are not the same as that of To obtain the original index, you can using the [`enumerate`](/commands/docs/enumerate.md) command. For example: ```nu -> $data | enumerate | select 1 +$data | enumerate | select 1 ``` ::: @@ -250,13 +250,13 @@ To obtain the original index, you can using the [`enumerate`](/commands/docs/enu Because `select` results in a new table, it's possible to specify multiple column names, row indices, or even both. This example creates a new table containing the date and condition columns of the first and second rows: ```nu -> $data | select date condition 0 1 -╭───┬─────────────┬───────────╮ -│ # │ date │ condition │ -├───┼─────────────┼───────────┤ -│ 0 │ 2 years ago │ sunny │ -│ 1 │ 2 years ago │ sunny │ -╰───┴─────────────┴───────────╯ +$data | select date condition 0 1 +# => ╭───┬─────────────┬───────────╮ +# => │ # │ date │ condition │ +# => ├───┼─────────────┼───────────┤ +# => │ 0 │ 2 years ago │ sunny │ +# => │ 1 │ 2 years ago │ sunny │ +# => ╰───┴─────────────┴───────────╯ ``` ## Key/Column names with spaces @@ -266,16 +266,16 @@ If a key name or column name contains spaces or other characters that prevent it Example: ```nu -> let record_example = { +let record_example = { "key x":12 "key y":4 } -> $record_example."key x" -12 +$record_example."key x" +# => 12 # or -> $record_example | get "key x" -12 +$record_example | get "key x" +# => 12 ``` Quotes are also required when a key name may be confused for a numeric value. @@ -283,14 +283,14 @@ Quotes are also required when a key name may be confused for a numeric value. Example: ```nu -> let record_example = { +let record_example = { "1": foo "2": baz "3": far } -> $record_example."1" - foo +$record_example."1" +# => foo ``` Do not confuse the key name with a row index in this case. Here, the first item is _assigned_ the key name `1` (a string). If converted to a table using the `transpose` command, key `1` (`string`) would be at row-index `0` (an integer). @@ -319,26 +319,26 @@ By default missing cells will be replaced by `null` when accessed via the option The [`default` command](/commands/docs/default.html) can be used to apply a default value to missing or null column result. ```nu -> let missing_value = [{a:1 b:2} {b:1}] -> $missing_value -╭───┬────┬───╮ -│ # │ a │ b │ -├───┼────┼───┤ -│ 0 │ 1 │ 2 │ -│ 1 │ ❎ │ 1 │ -╰───┴────┴───╯ - -> let with_default_value = ($missing_value | default 'n/a' a) -> $with_default_value -╭───┬─────┬───╮ -│ # │ a │ b │ -├───┼─────┼───┤ -│ 0 │ 1 │ 2 │ -│ 1 │ n/a │ 1 │ -╰───┴─────┴───╯ - -> $with_default_value.1.a -n/a +let missing_value = [{a:1 b:2} {b:1}] +$missing_value +# => ╭───┬────┬───╮ +# => │ # │ a │ b │ +# => ├───┼────┼───┤ +# => │ 0 │ 1 │ 2 │ +# => │ 1 │ ❎ │ 1 │ +# => ╰───┴────┴───╯ + +let with_default_value = ($missing_value | default 'n/a' a) +$with_default_value +# => ╭───┬─────┬───╮ +# => │ # │ a │ b │ +# => ├───┼─────┼───┤ +# => │ 0 │ 1 │ 2 │ +# => │ 1 │ n/a │ 1 │ +# => ╰───┴─────┴───╯ + +$with_default_value.1.a +# => n/a ``` ## Other commands for accessing structured data diff --git a/book/operators.md b/book/operators.md index ab53becf2f..14a1eb33ba 100644 --- a/book/operators.md +++ b/book/operators.md @@ -59,8 +59,8 @@ Presented in descending order of precedence, the article details the operations - Logical not (`not`) ``` -> 3 * (1 + 2) -9 +3 * (1 + 2) +# => 9 ``` ## Types @@ -68,18 +68,18 @@ Presented in descending order of precedence, the article details the operations Not all operations make sense for all data types. If you attempt to perform an operation on non-compatible data types, you will be met with an error message that should explain what went wrong: ```nu -> "spam" - 1 -Error: nu::parser::unsupported_operation (link) - - × Types mismatched for operation. - ╭─[entry #49:1:1] - 1 │ "spam" - 1 - · ───┬── ┬ ┬ - · │ │ ╰── int - · │ ╰── doesn't support these values. - · ╰── string - ╰──── - help: Change string or int to be the right types and try again. +"spam" - 1 +# => Error: nu::parser::unsupported_operation (link) +# => +# => × Types mismatched for operation. +# => ╭─[entry #49:1:1] +# => 1 │ "spam" - 1 +# => · ───┬── ┬ ┬ +# => · │ │ ╰── int +# => · │ ╰── doesn't support these values. +# => · ╰── string +# => ╰──── +# => help: Change string or int to be the right types and try again. ``` The rules might sometimes feel a bit strict, but on the other hand there should be less unexpected side effects. @@ -143,35 +143,35 @@ some individual values. This can be done with `append` and `prepend`, but the sp operator can let you do it more easily. ```nushell -> let dogs = [Spot, Teddy, Tommy] -> let cats = ["Mr. Humphrey Montgomery", Kitten] -> [ - ...$dogs - Polly - ...($cats | each { |elt| $"($elt) \(cat\)" }) - ...[Porky Bessie] - ...Nemo - ] -╭───┬───────────────────────────────╮ -│ 0 │ Spot │ -│ 1 │ Teddy │ -│ 2 │ Tommy │ -│ 3 │ Polly │ -│ 4 │ Mr. Humphrey Montgomery (cat) │ -│ 5 │ Kitten (cat) │ -│ 6 │ Porky │ -│ 7 │ Bessie │ -│ 8 │ ...Nemo │ -╰───┴───────────────────────────────╯ +let dogs = [Spot, Teddy, Tommy] +let cats = ["Mr. Humphrey Montgomery", Kitten] +[ + ...$dogs + Polly + ...($cats | each { |elt| $"($elt) \(cat\)" }) + ...[Porky Bessie] + ...Nemo +] +# => ╭───┬───────────────────────────────╮ +# => │ 0 │ Spot │ +# => │ 1 │ Teddy │ +# => │ 2 │ Tommy │ +# => │ 3 │ Polly │ +# => │ 4 │ Mr. Humphrey Montgomery (cat) │ +# => │ 5 │ Kitten (cat) │ +# => │ 6 │ Porky │ +# => │ 7 │ Bessie │ +# => │ 8 │ ...Nemo │ +# => ╰───┴───────────────────────────────╯ ``` The below code is an equivalent version using `append`: ```nushell -> $dogs | - append Polly | - append ($cats | each { |elt| $"($elt) \(cat\)" }) | - append [Porky Bessie] | - append ...Nemo +$dogs | + append Polly | + append ($cats | each { |elt| $"($elt) \(cat\)" }) | + append [Porky Bessie] | + append ...Nemo ``` Note that each call to `append` results in the creation of a new list, meaning that in this second @@ -187,11 +187,11 @@ The `...` also won't be recognized as the spread operator if there's any whitesp the next expression: ```nushell -> [ ... [] ] -╭───┬────────────────╮ -│ 0 │ ... │ -│ 1 │ [list 0 items] │ -╰───┴────────────────╯ +[ ... [] ] +# => ╭───┬────────────────╮ +# => │ 0 │ ... │ +# => │ 1 │ [list 0 items] │ +# => ╰───┴────────────────╯ ``` This is mainly so that `...` won't be confused for the spread operator in commands such as `mv ... $dir`. @@ -202,35 +202,35 @@ Let's say you have a record with some configuration information and you want to this record: ```nushell -> let config = { path: /tmp, limit: 5 } +let config = { path: /tmp, limit: 5 } ``` You can make a new record with all the fields of `$config` and some new additions using the spread operator. You can use the spread multiple records inside a single record literal. ```nushell -> { - ...$config, - users: [alice bob], - ...{ url: example.com }, - ...(sys mem) - } -╭────────────┬───────────────╮ -│ path │ /tmp │ -│ limit │ 5 │ -│ │ ╭───┬───────╮ │ -│ users │ │ 0 │ alice │ │ -│ │ │ 1 │ bob │ │ -│ │ ╰───┴───────╯ │ -│ url │ example.com │ -│ total │ 8.3 GB │ -│ free │ 2.6 GB │ -│ used │ 5.7 GB │ -│ available │ 2.6 GB │ -│ swap total │ 2.1 GB │ -│ swap free │ 18.0 MB │ -│ swap used │ 2.1 GB │ -╰────────────┴───────────────╯ +{ + ...$config, + users: [alice bob], + ...{ url: example.com }, + ...(sys mem) +} +# => ╭────────────┬───────────────╮ +# => │ path │ /tmp │ +# => │ limit │ 5 │ +# => │ │ ╭───┬───────╮ │ +# => │ users │ │ 0 │ alice │ │ +# => │ │ │ 1 │ bob │ │ +# => │ │ ╰───┴───────╯ │ +# => │ url │ example.com │ +# => │ total │ 8.3 GB │ +# => │ free │ 2.6 GB │ +# => │ used │ 5.7 GB │ +# => │ available │ 2.6 GB │ +# => │ swap total │ 2.1 GB │ +# => │ swap free │ 18.0 MB │ +# => │ swap used │ 2.1 GB │ +# => ╰────────────┴───────────────╯ ``` Similarly to lists, inside record literals, the spread operator can only be used before variables (`...$foo`), @@ -245,7 +245,7 @@ external command. Here is an example custom command that has a rest parameter: ```nushell -> def foo [ --flag req opt? ...args ] { [$flag, $req, $opt, $args] | to nuon } +def foo [ --flag req opt? ...args ] { [$flag, $req, $opt, $args] | to nuon } ``` It has one flag (`--flag`), one required positional parameter (`req`), one optional positional parameter @@ -256,39 +256,39 @@ If you have a list of arguments to pass to `args`, you can spread it the same wa recognized before variables, subexpressions, and list literals, and no whitespace is allowed in between. ```nushell -> foo "bar" "baz" ...[1 2 3] # With ..., the numbers are treated as separate arguments -[false, bar, baz, [1, 2, 3]] -> foo "bar" "baz" [1 2 3] # Without ..., [1 2 3] is treated as a single argument -[false, bar, baz, [[1, 2, 3]]] +foo "bar" "baz" ...[1 2 3] # With ..., the numbers are treated as separate arguments +# => [false, bar, baz, [1, 2, 3]] +foo "bar" "baz" [1 2 3] # Without ..., [1 2 3] is treated as a single argument +# => [false, bar, baz, [[1, 2, 3]]] ``` A more useful way to use the spread operator is if you have another command with a rest parameter and you want it to forward its arguments to `foo`: ```nushell -> def bar [ ...args ] { foo --flag "bar" "baz" ...$args } -> bar 1 2 3 -[true, bar, baz, [1, 2, 3]] +def bar [ ...args ] { foo --flag "bar" "baz" ...$args } +bar 1 2 3 +# => [true, bar, baz, [1, 2, 3]] ``` You can spread multiple lists in a single call, and also intersperse individual arguments: ```nushell -> foo "bar" "baz" 1 ...[2 3] 4 5 ...(6..9 | take 2) last -[false, bar, baz, [1, 2, 3, 4, 5, 6, 7, last]] +foo "bar" "baz" 1 ...[2 3] 4 5 ...(6..9 | take 2) last +# => [false, bar, baz, [1, 2, 3, 4, 5, 6, 7, last]] ``` Flags/named arguments can go after a spread argument, just like they can go after regular rest arguments: ```nushell -> foo "bar" "baz" 1 ...[2 3] --flag 4 -[true, bar, baz, [1, 2, 3, 4]] +foo "bar" "baz" 1 ...[2 3] --flag 4 +# => [true, bar, baz, [1, 2, 3, 4]] ``` If a spread argument comes before an optional positional parameter, that optional parameter is treated as being omitted: ```nushell -> foo "bar" ...[1 2] "not opt" # The null means no argument was given for opt -[false, bar, null, [1, 2, "not opt"]] +foo "bar" ...[1 2] "not opt" # The null means no argument was given for opt +# => [false, bar, null, [1, 2, "not opt"]] ``` diff --git a/book/overlays.md b/book/overlays.md index 71002961b4..118fe557d0 100644 --- a/book/overlays.md +++ b/book/overlays.md @@ -14,7 +14,7 @@ You should see the default overlay listed there. To create a new overlay, you first need a module: ```nu -> module spam { +module spam { export def foo [] { "foo" } @@ -40,22 +40,22 @@ The module can be created by any of the three methods described in [Modules](mod To create the overlay, call [`overlay use`](/commands/docs/overlay_use.md): ```nu -> overlay use spam +overlay use spam -> foo foo +# => foo -> bar bar +# => bar -> $env.BAZ -baz +$env.BAZ +# => baz -> overlay list -───┬────── - 0 │ zero - 1 │ spam -───┴────── +overlay list +# => ───┬────── +# => 0 │ zero +# => 1 │ spam +# => ───┴────── ``` It brought the module's definitions into the current scope and evaluated the [`export-env`](/commands/docs/export-env.md) block the same way as [`use`](/commands/docs/use.md) command would (see [Modules](modules.md#environment-variables) chapter). diff --git a/book/parallelism.md b/book/parallelism.md index 955f0953d6..f84e3cd72f 100644 --- a/book/parallelism.md +++ b/book/parallelism.md @@ -13,7 +13,7 @@ Like [`each`](/commands/docs/each.md), [`par-each`](/commands/docs/par-each.md) Let's say you wanted to count the number of files in each sub-directory of the current directory. Using [`each`](/commands/docs/each.md), you could write this as: ```nu -> ls | where type == dir | each { |row| +ls | where type == dir | each { |row| { name: $row.name, len: (ls $row.name | length) } } ``` @@ -25,7 +25,7 @@ On your machine, the times may vary. For this machine, it took 21 milliseconds f Now, since this operation can be run in parallel, let's convert the above to parallel by changing [`each`](/commands/docs/each.md) to [`par-each`](/commands/docs/par-each.md): ```nu -> ls | where type == dir | par-each { |row| +ls | where type == dir | par-each { |row| { name: $row.name, len: (ls $row.name | length) } } ``` @@ -35,7 +35,7 @@ On this machine, it now runs in 6ms. That's quite a difference! As a side note: Because [environment variables are scoped](environment.md#scoping), you can use [`par-each`](/commands/docs/par-each.md) to work in multiple directories in parallel (notice the [`cd`](/commands/docs/cd.md) command): ```nu -> ls | where type == dir | par-each { |row| +ls | where type == dir | par-each { |row| { name: $row.name, len: (cd $row.name; ls | length) } } ``` diff --git a/book/pipelines.md b/book/pipelines.md index 5544b49579..1b442f1a38 100644 --- a/book/pipelines.md +++ b/book/pipelines.md @@ -19,8 +19,8 @@ The last command, `save Cargo_new.toml`, is an output (sometimes called a "sink" The `$in` variable will collect the pipeline into a value for you, allowing you to access the whole stream as a parameter: ```nu -> [1 2 3] | $in.1 * $in.2 -6 +[1 2 3] | $in.1 * $in.2 +# => 6 ``` ## Multi-line pipelines @@ -40,7 +40,7 @@ let year = ( Take this example: ```nu -> line1; line2 | line3 +line1; line2 | line3 ``` Here, semicolons are used in conjunction with pipelines. When a semicolon is used, no output data is produced to be piped. As such, the `$in` variable will not work when used immediately after the semicolon. @@ -130,9 +130,8 @@ See: [Custom Commands -> Pipeline Input](custom_commands.html#pipeline-input) def echo_me [] { print $in } - - > true | echo_me - true + true | echo_me + # => true ``` - **_Rule 1.5:_** This is true throughout the current scope. Even on subsequent lines in a closure or block, `$in` is the same value when used in the first position of _any pipeline_ inside that scope. @@ -168,12 +167,11 @@ See: [Custom Commands -> Pipeline Input](custom_commands.html#pipeline-input) Example: ```nushell - > 4 # Pipeline input + 4 # Pipeline input | $in * $in # $in is 4 in this expression | $in / 2 # $in is now 16 in this expression | $in # $in is now 8 - - 8 + # => 8 ``` - **_Rule 2.5:_** Inside a closure or block, Rule 2 usage occurs inside a new scope (a sub-expression) where that "new" `$in` value is valid. This means that Rule 1 and Rule 2 usage can coexist in the same closure or block. @@ -224,17 +222,17 @@ See: [Custom Commands -> Pipeline Input](custom_commands.html#pipeline-input) Example: ```nushell - > # Input - > 1 | do { $in | describe } - int - > "Hello, Nushell" | do { $in | describe } - string - > {||} | do { $in | describe } - closure - - > # No input - > do { $in | describe } - nothing + # Input + 1 | do { $in | describe } + # => int + "Hello, Nushell" | do { $in | describe } + # => string + {||} | do { $in | describe } + # => closure + + # No input + do { $in | describe } + # => nothing ``` * **_Rule 4:_** In a multi-statement line separated by semicolons, `$in` cannot be used to capture the results of the previous _statement_. @@ -242,15 +240,15 @@ See: [Custom Commands -> Pipeline Input](custom_commands.html#pipeline-input) This is the same as having no-input: ```nushell - > ls / | get name; $in | describe - nothing +ls / | get name; $in | describe +# => nothing ``` Instead, simply continue the pipeline: ```nushell - > ls / | get name | $in | describe - list + ls / | get name | $in | describe + # => list ``` ### Best practice for `$in` in Multiline Code @@ -267,10 +265,10 @@ def "date info" [] { print $'... was day ($day | format date '%j') of the year' } -> '2000-01-01' | date info - 1-Jan-2000 -... was a Saturday -... was day 001 of the year +'2000-01-01' | date info +# => 1-Jan-2000 +# => ... was a Saturday +# => ... was day 001 of the year ``` ### Collectability of `$in` @@ -305,35 +303,35 @@ You can check what a command supports with [`help `](/commands/doc For example, through `help first` we can see that the [`first` command](/commands/docs/first.md) supports multiple input and output types: ```nu -> help first -[…] -Input/output types: - ╭───┬───────────┬────────╮ - │ # │ input │ output │ - ├───┼───────────┼────────┤ - │ 0 │ list │ any │ - │ 1 │ binary │ binary │ - │ 2 │ range │ any │ - ╰───┴───────────┴────────╯ - -> [a b c] | first took 1ms -a - -> 1..4 | first took 21ms -1 +help first +# => […] +# => Input/output types: +# => ╭───┬───────────┬────────╮ +# => │ # │ input │ output │ +# => ├───┼───────────┼────────┤ +# => │ 0 │ list │ any │ +# => │ 1 │ binary │ binary │ +# => │ 2 │ range │ any │ +# => ╰───┴───────────┴────────╯ + +[a b c] | first took 1ms +# => a + +1..4 | first took 21ms +# => 1 ``` As another example, the [`ls` command](/commands/docs/ls.md) supports output but not input: ```nu -> help ls -[…] -Input/output types: - ╭───┬─────────┬────────╮ - │ # │ input │ output │ - ├───┼─────────┼────────┤ - │ 0 │ nothing │ table │ - ╰───┴─────────┴────────╯ +help ls +# => […] +# => Input/output types: +# => ╭───┬─────────┬────────╮ +# => │ # │ input │ output │ +# => ├───┼─────────┼────────┤ +# => │ 0 │ nothing │ table │ +# => ╰───┴─────────┴────────╯ ``` This means, for example, that attempting to pipe into `ls` (`echo .. | ls`) leads to unintended results. @@ -342,7 +340,7 @@ The input stream is ignored, and `ls` defaults to listing the current directory. To integrate a command like `ls` into a pipeline, you have to explicitly reference the input and pass it as a parameter: ```nu -> echo .. | ls $in +echo .. | ls $in ``` Note that this only works if `$in` matches the argument type. For example, `[dir1 dir2] | ls $in` will fail with the error `can't convert list to string`. @@ -352,27 +350,27 @@ Other commands without default behavior may fail in different ways, and with exp For example, `help sleep` tells us that [`sleep`](/commands/docs/sleep.md) supports no input and no output types: ```nu -> help sleep -[…] -Input/output types: - ╭───┬─────────┬─────────╮ - │ # │ input │ output │ - ├───┼─────────┼─────────┤ - │ 0 │ nothing │ nothing │ - ╰───┴─────────┴─────────╯ +help sleep +# => […] +# => Input/output types: +# => ╭───┬─────────┬─────────╮ +# => │ # │ input │ output │ +# => ├───┼─────────┼─────────┤ +# => │ 0 │ nothing │ nothing │ +# => ╰───┴─────────┴─────────╯ ``` When we erroneously pipe into it, instead of unintended behavior like in the `ls` example above, we receive an error: ```nu -> echo 1sec | sleep -Error: nu::parser::missing_positional - - × Missing required positional argument. - ╭─[entry #53:1:18] - 1 │ echo 1sec | sleep - ╰──── - help: Usage: sleep ...(rest) . Use `--help` for more information. +echo 1sec | sleep +# => Error: nu::parser::missing_positional +# => +# => × Missing required positional argument. +# => ╭─[entry #53:1:18] +# => 1 │ echo 1sec | sleep +# => ╰──── +# => help: Usage: sleep ...(rest) . Use `--help` for more information. ``` While there is no steadfast rule, Nu generally tries to copy established conventions in command behavior, @@ -388,13 +386,13 @@ You may have wondered how we see a table if [`ls`](/commands/docs/ls.md) is an i In effect, the command: ```nu -> ls +ls ``` And the pipeline: ```nu -> ls | table +ls | table ``` Are one and the same. @@ -416,44 +414,44 @@ Sometimes you want to output Nushell structured data to an external command for For example, you want to find a file named "tutor" under "/usr/share/vim/runtime" and check its ownership ```nu -> ls /usr/share/nvim/runtime/ -╭────┬───────────────────────────────────────┬──────┬─────────┬───────────────╮ -│ # │ name │ type │ size │ modified │ -├────┼───────────────────────────────────────┼──────┼─────────┼───────────────┤ -│ 0 │ /usr/share/nvim/runtime/autoload │ dir │ 4.1 KB │ 2 days ago │ -.......... -.......... -.......... - -│ 31 │ /usr/share/nvim/runtime/tools │ dir │ 4.1 KB │ 2 days ago │ -│ 32 │ /usr/share/nvim/runtime/tutor │ dir │ 4.1 KB │ 2 days ago │ -├────┼───────────────────────────────────────┼──────┼─────────┼───────────────┤ -│ # │ name │ type │ size │ modified │ -╰────┴───────────────────────────────────────┴──────┴─────────┴───────────────╯ +ls /usr/share/nvim/runtime/ +# => ╭────┬───────────────────────────────────────┬──────┬─────────┬───────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├────┼───────────────────────────────────────┼──────┼─────────┼───────────────┤ +# => │ 0 │ /usr/share/nvim/runtime/autoload │ dir │ 4.1 KB │ 2 days ago │ +# => .......... +# => .......... +# => .......... +# => +# => │ 31 │ /usr/share/nvim/runtime/tools │ dir │ 4.1 KB │ 2 days ago │ +# => │ 32 │ /usr/share/nvim/runtime/tutor │ dir │ 4.1 KB │ 2 days ago │ +# => ├────┼───────────────────────────────────────┼──────┼─────────┼───────────────┤ +# => │ # │ name │ type │ size │ modified │ +# => ╰────┴───────────────────────────────────────┴──────┴─────────┴───────────────╯ ``` You decided to use `grep` and [pipe](https://www.nushell.sh/book/pipelines.html) the result to external `^ls` ```nu -> ls /usr/share/nvim/runtime/ | get name | ^grep tutor | ^ls -la $in -ls: cannot access ''$'\342\224\202'' 32 '$'\342\224\202'' /usr/share/nvim/runtime/tutor '$'\342\224\202\n': No such file or directory +ls /usr/share/nvim/runtime/ | get name | ^grep tutor | ^ls -la $in +# => ls: cannot access ''$'\342\224\202'' 32 '$'\342\224\202'' /usr/share/nvim/runtime/tutor '$'\342\224\202\n': No such file or directory ``` What's wrong? Nushell renders lists and tables (by adding a border with characters like `╭`,`─`,`┬`,`╮`) before piping them as text to external commands. If that's not the behavior you want, you must explicitly convert the data to a string before piping it to an external. For example, you can do so with [`to text`](/commands/docs/to_text.md): ```nu -> ls /usr/share/nvim/runtime/ | get name | to text | ^grep tutor | tr -d '\n' | ^ls -la $in -total 24 -drwxr-xr-x@ 5 pengs admin 160 14 Nov 13:12 . -drwxr-xr-x@ 4 pengs admin 128 14 Nov 13:42 en --rw-r--r--@ 1 pengs admin 5514 14 Nov 13:42 tutor.tutor --rw-r--r--@ 1 pengs admin 1191 14 Nov 13:42 tutor.tutor.json +ls /usr/share/nvim/runtime/ | get name | to text | ^grep tutor | tr -d '\n' | ^ls -la $in +# => total 24 +# => drwxr-xr-x@ 5 pengs admin 160 14 Nov 13:12 . +# => drwxr-xr-x@ 4 pengs admin 128 14 Nov 13:42 en +# => -rw-r--r--@ 1 pengs admin 5514 14 Nov 13:42 tutor.tutor +# => -rw-r--r--@ 1 pengs admin 1191 14 Nov 13:42 tutor.tutor.json ``` (Actually, for this simple usage you can just use [`find`](/commands/docs/find.md)) ```nu -> ls /usr/share/nvim/runtime/ | get name | find tutor | ^ls -al $in +ls /usr/share/nvim/runtime/ | get name | find tutor | ^ls -al $in ``` ## Command Output in Nushell @@ -461,7 +459,7 @@ drwxr-xr-x@ 4 pengs admin 128 14 Nov 13:42 en Unlike external commands, Nushell commands are akin to functions. Most Nushell commands do not print anything to `stdout` and instead just return data. ```nu -> do { ls; ls; ls; "What?!" } +do { ls; ls; ls; "What?!" } ``` This means that the above code will not display the files under the current directory three times. @@ -470,13 +468,13 @@ In fact, running this in the shell will only display `"What?!"` because that is Knowing when data is displayed is important when using configuration variables that affect the display output of commands such as `table`. ```nu -> do { $env.config.table.mode = "none"; ls } +do { $env.config.table.mode = "none"; ls } ``` For instance, the above example sets the `$env.config.table.mode` configuration variable to `none`, which causes the `table` command to render data without additional borders. However, as it was shown earlier, the command is effectively equivalent to ```nu -> do { $env.config.table.mode = "none"; ls } | table +do { $env.config.table.mode = "none"; ls } | table ``` Because Nushell `$env` variables are [scoped](https://www.nushell.sh/book/environment.html#scoping), this means that the `table` command in the example is not affected by the @@ -485,6 +483,6 @@ environment modification inside the `do` block and the data will not be shown wi When displaying data early is desired, it is possible to explicitly apply `| table` inside the scope, or use the `print` command. ```nu -> do { $env.config.table.mode = "none"; ls | table } -> do { $env.config.table.mode = "none"; print (ls) } +do { $env.config.table.mode = "none"; ls | table } +do { $env.config.table.mode = "none"; print (ls) } ``` diff --git a/book/scripts.md b/book/scripts.md index a521ffba6d..28aed8626e 100644 --- a/book/scripts.md +++ b/book/scripts.md @@ -3,13 +3,13 @@ In Nushell, you can write and run scripts in the Nushell language. To run a script, you can pass it as an argument to the `nu` commandline application: ```nu -> nu myscript.nu +nu myscript.nu ``` This will run the script to completion in a new instance of Nu. You can also run scripts inside the _current_ instance of Nu using [`source`](/commands/docs/source.md): ```nu -> source myscript.nu +source myscript.nu ``` Let's look at an example script file: @@ -69,8 +69,8 @@ def main [x: int] { ``` ```nu -> nu myscript.nu 100 -110 +nu myscript.nu 100 +# => 110 ``` ## Argument Type Interpretation @@ -94,11 +94,11 @@ def main [x: string] { ``` ```nu -> nu implicit_type.nu +1 -Hello int 1 +nu implicit_type.nu +1 +# => Hello int 1 -> nu explicit_type.nu +1 -Hello string +1 +nu explicit_type.nu +1 +# => Hello string +1 ``` ## Subcommands @@ -123,12 +123,12 @@ def main [] { You can then execute the script's subcommands when calling it: ```nu -> nu myscript.nu -hello from myscript! -> nu myscript.nu build -building -> nu myscript.nu run -running +nu myscript.nu +# => hello from myscript! +nu myscript.nu build +# => building +nu myscript.nu run +# => running ``` [Unlike modules](modules.html#main), `main` does _not_ need to exported in order to be visible. In the above example, our `main` command is not `export def`, however it was still executed when running `nu myscript.nu`. If we had used myscript as a module by running `use myscript.nu`, rather than running `myscript.nu` as a script, trying to execute the `myscript` command would not work since `myscript` is not exported. @@ -147,8 +147,8 @@ def "main build" [] { ``` ```nu -> nu myscript.nu build -> nu myscript.nu run +nu myscript.nu build +nu myscript.nu run ``` This is a limitation of the way scripts are currently processed. If your script only has subcommands, you can add an empty `main` to expose the subcommands, like so: @@ -167,8 +167,8 @@ On Linux and macOS you can optionally use a [shebang]( ./myscript -Hello World! +./myscript +# => Hello World! ``` For script to have access to standard input, `nu` should be invoked with `--stdin` flag: @@ -181,6 +181,6 @@ def main [] { ``` ```nu -> echo "Hello World!" | ./myscript -stdin: Hello World! +echo "Hello World!" | ./myscript +# => stdin: Hello World! ``` diff --git a/book/sorting.md b/book/sorting.md index f07d9ddf4e..c605c51769 100644 --- a/book/sorting.md +++ b/book/sorting.md @@ -9,31 +9,31 @@ Nushell offers many ways of sorting data, and which method you reach for will de Sorting a basic list works exactly how you might expect: ```nu -> [9 3 8 1 4 6] | sort -╭───┬───╮ -│ 0 │ 1 │ -│ 1 │ 3 │ -│ 2 │ 4 │ -│ 3 │ 6 │ -│ 4 │ 8 │ -│ 5 │ 9 │ -╰───┴───╯ +[9 3 8 1 4 6] | sort +# => ╭───┬───╮ +# => │ 0 │ 1 │ +# => │ 1 │ 3 │ +# => │ 2 │ 4 │ +# => │ 3 │ 6 │ +# => │ 4 │ 8 │ +# => │ 5 │ 9 │ +# => ╰───┴───╯ ``` However, things get a bit more complex when you start combining types. For example, let's see what happens when we have a list with numbers _and_ strings: ```nu -> ["hello" 4 9 2 1 "foobar" 8 6] | sort -╭───┬────────╮ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 4 │ -│ 3 │ 6 │ -│ 4 │ 8 │ -│ 5 │ 9 │ -│ 6 │ foobar │ -│ 7 │ hello │ -╰───┴────────╯ +["hello" 4 9 2 1 "foobar" 8 6] | sort +# => ╭───┬────────╮ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 4 │ +# => │ 3 │ 6 │ +# => │ 4 │ 8 │ +# => │ 5 │ 9 │ +# => │ 6 │ foobar │ +# => │ 7 │ hello │ +# => ╰───┴────────╯ ``` We can see that the numbers are sorted in order, and the strings are sorted to the end of the list, also in order. If you are coming from other programming languages, this may not be quite what you expect. In Nushell, as a general rule, **data can always be sorted without erroring**. @@ -45,13 +45,13 @@ If you _do_ want a sort containing differing types to error, see [strict sort](# Nushell's sort is also **stable**, meaning equal values will retain their original ordering relative to each other. This is illustrated here using the [case insensitive](#case-insensitive-sort) sort option: ```nu -> ["foo" "FOO" "BAR" "bar"] | sort -i -╭───┬─────╮ -│ 0 │ BAR │ -│ 1 │ bar │ -│ 2 │ foo │ -│ 3 │ FOO │ -╰───┴─────╯ +["foo" "FOO" "BAR" "bar"] | sort -i +# => ╭───┬─────╮ +# => │ 0 │ BAR │ +# => │ 1 │ bar │ +# => │ 2 │ foo │ +# => │ 3 │ FOO │ +# => ╰───┴─────╯ ``` Since this sort is case insensitive, `foo` and `FOO` are considered equal to each other, and the same is true for `bar` and `BAR`. In the result, the uppercase `BAR` precedes the lowercase `bar`, since the uppercase `BAR` also precedes the lowercase `bar` in the input. Similarly, the lowercase `foo` precedes the uppercase `FOO` in both the input and the result. @@ -62,22 +62,22 @@ Records can be sorted two ways: by key, and by value. By default, passing a reco ```nu {x: 123, a: hello!, foo: bar} | sort -╭─────┬────────╮ -│ a │ hello! │ -│ foo │ bar │ -│ x │ 123 │ -╰─────┴────────╯ +# => ╭─────┬────────╮ +# => │ a │ hello! │ +# => │ foo │ bar │ +# => │ x │ 123 │ +# => ╰─────┴────────╯ ``` To instead sort in order of values, use the `-v` flag: ```nu {x: 123, a: hello! foo: bar} | sort -v -╭─────┬────────╮ -│ x │ 123 │ -│ foo │ bar │ -│ a │ hello! │ -╰─────┴────────╯ +# => ╭─────┬────────╮ +# => │ x │ 123 │ +# => │ foo │ bar │ +# => │ a │ hello! │ +# => ╰─────┴────────╯ ``` ### Tables @@ -85,19 +85,19 @@ To instead sort in order of values, use the `-v` flag: Table rows are sorted by comparing rows by the columns in order. If two rows have equal values in their first column, they are sorted by their second column. This repeats until the rows are sorted different or all columns are equal. ```nu -> let items = [ +let items = [ {id: 100, quantity: 10, price: 5 } {id: 100, quantity: 5, price: 8 } {id: 100, quantity: 5, price: 1 } ] -> $items | sort -╭───┬─────┬──────────┬───────╮ -│ # │ id │ quantity │ price │ -├───┼─────┼──────────┼───────┤ -│ 0 │ 100 │ 5 │ 1 │ -│ 1 │ 100 │ 5 │ 8 │ -│ 2 │ 100 │ 10 │ 5 │ -╰───┴─────┴──────────┴───────╯ +$items | sort +# => ╭───┬─────┬──────────┬───────╮ +# => │ # │ id │ quantity │ price │ +# => ├───┼─────┼──────────┼───────┤ +# => │ 0 │ 100 │ 5 │ 1 │ +# => │ 1 │ 100 │ 5 │ 8 │ +# => │ 2 │ 100 │ 10 │ 5 │ +# => ╰───┴─────┴──────────┴───────╯ ``` In this example, the `id` column for all items is equal. Then, the two items with price `5` are sorted before the item with price `10`. Finally, the `item` with quantity `1` is sorted before the item with quantity `8`. @@ -111,29 +111,29 @@ In order to sort more complex types, such as tables, you can use the `sort-by` c Here's an example directory, sorted by filesize: ```nu -> ls | sort-by size -╭───┬─────────────────────┬──────┬──────────┬────────────────╮ -│ # │ name │ type │ size │ modified │ -├───┼─────────────────────┼──────┼──────────┼────────────────┤ -│ 0 │ my-secret-plans.txt │ file │ 100 B │ 10 minutes ago │ -│ 1 │ shopping_list.txt │ file │ 100 B │ 2 months ago │ -│ 2 │ myscript.nu │ file │ 1.1 KiB │ 2 weeks ago │ -│ 3 │ bigfile.img │ file │ 10.0 MiB │ 3 weeks ago │ -╰───┴─────────────────────┴──────┴──────────┴────────────────╯ +ls | sort-by size +# => ╭───┬─────────────────────┬──────┬──────────┬────────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├───┼─────────────────────┼──────┼──────────┼────────────────┤ +# => │ 0 │ my-secret-plans.txt │ file │ 100 B │ 10 minutes ago │ +# => │ 1 │ shopping_list.txt │ file │ 100 B │ 2 months ago │ +# => │ 2 │ myscript.nu │ file │ 1.1 KiB │ 2 weeks ago │ +# => │ 3 │ bigfile.img │ file │ 10.0 MiB │ 3 weeks ago │ +# => ╰───┴─────────────────────┴──────┴──────────┴────────────────╯ ``` We can also provide multiple cell paths to `sort-by`, which will sort by each cell path in order of priority. You can think of providing multiple cell paths as a "tiebreaker" for elements which have equal values. Let's sort first by size, then by modification time: ```nu -> ls | sort-by size modified -╭───┬─────────────────────┬──────┬──────────┬────────────────╮ -│ # │ name │ type │ size │ modified │ -├───┼─────────────────────┼──────┼──────────┼────────────────┤ -│ 0 │ shopping_list.txt │ file │ 100 B │ 2 months ago │ -│ 1 │ my-secret-plans.txt │ file │ 100 B │ 10 minutes ago │ -│ 2 │ myscript.nu │ file │ 1.1 KiB │ 2 weeks ago │ -│ 3 │ bigfile.img │ file │ 10.0 MiB │ 3 weeks ago │ -╰───┴─────────────────────┴──────┴──────────┴────────────────╯ +ls | sort-by size modified +# => ╭───┬─────────────────────┬──────┬──────────┬────────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├───┼─────────────────────┼──────┼──────────┼────────────────┤ +# => │ 0 │ shopping_list.txt │ file │ 100 B │ 2 months ago │ +# => │ 1 │ my-secret-plans.txt │ file │ 100 B │ 10 minutes ago │ +# => │ 2 │ myscript.nu │ file │ 1.1 KiB │ 2 weeks ago │ +# => │ 3 │ bigfile.img │ file │ 10.0 MiB │ 3 weeks ago │ +# => ╰───┴─────────────────────┴──────┴──────────┴────────────────╯ ``` This time, `shopping_list.txt` comes before `my-secret-plans.txt`, since it has an earlier modification time, but two larger files remain sorted after the `.txt` files. @@ -141,28 +141,28 @@ This time, `shopping_list.txt` comes before `my-secret-plans.txt`, since it has Furthermore, we can use more complex cell paths to sort nested data: ```nu -> let cities = [ +let cities = [ {name: 'New York', info: { established: 1624, population: 18_819_000 } } {name: 'Kyoto', info: { established: 794, population: 37_468_000 } } {name: 'São Paulo', info: { established: 1554, population: 21_650_000 } } ] -> $cities | sort-by info.established -╭───┬───────────┬────────────────────────────╮ -│ # │ name │ info │ -├───┼───────────┼────────────────────────────┤ -│ 0 │ Kyoto │ ╭─────────────┬──────────╮ │ -│ │ │ │ established │ 794 │ │ -│ │ │ │ population │ 37468000 │ │ -│ │ │ ╰─────────────┴──────────╯ │ -│ 1 │ São Paulo │ ╭─────────────┬──────────╮ │ -│ │ │ │ established │ 1554 │ │ -│ │ │ │ population │ 21650000 │ │ -│ │ │ ╰─────────────┴──────────╯ │ -│ 2 │ New York │ ╭─────────────┬──────────╮ │ -│ │ │ │ established │ 1624 │ │ -│ │ │ │ population │ 18819000 │ │ -│ │ │ ╰─────────────┴──────────╯ │ -╰───┴───────────┴────────────────────────────╯ +$cities | sort-by info.established +# => ╭───┬───────────┬────────────────────────────╮ +# => │ # │ name │ info │ +# => ├───┼───────────┼────────────────────────────┤ +# => │ 0 │ Kyoto │ ╭─────────────┬──────────╮ │ +# => │ │ │ │ established │ 794 │ │ +# => │ │ │ │ population │ 37468000 │ │ +# => │ │ │ ╰─────────────┴──────────╯ │ +# => │ 1 │ São Paulo │ ╭─────────────┬──────────╮ │ +# => │ │ │ │ established │ 1554 │ │ +# => │ │ │ │ population │ 21650000 │ │ +# => │ │ │ ╰─────────────┴──────────╯ │ +# => │ 2 │ New York │ ╭─────────────┬──────────╮ │ +# => │ │ │ │ established │ 1624 │ │ +# => │ │ │ │ population │ 18819000 │ │ +# => │ │ │ ╰─────────────┴──────────╯ │ +# => ╰───┴───────────┴────────────────────────────╯ ``` ### Sort by key closure @@ -170,35 +170,35 @@ Furthermore, we can use more complex cell paths to sort nested data: Sometimes, it's useful to sort data in a more complicated manner than "increasing" or "decreasing". Instead of using `sort-by` with a cell path, you can supply a [closure](types_of_data.html#closures), which will transform each value into a [sorting key](https://en.wikipedia.org/wiki/Collation#Sort_keys) _without changing the underlying data_. Here's an example of a key closure, where we want to sort a list of assignments by their average grade: ```nu -> let assignments = [ +let assignments = [ {name: 'Homework 1', grades: [97 89 86 92 89] } {name: 'Homework 2', grades: [91 100 60 82 91] } {name: 'Exam 1', grades: [78 88 78 53 90] } {name: 'Project', grades: [92 81 82 84 83] } ] -> $assignments | sort-by { get grades | math avg } -╭───┬────────────┬───────────────────────╮ -│ # │ name │ grades │ -├───┼────────────┼───────────────────────┤ -│ 0 │ Exam 1 │ [78, 88, 78, 53, 90] │ -│ 1 │ Project │ [92, 81, 82, 84, 83] │ -│ 2 │ Homework 2 │ [91, 100, 60, 82, 91] │ -│ 3 │ Homework 1 │ [97, 89, 86, 92, 89] │ -╰───┴────────────┴───────────────────────╯ +$assignments | sort-by { get grades | math avg } +# => ╭───┬────────────┬───────────────────────╮ +# => │ # │ name │ grades │ +# => ├───┼────────────┼───────────────────────┤ +# => │ 0 │ Exam 1 │ [78, 88, 78, 53, 90] │ +# => │ 1 │ Project │ [92, 81, 82, 84, 83] │ +# => │ 2 │ Homework 2 │ [91, 100, 60, 82, 91] │ +# => │ 3 │ Homework 1 │ [97, 89, 86, 92, 89] │ +# => ╰───┴────────────┴───────────────────────╯ ``` The value is passed into the pipeline input of the key closure, however, you can also use it as a parameter: ```nu -> let weight = {alpha: 10, beta: 5, gamma: 3} -> [alpha gamma beta gamma alpha] | sort-by {|val| $weight | get $val } -╭───┬───────╮ -│ 0 │ gamma │ -│ 1 │ gamma │ -│ 2 │ beta │ -│ 3 │ alpha │ -│ 4 │ alpha │ -╰───┴───────╯ +let weight = {alpha: 10, beta: 5, gamma: 3} +[alpha gamma beta gamma alpha] | sort-by {|val| $weight | get $val } +# => ╭───┬───────╮ +# => │ 0 │ gamma │ +# => │ 1 │ gamma │ +# => │ 2 │ beta │ +# => │ 3 │ alpha │ +# => │ 4 │ alpha │ +# => ╰───┴───────╯ ``` ### Custom sort order @@ -208,15 +208,15 @@ In addition to [key closures](#sort-by-key-closure), `sort-by` also supports clo For a simple example, we could rewrite a cell path sort as a custom sort. This can be read as "If $a.size is less than $b.size, a should appear before b in the sort order": ```nu -> ls | sort-by -c {|a, b| $a.size < $b.size } -╭───┬─────────────────────┬──────┬──────────┬────────────────╮ -│ # │ name │ type │ size │ modified │ -├───┼─────────────────────┼──────┼──────────┼────────────────┤ -│ 0 │ my-secret-plans.txt │ file │ 100 B │ 10 minutes ago │ -│ 1 │ shopping_list.txt │ file │ 100 B │ 2 months ago │ -│ 2 │ myscript.nu │ file │ 1.1 KiB │ 2 weeks ago │ -│ 3 │ bigfile.img │ file │ 10.0 MiB │ 3 weeks ago │ -╰───┴─────────────────────┴──────┴──────────┴────────────────╯ +ls | sort-by -c {|a, b| $a.size < $b.size } +# => ╭───┬─────────────────────┬──────┬──────────┬────────────────╮ +# => │ # │ name │ type │ size │ modified │ +# => ├───┼─────────────────────┼──────┼──────────┼────────────────┤ +# => │ 0 │ my-secret-plans.txt │ file │ 100 B │ 10 minutes ago │ +# => │ 1 │ shopping_list.txt │ file │ 100 B │ 2 months ago │ +# => │ 2 │ myscript.nu │ file │ 1.1 KiB │ 2 weeks ago │ +# => │ 3 │ bigfile.img │ file │ 10.0 MiB │ 3 weeks ago │ +# => ╰───┴─────────────────────┴──────┴──────────┴────────────────╯ ``` ::: tip @@ -229,13 +229,13 @@ The parameters are also passed to the custom closure as a two element list, so t Here's an example of a custom sort which couldn't be trivially written as a key sort. In this example, we have a queue of tasks with some amount of work time and a priority. We want to sort by priority (highest first). If a task has had zero work time, we want to schedule it immediately; otherwise, we ignore the work time. ```nu -> let queue = [ +let queue = [ {task: 139, work_time: 0, priority: 1 } {task: 52, work_time: 355, priority: 8 } {task: 948, work_time: 72, priority: 2 } {task: 583, work_time: 0, priority: 5 } ] -> let my_sort = {|a, b| +let my_sort = {|a, b| match [$a.work_time, $b.work_time] { [0, 0] => ($a.priority > $b.priority) # fall back to priority if equal work time [0, _] => true, # only a has 0 work time, so a comes before b in the sort order @@ -243,15 +243,7 @@ Here's an example of a custom sort which couldn't be trivially written as a key _ => ($a.priority > $b.priority) # both have non-zero work time, sort by priority } } -> $queue | sort-by -c $my_sort -╭───┬──────┬───────────┬──────────╮ -│ # │ task │ work_time │ priority │ -├───┼──────┼───────────┼──────────┤ -│ 0 │ 583 │ 0 │ 5 │ -│ 1 │ 139 │ 0 │ 1 │ -│ 2 │ 52 │ 355 │ 8 │ -│ 3 │ 948 │ 72 │ 2 │ -╰───┴──────┴───────────┴──────────╯ +$queue | sort-by -c $my_sort ``` ## Special sorts @@ -261,7 +253,7 @@ Here's an example of a custom sort which couldn't be trivially written as a key When using case insensitive sort, strings (and globs) which are the same except for different casing will be considered equal for sorting, while other types remain unaffected: ```nu -> let data = [ +let data = [ Nushell, foobar, 10, @@ -269,15 +261,15 @@ When using case insensitive sort, strings (and globs) which are the same except FoOBaR, 9 ] -> $data | sort -i -╭───┬─────────╮ -│ 0 │ 9 │ -│ 1 │ 10 │ -│ 2 │ foobar │ -│ 3 │ FoOBaR │ -│ 4 │ Nushell │ -│ 5 │ nushell │ -╰───┴─────────╯ +$data | sort -i +# => ╭───┬─────────╮ +# => │ 0 │ 9 │ +# => │ 1 │ 10 │ +# => │ 2 │ foobar │ +# => │ 3 │ FoOBaR │ +# => │ 4 │ Nushell │ +# => │ 5 │ nushell │ +# => ╰───┴─────────╯ ``` ### Natural sort @@ -285,45 +277,45 @@ When using case insensitive sort, strings (and globs) which are the same except The [natural sort option](https://en.wikipedia.org/wiki/Natural_sort_order) allows strings which contain numbers to be sorted in the same way that numbers are normally sorted. This works both for strings which consist solely of numbers, and strings which have numbers and letters: ```nu -> let data = ["10", "9", "foo123", "foo20", "bar123", "bar20"] -> $data | sort -╭───┬────────╮ -│ 0 │ 10 │ -│ 1 │ 9 │ -│ 2 │ bar123 │ -│ 3 │ bar20 │ -│ 4 │ foo123 │ -│ 5 │ foo20 │ -╰───┴────────╯ -> # "1" is sorted before "9", so "10" is sorted before "9" -> $data | sort -n -╭───┬────────╮ -│ 0 │ 9 │ -│ 1 │ 10 │ -│ 2 │ bar20 │ -│ 3 │ bar123 │ -│ 4 │ foo20 │ -│ 5 │ foo123 │ -╰───┴────────╯ +let data = ["10", "9", "foo123", "foo20", "bar123", "bar20"] +$data | sort +# => ╭───┬────────╮ +# => │ 0 │ 10 │ +# => │ 1 │ 9 │ +# => │ 2 │ bar123 │ +# => │ 3 │ bar20 │ +# => │ 4 │ foo123 │ +# => │ 5 │ foo20 │ +# => ╰───┴────────╯ +# "1" is sorted before "9", so "10" is sorted before "9" +$data | sort -n +# => ╭───┬────────╮ +# => │ 0 │ 9 │ +# => │ 1 │ 10 │ +# => │ 2 │ bar20 │ +# => │ 3 │ bar123 │ +# => │ 4 │ foo20 │ +# => │ 5 │ foo123 │ +# => ╰───┴────────╯ ``` Furthermore, natural sort allows you to sort numbers together with numeric strings: ```nu -> let data = [4, "6.2", 1, "10", 2, 8.1, "3", 5.5, "9", 7] -> $data | sort -n -╭───┬──────╮ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -│ 4 │ 5.50 │ -│ 5 │ 6.2 │ -│ 6 │ 7 │ -│ 7 │ 8.10 │ -│ 8 │ 9 │ -│ 9 │ 10 │ -╰───┴──────╯ +let data = [4, "6.2", 1, "10", 2, 8.1, "3", 5.5, "9", 7] +$data | sort -n +# => ╭───┬──────╮ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => │ 4 │ 5.50 │ +# => │ 5 │ 6.2 │ +# => │ 6 │ 7 │ +# => │ 7 │ 8.10 │ +# => │ 8 │ 9 │ +# => │ 9 │ 10 │ +# => ╰───┴──────╯ ``` ### Sorting with mixed types @@ -350,48 +342,47 @@ If you need to sort data which may contain mixed types, consider one of the foll Custom sort closures also provide a simple way to sort data while ensuring only types with well-defined comparisons are sorted together. This takes advantage of [operators requiring compatible data types](operators.html#types): ```nu -> let compatible = [8 3.2 null 58 2] -> let incompatible = ["hello" 4 9 2 1 "meow" 8 6] -> $compatible | sort-by -c {|a, b| $a < $b | default ($a != null) } -╭───┬──────╮ -│ 0 │ 2 │ -│ 1 │ 3.20 │ -│ 2 │ 8 │ -│ 3 │ 58 │ -│ 4 │ │ -╰───┴──────╯ -> $incompatible | sort-by -c {|a, b| $a < $b | default ($a != null) } -Error: nu::shell::type_mismatch - - × Type mismatch during operation. - ╭─[entry #26:1:36] - 1 │ $incompatible | sort-by -c {|a, b| $a < $b | default ($a != null) } - · ─┬ ┬ ─┬ - · │ │ ╰── string - · │ ╰── type mismatch for operator - · ╰── int - ╰──── - +let compatible = [8 3.2 null 58 2] +let incompatible = ["hello" 4 9 2 1 "meow" 8 6] +$compatible | sort-by -c {|a, b| $a < $b | default ($a != null) } +# => ╭───┬──────╮ +# => │ 0 │ 2 │ +# => │ 1 │ 3.20 │ +# => │ 2 │ 8 │ +# => │ 3 │ 58 │ +# => │ 4 │ │ +# => ╰───┴──────╯ +$incompatible | sort-by -c {|a, b| $a < $b | default ($a != null) } +# => Error: nu::shell::type_mismatch +# => +# => × Type mismatch during operation. +# => ╭─[entry #26:1:36] +# => 1 │ $incompatible | sort-by -c {|a, b| $a < $b | default ($a != null) } +# => · ─┬ ┬ ─┬ +# => · │ │ ╰── string +# => · │ ╰── type mismatch for operator +# => · ╰── int +# => ╰──── ``` Special handling is required for `null` values, since comparison between any value and `null` returns `null`. To instead reject `null` values, try the following: ```nu -> let baddata = [8 3.2 null 58 2] -> let strict = {|a, b| +let baddata = [8 3.2 null 58 2] +let strict = {|a, b| match [$a, $b] { [null, _] => (error make {msg: "Attempt to sort null"}), [_, null] => (error make {msg: "Attempt to sort null"}), _ => ($a < $b) } } -> $baddata | sort-by -c $strict -Error: × Attempt to sort null - ╭─[entry #3:4:21] - 3 │ match [$a, $b] { - 4 │ [null, _] => (error make {msg: "Attempt to sort null"}), - · ─────┬──── - · ╰── originates from here - 5 │ [_, null] => (error make {msg: "Attempt to sort null"}), - ╰──── +$baddata | sort-by -c $strict +# => Error: × Attempt to sort null +# => ╭─[entry #3:4:21] +# => 3 │ match [$a, $b] { +# => 4 │ [null, _] => (error make {msg: "Attempt to sort null"}), +# => · ─────┬──── +# => · ╰── originates from here +# => 5 │ [_, null] => (error make {msg: "Attempt to sort null"}), +# => ╰──── ``` diff --git a/book/stdout_stderr_exit_codes.md b/book/stdout_stderr_exit_codes.md index cccd41d220..4e9b935216 100644 --- a/book/stdout_stderr_exit_codes.md +++ b/book/stdout_stderr_exit_codes.md @@ -9,7 +9,7 @@ The first of these important streams is stdout. Stdout is the way that most external apps will send data into the pipeline or to the screen. Data sent by an external app to its stdout is received by Nushell by default if it's part of a pipeline: ```nu -> external | str join +external | str join ``` The above would call the external named `external` and would redirect the stdout output stream into the pipeline. With this redirection, Nushell can then pass the data to the next command in the pipeline, here [`str join`](/commands/docs/str_join.md). @@ -27,8 +27,8 @@ Finally, external commands have an "exit code". These codes help give a hint to Nushell tracks the last exit code of the recently completed external in one of two ways. The first way is with the `LAST_EXIT_CODE` environment variable. ```nu -> do { external } -> $env.LAST_EXIT_CODE +do { external } +$env.LAST_EXIT_CODE ``` The second way is to use the [`complete`](/commands/docs/complete.md) command. @@ -40,12 +40,12 @@ The [`complete`](/commands/docs/complete.md) command allows you to run an extern If we try to run the external `cat` on a file that doesn't exist, we can see what [`complete`](/commands/docs/complete.md) does with the streams, including the redirected stderr: ```nu -> cat unknown.txt | complete -╭───────────┬─────────────────────────────────────────────╮ -│ stdout │ │ -│ stderr │ cat: unknown.txt: No such file or directory │ -│ exit_code │ 1 │ -╰───────────┴─────────────────────────────────────────────╯ +cat unknown.txt | complete +# => ╭───────────┬─────────────────────────────────────────────╮ +# => │ stdout │ │ +# => │ stderr │ cat: unknown.txt: No such file or directory │ +# => │ exit_code │ 1 │ +# => ╰───────────┴─────────────────────────────────────────────╯ ``` ## `echo`, `print`, and `log` commands @@ -130,6 +130,6 @@ Nushell attempts to convert to text using UTF-8. If at any time the conversion f If you want more control over the decoding of the byte stream, you can use the [`decode`](/commands/docs/decode.md) command. The [`decode`](/commands/docs/decode.md) command can be inserted into the pipeline after the external, or other raw stream-creating command, and will handle decoding the bytes based on the argument you give decode. For example, you could decode shift-jis text this way: ```nu -> 0x[8a 4c] | decode shift-jis -貝 +0x[8a 4c] | decode shift-jis +# => 貝 ``` diff --git a/book/types_of_data.md b/book/types_of_data.md index ebe14b0c5c..8bfaba7301 100644 --- a/book/types_of_data.md +++ b/book/types_of_data.md @@ -9,8 +9,8 @@ Like many programming languages, Nu models data using a set of simple, structure The [`describe`](/commands/docs/describe.md) command returns the type of a data value: ```nu -> 42 | describe -int +42 | describe +# => int ``` ## Types at a Glance @@ -49,10 +49,10 @@ int Simple Example: ```nu -> 10 / 2 -5 -> 5 | describe -int +10 / 2 +# => 5 +5 | describe +# => int ``` ### Floats/Decimals @@ -67,16 +67,16 @@ int Simple Example: ```nu -> 2.5 / 5.0 -0.5 +2.5 / 5.0 +# => 0.5 ``` ::: tip As in most programming languages, decimal values in Nushell are approximate. ```nu -> 10.2 * 5.1 -52.01999999999999 +10.2 * 5.1 +# => 52.01999999999999 ``` ::: @@ -96,9 +96,9 @@ As with many languages, Nushell provides multiple ways to specify String values Simple (obligatory) example: ```nu -> let audience: string = "World" -> $"Hello, ($audience)" -Hello, World +let audience: string = "World" +$"Hello, ($audience)" +# => Hello, World ``` ### Booleans @@ -113,20 +113,20 @@ Hello, World Booleans are commonly the result of a comparison. For example: ```nu -> let mybool: bool = (2 > 1) -> $mybool -true -> let mybool: bool = ($env.HOME | path exists) -> $mybool -true +let mybool: bool = (2 > 1) +$mybool +# => true +let mybool: bool = ($env.HOME | path exists) +$mybool +# => true ``` A boolean result is commonly used to control the flow of execution: ```nu -> let num = -2 -> if $num < 0 { print "It's negative" } -It's negative +let num = -2 +if $num < 0 { print "It's negative" } +# => It's negative ``` ### Dates @@ -140,11 +140,11 @@ It's negative Simple example: ```nu -> date now -Mon, 12 Aug 2024 13:59:22 -0400 (now) +date now +# => Mon, 12 Aug 2024 13:59:22 -0400 (now) # Format as Unix epoch -> date now | format date '%s' -1723485562 +date now | format date '%s' +# => 1723485562 ``` ### Durations @@ -160,10 +160,10 @@ Durations support fractional values as well as calculations. Simple example: ```nu -> 3.14day -3day 3hr 21min -> 30day / 1sec # How many seconds in 30 days? -2592000 +3.14day +# => 3day 3hr 21min +30day / 1sec # How many seconds in 30 days? +# => 2592000 ``` ### File sizes @@ -179,12 +179,12 @@ Nushell also has a special type for file sizes. As with durations, Nushell supports fractional file sizes and calculations: ```nu -> 0.5kB -500 B -> 1GiB / 1B -1073741824 -> (1GiB / 1B) == 2 ** 30 -true +0.5kB +# => 500 B +1GiB / 1B +# => 1073741824 +(1GiB / 1B) == 2 ** 30 +# => true ``` See the [Language Reference](/lang-guide/chapters/types/basic_types/filesize.html) for a complete list of units and more detail. @@ -202,14 +202,14 @@ See the [Language Reference](/lang-guide/chapters/types/basic_types/filesize.htm Simple example: ```nu -> 1..5 -╭───┬───╮ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -│ 4 │ 5 │ -╰───┴───╯ +1..5 +# => ╭───┬───╮ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => │ 4 │ 5 │ +# => ╰───┴───╯ ``` ::: tip @@ -230,10 +230,10 @@ You can also easily create lists of characters with a form similar to ranges wit Simple example: ```nu -> let cp = $.2 +let cp = $.2 # Return list item at index 2 -> [ foo bar goo glue ] | get $cp -goo +[ foo bar goo glue ] | get $cp +# => goo ``` ### Closures @@ -250,15 +250,15 @@ Simple example: This closure returns a boolean result of the comparison and then uses it in a `filter` command to return all values greater than 5. ```nu -> let compare_closure = {|a| $a > 5 } -> let original_list = [ 40 -4 0 8 12 16 -16 ] -> $original_list | filter $compare_closure -╭───┬────╮ -│ 0 │ 40 │ -│ 1 │ 8 │ -│ 2 │ 12 │ -│ 3 │ 16 │ -╰───┴────╯ +let compare_closure = {|a| $a > 5 } +let original_list = [ 40 -4 0 8 12 16 -16 ] +$original_list | filter $compare_closure +# => ╭───┬────╮ +# => │ 0 │ 40 │ +# => │ 1 │ 8 │ +# => │ 2 │ 12 │ +# => │ 3 │ 16 │ +# => ╰───┴────╯ ``` Closures are a useful way to represent code that can be executed on each row of data via [filters](/lang-guide/chapters/filters/00_filters_overview.md) @@ -279,11 +279,11 @@ Binary data, like the data from an image file, is a group of raw bytes. Simple example - Confirm that a JPEG file starts with the proper identifier: ```nu -> open nushell_logo.jpg - | into binary - | first 2 - | $in == 0x[ff d8] -true +open nushell_logo.jpg +| into binary +| first 2 +| $in == 0x[ff d8] +# => true ``` ## Structured Data Types @@ -303,12 +303,12 @@ Nushell includes a collection of structured data types that can contain the prim Simple example: ```nu -> [Sam Fred George] -╭───┬────────╮ -│ 0 │ Sam │ -│ 1 │ Fred │ -│ 2 │ George │ -╰───┴────────╯ +[Sam Fred George] +# => ╭───┬────────╮ +# => │ 0 │ Sam │ +# => │ 1 │ Fred │ +# => │ 2 │ George │ +# => ╰───┴────────╯ ``` ### Records @@ -324,18 +324,18 @@ Simple example: Simple example: ```nu -> let my_record = { - name: "Kylian" - rank: 99 - } -> $my_record -╭───────┬────────────╮ -│ name │ Kylian │ -│ rank │ 99 │ -╰───────┴────────────╯ - - > $my_record | get name - Kylian +let my_record = { + name: "Kylian" + rank: 99 +} +$my_record +# => ╭───────┬────────────╮ +# => │ name │ Kylian │ +# => │ rank │ 99 │ +# => ╰───────┴────────────╯ + + $my_record | get name +# => Kylian ``` ### Tables @@ -354,11 +354,11 @@ The table is a core data structure in Nushell. As you run commands, you'll see t Internally, tables are simply **lists of records**. This means that any command which extracts or isolates a specific row of a table will produce a record. For example, `get 0`, when used on a list, extracts the first value. But when used on a table (a list of records), it extracts a record: ```nu -> [{x:12, y:5}, {x:3, y:6}] | get 0 -╭───┬────╮ -│ x │ 12 │ -│ y │ 5 │ -╰───┴────╯ +[{x:12, y:5}, {x:3, y:6}] | get 0 +# => ╭───┬────╮ +# => │ x │ 12 │ +# => │ y │ 5 │ +# => ╰───┴────╯ ``` ::: @@ -386,7 +386,7 @@ Internally, tables are simply **lists of records**. This means that any command Simple example: ```nu -> if true { print "It's true" } +if true { print "It's true" } ``` The `{ print "It's true" }` portion above is a block. @@ -405,13 +405,13 @@ The `{ print "It's true" }` portion above is a block. Using the optional operator `?` returns `null` if the requested cell-path doesn't exist: ```nu -> let simple_record = { a: 5, b: 10 } -> $simple_record.a? -5 -> $simple_record.c? +let simple_record = { a: 5, b: 10 } +$simple_record.a? +# => 5 +$simple_record.c? # => Nothing is output -> $simple_record.c? | describe -nothing -> $simple_record.c? == null -true +$simple_record.c? | describe +# => nothing +$simple_record.c? == null +# => true ``` diff --git a/book/variables.md b/book/variables.md index e91b6d4ba6..bb5ef249ce 100644 --- a/book/variables.md +++ b/book/variables.md @@ -10,31 +10,31 @@ After creating a variable, we can refer to it using `$` followed by its name. An immutable variable cannot change its value after declaration. They are declared using the `let` keyword, ```nu -> let val = 42 -> $val -42 -> $val = 100 -Error: nu::shell::assignment_requires_mutable_variable - - × Assignment to an immutable variable. - ╭─[entry #10:1:1] - 1 │ $val = 100 - · ──┬─ - · ╰── needs to be a mutable variable - ╰──── +let val = 42 +$val +# => 42 +$val = 100 +# => Error: nu::shell::assignment_requires_mutable_variable +# => +# => × Assignment to an immutable variable. +# => ╭─[entry #10:1:1] +# => 1 │ $val = 100 +# => · ──┬─ +# => · ╰── needs to be a mutable variable +# => ╰──── ``` However, immutable variables can be 'shadowed'. Shadowing means that they are redeclared and their initial value cannot be used anymore within the same scope. ```nu -> let val = 42 # declare a variable -> do { let val = 101; $val } # in an inner scope, shadow the variable -101 -> $val # in the outer scope the variable remains unchanged -42 -> let val = $val + 1 # now, in the outer scope, shadow the original variable -> $val # in the outer scope, the variable is now shadowed, and -43 # its original value is no longer available. +let val = 42 # declare a variable +do { let val = 101; $val } # in an inner scope, shadow the variable +# => 101 +$val # in the outer scope the variable remains unchanged +# => 42 +let val = $val + 1 # now, in the outer scope, shadow the original variable +$val # in the outer scope, the variable is now shadowed, and +# => 43 # its original value is no longer available. ``` ### Mutable Variables @@ -42,10 +42,10 @@ However, immutable variables can be 'shadowed'. Shadowing means that they are re A mutable variable is allowed to change its value by assignment. These are declared using the `mut` keyword. ```nu -> mut val = 42 -> $val += 27 -> $val -69 +mut val = 42 +$val += 27 +$val +# => 69 ``` There are a couple of assignment operators used with mutable variables @@ -103,28 +103,28 @@ Many, if not most, use-cases for mutable variables in Nushell have a functional For instance, loop counters are a common pattern for mutable variables and are built into most iterating commands. For example, you can get both each item and the index of each item using [`each`](/commands/docs/each.md) with [`enumerate`](/commands/docs/enumerate.md): ```nu -> ls | enumerate | each { |elt| $"Item #($elt.index) is size ($elt.item.size)" } -╭───┬───────────────────────────╮ -│ 0 │ Item #0 is size 812 B │ -│ 1 │ Item #1 is size 3.4 KiB │ -│ 2 │ Item #2 is size 11.0 KiB │ -│ 3 │ ... │ -│ 4 │ Item #18 is size 17.8 KiB │ -│ 5 │ Item #19 is size 482 B │ -│ 6 │ Item #20 is size 4.0 KiB │ -╰───┴───────────────────────────╯ +ls | enumerate | each { |elt| $"Item #($elt.index) is size ($elt.item.size)" } +# => ╭───┬───────────────────────────╮ +# => │ 0 │ Item #0 is size 812 B │ +# => │ 1 │ Item #1 is size 3.4 KiB │ +# => │ 2 │ Item #2 is size 11.0 KiB │ +# => │ 3 │ ... │ +# => │ 4 │ Item #18 is size 17.8 KiB │ +# => │ 5 │ Item #19 is size 482 B │ +# => │ 6 │ Item #20 is size 4.0 KiB │ +# => ╰───┴───────────────────────────╯ ``` You can also use the [`reduce`](/commands/docs/reduce.md) command to work in the same way you might mutate a variable in a loop. For example, if you wanted to find the largest string in a list of strings, you might do: ```nu -> [one, two, three, four, five, six] | reduce {|current_item, max| - if ($current_item | str length) > ($max | str length) { - $current_item - } else { - $max - } +[one, two, three, four, five, six] | reduce {|current_item, max| + if ($current_item | str length) > ($max | str length) { + $current_item + } else { + $max } +} three ``` @@ -209,6 +209,6 @@ Variable names in Nushell come with a few restrictions as to what characters the It is common for some scripts to declare variables that start with `$`. This is allowed, and it is equivalent to the `$` not being there at all. ```nu -> let $var = 42 +let $var = 42 # identical to `let var = 42` ``` diff --git a/book/working_with_lists.md b/book/working_with_lists.md index 71b91f9224..acb4ca5668 100644 --- a/book/working_with_lists.md +++ b/book/working_with_lists.md @@ -4,11 +4,11 @@ Lists are equivalent to the individual columns of tables. You can think of a list as essentially being a "one-column table" (with no column name). Thus, any command which operates on a column _also_ operates on a list. For instance, [`where`](/commands/docs/where.md) can be used with lists: ```nu -> [bell book candle] | where ($it =~ 'b') -╭───┬──────╮ -│ 0 │ bell │ -│ 1 │ book │ -╰───┴──────╯ +[bell book candle] | where ($it =~ 'b') +# => ╭───┬──────╮ +# => │ 0 │ bell │ +# => │ 1 │ book │ +# => ╰───┴──────╯ ``` ::: @@ -28,15 +28,15 @@ Nushell lists are similar to JSON arrays. The same `[ "Item1", "Item2", "Item3" We can [`insert`](/commands/docs/insert.md) values into lists as they flow through the pipeline, for example let's insert the value `10` into the middle of a list: ```nu -> [1, 2, 3, 4] | insert 2 10 -# [1, 2, 10, 3, 4] +[1, 2, 3, 4] | insert 2 10 +# => [1, 2, 10, 3, 4] ``` We can also use [`update`](/commands/docs/update.md) to replace the 2nd element with the value `10`. ```nu -> [1, 2, 3, 4] | update 1 10 -# [1, 10, 3, 4] +[1, 2, 3, 4] | update 1 10 +# => [1, 10, 3, 4] ``` ## Removing or Adding Items from List @@ -51,7 +51,8 @@ let colors = ($colors | prepend red) let colors = ($colors | append purple) let colors = ($colors ++ "blue") let colors = ("black" ++ $colors) -$colors # [black red yellow green purple blue] +$colors +# => [black red yellow green purple blue] ``` In case you want to remove items from list, there are many ways. [`skip`](/commands/docs/skip.md) allows you skip first rows from input, while [`drop`](/commands/docs/drop.md) allows you to skip specific numbered rows from end of list. @@ -60,7 +61,8 @@ In case you want to remove items from list, there are many ways. [`skip`](/comma let colors = [red yellow green purple] let colors = ($colors | skip 1) let colors = ($colors | drop 2) -$colors # [yellow] +$colors +# => [yellow] ``` We also have [`last`](/commands/docs/last.md) and [`first`](/commands/docs/first.md) which allow you to [`take`](/commands/docs/take.md) from the end or beginning of the list, respectively. @@ -68,7 +70,8 @@ We also have [`last`](/commands/docs/last.md) and [`first`](/commands/docs/first ```nu let colors = [red yellow green purple black magenta] let colors = ($colors | last 3) -$colors # [purple black magenta] +$colors +# => [purple black magenta] ``` And from the beginning of a list, @@ -76,7 +79,8 @@ And from the beginning of a list, ```nu let colors = [yellow green purple] let colors = ($colors | first 2) -$colors # [yellow green] +$colors +# => [yellow green] ``` ### Using the Spread Operator @@ -85,19 +89,19 @@ To append one or more lists together, optionally with values interspersed in bet [spread operator](/book/operators#spread-operator) (`...`): ```nu -> let x = [1 2] -> [ - ...$x - 3 - ...(4..7 | take 2) - ] -╭───┬───╮ -│ 0 │ 1 │ -│ 1 │ 2 │ -│ 2 │ 3 │ -│ 3 │ 4 │ -│ 4 │ 5 │ -╰───┴───╯ +let x = [1 2] +[ + ...$x + 3 + ...(4..7 | take 2) +] +# => ╭───┬───╮ +# => │ 0 │ 1 │ +# => │ 1 │ 2 │ +# => │ 2 │ 3 │ +# => │ 3 │ 4 │ +# => │ 4 │ 5 │ +# => ╰───┴───╯ ``` ## Iterating over Lists diff --git a/book/working_with_records.md b/book/working_with_records.md index b032557773..6c9cc91be2 100644 --- a/book/working_with_records.md +++ b/book/working_with_records.md @@ -4,15 +4,15 @@ Records are roughly equivalent to the individual rows of a table. You can think of a record as essentially being a "one-row table". Thus, most commands which operate on a table row _also_ operates on a record. For instance, [`update`](/commands/docs/update.md) can be used with records: ```nu -> let my_record = { - name: "Sam" - age: 30 - } -> $my_record | update age { $in + 1 } -╭──────┬─────╮ -│ name │ Sam │ -│ age │ 31 │ -╰──────┴─────╯ +let my_record = { + name: "Sam" + age: 30 + } +$my_record | update age { $in + 1 } +# => ╭──────┬─────╮ +# => │ name │ Sam │ +# => │ age │ 31 │ +# => ╰──────┴─────╯ ``` ::: @@ -23,19 +23,19 @@ A record is a collection of zero or more key-value pair mappings. It is similar ```nu # Nushell -> { "apples": 543, "bananas": 411, "oranges": 0 } -╭─────────┬─────╮ -│ apples │ 543 │ -│ bananas │ 411 │ -│ oranges │ 0 │ -╰─────────┴─────╯ +{ "apples": 543, "bananas": 411, "oranges": 0 } +# => ╭─────────┬─────╮ +# => │ apples │ 543 │ +# => │ bananas │ 411 │ +# => │ oranges │ 0 │ +# => ╰─────────┴─────╯ # JSON -> '{ "apples": 543, "bananas": 411, "oranges": 0 }' | from json -╭─────────┬─────╮ -│ apples │ 543 │ -│ bananas │ 411 │ -│ oranges │ 0 │ -╰─────────┴─────╯ +'{ "apples": 543, "bananas": 411, "oranges": 0 }' | from json +# => ╭─────────┬─────╮ +# => │ apples │ 543 │ +# => │ bananas │ 411 │ +# => │ oranges │ 0 │ +# => ╰─────────┴─────╯ ``` In Nushell, the key-value pairs of a record can also be separated using spaces or line-breaks. @@ -44,11 +44,11 @@ In Nushell, the key-value pairs of a record can also be separated using spaces o As records can have many fields, they are, by default, displayed vertically rather than left-to-right. To display a record left-to-right, convert it to a nuon. For example: ```nu - > { - name: "Sam" - rank: 10 - } | to nuon - {name: Sam, rank: 10} + { + name: "Sam" + rank: 10 + } | to nuon + # => {name: Sam, rank: 10} ``` ::: @@ -58,26 +58,26 @@ As records can have many fields, they are, by default, displayed vertically rath As with lists, you can [`insert`](/commands/docs/insert.md) values in records. For example, let's add some pears: ```nu -> { "apples": 543, "bananas": 411, "oranges": 0 } - | insert pears { 21 } -╭─────────┬─────╮ -│ apples │ 543 │ -│ bananas │ 411 │ -│ oranges │ 0 │ -│ pears │ 21 │ -╰─────────┴─────╯ +{ "apples": 543, "bananas": 411, "oranges": 0 } +| insert pears { 21 } +# => ╭─────────┬─────╮ +# => │ apples │ 543 │ +# => │ bananas │ 411 │ +# => │ oranges │ 0 │ +# => │ pears │ 21 │ +# => ╰─────────┴─────╯ ``` You can also [`update`](/commands/docs/update.md) values: ```nu -> { "apples": 543, "bananas": 411, "oranges": 0 } - | update oranges { 100 } -╭─────────┬─────╮ -│ apples │ 543 │ -│ bananas │ 411 │ -│ oranges │ 100 │ -╰─────────┴─────╯ +{ "apples": 543, "bananas": 411, "oranges": 0 } +| update oranges { 100 } +# => ╭─────────┬─────╮ +# => │ apples │ 543 │ +# => │ bananas │ 411 │ +# => │ oranges │ 100 │ +# => ╰─────────┴─────╯ ``` To make a copy of a record with new fields, you can either: @@ -85,28 +85,28 @@ To make a copy of a record with new fields, you can either: - Use the [`merge`](/commands/docs/merge.md) command: ```nu - > let first_record = { name: "Sam", rank: 10 } - > $first_record | merge { title: "Mayor" } - ╭───────┬───────╮ - │ name │ Sam │ - │ rank │ 10 │ - │ title │ Mayor │ - ╰───────┴───────╯ + let first_record = { name: "Sam", rank: 10 } + $first_record | merge { title: "Mayor" } +# => ╭───────┬───────╮ +# => │ name │ Sam │ +# => │ rank │ 10 │ +# => │ title │ Mayor │ +# => ╰───────┴───────╯ ``` - Use the [spread operator](/book/operators#spread-operator) (`...`) to expand the first record inside a new record: ```nu - > let first_record = { name: "Sam", rank: 10 } - > { - ...$first_record - title: "Mayor" - } - ╭───────┬───────╮ - │ name │ Sam │ - │ rank │ 10 │ - │ title │ Mayor │ - ╰───────┴───────╯ + let first_record = { name: "Sam", rank: 10 } + { + ...$first_record + title: "Mayor" + } + # => ╭───────┬───────╮ + # => │ name │ Sam │ + # => │ rank │ 10 │ + # => │ title │ Mayor │ + # => ╰───────┴───────╯ ``` ## Iterating over a Record @@ -114,14 +114,14 @@ To make a copy of a record with new fields, you can either: You can iterate over the key-value pairs of a record by first transposing it into a table: ```nu -> { "apples": 543, "bananas": 411, "oranges": 0 } - | transpose fruit count - | each {|f| $"We have ($f.count) ($f.fruit)" } -╭───┬─────────────────────╮ -│ 0 │ We have 543 apples │ -│ 1 │ We have 411 bananas │ -│ 2 │ We have 0 oranges │ -╰───┴─────────────────────╯ +{ "apples": 543, "bananas": 411, "oranges": 0 } +| transpose fruit count +| each {|f| $"We have ($f.count) ($f.fruit)" } +# => ╭───┬─────────────────────╮ +# => │ 0 │ We have 543 apples │ +# => │ 1 │ We have 411 bananas │ +# => │ 2 │ We have 0 oranges │ +# => ╰───┴─────────────────────╯ ``` ## Accessing Record Values diff --git a/book/working_with_strings.md b/book/working_with_strings.md index 59639f7ac6..2f4cd9f683 100644 --- a/book/working_with_strings.md +++ b/book/working_with_strings.md @@ -20,12 +20,12 @@ and much more. Strings are so common that Nushell offers multiple string formats The simplest string in Nushell is the single-quoted string. This string uses the `'` character to surround some text. Here's the text for hello world as a single-quoted string: ```nu -> 'hello world' -hello world -> 'The +'hello world' +# => hello world +'The end' -The -end +# => The +# => end ``` Single-quoted strings don't do anything to the text they're given, making them ideal for holding a wide range of text data. @@ -37,9 +37,9 @@ For more complex strings, Nushell also offers double-quoted strings. These strin For example, we could write the text hello followed by a new line and then world, using escape characters and a double-quoted string: ```nu -> "hello\nworld" -hello -world +"hello\nworld" +# => hello +# => world ``` Escape characters let you quickly add in a character that would otherwise be hard to type. @@ -65,8 +65,8 @@ by a starting `r#'` and a closing `'#`. This syntax should look familiar to user of Rust. ```nu -> r#'Raw strings can contain 'quoted' text.'# -Raw strings can contain 'quoted' text. +r#'Raw strings can contain 'quoted' text.'# +# => Raw strings can contain 'quoted' text. ``` Additional `#` symbols can be added to the start and end of the raw string to enclose @@ -74,8 +74,8 @@ one less than the same number of `#` symbols next to a `'` symbol in the string. be used to nest raw strings: ```nu -> r###'r##'This is an example of a raw string.'##'### -r##'This is an example of a raw string.'## +r###'r##'This is an example of a raw string.'##'### +# => r##'This is an example of a raw string.'## ``` ## Bare Word Strings @@ -83,46 +83,46 @@ r##'This is an example of a raw string.'## Like other shell languages (but unlike most other programming languages) strings consisting of a single 'word' can also be written without any quotes: ```nu -> print hello -hello -> [hello] | describe -list +print hello +# => hello +[hello] | describe +# => list ``` But be careful - if you use a bare word plainly on the command line (that is, not inside a data structure or used as a command parameter) or inside round brackets `(` `)`, it will be interpreted as an external command: ```nu -> hello -Error: nu::shell::external_command - - × External command failed - ╭─[entry #5:1:1] - 1 │ hello - · ──┬── - · ╰── executable was not found - ╰──── - help: program not found +hello +# => Error: nu::shell::external_command +# => +# => × External command failed +# => ╭─[entry #5:1:1] +# => 1 │ hello +# => · ──┬── +# => · ╰── executable was not found +# => ╰──── +# => help: program not found ``` Also, many bare words have special meaning in nu, and so will not be interpreted as a string: ```nu -> true | describe -bool -> [true] | describe -list -> [trueX] | describe -list -> trueX | describe -Error: nu::shell::external_command - - × External command failed - ╭─[entry #5:1:1] - 1 │ trueX | describe - · ──┬── - · ╰── executable was not found - ╰──── - help: program not found +true | describe +# => bool +[true] | describe +# => list +[trueX] | describe +# => list +trueX | describe +# => Error: nu::shell::external_command +# => +# => × External command failed +# => ╭─[entry #5:1:1] +# => 1 │ trueX | describe +# => · ──┬── +# => · ╰── executable was not found +# => ╰──── +# => help: program not found ``` So, while bare strings are useful for informal command line usage, when programming more formally in nu, you should generally use quotes. @@ -155,10 +155,10 @@ ls `./my dir/*` Backtick-quoted strings cannot contain _unmatched_ backticks in the string itself. For example: `````nu -> echo ```` +echo ```` `` -> echo ``` +echo ``` # Unterminated string which will start a new line in the CLI ````` @@ -169,8 +169,8 @@ You can place the `^` sigil in front of any string (including a variable) to hav ```nu ^'C:\Program Files\exiftool.exe' -> let foo = 'C:\Program Files\exiftool.exe' -> ^$foo +let foo = 'C:\Program Files\exiftool.exe' +^$foo ``` You can also use the [`run-external`](/commands/docs/run-external.md) command for this purpose, which provides additional flags and options. @@ -216,9 +216,9 @@ String interpolation uses `$" "` and `$' '` as ways to wrap interpolated text. For example, let's say we have a variable called `$name` and we want to greet the name of the person contained in this variable: ```nu -> let name = "Alice" -> $"greetings, ($name)" -greetings, Alice +let name = "Alice" +$"greetings, ($name)" +# => greetings, Alice ``` By wrapping expressions in `()`, we can run them to completion and use the results to help build the string. @@ -228,8 +228,8 @@ String interpolation has both a single-quoted, `$' '`, and a double-quoted, `$" As of version 0.61, interpolated strings support escaping parentheses, so that the `(` and `)` characters may be used in a string without Nushell trying to evaluate what appears between them: ```nu -> $"2 + 2 is (2 + 2) \(you guessed it!)" -2 + 2 is 4 (you guessed it!) +$"2 + 2 is (2 + 2) \(you guessed it!)" +# => 2 + 2 is 4 (you guessed it!) ``` Interpolated strings can be evaluated at parse time, but if they include values whose formatting depends @@ -238,7 +238,7 @@ So if you have something like this in your `config.nu`, `x` will be `"2.0 KB"` e `MB` for all file sizes (datetimes will similarly use the default config). ```nu -> const x = $"(2kb)" +const x = $"(2kb)" ``` ## Splitting Strings @@ -246,36 +246,36 @@ So if you have something like this in your `config.nu`, `x` will be `"2.0 KB"` e The [`split row`](/commands/docs/split_row.md) command creates a list from a string based on a delimiter. ```nu -> "red,green,blue" | split row "," -╭───┬───────╮ -│ 0 │ red │ -│ 1 │ green │ -│ 2 │ blue │ -╰───┴───────╯ +"red,green,blue" | split row "," +# => ╭───┬───────╮ +# => │ 0 │ red │ +# => │ 1 │ green │ +# => │ 2 │ blue │ +# => ╰───┴───────╯ ``` The [`split column`](/commands/docs/split_column.md) command will create a table from a string based on a delimiter. This applies generic column names to the table. ```nu -> "red,green,blue" | split column "," -╭───┬─────────┬─────────┬─────────╮ -│ # │ column1 │ column2 │ column3 │ -├───┼─────────┼─────────┼─────────┤ -│ 0 │ red │ green │ blue │ -╰───┴─────────┴─────────┴─────────╯ +"red,green,blue" | split column "," +# => ╭───┬─────────┬─────────┬─────────╮ +# => │ # │ column1 │ column2 │ column3 │ +# => ├───┼─────────┼─────────┼─────────┤ +# => │ 0 │ red │ green │ blue │ +# => ╰───┴─────────┴─────────┴─────────╯ ``` Finally, the [`split chars`](/commands/docs/split_chars.md) command will split a string into a list of characters. ```nu -> 'aeiou' | split chars -╭───┬───╮ -│ 0 │ a │ -│ 1 │ e │ -│ 2 │ i │ -│ 3 │ o │ -│ 4 │ u │ -╰───┴───╯ +'aeiou' | split chars +# => ╭───┬───╮ +# => │ 0 │ a │ +# => │ 1 │ e │ +# => │ 2 │ i │ +# => │ 3 │ o │ +# => │ 4 │ u │ +# => ╰───┴───╯ ``` ## The [`str`](/commands/docs/str.md) command @@ -285,8 +285,8 @@ Many string functions are subcommands of the [`str`](/commands/docs/str.md) comm For example, you can look if a string contains a particular substring using [`str contains`](/commands/docs/str_contains.md): ```nu -> "hello world" | str contains "o wo" -true +"hello world" | str contains "o wo" +# => true ``` (You might also prefer, for brevity, the `=~` operator (described below).) @@ -296,8 +296,8 @@ true You can trim the sides of a string with the [`str trim`](/commands/docs/str_trim.md) command. By default, the [`str trim`](/commands/docs/str_trim.md) commands trims whitespace from both sides of the string. For example: ```nu -> ' My string ' | str trim -My string +' My string ' | str trim +# => My string ``` You can specify on which side the trimming occurs with the `--right` and `--left` options. (`-r` and `-l` being the short-form options respectively) @@ -307,8 +307,8 @@ To trim a specific character, use `--char ` or `-c ` to sp Here's an example of all the options in action: ```nu -> '=== Nu shell ===' | str trim -r -c '=' -=== Nu shell +'=== Nu shell ===' | str trim -r -c '=' +# => === Nu shell ``` ### Substrings @@ -316,12 +316,12 @@ Here's an example of all the options in action: Substrings are slices of a string. They have a startpoint and an endpoint. Here's an example of using a substring: ```nu -> 'Hello World!' | str index-of 'o' -4 -> 'Hello World!' | str index-of 'r' -8 -> 'Hello World!' | str substring 4..8 -o Wo +'Hello World!' | str index-of 'o' +# => 4 +'Hello World!' | str index-of 'r' +# => 8 +'Hello World!' | str substring 4..8 +# => o Wo ``` ### String Padding @@ -329,10 +329,10 @@ o Wo With the [`fill`](/commands/docs/fill.md) command you can add padding to a string. Padding adds characters to string until it's a certain length. For example: ```nu -> '1234' | fill -a right -c '0' -w 10 -0000001234 -> '1234' | fill -a left -c '0' -w 10 | str length -10 +'1234' | fill -a right -c '0' -w 10 +# => 0000001234 +'1234' | fill -a left -c '0' -w 10 | str length +# => 10 ``` ### Reversing Strings @@ -340,14 +340,14 @@ With the [`fill`](/commands/docs/fill.md) command you can add padding to a strin This can be done easily with the [`str reverse`](/commands/docs/str_reverse.md) command. ```nu -> 'Nushell' | str reverse -llehsuN -> ['Nushell' 'is' 'cool'] | str reverse -╭───┬─────────╮ -│ 0 │ llehsuN │ -│ 1 │ si │ -│ 2 │ looc │ -╰───┴─────────╯ +'Nushell' | str reverse +# => llehsuN +['Nushell' 'is' 'cool'] | str reverse +# => ╭───┬─────────╮ +# => │ 0 │ llehsuN │ +# => │ 1 │ si │ +# => │ 2 │ looc │ +# => ╰───┴─────────╯ ``` ## String Parsing @@ -355,42 +355,42 @@ llehsuN With the [`parse`](/commands/docs/parse.md) command you can parse a string into columns. For example: ```nu -> 'Nushell 0.80' | parse '{shell} {version}' -╭───┬─────────┬─────────╮ -│ # │ shell │ version │ -├───┼─────────┼─────────┤ -│ 0 │ Nushell │ 0.80 │ -╰───┴─────────┴─────────╯ -> 'where all data is structured!' | parse --regex '(?P\w*\s?\w+) is (?P\w+)' -╭───┬──────────┬────────────╮ -│ # │ subject │ adjective │ -├───┼──────────┼────────────┤ -│ 0 │ all data │ structured │ -╰───┴──────────┴────────────╯ +'Nushell 0.80' | parse '{shell} {version}' +# => ╭───┬─────────┬─────────╮ +# => │ # │ shell │ version │ +# => ├───┼─────────┼─────────┤ +# => │ 0 │ Nushell │ 0.80 │ +# => ╰───┴─────────┴─────────╯ +'where all data is structured!' | parse --regex '(?P\w*\s?\w+) is (?P\w+)' +# => ╭───┬──────────┬────────────╮ +# => │ # │ subject │ adjective │ +# => ├───┼──────────┼────────────┤ +# => │ 0 │ all data │ structured │ +# => ╰───┴──────────┴────────────╯ ``` If a string is known to contain comma-separated, tab-separated or multi-space-separated data, you can use [`from csv`](/commands/docs/from_csv.md), [`from tsv`](/commands/docs/from_tsv.md) or [`from ssv`](/commands/docs/from_ssv.md): ```nu -> "acronym,long\nAPL,A Programming Language" | from csv -╭───┬─────────┬────────────────────────╮ -│ # │ acronym │ long │ -├───┼─────────┼────────────────────────┤ -│ 0 │ APL │ A Programming Language │ -╰───┴─────────┴────────────────────────╯ -> "name duration\nonestop.mid 4:06" | from ssv -╭───┬─────────────┬──────────╮ -│ # │ name │ duration │ -├───┼─────────────┼──────────┤ -│ 0 │ onestop.mid │ 4:06 │ -╰───┴─────────────┴──────────╯ -> "rank\tsuit\nJack\tSpades\nAce\tClubs" | from tsv -╭───┬──────┬────────╮ -│ # │ rank │ suit │ -├───┼──────┼────────┤ -│ 0 │ Jack │ Spades │ -│ 1 │ Ace │ Clubs │ -╰───┴──────┴────────╯ +"acronym,long\nAPL,A Programming Language" | from csv +# => ╭───┬─────────┬────────────────────────╮ +# => │ # │ acronym │ long │ +# => ├───┼─────────┼────────────────────────┤ +# => │ 0 │ APL │ A Programming Language │ +# => ╰───┴─────────┴────────────────────────╯ +"name duration\nonestop.mid 4:06" | from ssv +# => ╭───┬─────────────┬──────────╮ +# => │ # │ name │ duration │ +# => ├───┼─────────────┼──────────┤ +# => │ 0 │ onestop.mid │ 4:06 │ +# => ╰───┴─────────────┴──────────╯ +"rank\tsuit\nJack\tSpades\nAce\tClubs" | from tsv +# => ╭───┬──────┬────────╮ +# => │ # │ rank │ suit │ +# => ├───┼──────┼────────┤ +# => │ 0 │ Jack │ Spades │ +# => │ 1 │ Ace │ Clubs │ +# => ╰───┴──────┴────────╯ ``` ## String Comparison @@ -400,19 +400,19 @@ In addition to the standard `==` and `!=` operators, a few operators exist for s Those familiar with Bash and Perl will recognise the regex comparison operators: ```nu -> 'APL' =~ '^\w{0,3}$' -true -> 'FORTRAN' !~ '^\w{0,3}$' -true +'APL' =~ '^\w{0,3}$' +# => true +'FORTRAN' !~ '^\w{0,3}$' +# => true ``` Two other operators exist for simpler comparisons: ```nu -> 'JavaScript' starts-with 'Java' -true -> 'OCaml' ends-with 'Caml' -true +'JavaScript' starts-with 'Java' +# => true +'OCaml' ends-with 'Caml' +# => true ``` ## Converting Strings @@ -433,7 +433,7 @@ There are multiple ways to convert strings to and from other types. You can color strings with the [`ansi`](/commands/docs/ansi.md) command. For example: ```nu -> $'(ansi purple_bold)This text is a bold purple!(ansi reset)' +$'(ansi purple_bold)This text is a bold purple!(ansi reset)' ``` `ansi purple_bold` makes the text a bold purple diff --git a/book/working_with_tables.md b/book/working_with_tables.md index 348a6f9946..255a697633 100644 --- a/book/working_with_tables.md +++ b/book/working_with_tables.md @@ -9,18 +9,18 @@ One of the common ways of seeing data in Nu is through a table. Nu comes with a To start off, let's get a table that we can use: ```nu -> ls -───┬───────────────┬──────┬─────────┬──────────── - # │ name │ type │ size │ modified -───┼───────────────┼──────┼─────────┼──────────── - 0 │ files.rs │ File │ 4.6 KB │ 5 days ago - 1 │ lib.rs │ File │ 330 B │ 5 days ago - 2 │ lite_parse.rs │ File │ 6.3 KB │ 5 days ago - 3 │ parse.rs │ File │ 49.8 KB │ 1 day ago - 4 │ path.rs │ File │ 2.1 KB │ 5 days ago - 5 │ shapes.rs │ File │ 4.7 KB │ 5 days ago - 6 │ signature.rs │ File │ 1.2 KB │ 5 days ago -───┴───────────────┴──────┴─────────┴──────────── +ls +# => ───┬───────────────┬──────┬─────────┬──────────── +# => # │ name │ type │ size │ modified +# => ───┼───────────────┼──────┼─────────┼──────────── +# => 0 │ files.rs │ File │ 4.6 KB │ 5 days ago +# => 1 │ lib.rs │ File │ 330 B │ 5 days ago +# => 2 │ lite_parse.rs │ File │ 6.3 KB │ 5 days ago +# => 3 │ parse.rs │ File │ 49.8 KB │ 1 day ago +# => 4 │ path.rs │ File │ 2.1 KB │ 5 days ago +# => 5 │ shapes.rs │ File │ 4.7 KB │ 5 days ago +# => 6 │ signature.rs │ File │ 1.2 KB │ 5 days ago +# => ───┴───────────────┴──────┴─────────┴──────────── ``` ::: tip Changing how tables are displayed @@ -33,18 +33,18 @@ See [hooks](/book/hooks.md#changing-how-output-is-displayed) for more informatio We can sort a table by calling the [`sort-by`](/commands/docs/sort-by.md) command and telling it which columns we want to use in the sort. Let's say we wanted to sort our table by the size of the file: ```nu -> ls | sort-by size -───┬───────────────┬──────┬─────────┬──────────── - # │ name │ type │ size │ modified -───┼───────────────┼──────┼─────────┼──────────── - 0 │ lib.rs │ File │ 330 B │ 5 days ago - 1 │ signature.rs │ File │ 1.2 KB │ 5 days ago - 2 │ path.rs │ File │ 2.1 KB │ 5 days ago - 3 │ files.rs │ File │ 4.6 KB │ 5 days ago - 4 │ shapes.rs │ File │ 4.7 KB │ 5 days ago - 5 │ lite_parse.rs │ File │ 6.3 KB │ 5 days ago - 6 │ parse.rs │ File │ 49.8 KB │ 1 day ago -───┴───────────────┴──────┴─────────┴──────────── +ls | sort-by size +# => ───┬───────────────┬──────┬─────────┬──────────── +# => # │ name │ type │ size │ modified +# => ───┼───────────────┼──────┼─────────┼──────────── +# => 0 │ lib.rs │ File │ 330 B │ 5 days ago +# => 1 │ signature.rs │ File │ 1.2 KB │ 5 days ago +# => 2 │ path.rs │ File │ 2.1 KB │ 5 days ago +# => 3 │ files.rs │ File │ 4.6 KB │ 5 days ago +# => 4 │ shapes.rs │ File │ 4.7 KB │ 5 days ago +# => 5 │ lite_parse.rs │ File │ 6.3 KB │ 5 days ago +# => 6 │ parse.rs │ File │ 49.8 KB │ 1 day ago +# => ───┴───────────────┴──────┴─────────┴──────────── ``` We can sort a table by any column that can be compared. For example, we could also have sorted the above using the "name", "accessed", or "modified" columns. @@ -60,33 +60,33 @@ The following is a basic overview. For a more in-depth discussion of this topic, We can select data from a table by choosing to select specific columns or specific rows. Let's [`select`](/commands/docs/select.md) a few columns from our table to use: ```nu -> ls | select name size -───┬───────────────┬───────── - # │ name │ size -───┼───────────────┼───────── - 0 │ files.rs │ 4.6 KB - 1 │ lib.rs │ 330 B - 2 │ lite_parse.rs │ 6.3 KB - 3 │ parse.rs │ 49.8 KB - 4 │ path.rs │ 2.1 KB - 5 │ shapes.rs │ 4.7 KB - 6 │ signature.rs │ 1.2 KB -───┴───────────────┴───────── +ls | select name size +# => ───┬───────────────┬───────── +# => # │ name │ size +# => ───┼───────────────┼───────── +# => 0 │ files.rs │ 4.6 KB +# => 1 │ lib.rs │ 330 B +# => 2 │ lite_parse.rs │ 6.3 KB +# => 3 │ parse.rs │ 49.8 KB +# => 4 │ path.rs │ 2.1 KB +# => 5 │ shapes.rs │ 4.7 KB +# => 6 │ signature.rs │ 1.2 KB +# => ───┴───────────────┴───────── ``` This helps to create a table that's more focused on what we need. Next, let's say we want to only look at the 5 smallest files in this directory: ```nu -> ls | sort-by size | first 5 -───┬──────────────┬──────┬────────┬──────────── - # │ name │ type │ size │ modified -───┼──────────────┼──────┼────────┼──────────── - 0 │ lib.rs │ File │ 330 B │ 5 days ago - 1 │ signature.rs │ File │ 1.2 KB │ 5 days ago - 2 │ path.rs │ File │ 2.1 KB │ 5 days ago - 3 │ files.rs │ File │ 4.6 KB │ 5 days ago - 4 │ shapes.rs │ File │ 4.7 KB │ 5 days ago -───┴──────────────┴──────┴────────┴──────────── +ls | sort-by size | first 5 +# => ───┬──────────────┬──────┬────────┬──────────── +# => # │ name │ type │ size │ modified +# => ───┼──────────────┼──────┼────────┼──────────── +# => 0 │ lib.rs │ File │ 330 B │ 5 days ago +# => 1 │ signature.rs │ File │ 1.2 KB │ 5 days ago +# => 2 │ path.rs │ File │ 2.1 KB │ 5 days ago +# => 3 │ files.rs │ File │ 4.6 KB │ 5 days ago +# => 4 │ shapes.rs │ File │ 4.7 KB │ 5 days ago +# => ───┴──────────────┴──────┴────────┴──────────── ``` You'll notice we first sort the table by size to get to the smallest file, and then we use the `first 5` to return the first 5 rows of the table. @@ -94,14 +94,14 @@ You'll notice we first sort the table by size to get to the smallest file, and t You can also [`skip`](/commands/docs/skip.md) rows that you don't want. Let's skip the first two of the 5 rows we returned above: ```nu -> ls | sort-by size | first 5 | skip 2 -───┬───────────┬──────┬────────┬──────────── - # │ name │ type │ size │ modified -───┼───────────┼──────┼────────┼──────────── - 0 │ path.rs │ File │ 2.1 KB │ 5 days ago - 1 │ files.rs │ File │ 4.6 KB │ 5 days ago - 2 │ shapes.rs │ File │ 4.7 KB │ 5 days ago -───┴───────────┴──────┴────────┴──────────── +ls | sort-by size | first 5 | skip 2 +# => ───┬───────────┬──────┬────────┬──────────── +# => # │ name │ type │ size │ modified +# => ───┼───────────┼──────┼────────┼──────────── +# => 0 │ path.rs │ File │ 2.1 KB │ 5 days ago +# => 1 │ files.rs │ File │ 4.6 KB │ 5 days ago +# => 2 │ shapes.rs │ File │ 4.7 KB │ 5 days ago +# => ───┴───────────┴──────┴────────┴──────────── ``` We've narrowed it to three rows we care about. @@ -109,25 +109,25 @@ We've narrowed it to three rows we care about. Let's look at a few other commands for selecting data. You may have wondered why the rows of the table are numbers. This acts as a handy way to get to a single row. Let's sort our table by the file name and then pick one of the rows with the [`select`](/commands/docs/select.md) command using its row number: ```nu -> ls | sort-by name -───┬───────────────┬──────┬─────────┬──────────── - # │ name │ type │ size │ modified -───┼───────────────┼──────┼─────────┼──────────── - 0 │ files.rs │ File │ 4.6 KB │ 5 days ago - 1 │ lib.rs │ File │ 330 B │ 5 days ago - 2 │ lite_parse.rs │ File │ 6.3 KB │ 5 days ago - 3 │ parse.rs │ File │ 49.8 KB │ 1 day ago - 4 │ path.rs │ File │ 2.1 KB │ 5 days ago - 5 │ shapes.rs │ File │ 4.7 KB │ 5 days ago - 6 │ signature.rs │ File │ 1.2 KB │ 5 days ago -───┴───────────────┴──────┴─────────┴──────────── - -> ls | sort-by name | select 5 -───┬───────────────┬──────┬─────────┬──────────── - # │ name │ type │ size │ modified -───┼───────────────┼──────┼─────────┼──────────── - 0 │ shapes.rs │ File │ 4.7 KB │ 5 days ago -───┴───────────────┴──────┴─────────┴──────────── +ls | sort-by name +# => ───┬───────────────┬──────┬─────────┬──────────── +# => # │ name │ type │ size │ modified +# => ───┼───────────────┼──────┼─────────┼──────────── +# => 0 │ files.rs │ File │ 4.6 KB │ 5 days ago +# => 1 │ lib.rs │ File │ 330 B │ 5 days ago +# => 2 │ lite_parse.rs │ File │ 6.3 KB │ 5 days ago +# => 3 │ parse.rs │ File │ 49.8 KB │ 1 day ago +# => 4 │ path.rs │ File │ 2.1 KB │ 5 days ago +# => 5 │ shapes.rs │ File │ 4.7 KB │ 5 days ago +# => 6 │ signature.rs │ File │ 1.2 KB │ 5 days ago +# => ───┴───────────────┴──────┴─────────┴──────────── + +ls | sort-by name | select 5 +# => ───┬───────────────┬──────┬─────────┬──────────── +# => # │ name │ type │ size │ modified +# => ───┼───────────────┼──────┼─────────┼──────────── +# => 0 │ shapes.rs │ File │ 4.7 KB │ 5 days ago +# => ───┴───────────────┴──────┴─────────┴──────────── ``` ## Getting Data out of a Table @@ -135,16 +135,16 @@ Let's look at a few other commands for selecting data. You may have wondered why So far, we've worked with tables by trimming the table down to only what we need. Sometimes we may want to go a step further and only look at the values in the cells themselves rather than taking a whole column. Let's say, for example, we wanted to only get a list of the names of the files. For this, we use the [`get`](/commands/docs/get.md) command: ```nu -> ls | get name -───┬─────────────── - 0 │ files.rs - 1 │ lib.rs - 2 │ lite_parse.rs - 3 │ parse.rs - 4 │ path.rs - 5 │ shapes.rs - 6 │ signature.rs -───┴─────────────── +ls | get name +# => ───┬─────────────── +# => 0 │ files.rs +# => 1 │ lib.rs +# => 2 │ lite_parse.rs +# => 3 │ parse.rs +# => 4 │ path.rs +# => 5 │ shapes.rs +# => 6 │ signature.rs +# => ───┴─────────────── ``` We now have the values for each of the filenames. @@ -152,18 +152,18 @@ We now have the values for each of the filenames. This might look like the [`select`](/commands/docs/select.md) command we saw earlier, so let's put that here as well to compare the two: ```nu -> ls | select name -───┬─────────────── - # │ name -───┼─────────────── - 0 │ files.rs - 1 │ lib.rs - 2 │ lite_parse.rs - 3 │ parse.rs - 4 │ path.rs - 5 │ shapes.rs - 6 │ signature.rs -───┴─────────────── +ls | select name +# => ───┬─────────────── +# => # │ name +# => ───┼─────────────── +# => 0 │ files.rs +# => 1 │ lib.rs +# => 2 │ lite_parse.rs +# => 3 │ parse.rs +# => 4 │ path.rs +# => 5 │ shapes.rs +# => 6 │ signature.rs +# => ───┴─────────────── ``` These look very similar! Let's see if we can spell out the difference between these two commands to make it clear: @@ -187,12 +187,12 @@ We can concatenate tables using [`append`](/commands/docs/append.md): let first = [[a b]; [1 2]] let second = [[a b]; [3 4]] $first | append $second -───┬───┬─── - # │ a │ b -───┼───┼─── - 0 │ 1 │ 2 - 1 │ 3 │ 4 -───┴───┴─── +# => ───┬───┬─── +# => # │ a │ b +# => ───┼───┼─── +# => 0 │ 1 │ 2 +# => 1 │ 3 │ 4 +# => ───┴───┴─── ``` If the column names are not identical then additionally columns and values will be created as necessary: @@ -202,26 +202,26 @@ let first = [[a b]; [1 2]] let second = [[a b]; [3 4]] let third = [[a c]; [3 4]] $first | append $second | append $third -───┬───┬────┬──── - # │ a │ b │ c -───┼───┼────┼──── - 0 │ 1 │ 2 │ ❎ - 1 │ 3 │ 4 │ ❎ - 2 │ 3 │ ❎ │ 4 -───┴───┴────┴──── +# => ───┬───┬────┬──── +# => # │ a │ b │ c +# => ───┼───┼────┼──── +# => 0 │ 1 │ 2 │ ❎ +# => 1 │ 3 │ 4 │ ❎ +# => 2 │ 3 │ ❎ │ 4 +# => ───┴───┴────┴──── ``` You can also use the `++` operator as an inline replacement for `append`: ```nu $first ++ $second ++ $third -───┬───┬────┬──── - # │ a │ b │ c -───┼───┼────┼──── - 0 │ 1 │ 2 │ ❎ - 1 │ 3 │ 4 │ ❎ - 2 │ 3 │ ❎ │ 4 -───┴───┴────┴─── +# => ───┬───┬────┬──── +# => # │ a │ b │ c +# => ───┼───┼────┼──── +# => 0 │ 1 │ 2 │ ❎ +# => 1 │ 3 │ 4 │ ❎ +# => 2 │ 3 │ ❎ │ 4 +# => ───┴───┴────┴─── ``` ### Merging Tables @@ -232,39 +232,39 @@ We can use the [`merge`](/commands/docs/merge.md) command to merge two (or more) let first = [[a b]; [1 2]] let second = [[c d]; [3 4]] $first | merge $second -───┬───┬───┬───┬─── - # │ a │ b │ c │ d -───┼───┼───┼───┼─── - 0 │ 1 │ 2 │ 3 │ 4 -───┴───┴───┴───┴─── +# => ───┬───┬───┬───┬─── +# => # │ a │ b │ c │ d +# => ───┼───┼───┼───┼─── +# => 0 │ 1 │ 2 │ 3 │ 4 +# => ───┴───┴───┴───┴─── ``` Let's add a third table: ```nu -> let third = [[e f]; [5 6]] +let third = [[e f]; [5 6]] ``` We could join all three tables together like this: ```nu -> $first | merge $second | merge $third -───┬───┬───┬───┬───┬───┬─── - # │ a │ b │ c │ d │ e │ f -───┼───┼───┼───┼───┼───┼─── - 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 -───┴───┴───┴───┴───┴───┴─── +$first | merge $second | merge $third +# => ───┬───┬───┬───┬───┬───┬─── +# => # │ a │ b │ c │ d │ e │ f +# => ───┼───┼───┼───┼───┼───┼─── +# => 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 +# => ───┴───┴───┴───┴───┴───┴─── ``` Or we could use the [`reduce`](/commands/docs/reduce.md) command to dynamically merge all tables: ```nu -> [$first $second $third] | reduce {|elt, acc| $acc | merge $elt } -───┬───┬───┬───┬───┬───┬─── - # │ a │ b │ c │ d │ e │ f -───┼───┼───┼───┼───┼───┼─── - 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 -───┴───┴───┴───┴───┴───┴─── +[$first $second $third] | reduce {|elt, acc| $acc | merge $elt } +# => ───┬───┬───┬───┬───┬───┬─── +# => # │ a │ b │ c │ d │ e │ f +# => ───┼───┼───┼───┼───┼───┼─── +# => 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 +# => ───┴───┴───┴───┴───┴───┴─── ``` ### Adding a new Column @@ -272,53 +272,53 @@ Or we could use the [`reduce`](/commands/docs/reduce.md) command to dynamically We can use the [`insert`](/commands/docs/insert.md) command to add a new column to the table. Let's look at an example: ```nu -> open rustfmt.toml -─────────┬────── - edition │ 2018 -─────────┴────── +open rustfmt.toml +# => ─────────┬────── +# => edition │ 2018 +# => ─────────┴────── ``` Let's add a column called "next_edition" with the value 2021: ```nu -> open rustfmt.toml | insert next_edition 2021 -──────────────┬────── - edition │ 2018 - next_edition │ 2021 -──────────────┴────── +open rustfmt.toml | insert next_edition 2021 +# => ──────────────┬────── +# => edition │ 2018 +# => next_edition │ 2021 +# => ──────────────┴────── ``` This visual may be slightly confusing, because it looks like what we've just done is add a row. In this case, remember: rows have numbers, columns have names. If it still is confusing, note that appending one more row will make the table render as expected: ```nu -> open rustfmt.toml | insert next_edition 2021 | append {edition: 2021 next_edition: 2024} -───┬─────────┬────────────── - # │ edition │ next_edition -───┼─────────┼────────────── - 0 │ 2018 │ 2021 - 1 │ 2021 │ 2024 -───┴─────────┴────────────── +open rustfmt.toml | insert next_edition 2021 | append {edition: 2021 next_edition: 2024} +# => ───┬─────────┬────────────── +# => # │ edition │ next_edition +# => ───┼─────────┼────────────── +# => 0 │ 2018 │ 2021 +# => 1 │ 2021 │ 2024 +# => ───┴─────────┴────────────── ``` Notice that if we open the original file, the contents have stayed the same: ```nu -> open rustfmt.toml -─────────┬────── - edition │ 2018 -─────────┴────── +open rustfmt.toml +# => ─────────┬────── +# => edition │ 2018 +# => ─────────┴────── ``` Changes in Nu are functional changes, meaning that they work on values themselves rather than trying to cause a permanent change. This lets us do many different types of work in our pipeline until we're ready to write out the result with any changes we'd like if we choose to. Here we could write out the result using the [`save`](/commands/docs/save.md) command: ```nu -> open rustfmt.toml | insert next_edition 2021 | save rustfmt2.toml -> open rustfmt2.toml -──────────────┬────── - edition │ 2018 - next_edition │ 2021 -──────────────┴────── +open rustfmt.toml | insert next_edition 2021 | save rustfmt2.toml +open rustfmt2.toml +# => ──────────────┬────── +# => edition │ 2018 +# => next_edition │ 2021 +# => ──────────────┴────── ``` ### Updating a Column @@ -326,19 +326,19 @@ Changes in Nu are functional changes, meaning that they work on values themselve In a similar way to the [`insert`](/commands/docs/insert.md) command, we can also use the [`update`](/commands/docs/update.md) command to change the contents of a column to a new value. To see it in action let's open the same file: ```nu -> open rustfmt.toml -─────────┬────── - edition │ 2018 -─────────┴────── +open rustfmt.toml +# => ─────────┬────── +# => edition │ 2018 +# => ─────────┴────── ``` And now, let's update the edition to point at the next edition we hope to support: ```nu -> open rustfmt.toml | update edition 2021 -─────────┬────── - edition │ 2021 -─────────┴────── +open rustfmt.toml | update edition 2021 +# => ─────────┬────── +# => edition │ 2021 +# => ─────────┴────── ``` You can also use the [`upsert`](/commands/docs/upsert.md) command to insert or update depending on whether the column already exists. @@ -348,16 +348,16 @@ You can also use the [`upsert`](/commands/docs/upsert.md) command to insert or u You can use [`move`](/commands/docs/move.md) to move columns in the table. For example, if we wanted to move the "name" column from [`ls`](/commands/docs/ls.md) after the "size" column, we could do: ```nu -> ls | move name --after size -╭────┬──────┬─────────┬───────────────────┬──────────────╮ -│ # │ type │ size │ name │ modified │ -├────┼──────┼─────────┼───────────────────┼──────────────┤ -│ 0 │ dir │ 256 B │ Applications │ 3 days ago │ -│ 1 │ dir │ 256 B │ Data │ 2 weeks ago │ -│ 2 │ dir │ 448 B │ Desktop │ 2 hours ago │ -│ 3 │ dir │ 192 B │ Disks │ a week ago │ -│ 4 │ dir │ 416 B │ Documents │ 4 days ago │ -... +ls | move name --after size +# => ╭────┬──────┬─────────┬───────────────────┬──────────────╮ +# => │ # │ type │ size │ name │ modified │ +# => ├────┼──────┼─────────┼───────────────────┼──────────────┤ +# => │ 0 │ dir │ 256 B │ Applications │ 3 days ago │ +# => │ 1 │ dir │ 256 B │ Data │ 2 weeks ago │ +# => │ 2 │ dir │ 448 B │ Desktop │ 2 hours ago │ +# => │ 3 │ dir │ 192 B │ Disks │ a week ago │ +# => │ 4 │ dir │ 416 B │ Documents │ 4 days ago │ +# => ... ``` ### Renaming Columns @@ -365,16 +365,16 @@ You can use [`move`](/commands/docs/move.md) to move columns in the table. For e You can also [`rename`](/commands/docs/rename.md) columns in a table by passing it through the rename command. If we wanted to run [`ls`](/commands/docs/ls.md) and rename the columns, we can use this example: ```nu -> ls | rename filename filetype filesize date -╭────┬───────────────────┬──────────┬──────────┬──────────────╮ -│ # │ filename │ filetype │ filesize │ date │ -├────┼───────────────────┼──────────┼──────────┼──────────────┤ -│ 0 │ Applications │ dir │ 256 B │ 3 days ago │ -│ 1 │ Data │ dir │ 256 B │ 2 weeks ago │ -│ 2 │ Desktop │ dir │ 448 B │ 2 hours ago │ -│ 3 │ Disks │ dir │ 192 B │ a week ago │ -│ 4 │ Documents │ dir │ 416 B │ 4 days ago │ -... +ls | rename filename filetype filesize date +# => ╭────┬───────────────────┬──────────┬──────────┬──────────────╮ +# => │ # │ filename │ filetype │ filesize │ date │ +# => ├────┼───────────────────┼──────────┼──────────┼──────────────┤ +# => │ 0 │ Applications │ dir │ 256 B │ 3 days ago │ +# => │ 1 │ Data │ dir │ 256 B │ 2 weeks ago │ +# => │ 2 │ Desktop │ dir │ 448 B │ 2 hours ago │ +# => │ 3 │ Disks │ dir │ 192 B │ a week ago │ +# => │ 4 │ Documents │ dir │ 416 B │ 4 days ago │ +# => ... ``` ### Rejecting/Deleting Columns @@ -382,19 +382,19 @@ You can also [`rename`](/commands/docs/rename.md) columns in a table by passing You can also [`reject`](/commands/docs/reject.md) columns in a table by passing it through the reject command. If we wanted to run [`ls`](/commands/docs/ls.md) and delete the columns, we can use this example: ```nu -> ls -l / | reject readonly num_links inode created accessed modified -╭────┬────────┬─────────┬─────────┬───────────┬──────┬───────┬────────╮ -│ # │ name │ type │ target │ mode │ uid │ group │ size │ -├────┼────────┼─────────┼─────────┼───────────┼──────┼───────┼────────┤ -│ 0 │ /bin │ symlink │ usr/bin │ rwxrwxrwx │ root │ root │ 7 B │ -│ 1 │ /boot │ dir │ │ rwxr-xr-x │ root │ root │ 1.0 KB │ -│ 2 │ /dev │ dir │ │ rwxr-xr-x │ root │ root │ 4.1 KB │ -│ 3 │ /etc │ dir │ │ rwxr-xr-x │ root │ root │ 3.6 KB │ -│ 4 │ /home │ dir │ │ rwxr-xr-x │ root │ root │ 12 B │ -│ 5 │ /lib │ symlink │ usr/lib │ rwxrwxrwx │ root │ root │ 7 B │ -│ 6 │ /lib64 │ symlink │ usr/lib │ rwxrwxrwx │ root │ root │ 7 B │ -│ 7 │ /mnt │ dir │ │ rwxr-xr-x │ root │ root │ 0 B │ -... +ls -l / | reject readonly num_links inode created accessed modified +# => ╭────┬────────┬─────────┬─────────┬───────────┬──────┬───────┬────────╮ +# => │ # │ name │ type │ target │ mode │ uid │ group │ size │ +# => ├────┼────────┼─────────┼─────────┼───────────┼──────┼───────┼────────┤ +# => │ 0 │ /bin │ symlink │ usr/bin │ rwxrwxrwx │ root │ root │ 7 B │ +# => │ 1 │ /boot │ dir │ │ rwxr-xr-x │ root │ root │ 1.0 KB │ +# => │ 2 │ /dev │ dir │ │ rwxr-xr-x │ root │ root │ 4.1 KB │ +# => │ 3 │ /etc │ dir │ │ rwxr-xr-x │ root │ root │ 3.6 KB │ +# => │ 4 │ /home │ dir │ │ rwxr-xr-x │ root │ root │ 12 B │ +# => │ 5 │ /lib │ symlink │ usr/lib │ rwxrwxrwx │ root │ root │ 7 B │ +# => │ 6 │ /lib64 │ symlink │ usr/lib │ rwxrwxrwx │ root │ root │ 7 B │ +# => │ 7 │ /mnt │ dir │ │ rwxr-xr-x │ root │ root │ 0 B │ +# => ... ``` ### The # Index Column