Nushell 0.68
Nushell, or Nu for short, is a new shell that takes a modern, structured approach to your commandline. 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 commandline pipelines.
Today, we're releasing version 0.68 of Nu. This is release a rework of modules, a new source-env command, overlay changes, and more.
Where to get it
Nu 0.68 is available as pre-built binaries or from crates.io. If you have Rust installed you can install it using cargo install nu
.
If you want all the built-in goodies, you can install cargo install nu --features=extra
.
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>
.
Themes of this release
(Major changes!) Rework of modules and environment
Some of the changes here have far-reaching consequences and it might take a while to get the book up to speed.
This release includes a bundle of changes to environment handling and modules. For now, we kept also the old functionality, but in the 0.69, it will be removed. It is therefore recommended to port your scripts and modules to the new style to avoid breakages in the next release. You can read a more complete write-up on the motivation and overall design in this document.
source
becomes source-env
(Sophia, kubouch)
Note: Since the release we found out that source-env
with a dynamic path is not viable and had to make it require a constant string or path, just like source
. The command still works as described below but as of 0.68.1, source-env
requires a static path as an argument. This is not where our design was supposed to land and we'll be searching for alternatives. We might also postpone the deprecation of the existing module commands beyond 0.69. Thanks for understanding.
One of the most common pitfalls of Nushell was trying to source
a dynamic path, such as source ($env.PWD | path join foo.nu)
. Since Nushell is a "compiled" language where commands and aliases are analyzed while parsing ("compiling") the code, sourcing dynamic paths is not possible for the same reason you cannot dynamically set #include
file names in C or use
modules in Rust. You can read a bit more about this in our Thinking in Nu book chapter.
To address this pitfall, we decided to change source
to source-env
which can be used to bring in the environment, but not custom commands, aliases and variables anymore. A benefit of doing so is that it is now possible to pass dynamic paths: source-env ($env.PWD | path join foo.nu)
would bring in the environment from the foo.nu
file.
How do you bring in commands and aliases without source
? You need to use a module and the use
keyword. See our book chapter about modules, it's quite simple. Alternatively, you can use overlays.
How do you bring in variables without source
? This is not possible anymore. A workaround is to define a command in your module that will return the value you want.
source
still continues to work in this release but will be removed in 0.69. In 0.69, we will also change all config files to be modules, not plain scripts.
Module environment changes (kubouch, kubouch)
The way to define environment variables from modules used to be
> module spam {
export env FOO { 'bar' }
}
> use spam
This example shows one problem: it is easy to end up with namespaced environment variables, which in this case would be $env.'spam FOO'
. Another problem with the current design is that use
is a parser keyword (like the removed source
) but contains both parser ("compiled") and runtime (evaluated) functionality. Since 0.67, it is possible to use modules within other modules but because environment is 100% handled in runtime, and use
never evaluates the module itself, it was impossible to bring in environment variables from other modules inside a module.
Long story short, use
(and hide
) now handle only custom commands and aliases, not environment variables anymore. If you want to bring both environment and commands/aliases, you need to use the source-env
and use
commands separately (or use overlays).
Also, we simplified defining the environment in modules. Instead of defining environment variables with export env
individually, there is a single export-env { }
block for the whole module (see the example in the next section).
If you call source-env
on that module, the export-env
command will get evaluated and its environment kept in the current scope.
# spam.nu
export-env {
let-env FOO = 'foo'
let-env BAR = 'bar'
}
> source-env spam.nu
> $env.FOO
foo
> $env.BAR
bar
This release makes export env
deprecated and it will be removed in 0.69.
Syntax unification (kubouch)
Previously, modules had some reserved syntax that was not valid in scripts: the export
keywords. In this release, we allowed export
keywords to be used in scripts (they do nothing: export def
acts as def
etc.) and thus script syntax is a superset of module syntax.
Modules can now be evaluated. This is the reason the above example with source-env
works: Thanks to the unified syntax, source-env
will evaluate the module which evaluates the export-env
command inside the module.
Another nice thing about the unified syntax is that commands like nu-highlight
now do not break or do not need to rely on heuristics if they are asked to parse a module code. Any module code is a valid script code.
Overlay changes (kubouch, WindSoilder)
overlay add
and overlay remove
are now renamed to overlay use
and overlay hide
(see the breaking changes later).
The functionality of these commands remains largely the same with one change being that overlay use
will now evaluate the export-env { }
block. Consider this module:
# spam.nu
export-env {
load-env {
FOO: 'foo'
BAR: 'bar'
}
}
export def foo [] { 'foo' }
export alias bar = 'bar'
instead of:
> source-env spam.nu
> use spam.nu *
you can do just:
> overlay use spam.nu
You can think of overlay use
as calling source-env
and use
in one command and putting the result into a new overlay.
Summary
Here is a table that summarizes the changes:
command | previous release (0.67) | this release (0.68) | next release (0.69) |
---|---|---|---|
source | imports everything into the current scope | same (deprecated) | removed |
source-env | N/A | imports environment variables | same |
use | imports environment variables, commands and aliases | same | imports only commands and aliases |
hide | hides environment variables, commands and aliases | same | hides only commands and aliases |
hide-env | hides environment variables | same | same |
export env | defines a single environment variable in a module | same | removed |
export-env | N/A | (in a module) defines the environment for the whole module | same |
export-env | N/A | (in a script) when evaluated, preserves the environment from the block | same |
export ... | only allowed in a module | allowed in a script as well | same |
config.nu | plain script | plain script | module |
env.nu | plain script | plain script | module |
login.nu | plain script | plain script | module |
Allow parentheses around command signatures (Sophia)
To bring more familiarity with other languages, we added the option to define command signatures with parentheses ()
instead of only braces []
:
def foo (x: int) { $x + 100 }
The square braces []
continue to work as well. This change is intended to test it with a larger audience to decide which one we prefer the most.
We added a new command str distance
which implements the Levenshtein algorithm fdncred
This example shows that the edit distance
is one edit step difference using the Levenshtein algorithm.
> 'nushell' | str distance 'nutshell'
╭──────────┬───╮
│ distance │ 1 │
╰──────────┴───╯
We'd eventually like to add more similarity comparison functionality to nushell.
We added string duration conversion to named durations fdncred
The new parameter on into duration
--convert
allows you to convert from string durations into named durations.
> '7min' | into duration --convert sec
420 sec
External Completions (experimental) (herlon214, rsteube)
In this release, we're trying out integrating Nushell with external completers, instead of relying solely on Nushell ones. It is possible to set the external_completer
field in a config to be a block which will be evaluated if no Nushell completions were found. You can configure the block to run an external completer, such as carapace.
This example should enable carapace external completions:
# config.nu
let carapace_completer = {|spans|
carapace $spans.0 nushell $spans | from json
}
# The default config record. This is where much of your global configuration is setup.
let-env config = {
# ... your config
external_completer: $carapace_completer
}
Note that this functionality is not perfectly polished yet and in some cases the external completer is not triggered correctly (see this issue).
It is also possible to extend the parameters passed to the completer block that are required for other tools than carapace, such as cursor position etc. In theory, this feature could allow you to utilize any existing completions library from any shell, such as bash, as long as you can somehow get a list of completions from them.
Breaking changes
Renaming of all?
to all
, any?
to any
, and empty?
to is-empty
(adamijak)
The ?
suffix on the three commands all?
, any?
, empty?
did not indicate a specific meaning across other commands. Other commands returning a boolean value, like str contains
for example, don't carry the suffix. To remove a potential source of confusion and to free up the ?
for potential use in a more meaningful semantic context, we decided to remove the suffix and rename empty?
to is-empty
to clarify its role.
Please update your scripts accordingly:
old name | new name |
---|---|
all? | all |
any? | any |
empty? | is-empty |
Renaming overlay
commands (WindSoilder)
old name | new name |
---|---|
overlay add | overlay use |
overlay remove | overlay hide |
The main reason is that the overlay remove
does not really remove the overlay. It deactivates it and it can be resumed again from where you left off. Therefore, we felt like hide
is a better word to match this functionality and aligns with our existing use
and hide
keywords.
path split
behaviour for Windows paths (merelymyself)
path split
no longer returns drive letters and the root directory as separate elements for absolute Windows paths.
Previously, `C:\temp` | path split
returned C:
, \
, and temp
. Now it returns C:\
and temp
.
Next Steps
We've been progressing with our design towards 0.80 as outlined in this Notion page.
Some time was spent trying out possible new syntax directions but we were not confident to release them yet. In the next release we'll see a removal of features deprecated in this release and we'll continue to push ahead for the 0.80.
Full changelog
Nushell
- sophiajt created bump to 0.68, and Reverted "Make
$
on variable names optional" (just in case), and Allow parens around signatures, and Make$
on variable names optional, and Move fromsource
tosource-env
- sholderbach created Pin reedline to 0.11.0 release, and Terminate REPL if not connected to tty input, and Fix search terms for
str distance
, and [Experiment] Reenable CI build cache for tests, and Test command names and search terms for redundancy - merelymyself created let path split keeps 'C:' together, and Allow for rejecting nested record cells, and add tests, deal with pipes, newlines, tabs for
to nuon
, and preserve space by lettingto nuon
only add quotes when necessary, and letto nuon
convert column names with spaces, and default to file completion after first command, addcommand
option for completions - unrelentingtech created Avoid update_last_command_context "No command run" error, and Fix build on *BSD, illumos, etc.
- WindSoilder created Restrict plugin name starts with
nu_plugin_
, and remove capnp relative file, and shows wrong item when some commands runs to failed., and shows wrong item when each command runs to failed., and keep raw for variable inputted argument, and remove capnp protocol for plugin..., and Try to make argument with quotes for external command better, and Plugin: Add benchmark for different encoding protocol, and Rename overlay commands, and Try again: in unix like system, set foreground process while running external command - kubouch created Disable cyclical module imports, and Fix overlays not preserving hidden env vars, and Fix scoped
overlay use
not finding a module, and Bring in module's environment when activating overlay, and Allow "export-env" parsing in modules, and Allow parsing modules as scripts, and Addexport-env
command - adamijak created Rename
all?
,any?
andempty?
- dependabot[bot] created Bump lz4-sys from 1.9.3 to 1.9.4, and Bump iana-time-zone from 0.1.44 to 0.1.47
- obaudys created Fix ps command CPU usage on Apple Silicon M1 macs. #4142
- fdncred created Revert "Add support for optional list stream output formatting", and add more color highlighting to help, and add the ast command to peek at the internals of nushell, and convert string duration to named duration, and add a plugin registration script, and add another split words example, and add edit distance/levenshtein command, and add MessagePack as a plugin protocol, and fix the way lists are rendered in markdown, and add a split words command, and create clickable links in ls output if configured
- rgwood created Upgrade
which
dependency to fix case on Windows, and Disable clickable links in SSH sessions, and Always report errors incp
, and Makecp
errors more specific+accurate, and Add pause and cls to cmd.exe exceptions - dscottboggs created better error handling for nu_command::env::config::utils::get_editor
- nibon7 created Make run_external parameter required, and Fix the span of "invalid time zone", and register-plugin.nu: refactor register plugin, and register-plugin.nu: remove
.exe
extension match to simplify code, and Add test cases for $nu.config-path change, and Get$nu.config-path
and$nu.env-path
fromEngineState
, and Use string interpolation to construct log file path, and Return error whenkill
didn't terminate successfully - herlon214 created nu-command/filters: drop column check positive value, and nu-cli: merge completions tests into one file, and feat: external completions for commands/flags
- hustcer created Update nu version for release workflow, and Bump dev version
- volucris1 created Fix #6330
- panicbit created Add support for optional list stream output formatting
- dbuch created Fix slice indexing
- CohenAriel created Add --execute option
Documentation
- rgwood created Add Homebrew PATH documentation
- sholderbach created Update former question mark commands in docs
- chrjen created Update types_of_data.md with missing values
- hustcer created Upgrade vuepress and all related plugins to improve build performance, and Upgrade all vuepress plugins and fix doc search navigation by pressing
enter
key, and Upgrade all vuepress plugins and fix doc search navigation by pressingenter
key, and Try to fix deploy of docs by downgrade some plugins, and lock vuepress and plugins version to fix ci - fdncred created update to ubuntu-latest, and change from deprecated version of ubuntu
- pedromfedricci created Update accepted types for signatures
- Yethal created Add wrap-around merge
- merelymyself created Remove ambiguity about command quotes
- CAD97 created Note status of calling CMD builtins from Nushell, and Note Windows caveat in Escaping to the System, and Mention coming_from_cmd in coming_to_nu, and Update coming_from_cmd.md for nu 0.77, and Create coming_from_cmd.md
- 1submarine created correct escapes in coming_from_bash.md, and deduplicate `**' in operators.md
- amtoine created FIX:
overlay remove
flags
Nu Scripts
- dandavison created Async git prompt
- sholderbach created Update old question mark commands
any?
/all?
/empty?
toany
/all
/is-empty
- skelly37 created Added German diacritics
- Yethal created Add function to remove diacritics from string
- fdncred created remove engine-q references
- e2dk4r created custom completions: scoop: add some missing command completions, and custom completions: scoop: add some missing command completions
- mk00pl created added webscrapping script for twitter
- azzamsa created fix: zoxide support Nushell out of the box
reedline
- sholderbach created Prepare 0.11.0 release
- unrelentingtech created Add Reedline::has_last_command_context to allow checking if update_last_command_context will fail
- nibon7 created Fix panic when using sqlite as history backend
- morzel85 created README.md outline cleanup