Nushell 0.76

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.76 of Nu. This release adds more commands for debugging, multiplication to clone strings, and moves some file formats to a plugin, thanks to better plugin support.

Where to get it

Nu 0.76 is available as pre-built binariesopen in new window or from crates.ioopen in new window. 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>.

Themes of this release / New features

Debugging

We've added a few new commands to help with nushell debugging.

  • ast - The ast command works the same as before and produces an ast for any pipeline you give it.

  • debug - The debug command works the same as before and produces some output about nushell values.

  • explainopen in new window - Provides detailed information about pipeline contents in a closure

The explain command attempts to explain to you how the pipeline, in the passed in block, is going to be interpreted. It shows the pipeline and command index, the looked up and found command name, the command argument data type, and argument details, among other things. Note that spans are also included and can be used with view span.

explain command

The purpose of the inspect command is to help to debug pipelines. It works by allowing you to inject the inspect command into a pipeline at any point. Then it shows you what the input description is and what the input values are that are passed into inspect. With each step it prints this information out while also passing the value information on to the next step in the pipeline.

inspect command

  • metadata - The metadata command works the same as before.

  • profileopen in new window - Recursively profile pipelines and pipeline elements within a closure.

Enables fine-grained profiling of individual pipeline elements and recursively stepping into blocks/closures. The recursion depth can be controlled (default is 1) and it can optionally collect the profiled source segments for easier orientation and value in each step for easier debugging.

profile_prompt

Note: There are known limitations that the profiler can't run. For example, it can't collect data from subexpressions and loop iterations. It is caused by profiling data being collected as pipeline metadata and a known bug that pipeline metadata is not preserved in some cases.

〉timeit { ls | sort-by name type -i | get name }
2ms 509µs 900ns

view files lists the files and entries loaded into nushell's EngineState memory. Note the spans, for use with view span and the size of each file's contents stored.

explain command

〉def my-cmd [arg] { echo $arg }
〉my-cmd hi
hi
〉view source my-cmd
def my-cmd [ arg:any --help (-h) ] { echo $arg }

Spans are important to nushell. One of their uses is to show where errors are. For instance, in this example below, the leader lines pointing to parts of the command line are able to point to 10, /, and "bob" because each of those items have a span.

〉10 / "bob"
Error: nu::parser::unsupported_operation (link)

  × Types mismatched for operation.
   ╭─[entry #8:1:1]
 1  10 / "bob"
   · ─┬  ──┬──
   ·      ╰── string
   ·   ╰── doesn't support these values.
   ·  ╰── int
   ╰────
  help: Change int or string to be the right types and try again.

Example usage:

〉let a = 42
〉$a
42
〉metadata $a | get span
╭───────┬────────╮
 start  113226 
 end    113228 
╰───────┴────────╯
〉view span 113226 113228
42

You can also find spans by using the debug --raw command.

〉$env.config | get keybindings | first | debug -r
... bunch of stuff
                    span: Span {
                        start: 68065,
                        end: 68090,
                    },
                },
            ],
            span: Span {
                start: 68050,
                end: 68101,
            },
        },
    ],
    span: Span {
        start: 67927,
        end: 68108,
    },
}

〉view span 67927 68108
{
    name: clear_everything
    modifier: control
    keycode: char_l
    mode: emacs
    event: [
        { send: clearscrollback }
    ]
}

〉view span 68065 68090
{ send: clearscrollback }

〉view span 68050 68101
[
    { send: clearscrollback }
]

In an effort to have a little more organization, we've assigned a category of Debug to all commands that participate in nushell script debugging. Here is a list of commands that are in that category now.

  • ast
  • debug
  • explain
  • inspect
  • metadata
  • profile
  • timeit
  • view
  • view files
  • view source
  • view span

"Multiplication" of strings and lists is now supported. (WindSoilderopen in new window)

Like in Python you can now use the multiplication operator * to create n concatenated copies of a string or list. Here n has to be an int value.

This can be useful if you want to quickly build ASCII art 😃! Note that the operation is commutative.

〉" NU " * 3
 NU  NU  NU
〉3 * Shell
ShellShellShell

In the same spirit you can use it to quickly create lists with repeatedly the same element.

/home/stefan/nushell〉7 * [11]
╭───┬────╮
 0  11 
 1  11 
 2  11 
 3  11 
 4  11 
 5  11 
 6  11 
╰───┴────╯

Community Question

We are interested in your feedback regarding the list multiplication. Does this match your expectations or do you want to use this operator overload more often to do scalar multiplication and look for numerical broadcasting support. Let us know!

