# Nushell 0.32

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 0.32 of Nu. This release contains a large amount of usability improvements.

# Where to get it

Nu 0.32 is available as pre-built binaries (opens new window) or from crates.io (opens new window). If you have Rust installed you can install it using cargo install nu.

If you want all the goodies, you can install cargo install nu --features=extra.

If you'd like to try the experimental paging feature in this release, you can install with cargo install nu --features=table-pager.

As part of this release, we also publish a set of plugins you can install and use with Nu. To install, use cargo install nu_plugin_<plugin name>.

# What's New

There are a lot of new changes in this release of Nu. You can check these out by in this blog post, or, if you like, there is also an accompanying YouTube video of 0.32 features (opens new window) as well as updated Nushell samples (opens new window).

# New expression syntax (jt)

We've simplified our expression/subexpression logic to make it much more predictable and universal. The parser will now automatically handle by command calls and expressions in the same way, so that you don't have to remember to use = to switch from one mode to the next.

Before 0.32:

> = 10 + 3

With 0.32:

> 10 + 3

You can also use any value as an expression, including variables or strings:

> "hello world"
hello world

Subexpressions also follow a similar simplification. We've removed the previous $() style, replacing it with (). This allows you to put subexpressions anywhere that you want.

> 10 * (3 + 2)
> echo ((ls | length) / 2)

This allows parens to mean "do this first" in both math expression and command calls.

# Subexpressions and column paths (jt)

The new subexpressions can also use "column paths", or paths that start from the current value and travel to a subset of the structured data inside.

For example, you could combine column paths with some subtraction to find when you last booted your system:

> (date now) - (sys).host.uptime
2021-05-31 09:00:24.124736365 +12:00

# New string interpolation (jt)

We've also updated string interpolation to match the expression/subexpression simplification mentioned above. The same "parens mean do this first" pattern applies:

> $"the result is (3 + 2)"
the result is 5

For interpolation that uses column paths, wrap the entire column path in a pair of parens:

> $"uptime is (sys).host.uptime"
uptime is [row host cpu mem temp].host.uptime

> $"uptime is ((sys).host.uptime)"
uptime is 1day 19hr 57min 7sec

As part of this change, we removed the previous backtick string interpolation form.

# Environment loading (lily-mara)

In Nushell, we've worked hard to limit the amount of mutation that will happen in the system. This helps developers focus on the task at hand, and not have to think about non-local effects from the code they're running.

At the same time, we've also wanted to support virtual environment systems like virtualenv, conda, and others. Traditionally these systems updated the global environment from inside of their activate/deactivate commands.

With 0.32, we feel like we've managed to come up with a solution that meets both the Nushell philosophy of limiting mutation while also giving the freedom to port virtual environment scripts to Nushell.

We call it "environment loading". Here, rather than having commands mutate the global environment, they instead return a table of changes they'd like to apply to the environment. This table can be then loaded into the current scope, effectively separating the "what" of the update from the "when".

Let's try this by creating a table of three new environment variables we'll load:

def activate [] {
  [[name, value]; [FOO, BAR] [DEBUG, TRUE] [CURRENTENV, NUSHELL]]

load-env (activate)
echo $nu.env.FOO

The changes to the environment are still scoped to the block you're inside of. In the example above, because we're at the top level, we can safely shadow the previous environment values.

# Locale improvements (fdncred)

When you have filesize_format = "B" set in your config.toml file you should be able to see the thousands separators based on your locale. i.e. some locales use , other locales use . and i'm not sure if there are others.

This is with the de_DE locale on linux: (note the number separators) image

This is with en-US on windows: image

# Better line editing support (schrieveslaach, fdncred)

# Partial completions

With 0.32, you can use ctrl+right arrow to do a partial completion from a completion hint.

# Delete word

You can also use alt+backspace to delete whole words.

# And more

For a full list of updated line editing capabilities, check out the update sample keybinding file (opens new window).

# Explicit block parameters (jt)

You can now name block parameters. You can use this to help make working with blocks easier to read.

> ls | each { |row| echo $row.name }

# do supports passing arguments (stepnivik)

You can now pass arguments to give the running block as part of a do call:

> do { |x| $x + 100} 55

# New for..in command (jt)

With the new for..in command, you can write more natural iterating loops:

> for $x in 1..3 { echo ($x + 10) }

# Flags can now use equals (andrasio)

You can now use = between a flag and its value.

For example, in addition to:

> seq --separator ':' 1 10

You can also write:

> seq --separator=':' 1 10

# Other improvements

# Simple string concatenation (jt)

You can now create a new string by concatenating two strings "hello " + "world".

# Path relative-to (kubouch)

Implements path relative-to subcommand. It converts the input path as a relative to the argument path, like this:

> 'eggs/bacon/sausage/spam' | path relative-to 'eggs/bacon/sausage'

There are also additional path-related fixes (opens new window).

# Negative indexing for range (alexshadley)

You can now pass negative ranges to the range command, and it will work from the back of the input.

> echo [1 2 3 4 5] | range (-3..)

Will return [3, 4, 5].

# Default integer is now signed 64-bit (jt)

In 0.32, adds a new primitive data type for i64 and makes it the default integer type.

# Improved filename support (ahkrr, fdncred)

Filename quoting for # (opens new window). Pipes are also now escaped (opens new window)

# sqlite improvements (Garfield96)

A panic in sqlite support has been fixed (opens new window) and the support rusqlite crate has been updated (opens new window).

# seq is now more nu-like (fdncred)

The seq command is now more nushell friendly by returning numbers when it can and strings when it must. This will definitely break some scripts.


# Case-insensitive completions are now the default on Windows (Sympatron)

Since Windows filenames are case-insensitive, This changes to case-insensitive completion matching by default. All other platforms still use case-sensitive matching by default.

# Porting commands to the new engine (efx, LhKipp, elferherrera)

More commands have been updated to use the new engine-p engine.

# char now has more characters (fdncred, kubouch)

The char command now supports an additional set of characters (opens new window). It also supports the path separator character.

You can use char --list to see the full list of available character and ansi values.

# Protect against bad config more defensively (fdncred)

Nushell is now more resilient if it encounters a bad config file (opens new window).

# Better glob support for rm (lily-mara)

The * wildcard should not attempt to delete files with a leading dot unless the more explicit .* is used. rm * should also not attempt to delete the current directory or its parent directory (. and ..), either. With this release, these should now be followed.

# Breaking changes

  • The previous math mode command = has been replaced by a smarter parser that can autodetect math mode based on the first token. Math mode calls like = 10 / 2 are now simply 10 / 2.
  • Invocations of the style $() have now been replaced by () subexpressions. $(= 2 + 3) is now (2 + 3)
  • String interpolation of the style:
`the result is {{= 1 + 2}}`

Are now replaced with:

$"the result is (1 + 2)"
  • seq will now return numbers when possible
  • The default integer is now signed 64-bit integer and not big integers.
  • The unit type has now been split into filesize and duration for better utility.

# Looking ahead

Nushell 0.32 is the first version of Nushell that begins to show what the 1.0 Nushell language will feel like. The easier, and more uniform, expression and subexpression syntax will let us continue to evolve towards a language that's both easier to read and easier to write.

There are some long-standing issues in the engine that are preventing improved completions, and we'd like to address these issues and begin work on smarter completions.

Elferherrera has also been hard at work on a dataframe implementation that we're exploring for inclusion into Nushell. You can try this out by compiling with the dataframe feature. If you check it out, let us know how it goes.