Nushell 0.88.0
Nushell, or Nu for short, is a new shell that takes a modern, structured approach to your command line. It works seamlessly with the data from your filesystem, operating system, and a growing number of file formats to make it easy to build powerful command line pipelines.
Today, we're releasing version 0.88.0 of Nu. This release adds a spread operator, output stream improvements, dynamic switch support, and much more.
Where to get it
Nu 0.88.0 is available as pre-built binaries or from crates.io. If you have Rust installed you can install it using cargo install nu
.
Note
The optional dataframe functionality is available by cargo install nu --features=dataframe
.
As part of this release, we also publish a set of optional plugins you can install and use with Nu. To install, use cargo install nu_plugin_<plugin name>
.
Table of content
- Themes of this release / New features
- Hall of fame
- New spread operator for list and record literals
- Passing boolean switches dynamically
- Redirection to standard streams is getting better
- One-time theming of tables is there
- Exposing name of script to the wild
- Parsing human-friendly dates into Nushell values
- Show found externals via syntax highlighting in the REPL
- New "out of bound" error
- Details on the
0.87.1
hotfix release - Need help to wrap... commands?
- Restricting use of internal variables
- A small update on the LSP
- Our set of commands is evolving
- Breaking changes
- Full changelog
Themes of this release / New features [toc]
Hall of fame [toc]
Bug fixes [toc]
Thanks to all the contributors below for helping us solve issues and bugs 🙏
author | description | url |
---|---|---|
@dead10ck | into binary -c: return 0 as single byte | #11068 |
@zhiburt | Fix #11047 | #11054 |
@fdncred | tweak table example/parameter text | #11071 |
@fdncred | add "default" table theme | #11072 |
@fdncred | correct table example syntax | #11074 |
@fdncred | optimize/clean up a few of the table changes | #11076 |
@sophiajt | Fix the output type for 'view files' | #11077 |
@danielsomerfield | Fix toolkit to run workspace on 'check pr' (issue #10906) | #11112 |
@hustcer | Exit the release job if creating binary package failed | #11145 |
@hustcer | Fix release and nightly build workflow | #11146 |
@amtoine | fix the link to the nu_scripts in std clip deprecation | #11150 |
@NotLebedev | Cp target expansion | #11152 |
@MarikaChlebowska | Add metadata to some filters | #11160 |
@sholderbach | Revert "Adding support for Polars structs" | #11171 |
@sigoden | Fix spans passed to external_completer | #11008 |
@nibon7 | Add boundary check for str index-of | #11190 |
@WindSoilder | When using redirection, if a command generates non-zero exit code, the script should stop running | #11191 |
@nibon7 | Fix span of invalid range | #11207 |
@nibon7 | Fix capacity overflow caused by large range of ports | #11210 |
@IanManske | Fix get -i ignoring errors for only the first cellpath | #11213 |
@dtolnay | Fix Option<&str> == Option<&String> build error when using rust_decimal/rkyv feature | #11205 |
@nibon7 | Add checks for ports | #11214 |
@ysthakur | Fix highlighting of spread subexpressions in records | #11202 |
@nibon7 | Fix overlay_use_main_not_exported hanging when an external spam command exists | #11261 |
@AucaCoyan | 🐛 Fixes markdown formatting on LSP hover | #11253 |
@MarikaChlebowska | Add more descriptive error message when passing list to from_csv | #10962 |
@sophiajt | Respect non-zero exit code in subexpressions and blocks | #8984 |
@WindSoilder | Error on use path item1 item2 , if item1 is not a module | #11183 |
@KAAtheWiseGit | Match ++= capabilities with ++ | #11130 |
@fdncred | Add nu lib dirs default | #11248 |
Enhancing the documentation [toc]
Thanks to all the contributors below for helping us making the documentation of Nushell commands better 🙏
author | description | url |
---|---|---|
@sholderbach | Curate developer documentation in tree | #11052 |
@IanManske | Build nu-protocol docs with all features enabled | #11180 |
@poliorcetics | feat: Add default docs for aliases, generated from the command they point to | #10825 |
@amtoine | fix nu-std README | #11244 |
Working on internals [toc]
Thanks to all the contributors below for working on internals of Nushell, such as refactoring the code 🙏
author | description | url |
---|---|---|
@fdncred | bump rust-toolchain to 1.72.1 | #11079 |
@nibon7 | Apply nightly clippy fixes | #11083 |
@drbrain | Convert ShellError::CommandNotFound to named fields | #11094 |
@drbrain | Convert ShellError::NetworkFailure to named fields | #11093 |
@drbrain | Add Argument::span() and Call::arguments_span() | #10983 |
@IanManske | Refactor Value cell path functions to fix bugs | #11066 |
@sholderbach | Bump version to 0.87.2 | #11114 |
@sholderbach | Bump procfs to 0.16.0 | #11115 |
@drbrain | Remove ShellError::FlagNotFound | #11119 |
@drbrain | Convert ShellError::AliasNotFound to named fields | #11118 |
@drbrain | Convert FileNotFound to named fields | #11120 |
@hustcer | Upgrade Nu and script for release workflow | #11121 |
@sholderbach | Use record API in describe --detailed | #11075 |
@drbrain | Convert FileNotFoundCustom to named fields | #11123 |
@drbrain | Convert PluginFailedToLoad to named fields | #11124 |
@drbrain | Convert PluginFailedToEncode to named fields | #11125 |
@drbrain | Convert PluginFailedToDecode to named fields | #11126 |
@sholderbach | Move more commands to opaque Record type | #11122 |
@rfaulhaber | Bump sysinfo to 0.29.11 | #11166 |
@drbrain | Convert more ShellError variants to named fields | #11173 |
@WindSoilder | add echo_env_mixed testbin to reduce windows only tests | #11172 |
@cosineblast | Remove file I/O from tests that don't need it | #11182 |
@drbrain | Convert more ShellError variants to named fields | #11222 |
@nibon7 | Explicitly indicate duplicate flags | #11226 |
@ysthakur | Reduce code duplication in eval.rs and eval_const.rs | #11192 |
@ayax79 | Upgrading to polars 0.35 | #11241 |
@IanManske | Remove unnecessary boxing of Stack::recursion_count | #11238 |
@schrieveslaach | Upgrade lsp-server Dependency | #11252 |
@drbrain | Convert Shellerror::GenericError to named fields | #11230 |
@sholderbach | Bump version to 0.87.1 | #11056 |
@dead10ck | Testing support tweaks: exit status in Outcome | #10692 |
@nibon7 | Simplify clear implementation | #11273 |
@drbrain | Convert remainder of ShellError variants to named fields | #11276 |
New spread operator for list and record literals [toc]
#10598 asked for a spread operator (...
), and in #11006 and #11144, @ysthakur implemented a spread operator in lists and records, respectively. Spreading arguments to commands has not been implemented yet.
The spread operator can help you avoid append
in lists, e.g., this:
let list = ["foo"]
[
1,
...$list,
...("foo" | split chars),
...[3 9],
[]
] | to nuon
will give:
[1, foo, f, o, o, 3, 9, []]
In records, it can help you avoid merge
, e.g., this:
let record = { a: "foo" }
{
...$record,
y: "bar",
...{ z: 2 }
} | to nuon
will give:
{a: foo, y: bar, z: 2}
You can spread variables, subexpressions, and either lists (inside list literals) or records (inside record literals). Note that there needs to be no whitespace between the ...
and the expression being spread.
Passing boolean switches dynamically [toc]
In last release, a distinction has been introduced between switches, e.g. --enable-feature
, and boolean options, e.g. --do-something: bool
. The former is simply used as --enable-feature
and the latter expects a value as --do-something false
.
Up until now, this had the downside of disallowing one to pass boolean switches to inner calls of commands. An example would be two commands, foo
and bar
, which both have a --switch
and where foo
is calling bar
internally with the opposite switch. It would have to look something like
def bar [--switch] {
print $"switch in bar: ($switch)"
}
def foo [--switch] {
print $"switch in foo: ($switch)"
if $switch {
bar
} else {
bar --switch
}
}
or bar
would have to take a boolean value instead of a switch, which would make the command less nice to use as part of a public API...
def bar [--switch: bool] {
print $"switch in bar: ($switch)"
}
def foo [--switch] {
print $"switch in foo: ($switch)"
bar --switch (not $switch)
}
In this release and thanks to the work of @WindSoilder in #11057, boolean switches can now be passed around. This will simplify the code above and still preserve the nice signature of bar
:partying:
def bar [--switch] {
print $"switch in bar: ($switch)"
}
def foo [--switch] {
print $"switch in foo: ($switch)"
bar --switch=(not $switch)
}
Redirection to standard streams is getting better [toc]
Once again, @WindSoilder has been working on the redirection system of Nushell, fixing a bug and adding a new very nice feature:
- #10851: one pipeline output stream can be redirected and the other one used as input to the rest of the pipe. Given the following Bash script called
foo.sh
that outputs both to stdout and stderrit is now possible to run the following command, redirectingecho aaaaa echo bbb 1>&2 echo cc
bbb
to a file and the rest to thelines | each { ... }
part of the pipeline:resulting inbash test.sh err> err.txt | lines | each { str length}
[5, 2]
as expected andbbb
insideerr.txt
. - #10764: append to file with the
>>
syntax instead of overwriting with>
will create a file called(1 + 2 + 3) out> sum.txt "\n" out>> sum.txt (4 + 5 + 6) out>> sum.txt
sum.txt
with the following content6 15
One-time theming of tables is there [toc]
A common question and feature request from the community was: how can i change the theme of Nushell tables for just one command?
Because of how Nushell works, the way to do that has been the following for a long time
do { # use the scope of `do` to not alter the environment of the callee
$env.config.table.mode = "none" # set the theme
ls | table # call table to avoid just passing the value back to the callee and use the outside theme
}
In #11058, @zhiburt cracked the nut and added the long-wanted table --theme
option. Below is a simple example:
- let's define a table
let table = ls | where type == dir | reject type
- and show it with a particular theme
$table | table --theme ascii_rounded
.#--name----size-------modified------.
|0|assets |4.1 KB|2023-12-05 18:32:30|
|1|benches|4.1 KB|2023-12-09 22:33:44|
|2|crates |4.1 KB|2023-12-09 22:33:44|
|3|devdocs|4.1 KB|2023-12-09 22:33:44|
|4|docker |4.1 KB|2023-12-09 22:33:44|
|5|scripts|4.1 KB|2023-12-09 22:33:44|
|6|src |4.1 KB|2023-12-09 22:33:44|
|7|target |4.1 KB|2023-12-09 14:19:04|
|8|tests |4.1 KB|2023-12-05 18:32:30|
|9|wix |4.1 KB|2023-12-05 18:32:30|
'------------------------------------'
Exposing name of script to the wild [toc]
Coming from languages such as Python and Bash, it's quite expected to be able to access the name of the script itself the same way it's been called from the CLI: with sys.argv[0]
in Python and $0
in Bash.
This was not possible in Nushell until the work of @p00f in #11203. This will expose to any script a new environment variable called $env.PROCESS_PATH
and which will contain precisely something akin to argv[0]
!
#!/usr/bin/env nu
# in demo.nu
def main [] {
printf $"I was called as ($env.PROCESS_PATH)"
}
demo.nu # will show "I was called as demo.nu"
./demo.nu # will show "I was called as ./demo.nu"
/path/to/demo.nu # will show "I was called as /path/to/demo.nu"
Parsing human-friendly dates into Nushell values [toc]
In #11051, @fdncred added to into datetime
the ability to parse human readable dates into Nushell datetime
. This allows to write crazy things like
"Now" | into datetime # same as `date now`
"A week ago" | into datetime # same as `(date now) - 1wk`
Note
see the full list of examples with into datetime --list-human
Show found externals via syntax highlighting in the REPL [toc]
We've added a new experimental feature that changes the syntax highlighting of text in the command position in the repl. Here's how it works. As you type, if a command is found with the current letter you've typed, the command will be highlighted according to your configuration of your color theme, specifically shape_external_resolved
. As you keep typing, which
fires to find out if the command is found or not. This allows you to know whether you've created a typo before you ever hit enter in the nushell repl.
Since this might have a performance impact, we've put this behind a configuration point named highlight_resolved_externals
in the config.nu file. Set it to true
to enable this functionality and false
to disable it. It defaults to false
.
Right now, with a dark theme, here's one way of configuring these colors, in the config.nu color theme, that showcases this functionality. Also, make sure you have highlight_resolved_externals
set to true
.
shape_internalcall: cyan_bold # internal commands that are found will be this color
shape_external: darkorange # external "commands" that do not exist, will be this color
shape_external_resolved: light_yellow_bold # external commands that are found with `which`, will be this color
You can read more about it and see a gif in #11135 where @fdncred implemented the feature.
New "out of bound" error [toc]
@nibon7 introduces in #11201 a new error which is pretty common to programming languages: the "out of bound" error.
This will cause the following command to give an "out of bound" error:
"foo" | str index-of '' --range 10..11
Details on the 0.87.1
hotfix release [toc]
In between the last 0.87.0
release and the one from today, there has been a quick hotfix release to address two major bugs to two quite important filesystem commands: rm
and cp
.
Below are some details about these two bug fixes:
- @IanManske fixed
rm
in #11064 which has trouble removing files after acd
- @kubouch fixed a similar one about
cp
in #11080, addressing #10832
Need help to wrap... commands? [toc]
In the previous release, the extern-wrapped
command has been deprecated and it is now being removed. An issue did persist though, making def --wrapped
not a suitable replacement for the old command... which was fixed in #11235 by the changes from @KAAtheWiseGit: def --wrapped
commands won't create a help page anymore, allowing to send -h
and --help
to other commands:
def --wrapped foo [...rest] { echo $rest }
foo --help -h
will give no help page
─┬──────
0│--help
1│-h
─┴──────
Restricting use of internal variables [toc]
Nushell features some internal variables that users can't redeclare, i.e. $nu
, $env
and $in
.
Note
$env
is the special of the three because one can mutate it with
$env.FOO = "i'm foo"
but it is impossible to do let env = 123
However, up until now and the work of @KAAtheWiseGit in #11169 and #11228, it was possible to redefined these variables in command definition: the code would parse and run, but you would get the internal values instead of the ones passed to the command, which is a nasty silent bug! From now on, the following will give an error
def foo [nu] { print $nu }
def bar [env] { print $env }
def baz [in] { print $in }
Also, because $nu
and $env
don't have spans by construction, i.e. they are not defined in any script where a span would make sense but rather internally when Nushell starts, accessing their metadata
does not make sense. This release makes the error more helpful:
metadata $env
Error: × Built-in variables `$env` and `$nu` have no metadata
╭─[entry #1:1:1]
1 │ metadata $env
· ──┬─
· ╰── no metadata available
╰────
A small update on the LSP [toc]
@schrieveslaach has been working again on the built-in LSP of Nushell. With #10941, completions should get better with this release :partying:
Our set of commands is evolving [toc]
As usual, new release rhymes with changes to commands!
New commands [toc]
is-terminal
by @drbrain in #10970std null-device
by @WindSoilder in #11070mktemp
by @tskinn in #11005stor
by @fdncred in #11170 => see the section below
A local in-memory database with stor
With this release we've implemented a new sqlite family of commands called stor
. stor
is meant to be short for "storing data in an in-memory sqlite database". That's right, this family of commands supports an in-memory database. This in-memory database will be accessible as long as they share the same executable instance. A new instance is created with each new nushell instance and the in-memory database cannot be shared between instances. We're exited to see what new things you'll invent with this technology, although we still consider it in the experimental phase. Please feel free to submit PRs to make the usage of it better and more robust. There are examples of how to use each command in the PR.
Here the summary you get when you execute the stor
command.
Usage:
> stor
Subcommands:
stor create - Create a table in the in-memory sqlite database
stor delete - Delete a table or specified rows in the in-memory sqlite database
stor export - Export the in-memory sqlite database to a sqlite database file
stor import - Import a sqlite database file into the in-memory sqlite database
stor insert - Insert information into a specified table in the in-memory sqlite database
stor open - Opens the in-memory sqlite database
stor reset - Reset the in-memory database by dropping all tables
stor update - Update information in a specified table in the in-memory sqlite database
Flags:
-h, --help - Display the help message for this command
Input/output types:
╭─#─┬──input──┬─output─╮
│ 0 │ nothing │ string │
╰───┴─────────┴────────╯
Changes to existing commands [toc]
- thanks to @KAAtheWiseGit in #11195,
input list
will accept more input/output types - the
list<string> -> string
I/O pair has been added to thelast
command by @amtoine in #11137 - with the work of @IanManske in #11258,
insert
,update
andupsert
should now work more consistently withlist
s, e.g.
[0, 2] | update 0 {|i| $i + 1 } # will give [1, 2]
[0, 1, 2] | insert 5 5 # will give "index too large" error
Deprecated commands [toc]
std clip
in #11097: this command was handy but did not fit the philosophy of the standard librarystd testing
in #11151: even though in a VERY EARLY stage of its development, we would like to focus our efforts on the Nupm project and especially its simplenupm test
command
Removed commands [toc]
as part of the deprecation plan of last release, the following commands and options have been removed by @amtoine:
extern-wrapped
andexport extern-wrapped
in favor ofdef --wrapped
in #11000--not
fromglob
in favor of--exclude
in #10839size
in favor ofstr stats
in #10784unfold
in favor ofgenerate
in #10773def-env
andexport def-env
in favor ofdef --env
in #10999
Breaking changes [toc]
- #8984 Respect non-zero exit code in subexpressions and blocks
Starting with this release, if a subexpression (eg (echo foo.txt)
) or block (eg if true { echo foo.txt }
evaluated to a non-zero exit code, it will no longer be lost and instead will be the exit code of that expression. This allows them to act more naturally when an external command fails.
- #11144 No longer allow
{a: 1, a: 2}
We now error if you repeat the same field name when creating a record, for example {a: 1, a: 2}
.
We've removed the deprecated commands def-env
and export def-env
. Instead, use def --env
. Likewise, we've done the same for extern-wrapped
and export extern-wrapped
. Instead, use def --wrapped
.
- #10773 remove the
unfold
command
We've renamed the previous unfold
command. Instead, use the generate
command.
- #10784 remove
size
command in favor ofstr stats
We've also removed the size
command, which had an ambiguous name. Now, use str stats
to get information about string content.
- #10839 remove
--not
fromglob
This release replaces the confusing --not
flag of glob
to instead be glob --exclude
.
- #11058 nu-table/ Add
-t/theme
argument && Replace-n/start-number
with-i/index
To make how to update the table numbering more clear, we've replaced table -n
with table -i
/table --index
.
Full changelog [toc]
Nushell
- amtoine created
- remove the
unfold
command - remove
size
command in favor ofstr stats
- remove
--not
fromglob
- remove
def-env
andexport def-env
- remove
extern-wrapped
andexport extern-wrapped
- deprecate
std clip
- add
list<string> -> string
tolast
- fix the link to the
nu_scripts
instd clip
deprecation - deprecate
std testing
- fix
nu-std
README - add
nothing -> table
toformat date
- remove the
- app/dependabot created
- AucaCoyan created
- ayax79 created
- cosineblast created
- danielsomerfield created
- dead10ck created
- drbrain created
- Add is-terminal to determine if stdin/out/err are a terminal
- Add Argument::span() and Call::arguments_span()
- Convert ShellError::NetworkFailure to named fields
- Convert ShellError::CommandNotFound to named fields
- Convert ShellError::AliasNotFound to named fields
- Remove ShellError::FlagNotFound
- Convert FileNotFound to named fields
- Convert FileNotFoundCustom to named fields
- Convert PluginFailedToLoad to named fields
- Convert PluginFailedToEncode to named fields
- Convert PluginFailedToDecode to named fields
- Convert more ShellError variants to named fields
- Convert more ShellError variants to named fields
- Convert
Shellerror::GenericError
to named fields - Convert remainder of ShellError variants to named fields
- Ensure that command usage starts uppercase and ends period
- dtolnay created
- fdncred created
- allow parsing of human readable datetimes
- tweak
table
example/parameter text - add "default" table theme
- correct table example syntax
- optimize/clean up a few of the
table
changes - bump rust-toolchain to 1.72.1
- add shape
ExternalResolved
to show found externals via syntax highlighting in the repl - Add
stor
family of commands - add some tests for
stor create
- Add nu lib dirs default
- hustcer created
- IanManske created
- KAAtheWiseGit created
- kubouch created
- MarikaChlebowska created
- nibon7 created
- Apply nightly clippy fixes
- Add boundary check for str index-of
- Add OutOfBounds error
- Fix span of invalid range
- Fix capacity overflow caused by large range of ports
- Add checks for ports
- Explicitly indicate duplicate flags
- Fix overlay_use_main_not_exported hanging when an external spam command exists
- Simplify
clear
implementation
- NotLebedev created
- p00f created
- poliorcetics created
- rfaulhaber created
- schrieveslaach created
- sholderbach created
- Bump version for
0.87.0
release - Move to clearer reedline keyboard enhancement API
- Curate developer documentation in tree
- Pin reedline to 0.26 release
- Bump version to
0.87.1
- Use record API in
describe --detailed
- Bump version to
0.87.2
- Bump
procfs
to 0.16.0 - Move more commands to opaque
Record
type - Revert "Adding support for Polars structs"
- Bump version for
- sigoden created
- sophiajt created
- tskinn created
- WindSoilder created
- Support
o>>
,e>>
,o+e>>
to append output to an external file - Redirect: support redirect stderr with piping stdout to next commands.
- fix custom command's default value
- enable to pass switch values dynamically
- std: add cross platform null-device name
- add echo_env_mixed testbin to reduce windows only tests
- Error on
use path item1 item2
, if item1 is not a module - When using redirection, if a command generates non-zero exit code, the script should stop running
- Support
- ysthakur created
- zhiburt created
Extension
- glcraft created
Documentation
- 132ikl created
- amtoine created
- app/dependabot created
- app/github-actions created
- arnau created
- CAESIUS-TIM created
- FMotalleb created
- Hofer-Julian created
- hustcer created
- KAAtheWiseGit created
- Ktoks created
- MarikaChlebowska created
- ppenguin created
- sholderbach created
- sophiajt created
- stfacc created
- ysthakur created
Nu_Scripts
- Abdillah created
- amtoine created
- AucaCoyan created
- drbrain created
- Euphrasiologist created
- fj0r created
- fnuttens created
- glcraft created
- kjelly created
- RGBCube created
- sholderbach created
- WindSoilder created
Reedline
- ClementNerma created
- crides created
- Hofer-Julian created
- sholderbach created