Dataframe commands are again explicitly separated from core nushell commands. (#7998open in new window)

NOTE

The optional dataframe functionality is available by cargo install nu --features=dataframe or a distribution that includes that feature.

Dataframe commands have all been renamed in order to avoid confusion with nushell commands. It also makes our help commands less confusing. For instance, you can now do help select and understand how to use the traditional nushell select command and you can do help dfr select and understand how to use the dataframe specific select command. Previously this was a source of cryptic error messages that were confusing to users.

PATH vs Path (#8003open in new window)

We fixed a PATH vs. Path bug in completions, so now you should be able to do commands like cod<tab> and get completions like code and code.cmd across all operating systems.

More commands become plugins and plugins get first-class help support (WindSoilder, #7984open in new window, #7942open in new window)

In an effort to both make the core nushell binary smaller and to improve our plugins system along the way we moved the commands for several less common file formats to nu_plugin_formats.

To make sure you still have a first-class experience while using these commands, our plugins can now support code examples in the help and F1 menu.

Plugin nu_plugin_formats shows the help for from ini

As a result, plugin authors need to slightly update their command Signature to PluginSignature which supports the examples and recompile.

Improved error messages for int and string literals

Nushell now gives more specific and helpful messages when it detects syntax errors. In this release we've improved errors for string and int literals but we hope to improve more in the future. #7952open in new window

Errors in the format of escapes within double-quoted strings are reported specifically:

BeforeAfter
------------------------------------------
# Invalid 2 character escape
------------------------------------------
〉"bad: \z"
Error: nu::parser::parse_mismatch (link)

  × Parse mismatch during operation.
   ╭─[entry #19:1:1]
 1 │ "bad: \z"
   · ────┬────
   ·     ╰── expected any shape
   ╰────


------------------------------------------
# Invalid unicode escape
------------------------------------------
〉"bad: \u{1fbogus}"
Error: nu::parser::parse_mismatch (link)

  × Parse mismatch during operation.
   ╭─[entry #21:1:1]
 1 │ "bad: \u{1fbogus}"
   · ─────────┬────────
   ·          ╰── expected any shape
   ╰────
-------------------------------------------------------
# Invalid 2 character escape
-------------------------------------------------------
〉"bad: \z"
Error:
  × Invalid literal
   ╭─[entry #18:1:1]
 1 │ "bad: \z"
   ·       ─┬─
   ·        ╰── unrecognized escape after '\' in string
   ╰────



-------------------------------------------------------
# Invalid unicode escape
-------------------------------------------------------
〉"bad: \u{1fbogus}"
Error:
  × Invalid literal
   ╭─[entry #20:1:1]
 1 │ "bad: \u{1fbogus}"
   ·       ──────┬─────
   ·             ╰── invalid unicode escape '\u{X...}',
   .             must be 1-6 hex digits, max value 10FFFF in string
   ╰────

Invalid digits in radix-prefixed int literals are now flagged as a specific error. The old parser treated these invalid ints as bare strings:

BeforeAfter
------------------------------------------------------
# invalid radix-prefixed integer literals
------------------------------------------------------
〉( 0 + 0x22bogus ) # hex int literal
Error: nu::parser::unsupported_operation (link)

 × Types mismatched for operation.
  ╭─[entry #26:1:1]
1 │ ( 0 + 0x22bogus ) # hex int literal
  ·   ┬ ┬ ────┬────
  ·   │ │     ╰── string
  ·   │ ╰── doesn't support these values.
  ·   ╰── int
  ╰────
 help: Change int or string to be the right types and
       try again.

--------------------------------------------------------
# invalid radix-prefixed integer literals
--------------------------------------------------------
〉( 0 + 0x22bogus ) # hex int literal
Error:
  × Invalid literal
   ╭─[entry #24:1:1]
 1 │ ( 0 + 0x22bogus ) # hex int literal
   ·       ────┬────
   ·           ╰── invalid digits for radix 16 in int
   ╰────






General housekeeping in the Nu codebase (Hofer-Julian, fdncred, rgwood, sholderbach)

We are very lucky that we recently had a number of new contributors starting to help out with bug fixes and improvements to Nushell. We want to thank you and want to welcome you all!

In the background a number of contributors spent some time improving and refactoring the codebaseopen in new window to get us up-to-date and make it more approachable for newcomers. This includes work to break up less readable code in important places, and a significant effort to get us up-to-speed on some coding standards. We also updated a number of dependencies and want to continue to improve our dependency tree. We recently enlisted the relentless help of the dependabot. Furthermore, we enabled rudimentary tracking of test coverage through codecov.io. This should help us identify areas were additional tests are needed and can be a great contribution to the project.

Breaking changes

  • load-env can not accidentally set $env.PWD anymore (#7963open in new window)
  • The --numbered flag to enumerate entries has been removed from each, par-each, each while, and reduce. Use the enumerate command added in 0.75 instead. (#7777open in new window)
  • Plugin system: nu_plugin::Plugin::signature has changed from fn signature(&self) -> Vec<Signature> to fn signature(&self) -> Vec<PluginSignature> to support examples on plugin commands. Plugin authors have to update the relative structure to apply these changes. Normally you just need to perform a global search/replace from Signature to PluginSignature, then rebuild and run with the latest nushell version. (#7984open in new window)
  • benchmark renamed to timeit (#8018open in new window)
  • dataframe commands renamed with a prefix of dfr (#7998open in new window)
  • view-source renamed to view source (#7989open in new window)
  • Plugin commands can now include examples, which necessitated a change to the plugin signature, which causes all plugins to need to be recompiled for use. (#7984open in new window)
  • str lpad and str rpad have been superseded by fill in order to provide alignment (7846open in new window)
  • from ini, from vcf, from ics, from eml commands are moved to plugin called nu_plugin_formats to reduce the number of commands in nushell core, you need to install and register the plugin manually to use these command. (#7942open in new window)
  • http get -t,--timeout parameter is now -m,--max-time (8088open in new window)
  • Filesystem commands now print to stderr when using --verbose flag (8014open in new window)
  • The parse command will now create 0 indexed columns instead of 1 indexed (7897open in new window)

Full changelog

Nushell

Extension

Documentation

Nu_Scripts

reedline