You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Single line comment# Multi-line documentation# This is a comprehensive function# that follows Unix Philosophydefmy-function [] {
# Implementation
}
Help System
help# General helphelp commands# List all commandshelp<command># Specific command help<command>--help# Command-specific help
Basic Operations
# Arithmetic1+2# Addition10-5# Subtraction3*4# Multiplication15/3# Division2**3# Exponentiation17mod5# Modulo# Comparison5==5# Equal5!=3# Not equal5>3# Greater than5<10# Less than5>=5# Greater than or equal5<=10# Less than or equal# Logicaltrueandfalse# Logical ANDtrueorfalse# Logical ORnottrue# Logical NOT
Data Types
Primitive Types
# Numbers42# Integer3.14# Float0x2A# Hexadecimal0o52# Octal0b101010# Binary# Strings"hello world"# Double quoted'single quoted'# Single quoted`raw string`# Raw string (no escaping)# Booleanstruefalse# Nothing/Nullnullnothing# Duration1day# 1 day2hr# 2 hours30min# 30 minutes45sec# 45 seconds
Structured Types
# Lists
[1, 2, 3, 4] # Simple list
["a", "b", "c"] # String list
[1, "mixed", true] # Mixed types# Records
{ # Multi-line recordname:"John"age:30active:true
}
{name:"Jane", age:25} # Single-line record# Tables
[ # List of records
{name:"Alice", age:30}
{name:"Bob", age:25}
]
Type Checking
"hello"|describe# Get type information42|describe# "int"
[1, 2, 3] |describe# "list<int>"# Type predicates$value|is-empty# Check if empty$value|is-not-empty# Check if not empty
# For loopforitemin$list {
print$item
}
# While loopmuti=0while$i<10 {
print$i$i=$i+1
}
# Loop with break/continueforitemin$items {
if$item=="skip" {
continue
}
if$item=="stop" {
break
}
print$item
}
File Operations
File System Navigation
# Directory operationsls# List current directoryls-la# Detailed listingls**/*.nu# Recursive glob patterncd/path/to/directory# Change directorypwd# Print working directory# Path operations"path/to/file.txt"|path dirname# Get directory"path/to/file.txt"|path basename# Get filename"path/to/file.txt"|pathextension# Get extension"path/to"|path join"file.txt"# Join paths
File I/O
# Reading filesopenfile.txt# Open and read fileopendata.json# Parse JSONopendata.csv# Parse CSVopenconfig.toml# Parse TOMLopenimage.png# Read binary data# Writing files"content"|savefile.txt# Save string$data|to json|savedata.json# Save as JSON$table|to csv|savedata.csv# Save as CSV# Append to files"new line"|save--appendlog.txt
# List operations
[1, 2, 3] |length# Get length
[1, 2, 3] |first# First element
[1, 2, 3] |last# Last element
[1, 2, 3] |get1# Get by index
[1, 2, 3, 4] |slice1..3# Slice# List transformation
[1, 2, 3] |each {|x| $x*2} # Map
[1, 2, 3, 4] |filter {|x| $x>2} # Filter
[1, 2, 3] |reduce {|acc, x| $acc+$x} # Reduce# List manipulation
[1, 2] |append3# Add to end
[2, 3] |prepend1# Add to beginning
[1, 2, 3, 2] |uniq# Remove duplicates
[3, 1, 2] |sort# Sort
[1, 2, 3] |reverse# Reverse
Working with Records
# Record operations
{name:"John", age:30} |getname# Get field
{name:"John", age:30} |selectname# Select fields
{name:"John", age:30} |rejectage# Remove fields# Record transformation
{name:"john"} |updatename {|x| $x.name|strcapitalize}
{name:"John"} |insertage30# Add field
{name:"John", age:30} |upsertage31# Update or insert
Working with Tables
# Table operations$table|selectnameage# Select columns$table|whereage>25# Filter rows$table|sort-byage# Sort by column$table|group-bydepartment# Group by column# Table aggregation$table|math sum# Sum numeric columns$table|math avg# Average$table|math max# Maximum$table|math min# Minimum# Table joining$table1|join$table2id# Join tables$table1|merge$table2# Merge tables
Data Conversion
# Type conversion"123"|into int# String to int123|into string# Int to string"true"|into bool# String to bool"2023-01-01"|into datetime# String to datetime# Format conversion$data|to json# Convert to JSON$data|to csv# Convert to CSV$data|to toml# Convert to TOML$data|to yaml# Convert to YAML# From formats'{"name": "John"}'|from json# Parse JSON"name,age\nJohn,30"|from csv# Parse CSV
Database Operations
In-Memory SQLite (stor)
# Initialize and manage the in-memory databasestor open# Open in-memory databasestor reset# Drop all tables# Table managementstor createusers { # Create tableid:intname:stringemail:stringage:int
}
# Data operations
[{id:1, name:"Alice", email:"[email protected]", age:30}
{id:2, name:"Bob", email:"[email protected]", age:25}]
|stor insertusers# Insert data# Querying with SQLquery db"SELECT * FROM users WHERE age > 25"# Updates and deletionsstor updateusers--set"name = 'Alice Smith'"--where"id = 1"stor deleteusers--where"age < 18"# Delete records# Import/Exportstor importdatabase.db# Import SQLite filestor exportoutput.db# Export to SQLite file
Advanced Database Operations
# Complex queriesquery db" SELECT u.name, u.age, COUNT(*) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name, u.age HAVING COUNT(*) > 0"# Aggregationsquery db" SELECT age_group, COUNT(*) as count, AVG(age) as avg_age FROM ( SELECT CASE WHEN age < 30 THEN 'young' WHEN age < 50 THEN 'middle' ELSE 'senior' END as age_group, age FROM users ) GROUP BY age_group"# Combining with Nushell pipelinesquery db"SELECT name, age FROM users"|whereage>25|sort-byname|updatename {|row| $row.name|strupcase}
# Running external commands^ls-la# Run external command^gitstatus|lines|first10# Pipe external output# Process informationps|wherename=~"nushell"# List processeskill1234# Kill process by PID# Background processes^long-running-command&# Run in backgroundjobs# List background jobs
# Module structureexport moduleproject {
# Constants at the topexport constVERSION="1.0.0"export constDEFAULT_CONFIG="config.toml"# Type definitionsexport defuser-record [] {
{name:string, age:int, email:string}
}
# Public API functionsexport defcreate-user [name: string, age: int, email: string] {
# Validationvalidate-user-input$name$age$email# Create record
{
name:$nameage:$ageemail:$emailcreated: (date now)
}
}
# Private helper functionsdefvalidate-user-input [name: string, age: int, email: string] {
if ($name|str length) ==0 {
error make {msg:"Name cannot be empty"}
}
if$age<0 {
error make {msg:"Age must be positive"}
}
ifnot ($email|str contains"@") {
error make {msg:"Invalid email format"}
}
}
}
Documentation Patterns
# Comprehensive function documentation# Process user data with validation and transformation## This function takes raw user input, validates it according to business rules,# transforms it into the standard format, and returns a structured record.## Parameters:# input: Raw user data (any format)# strict: Enable strict validation mode## Returns:# Validated and normalized user record## Errors:# - ValidationError: Input data doesn't meet requirements# - TransformError: Unable to transform data to required format## Examples:# process-user {name: "John", age: "30"} # process-user $raw_data --strictdefprocess-user [
input: any# Raw user data to process--strict# Enable strict validation mode
]: any->record {
# Implementation with comprehensive error handlingtry {
validate-input$input$stricttransform-data$input
} catch {|error|
error make {
msg:$"Failed to process user: ($error.msg)"help:"Check input format and try again"
}
}
}
Ctrl+C# Interrupt current commandCtrl+D# Exit shellCtrl+L# Clear screenCtrl+R# Reverse search historyTab# Auto-completionShift+Tab# Reverse completionUp/Down# Command historyCtrl+A# Move to beginning of lineCtrl+E# Move to end of line
Environment Variables
$env.PATH# System PATH$env.HOME# Home directory$env.PWD# Current directory$env.USER# Current user$nu.config-path# Nushell config file$nu.env-path# Nushell environment file$nu.home-path# Nushell home directory
This cheatsheet covers Nushell v0.107.0+ features following Unix Philosophy principles and modern development practices. For the latest updates, refer to the official Nushell documentation.
---home: trueheroImage: nullheroText: Nushelltagline: A new type of shellactionText: Get Started →actionLink: /book/features:
- title: Cross-platformdetails: Nu works on Linux, macOS, BSD, and Windows. Learn it once, then use it anywhere.
- title: Everything is datadetails: Nu pipelines use structured data so you can safely select, filter, and sort the same way every time. Stop parsing strings and start solving problems.
- title: Powerful pluginsdetails: It's easy to extend Nu using a powerful plugin system.---
<imgsrc="https://www.nushell.sh/frontpage/ls-example.png"alt="Screenshot showing using the ls command"class="hero"/>
### Nu works with existing data
Nu speaks [JSON, YAML, SQLite, Excel, and more](/book/loading_data.html) out of the box. It's easy to bring data into a Nu pipeline whether it's in a file, a database, or a web API:
<imgsrc="https://www.nushell.sh/frontpage/fetch-example.png"alt="Screenshot showing fetch with a web API"class="hero"/>
### Nu has great error messages
Nu operates on typed data, so it catches bugs that other shells don't. And when things break, Nu tells you exactly where and why:
<imgsrc="https://www.nushell.sh/frontpage/miette-example.png"alt="Screenshot showing Nu catching a type error"class="hero"/>
## Get Nu
Nushell is available as [downloadable binaries](https://github.com/nushell/nushell/releases), [via your favourite package manager](https://repology.org/project/nushell/versions), in [a GitHub Action](https://github.com/marketplace/actions/setup-nu), and as [source code](https://github.com/nushell/nushell). Read [the detailed installation instructions](/book/installation.html) or dive right in:
#### macOS / Linux:##### Homebrew```shell
$ brew install nushell
Nix profile
$ nix profile install nixpkgs#nushell
Windows:
# Install to user scope (by default).
winget install nushell
# Machine scope installation (Run as admin).
winget install nushell --scope machine
After installing, launch Nu by typing nu.
Documentation
Getting Started guides you through getting familiar with Nushell
Coming to Nu describes similarities and differences to other languages and shells
Nu Fundamentals is a more elaborate and structured description of the fundamentals
`book/3rdpartyprompts.md`:
```md
# How to Configure 3rd Party Prompts
## Nerd Fonts
Nerd Fonts are not required, but they can improve the prompt presentation through additional glyphs and iconography.
> Nerd Fonts patches developer targeted fonts with a high number of glyphs (icons).
> Specifically to add a high number of extra glyphs from popular ‘iconic fonts’ such as Font Awesome, Devicons, Octicons, and others.
- [Nerd Fonts website](https://www.nerdfonts.com)
- [Source Repository](https://github.com/ryanoasis/nerd-fonts)
## oh-my-posh
[site](https://ohmyposh.dev/)
[repo](https://github.com/JanDeDobbeleer/oh-my-posh)
If you like [oh-my-posh](https://ohmyposh.dev/), you can use oh-my-posh with Nushell with a few steps. It works great with Nushell. How to setup oh-my-posh with Nushell:
1. Install Oh My Posh and download oh-my-posh's themes following [guide](https://ohmyposh.dev/docs/installation/linux).
2. Download and install a [nerd font](https://github.com/ryanoasis/nerd-fonts).
3. Generate the .oh-my-posh.nu file. By default it will be generated to your home directory. You can use `--config` to specify a theme, other wise, oh-my-posh comes with a default theme.
4. Initialize oh-my-posh prompt by adding in ~/.config/nushell/config.nu(or the path output by `$nu.config-path`) to source ~/.oh-my-posh.nu.
```nu
# Generate the .oh-my-posh.nu file
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
For MacOS users:
You can install oh-my-posh using brew, just following the guide here
Use the config example below. Make sure to set the STARSHIP_SHELL environment variable.
::: tip
An alternate way to enable Starship is described in the Starship Quick Install instructions.
The link above is the official integration of Starship and Nushell and is the simplest way to get
Starship running without doing anything manual:
Starship will create its own configuration / environment setup script
you simply have to create it in env.nu and use it in config.nu
:::
Here's an example config section for Starship:
$env.STARSHIP_SHELL="nu"
def create_left_prompt [] {
starship prompt --cmd-duration $env.CMD_DURATION_MS $'--status=($env.LAST_EXIT_CODE)'
}
# Use nushell functions to define your right and left prompt$env.PROMPT_COMMAND= { || create_left_prompt }
$env.PROMPT_COMMAND_RIGHT=""# The prompt indicators are environmental variables that represent# the state of the prompt$env.PROMPT_INDICATOR=""$env.PROMPT_INDICATOR_VI_INSERT=": "$env.PROMPT_INDICATOR_VI_NORMAL="〉"$env.PROMPT_MULTILINE_INDICATOR="::: "
`book/README.md`:
```md
# Introduction
Hello, and welcome to the Nushell project.
The goal of this project is to take the Unix philosophy of shells, where pipes connect simple commands together, and bring it to the modern style of development.
Thus, rather than being either a shell, or a programming language, Nushell connects both by bringing a rich programming language and a full-featured shell together into one package.
Nu takes cues from a lot of familiar territory: traditional shells like bash, object based shells like PowerShell, gradually typed languages like TypeScript, functional programming, systems programming, and more. But rather than trying to be a jack of all trades, Nu focuses its energy on doing a few things well:
- Being a flexible cross-platform shell with a modern feel
- Solving problems as a modern programming language that works with the structure of your data
- Giving clear error messages and clean IDE support
## This Book
The book is split into chapters which are further broken down into sections.
You can click on the chapter headers to get more information about it.
- [Installation](installation.md), of course, helps you get Nushell onto your system.
- [Getting Started](getting_started.md) shows you the ropes. It also explains some of the design principles where Nushell differs from typical shells, such as Bash.
- [Nu Fundamentals](nu_fundamentals.md) explains basic concepts of the Nushell language.
- [Programming in Nu](programming_in_nu.md) dives more deeply into the language features and shows several ways how to organize and structure your code.
- [Nu as a Shell](nu_as_a_shell.md) focuses on the shell features, most notably the configuration and environment.
- [Coming to Nu](coming_to_nu.md) is intended to give a quick start for users coming from other shells or languages.
- [Design Notes](design_notes.md) has in-depth explanation of some of the Nushell's design choices.
- [(Not So) Advanced](advanced.md) includes some more advanced topics (they are not _so_ advanced, make sure to check them out, too!).
## The Many Parts of Nushell
The Nushell project consists of multiple different repositories and subprojects.
You can find all of them under [our organization on GitHub](https://github.com/nushell).
- The main Nushell repository can be found [here](https://github.com/nushell/nushell). It is broken into multiple crates that can be used as independent libraries in your own project, if you wish so.
- The repository of our [nushell.sh](https://www.nushell.sh) page, including this book, can be found [here](https://github.com/nushell/nushell.github.io).
- Nushell has its own line editor which [has its own repository](https://github.com/nushell/reedline)
- [`nu_scripts`](https://github.com/nushell/nu_scripts) is a place to share scripts and modules with other users until we have some sort of package manager.
- [Nana](https://github.com/nushell/nana) is an experimental effort to explore graphical user interface for Nushell.
- [Awesome Nu](https://github.com/nushell/awesome-nu) contains a list of tools that work with the Nushell ecosystem: plugins, scripts, editor extension, 3rd party integrations, etc.
- [Nu Showcase](https://github.com/nushell/showcase) is a place to share works about Nushell, be it blogs, artwork or something else.
- [Request for Comment (RFC)](https://github.com/nushell/rfcs) serves as a place to propose and discuss major design changes. While currently under-utilized, we expect to use it more as we get closer to and beyond 1.0.
## Contributing
We welcome contributions!
[As you can see](#the-many-parts-of-nushell), there are a lot of places to contribute to.
Most repositories contain `CONTRIBUTING.md` file with tips and details that should help you get started (if not, consider contributing a fix!).
Nushell itself is written in [Rust](https://www.rust-lang.org).
However, you do not have to be a Rust programmer to help.
If you know some web development, you can contribute to improving this website or the Nana project.
[Dataframes](dataframes.md) can use your data processing expertise.
If you wrote a cool script, plugin or integrated Nushell somewhere, we'd welcome your contribution to `nu_scripts` or Awesome Nu.
Discovering bugs with reproduction steps and filing GitHub issues for them is a valuable help, too!
You can contribute to Nushell just by using Nushell!
Since Nushell evolves fast, this book is in a constant need of updating.
Contributing to this book does not require any special skills aside from a basic familiarity with Markdown.
Furthermore, you can consider translating parts of it to your language.
## Community
The main place to discuss anything Nushell is our [Discord](https://discord.com/invite/NtAbbGn).
You can also follow our [blog](https://www.nushell.sh/blog) for news and updates.
Finally, you can use the GitHub discussions or file GitHub issues.
book/advanced.md:
---prev:
text: How Nushell Code Gets Runlink: /book/how_nushell_code_gets_run.mdnext:
text: Standard Library (Preview)link: /book/standard_library.md---# (Not so) Advanced
While the "Advanced" title might sound daunting and you might be tempted to skip this chapter, in fact, some of the most interesting and powerful features can be found here.
Besides the built-in commands, Nushell has a [standard library](standard_library.md).
Nushell operates on _structured data_.
You could say that Nushell is a "data-first" shell and a programming language.
To further explore the data-centric direction, Nushell includes a full-featured dataframe processing engine using [Polars](https://github.com/pola-rs/polars) as the backend.
Make sure to check the [Dataframes documentation](dataframes.md) if you want to process large data efficiently directly in your shell.
Values in Nushell contain some extra [metadata](metadata.md).
This metadata can be used, for example, to [create custom errors](creating_errors.md).
Thanks to Nushell's strict scoping rules, it is very easy to [iterate over collections in parallel](parallelism.md) which can help you speed up long-running scripts by just typing a few characters.
You can [interactively explore data](explore.md) with the [`explore`](/commands/docs/explore.md) command.
Finally, you can extend Nushell's functionality with [plugins](plugins.md).
Almost anything can be a plugin as long as it communicates with Nushell in a protocol that Nushell understands.
book/aliases.md:
# Aliases
Aliases in Nushell offer a way of doing a simple replacement of command calls (both external and internal commands). This allows you to create a shorthand name for a longer command, including its default arguments.
For example, let's create an alias called `ll` which will expand to `ls -l`.
```nualias ll = ls -l
We can now call this alias:
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:
ll -a
And get the equivalent to having typed ls -l -a.
List All Loaded Aliases
Your useable aliases can be seen in scope aliases and help aliases.
Persisting
To make your aliases persistent they must be added to your config.nu file by running config nu to open an editor and inserting them, and then restarting nushell.
e.g. with the above ll alias, you can add alias ll = ls -l anywhere in config.nu
$env.config = {
# main configuration
}
alias ll = ls -l
# some other config and script loading
Piping in Aliases
Note that alias uuidgen = uuidgen | tr A-F a-f (to make uuidgen on mac behave like linux) won't work.
The solution is to define a command without parameters that calls the system program uuidgen via ^.
Or a more idiomatic example with nushell internal commands
def lsg [] { ls | sort-by type name -i | grid -c | str trim }
displaying all listed files and folders in a grid.
Replacing Existing Commands Using Aliases
::: warning Caution!
When replacing commands it is best to "back up" the command first and avoid recursion error.
:::
How to back up a command like ls:
alias core-ls = ls # This will create a new alias core-ls for ls
Now you can use core-ls as ls in your nu-programming. You will see further down how to use core-ls.
The reason you need to use alias is because, unlike def, aliases are position-dependent. So, you need to "back up" the old command first with an alias, before re-defining it.
If you do not backup the command and you replace the command using def you get a recursion error.
def ls [] { ls }; ls # Do *NOT* do this! This will throw a recursion error#output:#Error: nu::shell::recursion_limit_reached## × Recursion limit (50) reached# ╭─[C:\Users\zolodev\AppData\Roaming\nushell\config.nu:807:1]# 807 │# 808 │ def ls [] { ls }; ls# · ───┬──# · ╰── This called itself too many times# ╰────
The recommended way to replace an existing command is to shadow the command.
Here is an example shadowing the ls command.
# alias the built-in ls command to ls-builtins
alias ls-builtin = ls
# List the filenames, sizes, and modification times of items in a directory.
def ls [
--all (-a),# Show hidden files--long (-l),# Get all available columns for each entry (slower; columns are platform-dependent)--short-names (-s),# Only print the file names, and not the path--full-paths (-f),# display paths as absolute paths--du (-d),# Display the apparent directory size ("disk usage") in place of the directory metadata size--directory (-D),# List the specified directory itself instead of its contents--mime-type (-m),# Show mime-type in type column instead of 'file' (based on filenames only; files' contents are not examined)--threads (-t),# Use multiple threads to list contents. Output will be non-deterministic....pattern: glob,# The glob pattern to use.
]: [ nothing -> table ] {
let pattern =if ($pattern| is-empty) { [ '.' ] } else { $pattern }
(ls-builtin
--all=$all--long=$long--short-names=$short_names--full-paths=$full_paths--du=$du--directory=$directory--mime-type=$mime_type--threads=$threads...$pattern
) | sort-by type name -i
}
`book/background_jobs.md`:
```md
---
next:
text: Coming to Nu
link: /book/coming_to_nu.md
---
# Background Jobs
Nushell currently has experimental support for thread-based background jobs.
## Spawning Jobs
Jobs can be can be spawned using [`job spawn`](/commands/docs/job_spawn.md), which receives a closure and starts its execution in a background thread, returning
an unique integer id for the spawned job:
```nu
'i am' | save status.txt
job spawn { sleep 10sec; ' inevitable' | save --append status.txt }
# => 1
open status.txt
# => i am
# wait for 10 seconds
sleep 10sec
open status.txt
# => i am inevitable
Listing and Killing jobs
Active jobs can be queried with the job list command, which returns a table with the information of the jobs which are currently executing.
Jobs can also be killed/interrupted by using the job kill command, which interrupts the job's thread and kills all of the job's child processes:
On Unix targets, such as Linux and macOS, Nushell also supports suspending external commands using Ctrl+Z. When a running process is suspended, it is turned into a "frozen" background job:
long_running_process # this starts running, then Ctrl+Z is pressed# => Job 1 is frozen
job list# => ┏━━━┳━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━┓# => ┃ # ┃ id ┃ type ┃ pids ┃# => ┣━━━╋━━━━╋━━━━━━━━╋━━━━━━━━━━━━━━━━┫# => ┃ 0 ┃ 1 ┃ frozen ┃ [list 1 items] ┃# => ┗━━━┻━━━━┻━━━━━━━━┻━━━━━━━━━━━━━━━━┛
A frozen job can be brought back into foreground with the job unfreeze command:
job unfreeze
# process is brought back where it stopped
::: tip Tip
For those familiar with other Unix shells, you can create an alias to emulate the behavior of the fg command:
alias fg = job unfreeze
:::
By default, job unfreeze will unfreeze the most recently frozen job. However, you can also specify the id of a specific job to unfreeze:
vim
# => Job 1 is frozen
long_running_process
# => Job 2 is frozen
job unfreeze 1# we're back in vim
Communicating between jobs
Data can be sent to a job using job send <id>, and the job can receive it using job recv:
let jobId = job spawn {
job recv | save sent.txt
}
'hello from the main thread' | job send$jobId
sleep 1sec
open sent.txt
# => hello from the main thread
The main thread has a job ID of 0, so you can also send data in the other direction:
job spawn {
sleep 1sec
'Hello from a background job' | job send0
}
job recv
# => Hello from a background job
Exit Behavior
Unlike many other shells, Nushell jobs are not separate processes,
and are instead implemented as background threads.
An important side effect of this, is that all background jobs will terminate once the shell
process exits.
For this reason, Nushell has no UNIX-like disown command to prevent jobs from terminating once the shell exits.
To account for that, there are plans for a job dispatch implementation in the future,
for spawning independent background processes (see #15201 for progress).
Additionally, if the user is running an interactive Nushell session and runs
exit while there are background jobs running,
the shell will warn about them before prompting the user to confirm exit.
`book/cheat_sheet.md`:
```md
---
next:
text: Nu Fundamentals
link: /book/nu_fundamentals.md
---
# Nushell Cheat Sheet
## Data Types
convert string to integer:
```nu
"12" | into int
convert present date to provided time zone:
date now | date to-timezone "Europe/London"
update a record's language and if none is specified insert provided value:
{'name': 'nu', 'stars': 5, 'language': 'Python'} | upsert language 'Rust'
let planets = [MercuryVenusEarthMarsJupiterSaturnUranusNeptune]
$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 │# => ╰───┴─────────────────────────────────────────╯
import module from file and use its environment in current scope:
# greetings.nu
export-env {
$env.MYNAME="Arthur, King of the Britons"
}
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 main command in module:
# greetings.nu
export def hello [name: string] {
$"hello ($name)!"
}
export def hi [where: string] {
$"hi ($where)!"
}
export def main [] {
"greetings and salutations!"
}
use greetings.nu
greetings
# => greetings and salutations!
greetings hello world
# => hello world!
`book/coloring_and_theming.md`:
```md
# Coloring and Theming in Nu
Many parts of Nushell's interface can have their color customized. All of these can be set in the `config.nu` configuration file. If you see the `#` outside of a text value in the config file it means the text after it is commented out.
## Table Borders
Table borders are controlled by the `$env.config.table.mode` setting. It can be changed at run time, or in the `config.nu` file:
```nu
$env.config.table.mode = 'rounded'
The options for $env.config.table.mode can be listed with table --list:
The color configuration is defined in $env.config.color_config. The current configuration can be printed with:
$env.config.color_config | sort
The color and style-attributes can be declared in multiple alternative formats.
r - normal color red's abbreviation
rb - normal color red's abbreviation with bold attribute
red - normal color red
red_bold - normal color red with bold attribute
"#ff0000" - "#hex" format foreground color red (quotes are required)
{ fg: "#ff0000" bg: "#0000ff" attr: b } - "full #hex" format foreground red in "#hex" format with a background of blue in "#hex" format with an attribute of bold abbreviated.
{|x| 'yellow' } - closure returning a string with one of the color representations listed above
{|x| { fg: "#ff0000" bg: "#0000ff" attr: b } } - closure returning a valid record
Attributes
code
meaning
l
blink
b
bold
d
dimmed
h
hidden
i
italic
r
reverse
s
strikethrough
u
underline
n
nothing
defaults to nothing
Normal Colors and Abbreviations
code
name
g
green
gb
green_bold
gu
green_underline
gi
green_italic
gd
green_dimmed
gr
green_reverse
bg_g
bg_green
lg
light_green
lgb
light_green_bold
lgu
light_green_underline
lgi
light_green_italic
lgd
light_green_dimmed
lgr
light_green_reverse
bg_lg
bg_light_green
r
red
rb
red_bold
ru
red_underline
ri
red_italic
rd
red_dimmed
rr
red_reverse
bg_r
bg_red
lr
light_red
lrb
light_red_bold
lru
light_red_underline
lri
light_red_italic
lrd
light_red_dimmed
lrr
light_red_reverse
bg_lr
bg_light_red
u
blue
ub
blue_bold
uu
blue_underline
ui
blue_italic
ud
blue_dimmed
ur
blue_reverse
bg_u
bg_blue
lu
light_blue
lub
light_blue_bold
luu
light_blue_underline
lui
light_blue_italic
lud
light_blue_dimmed
lur
light_blue_reverse
bg_lu
bg_light_blue
b
black
bb
black_bold
bu
black_underline
bi
black_italic
bd
black_dimmed
br
black_reverse
bg_b
bg_black
ligr
light_gray
ligrb
light_gray_bold
ligru
light_gray_underline
ligri
light_gray_italic
ligrd
light_gray_dimmed
ligrr
light_gray_reverse
bg_ligr
bg_light_gray
y
yellow
yb
yellow_bold
yu
yellow_underline
yi
yellow_italic
yd
yellow_dimmed
yr
yellow_reverse
bg_y
bg_yellow
ly
light_yellow
lyb
light_yellow_bold
lyu
light_yellow_underline
lyi
light_yellow_italic
lyd
light_yellow_dimmed
lyr
light_yellow_reverse
bg_ly
bg_light_yellow
p
purple
pb
purple_bold
pu
purple_underline
pi
purple_italic
pd
purple_dimmed
pr
purple_reverse
bg_p
bg_purple
lp
light_purple
lpb
light_purple_bold
lpu
light_purple_underline
lpi
light_purple_italic
lpd
light_purple_dimmed
lpr
light_purple_reverse
bg_lp
bg_light_purple
m
magenta
mb
magenta_bold
mu
magenta_underline
mi
magenta_italic
md
magenta_dimmed
mr
magenta_reverse
bg_m
bg_magenta
lm
light_magenta
lmb
light_magenta_bold
lmu
light_magenta_underline
lmi
light_magenta_italic
lmd
light_magenta_dimmed
lmr
light_magenta_reverse
bg_lm
bg_light_magenta
c
cyan
cb
cyan_bold
cu
cyan_underline
ci
cyan_italic
cd
cyan_dimmed
cr
cyan_reverse
bg_c
bg_cyan
lc
light_cyan
lcb
light_cyan_bold
lcu
light_cyan_underline
lci
light_cyan_italic
lcd
light_cyan_dimmed
lcr
light_cyan_reverse
bg_lc
bg_light_cyan
w
white
wb
white_bold
wu
white_underline
wi
white_italic
wd
white_dimmed
wr
white_reverse
bg_w
bg_white
dgr
dark_gray
dgrb
dark_gray_bold
dgru
dark_gray_underline
dgri
dark_gray_italic
dgrd
dark_gray_dimmed
dgrr
dark_gray_reverse
bg_dgr
bg_dark_gray
def
default
defb
default_bold
defu
default_underline
defi
default_italic
defd
default_dimmed
defr
default_reverse
bg_def
bg_default
"#hex" Format
The "#hex" format is one way you typically see colors represented. It's simply the # character followed by 6 characters. The first two are for red, the second two are for green, and the third two are for blue. It's important that this string be surrounded in quotes, otherwise Nushell thinks it's a commented out string.
Example: The primary red color is "#ff0000" or "#FF0000". Upper and lower case in letters shouldn't make a difference.
This "#hex" format allows us to specify 24-bit truecolor tones to different parts of Nushell.
Full "#hex" Format
The full "#hex" format is a take on the "#hex" format but allows one to specify the foreground, background, and attributes in one line.
Example: { fg: "#ff0000" bg: "#0000ff" attr: b }
foreground of red in "#hex" format
background of blue in "#hex" format
attribute of bold abbreviated
Closure
Note: Closures are only executed for table output. They do not work in other contexts like for shape_ configurations, when printing a value directly, or as a value in a list.
╭───┬───────────╮
│ a │ true │
│ b │ false │
│ c │ 0B │
│ d │ 488.3KiB │
│ e │ 10.0MiB │
╰───┴───────────╯
with a green true, a light red false, a dark grey 0 B, a cyan 488.3 KiB, and a blue 10.0 MiB.
Primitive Values
Primitive values are things like int and string. Primitive values and shapes can be set with a variety of color symbologies seen above.
This is the current list of primitives. Not all of these are configurable. The configurable ones are marked with *.
primitive
default color
configurable
any
binary
Color::White.normal()
*
block
Color::White.normal()
*
bool
Color::White.normal()
*
cellpath
Color::White.normal()
*
condition
custom
date
Color::White.normal()
*
duration
Color::White.normal()
*
expression
filesize
Color::White.normal()
*
float
Color::White.normal()
*
glob
import
int
Color::White.normal()
*
list
Color::White.normal()
*
nothing
Color::White.normal()
*
number
operator
path
range
Color::White.normal()
*
record
Color::White.normal()
*
signature
string
Color::White.normal()
*
table
var
vardecl
variable
Special "primitives" (not really primitives but they exist solely for coloring)
primitive
default color
configurable
leading_trailing_space_bg
Color::Rgb(128, 128, 128))
*
header
Color::Green.bold()
*
empty
Color::Blue.normal()
*
row_index
Color::Green.bold()
*
hints
Color::DarkGray.normal()
*
Here's a small example of changing some of these values.
$env.config.color_config.separator = purple
$env.config.color_config.leading_trailing_space_bg ="#ffffff"$env.config.color_config.header = gb
$env.config.color_config.date = wd
$env.config.color_config.filesize = c
$env.config.color_config.row_index = cb
$env.config.color_config.bool = red
$env.config.color_config.int = green
$env.config.color_config.duration = blue_bold
$env.config.color_config.range = purple
$env.config.color_config.float = red
$env.config.color_config.string = white
$env.config.color_config.nothing = red
$env.config.color_config.binary = red
$env.config.color_config.cellpath = cyan
$env.config.color_config.hints = dark_gray
Here's another small example using multiple color syntaxes with some comments.
$env.config.color_config.separator ="#88b719"# this sets only the foreground color like PR #486$env.config.color_config.leading_trailing_space_bg = white # this sets only the foreground color in the original style$env.config.color_config.header = { # this is like PR #489
fg: "#B01455",# note, quotes are required on the values with hex colors
bg: "#ffb900",# note, commas are not required, it could also be all on one line
attr: bli # note, there are no quotes around this value. it works with or without quotes
}
$env.config.color_config.date ="#75507B"$env.config.color_config.filesize ="#729fcf"$env.config.color_config.row_index = {
# note, that this is another way to set only the foreground, no need to specify bg and attr
fg: "#e50914"
}
Shape Values
As mentioned above, shape is a term used to indicate the syntax coloring.
Here's the current list of flat shapes.
shape
default style
configurable
shape_block
fg(Color::Blue).bold()
*
shape_bool
fg(Color::LightCyan)
*
shape_custom
bold()
*
shape_external
fg(Color::Cyan)
*
shape_externalarg
fg(Color::Green).bold()
*
shape_filepath
fg(Color::Cyan)
*
shape_flag
fg(Color::Blue).bold()
*
shape_float
fg(Color::Purple).bold()
*
shape_garbage
fg(Color::White).on(Color::Red).bold()
*
shape_globpattern
fg(Color::Cyan).bold()
*
shape_int
fg(Color::Purple).bold()
*
shape_internalcall
fg(Color::Cyan).bold()
*
shape_list
fg(Color::Cyan).bold()
*
shape_literal
fg(Color::Blue)
*
shape_nothing
fg(Color::LightCyan)
*
shape_operator
fg(Color::Yellow)
*
shape_pipe
fg(Color::Purple).bold()
*
shape_range
fg(Color::Yellow).bold()
*
shape_record
fg(Color::Cyan).bold()
*
shape_signature
fg(Color::Green).bold()
*
shape_string
fg(Color::Green)
*
shape_string_interpolation
fg(Color::Cyan).bold()
*
shape_table
fg(Color::Blue).bold()
*
shape_variable
fg(Color::Purple)
*
Here's a small example of how to apply color to these items. Anything not overridden will receive its default color.
The Nushell prompt is configurable through these environment variables and config items:
PROMPT_COMMAND: Code to execute for setting up the prompt (block)
PROMPT_COMMAND_RIGHT: Code to execute for setting up the RIGHT prompt (block) (see oh-my.nu in nu_scripts)
PROMPT_INDICATOR = "〉": The indicator printed after the prompt (by default ">"-like Unicode symbol)
PROMPT_INDICATOR_VI_INSERT = ": "
PROMPT_INDICATOR_VI_NORMAL = "v "
PROMPT_MULTILINE_INDICATOR = "::: "
render_right_prompt_on_last_line: Bool value to enable or disable the right prompt to be rendered on the last line of the prompt
Example: For a simple prompt one could do this. Note that PROMPT_COMMAND requires a block whereas the others require a string.
$env.PROMPT_COMMAND= { $"(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.
$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:
Coloring of the prompt is controlled by the block in PROMPT_COMMAND where you can write your own custom prompt. We've written a slightly fancy one that has git statuses located in the nu_scripts repo.
Transient Prompt
If you want a different prompt displayed for previously entered commands, you can use Nushell's transient prompt feature. This can be useful if your prompt has lots of information that is unnecessary to show for previous lines (e.g. time and Git status), since you can make it so that previous lines show with a shorter prompt.
Each of the PROMPT_* variables has a corresponding TRANSIENT_PROMPT_* variable to be used for changing that segment when displaying past prompts: TRANSIENT_PROMPT_COMMAND, TRANSIENT_PROMPT_COMMAND_RIGHT, TRANSIENT_PROMPT_INDICATOR, TRANSIENT_PROMPT_INDICATOR_VI_INSERT, TRANSIENT_PROMPT_INDICATOR_VI_NORMAL, TRANSIENT_PROMPT_MULTILINE_INDICATOR. By default, the PROMPT_* variables are used for displaying past prompts.
For example, if you want to make past prompts show up without a left prompt entirely and leave only the indicator, you can use:
$env.TRANSIENT_PROMPT_COMMAND=""
If you want to go back to the normal left prompt, you'll have to unset TRANSIENT_PROMPT_COMMAND:
Nushell will respect and use the LS_COLORS environment variable setting on Mac, Linux, and Windows. This setting allows you to define the coloring of file types when you do a ls. For instance, you can make directories one color, .md Markdown files another color, .toml files yet another color, etc. There are a variety of ways to color and style your file types.
If LS_COLORS is not set, nushell will default to a built-in LS_COLORS setting, based on 8-bit (extended) ANSI colors.
Understanding LS_COLORS
LS_COLORS contains a colon (:) separated list of records that map file types and file names to styling attributes (selector=attributes).
The selector can be a file type specified like di for "directory identifier", or *.nu for files with the .nu file extension.
The attributes are a list of semicolon (;) separated numbers. Note that which attributes and attribute formats are supported depends on the terminal you are using.
$env.LS_COLORS = "di=48;2;200;0;0;5": Red background blinking directories
vivid Themes
For example, you can use the third-party tool vivid, which runs on multiple platforms, has many themes defined, and generates a LS_COLORS configuration from it.
After downloading and extracting the binary, you can use it with:
$env.LS_COLORS= (vivid generate molokai)
or with an alternative theme:
$env.LS_COLORS= (vivid generate ayu)
You can put this command into your Nushell configuration for it to become the default coloring.
Theming
Theming combines all the coloring above. Here's a quick example of one we put together quickly to demonstrate the ability to theme. This is a spin on the base16 themes that we see so widespread on the web.
The key to making theming work is to make sure you specify all themes and colors you're going to use in the config.nu file before you declare the let config = line.
# let's define some colorslet base00 ="#181818"# Default Backgroundlet base01 ="#282828"# Lighter Background (Used for status bars, line number and folding marks)let base02 ="#383838"# Selection Backgroundlet base03 ="#585858"# Comments, Invisibles, Line Highlightinglet base04 ="#b8b8b8"# Dark Foreground (Used for status bars)let base05 ="#d8d8d8"# Default Foreground, Caret, Delimiters, Operatorslet base06 ="#e8e8e8"# Light Foreground (Not often used)let base07 ="#f8f8f8"# Light Background (Not often used)let base08 ="#ab4642"# Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deletedlet base09 ="#dc9656"# Integers, Boolean, Constants, XML Attributes, Markup Link Urllet base0a ="#f7ca88"# Classes, Markup Bold, Search Text Backgroundlet base0b ="#a1b56c"# Strings, Inherited Class, Markup Code, Diff Insertedlet base0c ="#86c1b9"# Support, Regular Expressions, Escape Characters, Markup Quoteslet base0d ="#7cafc2"# Functions, Methods, Attribute IDs, Headingslet base0e ="#ba8baf"# Keywords, Storage, Selector, Markup Italic, Diff Changedlet base0f ="#a16946"# Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?># we're creating a theme here that uses the colors we defined above.let base16_theme = {
separator: $base03
leading_trailing_space_bg: $base04
header: $base0b
date: $base0e
filesize: $base0d
row_index: $base0c
bool: $base08
int: $base0b
duration: $base08
range: $base08
float: $base08
string: $base04
nothing: $base08
binary: $base08
cellpath: $base08
hints: dark_gray
# shape_garbage: { fg: $base07 bg: $base08 attr: b } # base16 white on red# but i like the regular white on red for parse errors
shape_garbage: { fg: "#FFFFFF" bg: "#FF0000" attr: b }
shape_bool: $base0d
shape_int: { fg: $base0e attr: b }
shape_float: { fg: $base0e attr: b }
shape_range: { fg: $base0a attr: b }
shape_internalcall: { fg: $base0c attr: b }
shape_external: $base0c
shape_externalarg: { fg: $base0b attr: b }
shape_literal: $base0d
shape_operator: $base0a
shape_signature: { fg: $base0b attr: b }
shape_string: $base0b
shape_filepath: $base0d
shape_globpattern: { fg: $base0d attr: b }
shape_variable: $base0e
shape_flag: { fg: $base0d attr: b }
shape_custom: { attr: b }
}
# now let's apply our regular config settings but also apply the "color_config:" theme that we specified above.$env.config.animate_prompt: false
$env.config.color_config: $base16_theme# <-- this is the theme$env.config.edit_mode: emacs # vi$env.config.filesize_format: "b"# b, kb, kib, mb, mib, gb, gib, tb, tib, pb, pib, eb, eib, auto$env.config.filesize_metric: true
$env.config.float_precision: 2$env.config.footer_mode: always #always, never, number_of_rows, auto$env.config.log_level: error
$env.config.max_history_size: 10000$env.config.table_mode: rounded # basic, compact, compact_double, light, thin, with_love, rounded, reinforced, heavy, none, other$env.config.use_ansi_coloring: true
$env.config.use_grid_icons: true
$env.config.use_ls_colors: true
if you want to go full-tilt on theming, you'll want to theme all the items I mentioned at the very beginning, including LS_COLORS, and the prompt. Good luck!
Working on Light Background Terminal
Nushell's standard library contains a config module with default light and dark themes.
If you are working on a light background terminal, you can apply the light theme easily.
# in $nu.config-path
use std/config light-theme # add this line to load the theme into scope$env.config = { # ... color_config: (light-theme) # after using dark-theme or light-theme from std, you can change this with `(dark-theme)` in place of `(light-theme)`. # ...}
You can also load the dark theme.
# in $nu.config-path
use std/config dark-theme$env.config = { # ... color_config: (dark-theme) # ...}
Accessibility
It's often desired to have the minimum amount of decorations when using a screen reader. In those cases, it's possible to disable borders and other decorations for both table and errors with the following options:
Reedline (Nu’s line editor) style is not using the color_config key.
Instead, each menu has its own style to be configured separately.
See the section dedicated to Reedline’s menus configuration to learn more on this.
`book/coming_from_bash.md`:
```md
---
prev:
text: Coming to Nu
link: /book/coming_to_nu.md
---
# Coming from Bash
::: tip
If you're coming from `Git Bash` on Windows, then the external commands you're used to (e.g, `ln`, `grep`, `vi`, etc) will not be available in Nushell by default unless you have already explicitly made them available in the Windows Path environment variable.
To make these commands available in Nushell as well, add the following line to your `config.nu` with either `append` or `prepend`.
```nu
$env.Path = ($env.Path | prepend 'C:\Program Files\Git\usr\bin')
:::
Command Equivalents:
Bash
Nu
Task
ls
ls
Lists the files in the current directory
ls <dir>
ls <dir>
Lists the files in the given directory
ls pattern*
ls pattern*
Lists files that match a given pattern
ls -la
ls --long --all or ls -la
List files with all available information, including hidden files
ls -d */
ls | where type == dir
List directories
find . -name *.rs
ls **/*.rs
Find recursively all files that match a given pattern
find . -name Makefile | xargs vim
ls **/Makefile | get name | vim ...$in
Pass values as command parameters
cd <directory>
cd <directory>
Change to the given directory
cd
cd
Change to the home directory
cd -
cd -
Change to the previous directory
mkdir <path>
mkdir <path>
Creates the given path
mkdir -p <path>
mkdir <path>
Creates the given path, creating parents as necessary
touch test.txt
touch test.txt
Create a file
> <path>
out> <path> or o> <path>
Save command output to a file
| save <path>
Save command output to a file as structured data
>> <path>
out>> <path> or o>> <path>
Append command output to a file
| save --append <path>
Append command output to a file as structured data
> /dev/null
| ignore
Discard command output
> /dev/null 2>&1
out+err>| ignore or o+e>| ignore
Discard command output, including stderr
command 2>&1 | less
command out+err>| less or command o+e>| less
Pipe stdout and stderr of an external command into less (NOTE: use explore for paging output of internal commands)
cmd1 | tee log.txt | cmd2
cmd1 | tee { save log.txt } | cmd2
Tee command output to a log file
command | head -5
command | first 5
Limit the output to the first 5 rows of an internal command (see also last and skip)
cat <path>
open --raw <path>
Display the contents of the given file
open <path>
Read a file as structured data
cat <(<command1>) <(<command2>)
[(command1), (command2)] | str join
Concatenate the outputs of command1 and command2
cat <path> <(<command>)
[(open --raw <path>), (command)] | str join
Concatenate the contents of the given file and output of command
Run a command, and if it's successful run a second
stat $(which git)
stat ...(which git).path
Use command output as argument for other command
echo /tmp/$RANDOM
$"/tmp/(random int)"
Use command output in a string
cargo b --jobs=$(nproc)
cargo b $"--jobs=(sys cpu | length)"
Use command output in an option
echo $PATH
$env.PATH (Non-Windows) or $env.Path (Windows)
See the current path
echo $?
$env.LAST_EXIT_CODE
See the exit status of the last executed command
<update ~/.bashrc>
vim $nu.config-path
Update PATH permanently
export PATH = $PATH:/usr/other/bin
$env.PATH = ($env.PATH | append /usr/other/bin)
Update PATH temporarily
export
$env
List the current environment variables
<update ~/.bashrc>
vim $nu.config-path
Update environment variables permanently
FOO=BAR ./bin
FOO=BAR ./bin
Update environment temporarily
export FOO=BAR
$env.FOO = BAR
Set environment variable for current session
echo $FOO
$env.FOO
Use environment variables
echo ${FOO:-fallback}
$env.FOO? | default "ABC"
Use a fallback in place of an unset variable
unset FOO
hide-env FOO
Unset environment variable for current session
alias s="git status -sb"
alias s = git status -sb
Define an alias temporarily
type FOO
which FOO
Display information about a command (builtin, alias, or executable)
<update ~/.bashrc>
vim $nu.config-path
Add and edit alias permanently (for new shells)
bash -c <commands>
nu -c <commands>
Run a pipeline of commands
bash <script file>
nu <script file>
Run a script file
\
( <command> )
A command can span multiple lines when wrapped with ( and )
pwd or echo $PWD
pwd or $env.PWD
Display the current directory
read var
let var = input
Get input from the user
read -s secret
let secret = input -s
Get a secret value from the user without printing keystrokes
History Substitutions and Default Keybindings:
Bash
Nu
Task
!!
!!
Insert last command-line from history
!$
!$
Insert last spatially separated token from history
!<n> (e.g., !5)
!<n>
Insert <n>th command from the beginning of the history
Tip: history | enumerate | last 10 to show recent positions
!<-n> (e.g., !-5)
!<-n>
Insert <n>th command from the end of the history
!<string> (e.g., !ls)
!<string>
Insert the most recent history item that begins with the string
Ctrl/Cmd+R
Ctrl/Cmd+R
Reverse history search
(Emacs Mode) Ctrl+XCtrl+E
Ctrl/Cmd+O
Edit the command-line in the editor defined by $env.EDITOR
(Vi Command Mode) V
Ctrl/Cmd+O
Edit the command-line in the editor defined by $env.EDITOR
Most common Emacs-mode and Vi-mode keybindings are also available. See the Reedline Chapter.
::: tip
In Bash, history substitution occurs immediately after pressing Enter
to execute the command-line. Nushell, however, inserts the substitution into
the command-line after pressing Enter. This allows you to confirm
the substitution and, if needed, make additional edits before execution.
This behavior extends to "Edit command-line in Editor" as well. While Bash immediately
executes the command after exiting the editor, Nushell (like other, more modern shells
such as Fish and Zsh) inserts the editor contents into the command-line, allowing you
to review and make changes before committing it to execution.
:::
`book/coming_from_cmd.md`:
```md
# Coming from CMD.EXE
This table was last updated for Nu 0.67.0.
| CMD.EXE | Nu | Task |
| ------------------------------------ | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `ASSOC` | | Displays or modifies file extension associations |
| `BREAK` | | Trigger debugger breakpoint |
| `CALL <filename.bat>` | `<filename.bat>` | Run a batch program |
| | `nu <filename>` | Run a nu script in a fresh context |
| | `source <filename>` | Run a nu script in this context |
| | `use <filename>` | Run a nu script as a module |
| `CD` or `CHDIR` | `$env.PWD` | Get the present working directory |
| `CD <directory>` | `cd <directory>` | Change the current directory |
| `CD /D <drive:directory>` | `cd <drive:directory>` | Change the current directory |
| `CLS` | `clear` | Clear the screen |
| `COLOR` | | Set the console default foreground/background colors |
| | `ansi {flags} (code)` | Output ANSI codes to change color |
| `COPY <source> <destination>` | `cp <source> <destination>` | Copy files |
| `COPY <file1>+<file2> <destination>` | `[<file1>, <file2>] \| each { open --raw } \| str join \| save --raw <destination>` | Append multiple files into one |
| `DATE /T` | `date now` | Get the current date |
| `DATE` | | Set the date |
| `DEL <file>` or `ERASE <file>` | `rm <file>` | Delete files |
| `DIR` | `ls` | List files in the current directory |
| `ECHO <message>` | `print <message>` | Print the given values to stdout |
| `ECHO ON` | | Echo executed commands to stdout |
| `ENDLOCAL` | `export-env` | Change env in the caller |
| `EXIT` | `exit` | Close the prompt or script |
| `FOR %<var> IN (<set>) DO <command>` | `for $<var> in <set> { <command> }` | Run a command for each item in a set |
| `FTYPE` | | Displays or modifies file types used in file extension associations |
| `GOTO` | | Jump to a label |
| `IF ERRORLEVEL <number> <command>` | `if $env.LAST_EXIT_CODE >= <number> { <command> }` | Run a command if the last command returned an error code >= specified |
| `IF <string> EQU <string> <command>` | `if <string> == <string> { <command> }` | Run a command if strings match |
| `IF EXIST <filename> <command>` | `if (<filename> \| path exists) { <command> }` | Run a command if the file exists |
| `IF DEFINED <variable> <command>` | `if '$<variable>' in (scope variables).name { <command> }` | Run a command if the variable is defined |
| `MD` or `MKDIR` | `mkdir` | Create directories |
| `MKLINK` | | Create symbolic links |
| `MOVE` | `mv` | Move files |
| `PATH` | `$env.Path` | Display the current path variable |
| `PATH <path>;%PATH%` | `$env.Path = ($env.Path \| append <path>`) | Edit the path variable |
| `PATH %PATH%;<path>` | `$env.Path = ($env.Path \| prepend <path>`) | Edit the path variable |
| `PAUSE` | `input "Press any key to continue . . ."` | Pause script execution |
| `PROMPT <template>` | `$env.PROMPT_COMMAND = { <command> }` | Change the terminal prompt |
| `PUSHD <path>`/`POPD` | `enter <path>`/`dexit` | Change working directory temporarily |
| `REM` | `#` | Comments |
| `REN` or `RENAME` | `mv` | Rename files |
| `RD` or `RMDIR` | `rm` | Remove directory |
| `SET <var>=<string>` | `$env.<var> = <string>` | Set environment variables |
| `SETLOCAL` | (default behavior) | Localize environment changes to a script |
| `START <path>` | Partially covered by `start <path>` | Open the path in the system-configured default application |
| `START <internal command>` | | Start a separate window to run a specified internal command |
| `START <batch file>` | | Start a separate window to run a specified batch file |
| `TIME /T` | `date now \| format date "%H:%M:%S"` | Get the current time |
| `TIME` | | Set the current time |
| `TITLE` | | Set the cmd.exe window name |
| `TYPE` | `open --raw` | Display the contents of a text file |
| | `open` | Open a file as structured data |
| `VER` | | Display the OS version |
| `VERIFY` | | Verify that file writes happen |
| `VOL` | | Show drive information |
## Forwarded CMD.EXE commands
Nu accepts and runs *some* of CMD.EXE's internal commands through `cmd.exe`.
The internal commands are: `ASSOC`, `CLS`, `ECHO`, `FTYPE`, `MKLINK`, `PAUSE`, `START`, `VER`, `VOL`
These internal commands take precedence over external commands.
For example, with a `ver.bat` file in the current working directory, executing `^ver` executes CMD.EXE's internal `VER` command, *NOT* the `ver.bat` file.
Executing `./ver` or `ver.bat` *will* execute the local bat file though.
Note that Nushell has its own [`start` command](/commands/docs/start.md) which takes precedence.
You can call the CMD.EXE's internal `START` command with the external command syntax `^start`.
book/coming_to_nu.md:
---prev:
text: Background Jobslink: /book/background_jobs.mdnext:
text: Coming from Bashlink: /book/coming_from_bash.md---# Coming to Nu
If you are familiar with other shells or programming languages, you might find this chapter useful to get up to speed.
[Coming from Bash](coming_from_bash.md) shows how some patterns typical for Bash, or POSIX shells in general, can be mapped to Nushell.
Similarly, [Coming from CMD.EXE](coming_from_cmd.md) shows how built-in commands in the Windows Command Prompt can be mapped to Nushell.
Similar comparisons are made for some [other shells and domain-specific languages](nushell_map.md), [imperative languages](nushell_map_imperative.md), and [functional languages](nushell_map_functional.md).
A separate comparison is made specifically for [operators](nushell_operator_map.md).
book/configuration.md:
---prev:
text: Nu as a Shelllink: /book/nu_as_a_shell.md---# Configuration## Quickstart
While Nushell provides many options for managing its startup and configuration, new users
can get started with just a few simple steps:
1. Tell Nushell what editor to use:
```nu $env.config.buffer_editor = <path_to_your_preferred_editor>
For example:
$env.config.buffer_editor ="code"# or$env.config.buffer_editor ="nano"# or$env.config.buffer_editor ="hx"# or$env.config.buffer_editor ="vi"# with args$env.config.buffer_editor = ["emacsclient","-s","light","-t"]
# etc.
Edit config.nu using:
config nu
This will open the current config.nu in the editor defined above.
Add commands to this file that should run each time Nushell starts. A good first example might be the buffer_editor setting above.
You can find a detailed list of available settings using:
config nu --doc | nu-highlight | less -R
Save, exit the editor, and start a new Nushell session to load these settings.
That's it! More details are below when you need them ...
[[toc]]
::: tip
To view a simplified version of this documentation from inside Nushell, run:
config nu --doc | nu-highlight | less -R
:::
Configuration Overview
Nushell uses multiple, optional configuration files. These files are loaded in the following order:
The first file loaded is env.nu, which was historically used to override environment variables. However, the current "best-practice" recommendation is to set all environment variables (and other configuration) using config.nu and the autoload directories below.
config.nu is typically used to override default Nushell settings, define (or import) custom commands, or run any other startup tasks.
*.nu files in $nu.vendor-autoload-dirs are loaded. These directories are intended for vendors' and package managers' startup files.
*.nu files in $nu.user-autoload-dirs are loaded. These files may be used for any startup tasks and are a good way to modularize the configuration.
login.nu runs commands or handles configuration that should only take place when Nushell is running as a login shell.
By default, env.nu, config.nu, and login.nu are read from the $nu.default-config-dir directory. For example:
The first time Nushell is launched, it will create the configuration directory and an empty (other than comments) env.nu and config.nu.
::: tip
You can quickly open config.nu in your default text editor using the config nu command. Likewise, the config env command will open env.nu.
This requires that you have configured a default editor using either:
Nushell's $env.config.buffer_editor setting
The $env.VISUAL or $env.EDITOR environment variables
For example, place this in your config.nu to edit your files in Visual Studio Code:
$env.config.buffer_editor = 'code'
:::
Common Configuration Tasks in config.nu:
::: tip
Some users will prefer a "monolithic" configuration file with most or all startup tasks in one place. config.nu can be used for this purpose.
Other users may prefer a "modular" configuration where each file handles a smaller, more focused set of tasks. Files in the autoload dirs can be used to create this experience.
:::
Load modules or source files so that their commands are readily available
Run any other applications or commands at startup
Set Environment Variables
::: tip See Also
The Environment Chapter covers additional information on how to set and access environment variables.
:::
Path Configuration
As with most shells, Nushell searches the environment variable named PATH (or variants).
:::tip
Unlike some shells, Nushell attempts to be "case agnostic" with environment variables. Path, path, PATH, and even pAtH are all allowed variants of the same environment variable. See Environment - Case Sensitivity for details.
:::
When Nushell is launched, it usually inherits the PATH as a string. However, Nushell automatically converts this to a Nushell list for easy access. This means that you can append to the path using, for example:
$env.path ++= ["~/.local/bin"]
The Standard Library also includes a helper command. The default path add behavior is to prepend
a directory so that it has higher precedence than the rest of the path. For example, the following can be
added to your startup config:
::: tip
Notice the use of path join in the example above. This command properly joins two path
components regardless of whether or not the path separator is present. See help path for
more commands in this category.
:::
Prompt Configuration
Nushell provides a number of prompt configuration options. By default, Nushell includes:
A prompt which includes the current directory, abbreviated using ~ if it is (or is under)
the home directory.
A prompt indicator which appears immediately to the right of the prompt. This defaults to > when in normal editing mode, or a : when in Vi-insert mode. Note extra space after the character to provide separation of the command from the prompt.
A right-prompt with the date and time
An indicator which is displayed when the current commandline extends over multiple lines - ::: by default
The environment variables which control these prompt components are:
$env.PROMPT_COMMAND: The prompt itself
$env.PROMPT_COMMAND_RIGHT: A prompt which can appear on the right side of the terminal
Nushell also supports transient prompts, which allow a different prompt to be shown after a commandline has been executed. This can be useful in several situations:
When using a multi-line prompt, the transient prompt can be a more condensed version.
Removing the transient multiline indicator and right-prompt can simplify copying from the terminal.
As with the normal prompt commands above, each transient prompt can accept a (static) string, a (dynamic) closure, or a null to use the Nushell internal defaults.
The environment variables which control the transient prompt components are:
$env.TRANSIENT_PROMPT_COMMAND: The prompt itself after the commandline has been executed
$env.TRANSIENT_PROMPT_COMMAND_RIGHT: A prompt which can appear on the right side of the terminal
$env.TRANSIENT_PROMPT_MULTILINE_INDICATOR: The multi-line indicator
::: tip
Nushell sets TRANSIENT_PROMPT_COMMAND_RIGHT and TRANSIENT_PROMPT_MULTILINE_INDICATOR to an empty string ("") so that each disappears after the previous command is entered. This simplifies copying and pasting from the terminal.
To disable this feature and always show those items, set:
Certain variables, such as those containing multiple paths, are often stored as a
colon-separated string in other shells. Nushell can convert these automatically to a
more convenient Nushell list. The ENV_CONVERSIONS variable specifies how environment
variables are:
converted from a string to a value on Nushell startup (from_string)
converted from a value back to a string when running external commands (to_string)
ENV_CONVERSIONS is a record, where:
each key is an environment variable to be converted
each value is another record containing a:
{
from_string: <closure>
to_string: <closure>
}
::: tip
As mentioned above, the OS Path variable is automatically converted by Nushell. As a result, it can be treated as a list within your startup config without needing to be present in ENV_CONVERSIONS. Other colon-separated paths, like XDG_DATA_DIRS, are not automatically converted.
:::
To add an additional conversion, merge it into the $env.ENV_CONVERSIONS record. For example, to add a conversion for the XDG_DATA_DIRS variable:
As with many ls-like utilities, Nushell's directory listings make use of the LS_COLORS environment variable for defining styles/colors to apply to certain file types and patterns.
Nushell Settings in the $env.config Record
Changing Settings in the $env.config Record
The primary mechanism for changing Nushell's behavior is the $env.config record. While this record is accessed as an environment variable, unlike most other variables it is:
Not inherited from the parent process. Instead, it is populated by Nushell itself with certain defaults.
Not exported to child processes started by Nushell.
To examine the current settings in $env.config, just type the variable name:
$env.config
::: tip
Since Nushell provides so many customization options, it may be better to send this to a pager like:
$env.config | table -e | less -R# or, if bat is installed:$env.config | table -e | bat -p
:::
An appendix documenting each setting will be available soon. In the meantime, abbreviated documentation on each setting can be viewed in Nushell using:
config nu --doc | nu-highlight | bat
# or
config nu --doc | nu-highlight | less -R
To avoid overwriting existing settings, it's best to simply assign updated values to the desired configuration keys, rather than the entire config record. In other words:
::: warning Wrong
$env.config = {
show_banner: false
}
This would reset any other settings that had been changed, since the entire record would be overwritten.
:::
::: tip Right
$env.config.show_banner = false
This changes only the show_banner key/value pair, leaving all other keys with their existing values.
:::
Certain keys are themselves also records. It's okay to overwrite these records, but it's best-practice
to set all values when doing so. For example:
:::note
This section is linked directly from the banner message, so it repeats some information from above.
:::
To remove the welcome message that displays each time Nushell starts:
Type config nu to edit your configuration file.
If you receive an error regarding the editor not being defined:
$env.config.buffer_editor =<path to your preferred editor># Such as:$env.config.buffer_editor ="code"$env.config.buffer_editor ="vi"# Or with editor arguments:$env.config.buffer_editor = ["emacsclient","-s","light","-t"]
Then repeat step 1.
Add the following line to the end of the file:
$env.config.show_banner = false
Save and exit your editor.
Restart Nushell to test the change.
Additional Startup Configuration
Changing default directories
::: warning Important
As discussed below, variables in this section must be set before Nushell is launched.
:::
Some variables that control Nushell startup file locations must be set before Nushell is loaded. This is often done by a parent process such as:
The terminal application in which Nushell is run
The operating system or window manager. When running Nushell as a login shell, this will likely be the only mechanism available.
For example, on Windows, you can set environment variables through the Control Panel. Choose the Start Menu and search for "environment variables".
On Linux systems using PAM, /etc/environment (and other system-specific mechanisms) can be used.
A parent shell. For example, exporting the value from bash before running nu.
Startup Variables
The variables that affect Nushell file locations are:
$env.XDG_CONFIG_HOME: If this environment variable is set, it is used to change the directory that Nushell searches for its configuration files such as env.nu, config.nu, login.nu, and the <config>/autoload directory. The history and plugin files are also stored in this directory by default.
Once Nushell starts, this value is stored in the $nu.default-config-dir constant. See Using Constants below.
$env.XDG_DATA_HOME: If this environment variable is set, Nushell sets the $nu.data-dir constant to this value. The data-dir is used in several startup tasks:
($nu.data-dir)/completions is added to the $env.NU_LIB_DIRS search path.
($nu.data-dir)/vendor/autoload is added as the last path in nu.vendor-autoload-dirs. Files in this directory will be read after the other vendor-auto-load directories, thus overriding any of their settings.
Note that the directory represented by $nu.data-dir, nor any of its subdirectories, are created by default. Creation and use of these directories is up to the user.
$env.XDG_DATA_DIRS(Unix Platforms Only): If this environment variable is set, it is used to populate the $nu.vendor-auto-load directories in the order listed. The first directory in the list is processed first, meaning the last one read will have the ability to override previous definitions.
::: warning
The XDG_* variables are not Nushell-specific and should not be set to a directory with only Nushell files. Instead, set the environment variable to the directory above the one with the nushell directory.
For example, if you set $env.XDG_CONFIG_HOME to:
/users/username/dotfiles/nushell
... Nushell will look for config files in /Users/username/dotfiles/nushell/nushell. The proper setting would be:
/users/username/dotfiles
Also keep in mind that if the system has already set XDG variables, then there may already be files in use in those directories. Changing the location may require that you move other application's files to the new directory.
:::
::: tip
You can easily test out config changes in a "fresh" environment using the following recipe. The following is run from inside Nushell, but can be
adapted to other shells as well:
# Create an empty temporary directorylet temp_home = (mktemp -d)
# Set the configuration path to this directory$env.XDG_CONFIG_HOME=$temp_home# Set the data-dir to this directory$env.XDG_DATA_HOME=$temp_home# Remove other potential autoload directories$env.XDG_DATA_HOME=""# Run Nushell in this environment
nu
# Edit config
config nu
# Exit the subshell
exit
# Run the temporary config
nu
When done testing the configuration:
# Remove the temporary config directory, if desired
rm $temp_home
Important: Then exit the parent shell so that the XDG changes are not accidentally propagated to other processes.
:::
Using Constants
Some important commands, like source and use, that help define custom commands (and other definitions) are parse-time keywords. Among other things, this means that all arguments must be known at parse-time.
In other words, variable arguments are not allowed for parser keywords.
However, Nushell creates some convenience constants that can be used to help identify common file locations. For instance, you can source a file in the default configuration directory using:
To see a list of the built-in Nushell constants, examine the record constant using $nu (including the dollar sign).
NU_LIB_DIRS Constant
Nushell can also make use of a NU_LIB_DIRSconstant which can act like the $env.NU_LIB_DIRS variable mentioned above. However, unlike $env.NU_LIB_DIRS, it can be defined and used in config.nu. For example:
# Define module and source search path
const NU_LIB_DIRS= [
'~/myscripts']# Load myscript.nu from the ~/myscripts directory
source myscript.nu
If both the variable $env.NU_LIB_DIRS and the const NU_LIB_DIRS are defined, both sets
of paths will be searched. The constant NU_LIB_DIRS will be searched first and have
precedence. If a file matching the name is found in one of those directories, the search will
stop. Otherwise, it will continue into the $env.NU_LIB_DIRS search path.
NU_PLUGIN_DIRS Constant
const NU_PLUGIN_DIRS works in the same way for the plugin search path.
The following NU_PLUGIN_DIRS configuration will allow plugins to be loaded from;
The directory where the nu executable is located. This is typically where plugins are located in release packages.
A directory in $nu.data-dirs named after the version of Nushell running (e.g. 0.100.0).
You can learn more about setting up colors and theming in the associated chapter.
Configuring Nu as a Login Shell
The login shell is often responsible for setting certain environment variables which will be inherited by subshells and other processes. When setting Nushell as a user's default login shell, you'll want to make sure that the login.nu handles this task.
Many applications will assume a POSIX or PowerShell login shell, and will either provide instructions for modifying the system or user profile that is loaded by POSIX login-shells (or .ps1 file on PowerShell systems).
As you may have noticed by now, Nushell is not a POSIX shell, nor is it PowerShell, and it won't be able to process a profile written for these. You'll need to set these values in login.nu instead.
To find environment variables that may need to be set through login.nu, examine the inherited environment from your login shell by running nu from within your previous login shell. Run:
$env| reject config | transpose key val | each {|r| echo $"$env.($r.key) = '($r.val)'"} | str join (char nl)
Look for any values that may be needed by third-party applications and copy these to your login.nu. Many of these will not be needed. For instance, the PS1 setting is the current prompt in POSIX shells and won't be useful in Nushell.
When ready, add Nushell to your /etc/shells (Unix) and chsh as discussed in the Installation Chapter.
macOS: Keeping /usr/bin/open as open
Some tools such as Emacs rely on an open command to open files on Mac.
Since Nushell has its own open command with a different meaning which shadows (overrides) /usr/bin/open, these tools will generate an error when trying to use the command.
One way to work around this is to define a custom command for Nushell's open and create an alias for the system's open in your config.nu file like this:
alias nu-open = open
alias open = ^open
Place this in your config.nu to make it permanent.
The ^ symbol tells Nushell to run the following command as an external command, rather than as a Nushell built-in. After running these commands, nu-open will be the Nushell internal version, and the open alias will call the Mac, external open instead.
This section contains a more detailed description of how different configuration (and flag) options can be used to
change Nushell's startup behavior.
Launch Stages
The following stages and their steps may occur during startup, based on the flags that are passed to nu. See Flag Behavior immediately following this table for how each flag impacts the process:
Step
Stage
Nushell Action
0.
(misc)
Sets internal defaults via its internal Rust implementation. In practice, this may not take place until "first use" of the setting or variable, but there will typically be a Rust default for most (but not all) settings and variables that control Nushell's behavior. These defaults can then be superseded by the steps below.
1.
(main)
Inherits its initial environment from the calling process. These will initially be converted to Nushell strings, but can be converted to other structures later using ENV_CONVERSIONS (see below).
2.
(main)
Gets the configuration directory. This is OS-dependent (see dirs::config_dir), but can be overridden using XDG_CONFIG_HOME on all platforms as discussed above.
3.
(main)
Creates the initial $env.NU_LIB_DIRS variable. By default, it is an empty list.
4.
(main)
Creates the initial $NU_LIB_DIRS variable. By default, it includes (1) the scripts directory under the configuration directory, and (2) nushell/completions under the default data directory (either $env.XDG_DATA_HOME or the default provided by the dirs crate). These directories are not created by default.
5.
(main)
Creates the initial $env.NU_PLUGIN_DIRS variable. By default, it is an empty list.
6.
(main)
Creates the initial $NU_PLUGIN_DIRS variable. By default, this will include (1) the plugins directory under the configuration directory, and (2) the directory where the currently running nu/nu.exe is located.
7.
(main)
Initializes the in-memory SQLite database. This allows the stor family of commands to be used in the following configuration files.
8.
(main)
Processes commandline arguments such as --plugin-config <file>, --plugins <list>, and others. See nu --help for a complete list.
9.
(main)
Gets the path to env.nu and config.nu. By default, these are located in the config directory, but either or both can be overridden using the --env-config <path> and --config <path> flags.
10.
(main)
If the --include-path (-I) flag was used, it overrides the default $env.NU_LIB_DIRS that was obtained above.
11.
(main)
Loads the initial $env.config values from the internal defaults.
12.
(main)
Converts the search path from the inherited string to a Nushell list.
13.
(stdlib)
Loads the Standard Library and std-rfc into the virtual filesystem. It is not parsed or evaluated at this point.
14.
(stdlib)
Parses and evaluates std/prelude, which brings the banner and pwd commands into scope.
15.
(main)
Generates the initial $nu record constant so that items such as $nu.default-config-dir can be used in the following config files.
16.
(main)
Loads any plugins that were specified using the --plugin flag.
17.
(repl)
Sets several default environment variables that only apply in the REPL (prompt-related and SHLVL). Note that prompt-related variables using closures are set in default_env.nu.
18.
(config files) (plugin)
Processes the signatures in the user's plugin.msgpackz (located in the configuration directory) so that added plugins can be used in the following config files.
19.
(config files)
If this is the first time Nushell has been launched, then it creates the configuration directory. "First launch" is determined by whether or not the configuration directory exists.
20.
(config files)
Also, if this is the first time Nushell has been launched, creates a mostly empty (other than a few comments) env.nu and config .nu in that directory.
21.
(config files) (default_env.nu)
Loads default environment variables from the internal default_env.nu. This file can be viewed with: config env --default | nu-highlight | less -R.
22.
(config files) (env.nu)
Converts the PATH variable into a list so that it can be accessed more easily in the next step.
23.
(config files) (env.nu)
Loads (parses and evaluates) the user's env.nu (the path to which was determined above).
24.
(config files) (config.nu)
Loads a minimal $env.config record from the internal default_config.nu. This file can be viewed with: config nu --default | nu-highlight | less -R. Most values that are not defined in default_config.nu will be auto-populated into $env.config using their internal defaults as well.
25.
(config files) (config.nu)
Loads (parses and evaluates) the user's config.nu (the path to which was determined above).
26.
(config files) (login)
When Nushell is running as a login shell, loads the user's login.nu.
27.
(config files)
Loops through the vendor autoload directories and loads any .nu files found. The directories are processed in the order found in $nu.vendor-autoload-dirs, and files in those directories are processed in alphabetical order.
28.
(config files)
Loops through the user autoload directories and loads any .nu files found. The directories are processed in the order found in $nu.user-autoload-dirs, and files in those directories are processed in alphabetical order.
29.
(repl) and (stdlib)
Shows the banner if configured.
29.
(repl)
Nushell enters the normal commandline (REPL).
Flag Behavior
Mode
Command/Flags
Behavior
Normal Shell
nu (no flags)
All launch steps except those marked with (login) occur.
Login Shell
nu --login/-l
All launch steps occur.
Command-string
nu --commands <command-string> (or -c)
All Launch stages except those marked with (config files) or (repl) occur. However, (default_env) and (plugin) do occur. The first allows the path ENV_CONVERSIONS defined there can take place. The second allows plugins to be used in the command-string.
Script file
nu <script_file>
Same as with Command-string.
No config
nu -n
(config files) stages do not occur, regardless of other flags.
No Standard Library
nu --no-std-lib
Regardless of other flags, the steps marked (stdlib) will not occur.
Force config file
nu --config <file>
Forces steps marked with (config.nu) above to run with the provided config <file>, unless -n was also specified
Force env file
nu --env-config <file>
Forces steps marked with (default_env.nu) and (env.nu) above to run with the specified env <file>, unless -n was also specified
Scenarios
nu:
✅ Makes the Standard Library available
✅ Reads user's plugin.msgpackz file if it exists in the config directory
✅ Sources the default_env.nu file internally
✅ Sources the user's env.nu file if it exists in the config directory
✅ Sources the default_config.nu file internally
✅ Sources user's config.nu file if it exists if it exists in the config directory
❌ Does not read personal login.nu file
✅ Enters the REPL
nu -c "ls":
✅ Makes the Standard Library available
✅ Reads user's plugin.msgpackz file if it exists in the config directory
✅ Sources the default_env.nu file internally
❌ Does not source the user's env.nu
❌ Does not read the internal default_config.nu file
❌ Does not read the user's config.nu file
❌ Does not read the user's login.nu file
✅ Runs the ls command and exits
❌ Does not enter the REPL
nu -l -c "ls":
✅ Makes the Standard Library available
✅ Reads user's plugin.msgpackz file if it exists in the config directory
✅ Sources the default_env.nu file internally
✅ Sources the user's env.nu file if it exists in the config directory
✅ Sources the default_config.nu file internally
✅ Sources user's config.nu file if it exists in the config directory
✅ Sources the user's login.nu file if it exists in the config directory
✅ Runs the ls command and exits
❌ Does not enter the REPL
nu -l -c "ls" --config foo_config.nu
Same as above, but reads an alternative config file named foo_config.nu from the config directory
nu -n -l -c "ls":
✅ Makes the Standard Library available
❌ Does not read user's plugin.msgpackz
❌ Does not read the internal default_env.nu
❌ Does not source the user's env.nu
❌ Does not read the internal default_config.nu file
❌ Does not read the user's config.nu file
❌ Does not read the user's login.nu file
✅ Runs the ls command and exits
❌ Does not enter the REPL
nu test.nu:
✅ Makes the Standard Library available
✅ Reads user's plugin.msgpackz file if it exists in the config directory
✅ Sources the default_env.nu file internally
❌ Does not source the user's env.nu
❌ Does not read the internal default_config.nu file
❌ Does not read the user's config.nu file
❌ Does not read the user's login.nu file
✅ Runs test.nu file as a script
❌ Does not enter the REPL
nu --config foo_config.nu test.nu
✅ Makes the Standard Library available
✅ Reads user's plugin.msgpackz file if it exists in the config directory
✅ Sources the default_env.nu file internally
❌ Does not source the user's env.nu (no --env-config was specified)
✅ Sources the default_config.nu file internally. Note that default_config.nu is always handled before a user's config
✅ Sources user's config.nu file if it exists in the config directory
❌ Does not read the user's login.nu file
✅ Runs test.nu file as a script
❌ Does not enter the REPL
nu -n --no-std-lib (fastest REPL startup):
❌ Does not make the Standard Library available
❌ Does not read user's plugin.msgpackz
❌ Does not read the internal default_env.nu
❌ Does not source the user's env.nu
❌ Does not read the internal default_config.nu file
❌ Does not read the user's config.nu file
❌ Does not read the user's login.nu file
✅ Enters the REPL
nu -n --no-std-lib -c "ls" (fastest command-string invocation):
❌ Does not make the Standard Library available
❌ Does not read user's plugin.msgpackz
❌ Does not read the internal default_env.nu
❌ Does not source the user's env.nu
❌ Does not read the internal default_config.nu file
❌ Does not read the user's config.nu file
❌ Does not read the user's login.nu file
✅ Runs the ls command and exits
❌ Does not enter the REPL
`book/control_flow.md`:
```md
# Control Flow
Nushell provides several commands that help determine how different groups of code are executed. In programming languages this functionality is often referred to as _control flow_.
::: tip
One thing to note is that all of the commands discussed on this page use [blocks](/book/types_of_data.html#blocks). This means you can mutate [environmental variables](/book/environment.html) and other [mutable variables](/book/variables.html#mutable-variables) in them.
:::
## Already covered
Below we cover some commands related to control flow, but before we get to them, it's worthwhile to note there are several pieces of functionality and concepts that have already been covered in other sections that are also related to control flow or that can be used in the same situations. These include:
- Pipes on the [pipelines](/book/pipelines.html) page.
- Closures on the [types of data](/book/types_of_data.html) page.
- Iteration commands on the [working with lists](/book/working_with_lists.html) page. Such as:
- [`each`](/commands/docs/each.html)
- [`where`](/commands/docs/where.html)
- [`reduce`](/commands/docs/reduce.html)
## Choice (Conditionals)
The following commands execute code based on some given condition.
::: tip
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
:::
if
if evaluates branching blocks of code based on the results of one or more conditions similar to the "if" functionality in other programming languages. For example:
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).
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:
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).
We can also chain multiple ifs together like the following:
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).
match
match executes one of several conditional branches based on the value given to match. You can also do some pattern matching to unpack values in composite types like lists and records.
Basic usage of match can conditionally run different code like a "switch" statement common in other languages. match checks if the value after the word match 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 =>.
match 3 {
1=> 'one',2=> {
let w ='w''t'+$w+'o'
},3=> 'three',4=> 'four'
}
# => three
The branches can either return a single value or, as shown in the second branch, can return the results of a block.
Catch all 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 _.
let foo = match 7 {
1=> 'one',2=> 'two',3=> 'three',
_ => 'other number'
}
$foo# => other number
(Reminder, match is an expression which is why we can assign the result to $foo here).
Pattern Matching
You can "unpack" values from types like lists and records with pattern matching. You can then assign variables to the parts you want to unpack and use them in the matched expressions.
The _ in the second branch means it matches any record with field name and count, not just ones where name is 'bar'.
Guards
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 =>.
The loop commands allow you to repeat a block of code multiple times.
Loops and Other Iterating Commands
The functionality of the loop commands is similar to commands that apply a closure over elements in a list or table like each or where and many times you can accomplish the same thing with either. For example:
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 (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.
Loop Disadvantages
The biggest downside of loops is that they are statements, unlike each which is an expression. Expressions, like each always result in some output value, however statements do not.
This means that they don't work well with immutable variables and using immutable variables is considered a more Nushell-style. Without a mutable variable declared beforehand in the example in the previous section, it would be impossible to use for to get the list of numbers with incremented numbers, or any value at all.
Statements also don't work in Nushell pipelines which require some output. In fact Nushell will give an error if you try:
[123] |for x in $in { $x+1 } |$in++ [567]
# => 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 is typically more natural than loop statements.
Loop Advantages
If loops have such a big disadvantage, why do they exist? Well, one reason is that closures, like each 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:
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 which means they can modify a regular mutable variable or an environmental variable within the larger scope.
loop loops a block infinitely. You can use break (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.
break will stop executing the code in a loop and resume execution after the loop. Effectively "break"ing out of the loop.
for x in 1..10 { if$x>3 { break }; print $x }# => 1# => 2# => 3
continue
continue 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 has iterated through all the given elements, or if while's condition is now false, it won't loop again and execution will continue after the loop block.
mut x =-1; while $x <= 6 { $x = $x + 1; if $x mod 3 == 0 { continue }; print $x }# => 1# => 2# => 4# => 5# => 7
Errors
error make
error make creates an error that stops execution of the code and any code that called it, until either it is handled by a try block, or it ends the script and outputs the error message. This functionality is the same as "exceptions" in other languages.
The resulting value will be nothing if an error occurs and the returned value of the block if an error did not occur.
If you include a catch block after the try block, it will execute the code in the catch block if an error occurred in the try block.
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.
try also works for external commands:
try { ^nonexisting }; print 'a'# => a
^nonexisting; print 'a'# => Error: nu::shell::external_command# => # => × External command failed# => ╭─[entry #3:1:2]# => 1 │ ^nonexisting; print 'a'# => · ─────┬─────# => · ╰── Command `nonexisting` not found# => ╰────# => help: `nonexisting` is neither a Nushell built-in or a known external command
Other
return
return Ends a closure or command early where it is called, without running the rest of the command/closure, and returns the given value. Not often necessary since the last value in a closure or command is also returned, but it can sometimes be convenient.
`book/creating_errors.md`:
```md
# Creating Your Own Errors
Using the [metadata](metadata.md) information, you can create your own custom error messages. Error messages are built of multiple parts:
- The title of the error
- The label of error message, which includes both the text of the label and the span to underline
You can use the [`error make`](/commands/docs/error_make.md) command to create your own error messages. For example, let's say you had your own command called `my-command` and you wanted to give an error back to the caller about something wrong with a parameter that was passed in.
First, you can take the span of where the argument is coming from:
```nu
let span = (metadata $x).span;
Next, you can create an error using the error make command. This command takes in a record that describes the error to create:
error make {msg: "this is fishy", label: {text: "fish right here", span: $span } }
Together with your custom command, it might look like this:
def my-command [x] {
let span = (metadata $x).span;
error make {
msg: "this is fishy",
label: {
text: "fish right here",
span: $span
}
}
}
When called with a value, we'll now see an error message returned:
my-command 100# => Error:# => × this is fishy# => ╭─[entry #5:1:1]# => 1 │ my-command 100# => · ─┬─# => · ╰── fish right here# => ╰────
`book/custom_commands.md`:
```md
---
prev:
text: Programming in Nu
link: /book/programming_in_nu.md
---
# Custom Commands
As with any programming language, you'll quickly want to save longer pipelines and expressions so that you can call them again easily when needed.
This is where custom commands come in.
::: tip Note
Custom commands are similar to functions in many languages, but in Nushell, custom commands _act as first-class commands themselves_. As you'll see below, they are included in the Help system along with built-in commands, can be a part of a pipeline, are parsed in real-time for type errors, and much more.
:::
[[toc]]
## Creating and Running a Custom Command
Let's start with a simple `greet` custom command:
```nu
def greet [name] {
$"Hello, ($name)!"
}
Here, we define the greet command, which takes a single parameter name. Following this parameter is the block that represents what will happen when the custom command runs. When called, the custom command will set the value passed for name as the $name variable, which will be available to the block.
To run this command, we can call it just as we would call built-in commands:
greet "World"# => Hello, World!
Returning Values from Commands
You might notice that there isn't a return or echo statement in the example above.
Like some other languages, such as PowerShell and JavaScript (with arrow functions), Nushell features an implicit return, where the value of the final expression in the command becomes its return value.
In the above example, there is only one expression—The string. This string becomes the return value of the command.
greet "World"| describe
# => string
A typical command, of course, will be made up of multiple expressions. For demonstration purposes, here's a non-sensical command that has 3 expressions:
def eight [] {
1+12+24+4
}
eight
# => 8
The return value, again, is simply the result of the final expression in the command, which is 4 + 4 (8).
Additional examples:
::: details Early return
Commands that need to exit early due to some condition can still return a value using the return statement.
def process-list [] {
let input_length = length
if$input_length> 10_000 {
print"Input list is too long"return null
}
$in| each {|i|# Process the list$i*4.25
}
}
:::
::: details Suppressing the return value
You'll often want to create a custom command that acts as a statement rather than an expression, and doesn't return a value.
Without the ignore at the end of the pipeline, the command will return an empty list from the each statement.
You could also return a null as the final expression. Or, in this contrived example, use a for statement, which doesn't return a value (see next example).
:::
::: details Statements which don't return a value
Some keywords in Nushell are statements which don't return a value. If you use one of these statements as the final expression of a custom command, the return value will be null. This may be unexpected in some cases. For example:
def exponents-of-three [] {
for x in [ 012345 ] {
3**$x
}
}
exponents-of-three
The above command will not display anything, and the return value is empty, or null because for is a statement which doesn't return a value.
To return a value from an input list, use a filter such as the each command:
def exponents-of-three [] {
[ 012345 ] | each {|x|3**$x
}
}
exponents-of-three
# => ╭───┬─────╮# => │ 0 │ 1 │# => │ 1 │ 3 │# => │ 2 │ 9 │# => │ 3 │ 27 │# => │ 4 │ 81 │# => │ 5 │ 243 │# => ╰───┴─────╯
:::
::: details Match expression
```nu
# Return a random file in the current directory
def "random file" [] {
let files = (ls)
let num_files = ($files| length)
match $num_files {
0=> null # Return null for empty directory
_ => {
let random_file = (random int 0..($num_files-1))
($files| get $random_file)
}
}
}
In this case, the final expression is the match statement which can return:
null if the directory is empty
Otherwise, a record representing the randomly chosen file
:::
Custom Commands and Pipelines
Just as with built-in commands, the return value of a custom command can be passed into the next command in a pipeline. Custom commands can also accept pipeline input. In addition, whenever possible, pipeline input and output is streamed as it becomes available.
This lets us easily build custom commands and process their output. Remember that we don't use return statements like other languages. Instead, the implicit return allows us to build pipelines that output streams of data that can be connected to other pipelines.
::: tip Note
The ls content is still streamed in this case, even though it is in a separate command. Running this command against a long-directory on a slow (e.g., networked) filesystem would return rows as they became available.
:::
Pipeline Input
Custom commands can also take input from the pipeline, just like other commands. This input is automatically passed to the custom command's block.
Let's make our own command that doubles every value it receives as input:
def double [] {
each { |num|2*$num }
}
Now, if we call the above command later in a pipeline, we can see what it does with the input:
::: tip Cool!
This command demonstrates both input and output streaming. Try running it with an infinite input:
1..| each {||} | double
Even though the input command hasn't ended, the double command can still receive and output values as they become available.
Press Ctrl+C to stop the command.
:::
We can also store the input for later use using the $in variable:
def nullify [...cols] {
let start =$in$cols| reduce --fold $start { |col, table|$table| upsert $col null
}
}
ls | nullify name size
# => ╭───┬──────┬──────┬──────┬───────────────╮# => │ # │ name │ type │ size │ modified │# => ├───┼──────┼──────┼──────┼───────────────┤# => │ 0 │ │ file │ │ 8 minutes ago │# => │ 1 │ │ file │ │ 8 minutes ago │# => │ 2 │ │ file │ │ 8 minutes ago │# => ╰───┴──────┴──────┴──────┴───────────────╯
Naming Commands
In Nushell, a command name can be a string of characters. Here are some examples of valid command names: greet, get-size, mycommand123, my command, 命令 (English translation: "command"), and even 😊.
Strings which might be confused with other parser patterns should be avoided. For instance, the following command names might not be callable:
1, "1", or "1.5": Nushell will not allow numbers to be used as command names
4MiB or "4MiB": Nushell will not allow filesizes to be used as command names
"number#four" or "number^four": Carets and hash symbols are not allowed in command names
-a, "{foo}", "(bar)": Will not be callable, as Nushell will interpret them as flags, closures, or expressions.
While names like "+foo" might work, they are best avoided as the parser rules might change over time. When in doubt, keep command names as simple as possible.
::: tip
It's common practice in Nushell to separate the words of the command with - for better readability. For example get-size instead of getsize or get_size.
:::
::: tip
Because def is a parser keyword, the command name must be known at parse time. This means that command names may not be a variable or constant. For example, the following is not allowed:
let name ="foo"
def $name [] { foo }
:::
Subcommands
You can also define subcommands of commands using a space. For example, if we wanted to add a new subcommand to str, we can create it by naming our subcommand starting with "str ". For example:
def "str mycommand" [] {
"hello"
}
Now we can call our custom command as if it were a built-in subcommand of str:
str mycommand
Of course, commands with spaces in their names are defined in the same way:
def "custom command" [] {
"This is a custom command with a space in the name!"
}
Parameters
Multiple parameters
In the def command, the parameters are defined in a list. This means that multiple parameters can be separated with spaces, commas, or line-breaks.
For example, here's a version of greet that accepts two names. Any of these three definitions will work:
The basic argument definitions used above are positional. The first argument passed into the greet command above is assigned to the name1 parameter (and, as mentioned above, the $name1 variable). The second argument becomes the name2 parameter and the $name2 variable.
By default, positional parameters are required. Using our previous definition of greet with two required, positional parameters:
::: tip
Try typing a third name after this version of greet. Notice that the parser automatically detects the error and highlights the third argument as an error even before execution.
:::
Optional Positional Parameters
We can define a positional parameter as optional by putting a question mark (?) after its name. For example:
::: tip
Notice that the name used to access the variable does not include the ?; only its definition in the command signature.
:::
When an optional parameter is not passed, its value in the command body is equal to null. The above example uses the default command to provide a default of "You" when name is null.
You could also compare the value directly:
def greet [name?: string] {
match $name {
null =>"Hello! I don't know your name!"
_ => $"Hello, ($name)!"
}
}
greet
# => Hello! I don't know your name!
If required and optional positional parameters are used together, then the required parameters must appear in the definition first.
Parameters with a Default Value
You can also set a default value for the parameter when it is missing. Parameters with a default value are also optional when calling the command.
You can also combine a default value with a type annotation:
def congratulate [age: int =18] {
$"Happy birthday! You are ($age) years old now!"
}
Parameter Types
For each parameter, you can optionally define its type. For example, you can write the basic greet command as:
def greet [name: string] {
$"Hello, ($name)"
}
If a parameter is not type-annotated, Nushell will treat it as an any type. If you annotate a type on a parameter, Nushell will check its type when you call the function.
For example, let's say you wanted to only accept an int instead of a string:
def greet [name: int] {
$"hello ($name)"
}
greet World
If we try to run the above, Nushell will tell us that the types don't match:
Error: nu::parser::parse_mismatch
× Parse mismatch during operation.
╭─[entry #1:1:7]1 │ greet World
· ──┬──
· ╰── expected int
╰────
::: tip Cool!
Type checks are a parser feature. When entering a custom command at the command-line, the Nushell parser can even detect invalid argument types in real-time and highlight them before executing the command.
The highlight style can be changed using a theme or manually using $env.config.color_config.shape_garbage.
:::
::: details List of Type Annotations
Most types can be used as type-annotations. In addition, there are a few "shapes" which can be used. For instance:
number: Accepts either an int or a float
path: A string where the ~ and . characters have special meaning and will automatically be expanded to the full-path equivalent. See Path in the Language Reference Guide for example usage.
directory: A subset of path (above). Only directories will be offered when using tab-completion for the parameter. Expansions take place just as with path.
error: Available, but currently no known valid usage. See Error in the Language Reference Guide for more information.
The following types can be used for parameter annotations:
any
binary
bool
cell-path
closure
datetime
duration
filesize
float
glob
int
list
nothing
range
record
string
table
:::
Flags
In addition to positional parameters, you can also define named flags.
In this version of greet, we define the name positional parameter as well as an age flag. The positional parameter (since it doesn't have a ?) is required. The named flag is optional. Calling the command without the --age flag will set $age to null.
The --age flag can go before or after the positional name. Examples:
greet Lucia--age 23# => ╭──────┬───────╮# => │ name │ Lucia │# => │ age │ 23 │# => ╰──────┴───────╯
greet --age 39Ali# => ╭──────┬─────╮# => │ name │ Ali │# => │ age │ 39 │# => ╰──────┴─────╯
greet World# => ╭──────┬───────╮# => │ name │ World │# => │ age │ │# => ╰──────┴───────╯
Flags can also be defined with a shorthand version. This allows you to pass a simpler flag as well as a longhand, easier-to-read flag.
Let's extend the previous example to use a shorthand flag for the age value:
::: tip
The resulting variable is always based on the long flag name. In the above example, the variable continues to be $age. $a would not be valid.
:::
Now, we can call this updated definition using the shorthand flag:
greet Akosua-a 35# => ╭──────┬────────╮# => │ name │ Akosua │# => │ age │ 35 │# => ╰──────┴────────╯
Flags can also be used as basic switches. When present, the variable based on the switch is true. When absent, it is false.
There may be cases when you want to define a command which takes any number of positional arguments. We can do this with a "rest" parameter, using the following ... syntax:
We could call the above definition of the greet command with any number of arguments, including none at all. All of the arguments are collected into $names as a list.
Rest parameters can be used together with positional parameters:
def vip-greet [vip: string,...names: string] {
for$name in $names {
print $"Hello, ($name)!"
}
print $"And a special welcome to our VIP today, ($vip)!"
}
# $vip $name# ----- -------------------------
vip-greet RahulPriyaArjunAnjaliVikram# => Hello, Priya!# => Hello, Arjun!# => Hello, Anjali!# => Hello, Vikram!# => And a special welcome to our VIP today, Rahul!
To pass a list to a rest parameter, you can use the spread operator (...). Using the vip-greet command definition above:
let vip ="Tanisha"let guests = [ Dwayne,Shanice,Jerome ]
vip-greet $vip...$guests# => Hello, Dwayne!# => Hello, Shanice!# => Hello, Jerome!# => And a special welcome to our VIP today, Tanisha!
Rest Parameters with Wrapped External Commands
Custom commands defined with def --wrapped will collect any unknown flags and arguments into a
rest-parameter which can then be passed, via list-spreading, to an external command. This allows
a custom command to "wrap" and extend the external command while still accepting all of its original
parameters. For example, the external eza command displays a directory listing. By default, it displays
a grid arrangement:
eza commands
# => categories docs README.md
We can define a new command ezal which will always display a long-listing, adding icons:
def --wrapped ezal [...rest] {
eza -l ...$rest
}
:::note
You could also add --icons. We're omitting that in this example simply because those icons don't
display well in this guide.
:::
Notice that --wrapped forces any additional parameters into the rest parameter, so the command
can be called with any parameter that eza supports. Those additional parameters will be expanded via
the list-spreading operation ...$rest.
ezal commands
# => drwxr-xr-x - ntd 7 Feb 11:41 categories# => drwxr-xr-x - ntd 7 Feb 11:41 docs# => .rw-r--r-- 936 ntd 14 Jun 2024 README.md
ezal -d commands
# => drwxr-xr-x - ntd 14 Jun 2024 commands
The custom command can check for certain parameters and change its behavior accordingly. For instance,
when using the -G option to force a grid, we can omit passing a -l to eza:
By default, custom commands accept <any> type as pipeline input and likewise can output <any> type. But custom commands can also be given explicit signatures to narrow the types allowed.
For example, the signature for str stats looks like this:
def "str stats" []: string -> record { }
Here, string -> record defines the allowed types of the pipeline input and output of the command:
It accepts a string as pipeline input
It outputs a record
If there are multiple input/output types, they can be placed within brackets and separated with commas or newlines, as in str join:
This indicates that str join can accept either a list<any> or a string as pipeline input. In either case, it will output a string.
Some commands don't accept or require data as pipeline input. In this case, the input type will be <nothing>. The same is true for the output type if the command returns null (e.g., rm or hide):
And attempting to pass an invalid type into a command:
def inc []: int -> int { $in+1 }
"Hi"| inc
# => Error: nu::parser::input_type_mismatch# =># => × Command does not support string input.# => ╭─[entry #1:1:8]# => 1 │ "Hi" | inc# => · ─┬─# => · ╰── command doesn't support string input# => ╰────
:::
Documenting Your Command
In order to best help users understand how to use your custom commands, you can also document them with additional descriptions for the commands and parameters.
Run help vip-greet to examine our most recent command defined above:
Usage:
> vip-greet <vip> ...(names)
Flags:
-h, --help - Display the help message for this command
Parameters:
vip <string>
...names <string>
Input/output types:
╭───┬───────┬────────╮
│ # │ input │ output │
├───┼───────┼────────┤
│ 0 │ any │ any │
╰───┴───────┴────────╯
::: tip Cool!
You can see that Nushell automatically created some basic help for the command simply based on our definition so far. Nushell also automatically adds a --help/-h flag to the command, so users can also access the help using vip-greet --help.
:::
We can extend the help further with some simple comments describing the command and its parameters:
# Greet guests along with a VIP## Use for birthdays, graduation parties,# retirements, and any other event which# celebrates an event # for a particular# person.
def vip-greet [
vip: string # The special guest...names: string # The other guests
] {
for$name in $names {
print $"Hello, ($name)!"
}
print $"And a special welcome to our VIP today, ($vip)!"
}
Now run help vip-greet again to see the difference:
Greet guests along with a VIP
Use for birthdays, graduation parties,
retirements, and any other event which
celebrates an event # for a particular
person.
Category: default
This command:
- does not create a scope.
- is not a built-in command.
- is not a subcommand.
- is not part of a plugin.
- is a custom command.
- is not a keyword.
Usage:
> vip-greet <vip>
Flags:
-h, --help - Display the help message for this command
Signatures:
<any> | vip-greet[ <string>] -> <any>
Parameters:
vip: <string> The special guest
...rest: <string> The other guests
Notice that the comments on the lines immediately before the def statement become a description of the command in the help system. Multiple lines of comments can be used. The first line (before the blank-comment line) becomes the Help description. This information is also shown when tab-completing commands.
The remaining comment lines become its extra_description in the help data.
::: tip
Run:
scope commands
| where name == 'vip-greet'
| wrap help
This will show the Help record that Nushell creates.
:::
The comments following the parameters become their description. Only a single-line comment is valid for parameters.
::: tip Note
A Nushell comment that continues on the same line for argument documentation purposes requires a space before the # pound sign.
:::
Changing the Environment in a Custom Command
Normally, environment variable definitions and changes are scoped within a block. This means that changes to those variables are lost when they go out of scope at the end of the block, including the block of a custom command.
Likewise, changing the directory using the cd command results in a change of the $env.PWD environment variable. This means that directory changes (the $env.PWD variable) will also be reset when a custom command ends. The solution, as above, is to use def --env or export def --env.
def --env go-home [] {
cd ~
}
cd /go-homepwd# => Your home directory
Persisting
To make custom commands available in future Nushell sessions, you'll want to add them to your startup configuration. You can add command definitions:
`book/custom_completions.md`:
```md
# Custom Completions
Custom completions allow you to mix together two features of Nushell: custom commands and completions. With them, you're able to create commands that handle the completions for positional parameters and flag parameters. These custom completions work both for [custom commands](custom_commands.md) and [known external, or `extern`, commands](externs.md).
A completion is defined in two steps:
- Define a completion command (a.k.a. completer) that returns the possible values to suggest
- Attach the completer to the type annotation (shape) of another command's argument using `<shape>@<completer>`
Here's a simple example:
```nu
# Completion command
def animals [] { ["cat", "dog", "eel" ] }
# Command to be completed
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.
::: tip
To suppress completions for an argument (for example, an int that can accept any integer), define a completer that returns an empty list ([ ]).
:::
In the second line, string@animals tells Nushell two things—the shape of the argument for type-checking and the completer which will suggest possible values for the argument.
The third line is demonstration of the completion. Type the name of the custom command my-command, followed by a space, and then the Tab key. This displays a menu with the possible completions. Custom completions work the same as other completions in the system, allowing you to type e followed by the Tab key to complete "eel" automatically.
::: tip
When the completion menu is displayed, the prompt changes to include the | character by default. To change the prompt marker, modify the marker value of the record, where the name key is completion_menu, in the $env.config.menus list. See also the completion menu configuration.
:::
::: tip
To fall back to Nushell's built-in file completions, return null rather than a list of suggestions.
:::
Options for Custom Completions
If you want to choose how your completions are filtered and sorted, you can also return a record rather than a list. The list of completion suggestions should be under the completions key of this record. Optionally, it can also have, under the options key, a record containing the following optional settings:
sort - Set this to false to stop Nushell from sorting your completions. By default, this is true, and completions are sorted according to $env.config.completions.sort.
case_sensitive - Set to true for the custom completions to be matched case sensitively, false otherwise. Used for overriding $env.config.completions.case_sensitive.
completion_algorithm - Set this to prefix, substring, or fuzzy to choose how your completions are matched against the typed text. Used for overriding $env.config.completions.algorithm.
Here's an example demonstrating how to set these options:
Now, if you try to complete A, you get the following completions:
>| my-command A
cat rat bat
Because we made matching case-insensitive, Nushell will find the substring "a" in all of the completion suggestions. Additionally, because we set sort: false, the completions will be left in their original order. This is useful if your completions are already sorted in a particular order unrelated to their text (e.g. by date).
Modules and Custom Completions
Since completion commands aren't meant to be called directly, it's common to define them in modules.
In this module, only the the custom command my-command is exported. The animals completion is not exported. This allows users of this module to call the command, and even use the custom completion logic, without having access to the completion command itself. This results in a cleaner and more maintainable API.
::: tip
Completers are attached to custom commands using @ at parse time. This means that, in order for a change to the completion command to take effect, the public custom command must be reparsed as well. Importing a module satisfies both of these requirements at the same time with a single use statement.
:::
Context Aware Custom Completions
It is possible to pass the context to the completion command. This is useful in situations where it is necessary to know previous arguments or flags to generate accurate completions.
Applying this concept to the previous example:
module commands {
def animals [] {
["cat","dog","eel" ]
}
def animal-names [context: string] {
match ($context| split words | last) {
cat => ["Missy","Phoebe"]
dog => ["Lulu","Enzo"]
eel => ["Eww","Slippy"]
}
}
export def my-command [
animal: string@animals
name: string@animal-names
] {
print $"The ($animal) is named ($name)."
}
}
Here, the command animal-names returns the appropriate list of names. $context is a string where the value is the command-line that has been typed so far.
>| my-command
cat dog eel
>| my-command dog
LuluEnzo>my-command dog enzo
The dog is named Enzo
On the second line, after pressing the tab key, the argument "my-command dog" is passed to the animal-names completer as context.
::: tip
Completers can also obtain the current cursor position on the command-line using:
A powerful combination is adding custom completions to known extern commands. These work the same way as adding a custom completion to a custom command: by creating the custom completion and then attaching it with a @ to the type of one of the positional or flag arguments of the extern.
If you look closely at the examples in the default config, you'll see this:
export extern "git push" [
remote?: string@"nu-complete git remotes",# the name of the remote
refspec?: string@"nu-complete git branches"# the branch / refspec...
]
Custom completions will serve the same role in this example as in the previous examples. The examples above call into two different custom completions, based on the position the user is currently in.
Custom Descriptions and Styles
As an alternative to returning a list of strings, a completion function can also return a list of records with a value field as well as optional description and style fields. The style can be one of the following:
A string with the foreground color, either a hex code or a color name such as yellow. For a list of valid color names, see ansi --list.
A record with the fields fg (foreground color), bg (background color), and attr (attributes such as underline and bold). This record is in the same format that ansi --escape accepts. See the ansi command reference for a list of possible values for the attr field.
You can configure the closure to run an external completer, such as carapace.
An external completer is a function that takes the current command as a string list, and outputs a list of records with value and description keys, like custom completion functions. When the closure returns null, it defaults to file completion.
::: tip Note
This closure will accept the current command as a list. For example, typing my-command --arg1 <tab> will receive [my-command --arg1 " "].
:::
This example will enable carapace external completions:
let carapace_completer = {|spans|
carapace $spans.0 nushell ...$spans| from json
}
`book/dataframes.md`:
```md
# Dataframes
::: warning Important!
This feature requires the Polars plugin. See the
[Plugins Chapter](plugins.md) to learn how to install it.
To test that this plugin is properly installed, run `help polars`.
:::
As we have seen so far, Nushell makes working with data its main priority.
`Lists` and `Tables` are there to help you cycle through values in order to
perform multiple operations or find data in a breeze. However, there are
certain operations where a row-based data layout is not the most efficient way
to process data, especially when working with extremely large files. Operations
like group-by or join using large datasets can be costly memory-wise, and may
lead to large computation times if they are not done using the appropriate
data format.
For this reason, the `DataFrame` structure was introduced to Nushell. A
`DataFrame` stores its data in a columnar format using as its base the [Apache
Arrow](https://arrow.apache.org/) specification, and uses
[Polars](https://github.com/pola-rs/polars) as the motor for performing
extremely [fast columnar operations](https://h2oai.github.io/db-benchmark/).
You may be wondering now how fast this combo could be, and how could it make
working with data easier and more reliable. For this reason, we'll start this
chapter by presenting benchmarks on common operations that are done when
processing data.
[[toc]]
## Benchmark Comparisons
For this little benchmark exercise we will be comparing native Nushell
commands, dataframe Nushell commands and [Python
Pandas](https://pandas.pydata.org/) commands. For the time being don't pay too
much attention to the [`Dataframe` commands](/commands/categories/dataframe.md). They will be explained in later
sections of this page.
::: tip System Details
The benchmarks presented in this section were run using a Macbook with a processor M1 pro and 32gb of ram. All examples were run on Nushell version 0.97 using `nu_plugin_polars 0.97`.
:::
### File Information
The file that we will be using for the benchmarks is the
[New Zealand business demography](https://www.stats.govt.nz/assets/Uploads/New-Zealand-business-demography-statistics/New-Zealand-business-demography-statistics-At-February-2020/Download-data/Geographic-units-by-industry-and-statistical-area-2000-2020-descending-order-CSV.zip) dataset.
Feel free to download it if you want to follow these tests.
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 │
# => ╰──────────────────────────────────────┴───────────┴─────────┴─────────┴────────────────╯
::: tip
As of nushell 0.97, polars open will open as a lazy dataframe instead of a eager dataframe.
To open as an eager dataframe, use the --eager flag.
:::
We can have a look at the first lines of the file using first:
Not bad at all. Pandas managed to get it 2.6 times faster than Nushell.
And with bigger files, the superiority of Pandas should increase here.
To finish the comparison, let's try Nushell dataframes. We are going to put
all the operations in one nu file, to make sure we are doing the correct
comparison:
( 'polars open Data7602DescendingYearOrder.csv
| polars group-by year
| polars agg (polars col geo_count | polars sum)
| polars collect'
| save load.nu -f )
and the benchmark with dataframes (together with loading a new nushell and polars
instance for each test in order of honest comparison) is:
The polars dataframes plugin managed to finish operation 10 times
faster than pandas with python. Isn't that great?
As you can see, the Nushell's polars plugin is performant like polars itself.
Coupled with Nushell commands and pipelines, it is capable of conducting sophisticated
analysis without leaving the terminal.
Let's clean up the cache from the dataframes that we used during benchmarking.
To do that, let's stop the polars.
When we execute our next commands, we will start a new instance of plugin.
plugin stop polars
Working with Dataframes
After seeing a glimpse of the things that can be done with Dataframe commands,
now it is time to start testing them. To begin let's create a sample
CSV file that will become our sample dataframe that we will be using along with
the examples. In your favorite file editor paste the next lines to create out
sample csv file.
("int_1,int_2,float_1,float_2,first,second,third,word1,11,0.1,1.0,a,b,c,first2,12,0.2,1.0,a,b,c,second3,13,0.3,2.0,a,b,c,third4,14,0.4,3.0,b,a,c,second0,15,0.5,4.0,b,a,a,third6,16,0.6,5.0,b,a,a,second7,17,0.7,6.0,b,c,a,third8,18,0.8,7.0,c,c,b,eight9,19,0.9,8.0,c,c,b,ninth0,10,0.0,9.0,c,c,b,ninth"| save --raw --force test_small.csv)
Save the file and name it however you want to, for the sake of these examples
the file will be called test_small.csv.
Now, to read that file as a dataframe use the polars open command like
this:
let df_1 = polars open --eager test_small.csv
This should create the value $df_1 in memory which holds the data we just
created.
::: tip
The polars open command can read files in formats: csv, tsv, parquet, json(l), arrow, and avro.
:::
To see all the dataframes that are stored in memory you can use
As you can see, the command shows the created dataframes together with basic
information about them.
And if you want to see a preview of the loaded dataframe you can send the
dataframe variable to the stream
$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
DataFrame
::: tip
If you want to see all the dataframe commands that are available you
can use scope commands | where category =~ dataframe
:::
Basic Aggregations
Let's start with basic aggregations on the dataframe. Let's sum all the columns
that exist in df by using the aggregate command
$df_1| polars sum | polars collect
# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬──────╮# => │ # │ 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
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 command
You can perform several aggregations on the dataframe in order to extract basic
information from the dataframe and do basic data analysis on your brand new
dataframe.
Joining a DataFrame
It is also possible to join two dataframes using a column as reference. We are
going to join our mini dataframe with another mini dataframe. Copy these lines
in another file and create the corresponding dataframe (for these examples we
are going to call it test_small_a.csv)
"int_1,int_2,float_1,float_2,first9,14,0.4,3.0,a8,13,0.3,2.0,a7,12,0.2,1.0,a6,11,0.1,0.0,b"| save --raw --force test_small_a.csv
We use the polars open command to create the new variable
let df_2 = polars open --eager test_small_a.csv
Now, with the second dataframe loaded in memory we can join them using the
column called int_1 from the left dataframe and the column int_1 from the
right dataframe
$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
In Nu when a command has multiple arguments that are expecting
multiple values we use brackets [] to enclose those values. In the case of
polars join we can join on multiple columns
as long as they have the same type.
:::
For example:
$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
rows where both dataframes share the same value. You can select a left join to
keep the missing rows from the left dataframe. You can also save this result
in order to use it for further operations.
DataFrame group-by
One of the most powerful operations that can be performed with a DataFrame is
the polars group-by. This command will allow you to perform aggregation operations
based on a grouping criteria. In Nushell, a GroupBy is a type of object that
can be stored and reused for multiple aggregations. This is quite handy, since
the creation of the grouped pairs is the most expensive operation while doing
group-by and there is no need to repeat it if you are planning to do multiple
operations with the same group condition.
To create a GroupBy object you only need to use the polars_group-by command
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
lazy operation waiting to be completed by adding an aggregation. Using the
GroupBy we can create aggregations on a column
As you can see, the GroupBy object is a very powerful variable and it is
worth keeping in memory while you explore your dataset.
Creating Dataframes
It is also possible to construct dataframes from basic Nushell primitives, such
as integers, decimals, or strings. Let's create a small dataframe using the
command polars into-df.
::: tip
For the time being, not all of Nushell primitives can be converted into
a dataframe. This will change in the future, as the dataframe feature matures
:::
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
Nushell's powerful piping syntax allows us to create new dataframes by
taking data from other dataframes and appending it to them. Now, if you list your
dataframes you will see in total five dataframes
One thing that is important to mention is how the memory is being optimized
while working with dataframes, and this is thanks to Apache Arrow and
Polars. In a very simple representation, each column in a DataFrame is an
Arrow Array, which is using several memory specifications in order to maintain
the data as packed as possible (check Arrow columnar
format). The other
optimization trick is the fact that whenever possible, the columns from the
dataframes are shared between dataframes, avoiding memory duplication for the
same data. This means that dataframes $df_3 and $df_4 are sharing the same two
columns we created using the polars into-df command. For this reason, it isn't
possible to change the value of a column in a dataframe. However, you can
create new columns based on data from other columns or dataframes.
Working with Series
A Series is the building block of a DataFrame. Each Series represents a
column with the same data type, and we can create multiple Series of different
types, such as float, int or string.
Let's start our exploration with Series by creating one using the polars into-df
command:
We have created a new series from a list of integers (we could have done the
same using floats or strings)
Series have their own basic operations defined, and they can be used to create
other Series. Let's create a new Series by doing some arithmetic on the
previously created column.
Nushell's piping system can help you create very interesting workflows.
Series and Masks
Series have another key use in when working with DataFrames, and it is the fact
that we can build boolean masks out of them. Let's start by creating a simple
mask using the equality operator
and this new mask can be used to filter the dataframe
$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
from a series. For example, we can change the value in the column first where
the value is equal to a
$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
Series can be also used as a way of filtering a dataframe by using them as a
list of indices. For example, let's say that we want to get rows 1, 4, and 6
from our original dataframe. With that in mind, we can use the next command to
extract that information
let indices_0 = [146] | 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 is very handy, especially if we mix it with other commands.
Let's say that we want to extract all rows for the first duplicated element for
column first. In order to do that, we can use the command polars arg-unique as
shown in the next example
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.
We can use the arg-sort to accomplish that. In the next example we
can sort the dataframe by the column word
::: tip
The same result could be accomplished using the command sort
:::
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
Another operation that can be done with Series is to search for unique values
in a list or column. Lets use again the first dataframe we created to test
these operations.
The first and most common operation that we have is value_counts. This
command calculates a count of the unique values that exist in a Series. For
example, we can use it to count how many occurrences we have in the column
first
$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
queries.
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
$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
unique or duplicated. For example, we can select the rows for unique values
in column word
$df_1| polars filter-with ($in.word | polars is-unique)
# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬───────╮# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼───────┤# => │ 0 │ 1 │ 11 │ 0.10 │ 1.00 │ a │ b │ c │ first │# => │ 1 │ 8 │ 18 │ 0.80 │ 7.00 │ c │ c │ b │ eight │# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴───────╯
Or all the duplicated ones
$df_1| polars filter-with ($in.word | polars is-duplicated)
# => ╭───┬───────┬───────┬─────────┬─────────┬───────┬────────┬───────┬────────╮# => │ # │ int_1 │ int_2 │ float_1 │ float_2 │ first │ second │ third │ word │# => ├───┼───────┼───────┼─────────┼─────────┼───────┼────────┼───────┼────────┤# => │ 0 │ 2 │ 12 │ 0.20 │ 1.00 │ a │ b │ c │ second │# => │ 1 │ 3 │ 13 │ 0.30 │ 2.00 │ a │ b │ c │ third │# => │ 2 │ 4 │ 14 │ 0.40 │ 3.00 │ b │ a │ c │ second │# => │ 3 │ 0 │ 15 │ 0.50 │ 4.00 │ b │ a │ a │ third │# => │ 4 │ 6 │ 16 │ 0.60 │ 5.00 │ b │ a │ a │ second │# => │ 5 │ 7 │ 17 │ 0.70 │ 6.00 │ b │ c │ a │ third │# => │ 6 │ 9 │ 19 │ 0.90 │ 8.00 │ c │ c │ b │ ninth │# => │ 7 │ 0 │ 10 │ 0.00 │ 9.00 │ c │ c │ b │ ninth │# => ╰───┴───────┴───────┴─────────┴─────────┴───────┴────────┴───────┴────────╯
Lazy Dataframes
Lazy dataframes are a way to query data by creating a logical plan. The
advantage of this approach is that the plan never gets evaluated until you need
to extract data. This way you could chain together aggregations, joins and
selections and collect the data once you are happy with the selected
operations.
As you can see, the resulting dataframe is not yet evaluated, it stays as a
set of instructions that can be done on the data. If you were to collect that
dataframe you would get the next result
$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
table for you.
All dataframes operations should work with eager or lazy dataframes. They are
converted in the background for compatibility. However, to take advantage of
lazy operations if is recommended to only use lazy operations with lazy
dataframes.
To find all lazy dataframe operations you can use
scope commands | where category =~ lazyframe | select name category usage
With your lazy frame defined we can start chaining operations on it. For
example this
$lf_0| polars reverse
| polars with-column [
((polars col a) *2| polars as double_a)
((polars col a) /2| polars as half_a)
]
| polars collect
# => ╭───┬───┬───┬──────────┬────────╮# => │ # │ a │ b │ double_a │ half_a │# => ├───┼───┼───┼──────────┼────────┤# => │ 0 │ 4 │ d │ 8 │ 2 │# => │ 1 │ 3 │ c │ 6 │ 1 │# => │ 2 │ 2 │ b │ 4 │ 1 │# => │ 3 │ 1 │ a │ 2 │ 0 │# => ╰───┴───┴───┴──────────┴────────╯
:::tip
You can use the line buffer editor to format your queries (ctr + o) easily
:::
This query uses the lazy reverse command to invert the dataframe and the
polars with-column command to create new two columns using expressions.
An expression is used to define an operation that is executed on the lazy
frame. When put together they create the whole set of instructions used by the
lazy commands to query the data. To list all the commands that generate an
expression you can use
scope commands | where category =~ expression | select name category usage
In our previous example, we use the polars col command to indicate that column a
will be multiplied by 2 and then it will be aliased to the name double_a.
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
Let's try something more complicated and create aggregations from a lazy
dataframe
let lf_1 = [[name value]; [one 1] [two 2] [one 1] [two 3]] | polars into-lazy$lf_1| polars group-by name
| polars agg [
(polars col value | polars sum | polars as sum)
(polars col value | polars mean | polars as mean)
]
| polars collect
# => ╭───┬──────┬─────┬──────╮# => │ # │ name │ sum │ mean │# => ├───┼──────┼─────┼──────┤# => │ 0 │ two │ 5 │ 2.50 │# => │ 1 │ one │ 2 │ 1.00 │# => ╰───┴──────┴─────┴──────╯
And we could join on a lazy dataframe that hasn't being collected. Let's join
the resulting group by to the original lazy frame
let lf_2 = [[name value]; [one 1] [two 2] [one 1] [two 3]] | polars into-lazylet group =$lf_2| polars group-by name
| polars agg [
(polars col value | polars sum | polars as sum)
(polars col value | polars mean | polars as mean)
]
$lf_2| polars join $group name name | polars collect
# => ╭───┬──────┬───────┬─────┬──────╮# => │ # │ name │ value │ sum │ mean │# => ├───┼──────┼───────┼─────┼──────┤# => │ 0 │ one │ 1 │ 2 │ 1.00 │# => │ 1 │ two │ 2 │ 5 │ 2.50 │# => │ 2 │ one │ 1 │ 2 │ 1.00 │# => │ 3 │ two │ 3 │ 5 │ 2.50 │# => ╰───┴──────┴───────┴─────┴──────╯
As you can see lazy frames are a powerful construct that will let you query
data using a flexible syntax, resulting in blazing fast results.
Dataframe Commands
So far we have seen quite a few operations that can be done using DataFrames
commands. However, the commands we have used so far are not all the commands
available to work with data and be assured that there will be more as the
feature becomes more stable.
The next list shows the available dataframe commands with their descriptions, and
whenever possible, their analogous Nushell command.
We hope that by the end of this page you have a solid grasp of how to use the
dataframe commands. As you can see they offer powerful operations that can
help you process data faster and natively.
However, the future of these dataframes is still very experimental. New
commands and tools that take advantage of these commands will be added as they
mature.
Check this chapter, as well as our Blog, regularly to learn about new
dataframes features and how they can help you process data faster and efficiently.
`book/default_shell.md`:
```md
---
prev:
text: Installing Nu
link: /book/installation.md
next:
text: Getting Started
link: /book/getting_started.md
---
# Default Shell
## Setting Nu as default shell on your terminal
| Terminal | Platform | Instructions |
| :--------------: | ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| GNOME Terminal | Linux & BSDs | Open `Edit > Preferences`. In the right-hand panel, select the `Command` tab, tick `Run a custom command instead of my shell`, and set `Custom command` to the path to Nu. |
| GNOME Console | Linux & BSDs | Type the command `gsettings set org.gnome.Console shell "['/usr/bin/nu']"` (replace `/usr/bin/nu` with the path to Nu). Equivalently, use [dconf Editor](https://apps.gnome.org/DconfEditor/) to edit the `/org/gnome/Console/shell` key. |
| Kitty | Linux & BSDs | Press `Ctrl`+`Shift`+`F2` to open `kitty.conf`. Go to `shell` variable, uncomment the line and replace the `.` with the path to Nu. |
| Konsole | Linux & BSDs | Open `Settings > Edit Current Profile`. Set `Command` to the path to Nu. |
| XFCE Terminal | Linux & BSDs | Open `Edit > Preferences`. Check `Run a custom command instead of my shell`, and set `Custom command` to the path to Nu. |
| Terminal.app | macOS | Open `Terminal > Preferences`. Ensure you are on the `Profiles` tab, which should be the default tab. In the right-hand panel, select the `Shell` tab. Tick `Run command`, put the path to Nu in the textbox, and untick `Run inside shell`. |
| iTerm2 | macOS | Open `iTerm > Preferences`. Select the `Profiles` tab. In the right-hand panel under `Command`, change the dropdown from `Login Shell` to `Custom Shell`, and put the path to Nu in the textbox. |
| Windows Terminal | Windows | Press `Ctrl`+`,` to open `Settings`. Go to `Add a new profile > New empty profile`. Fill in the 'Name' and enter path to Nu in the 'Command line' textbox. Go to `Startup` option and select Nu as the 'Default profile'. Hit `Save`. |
## Setting Nu as login shell (Linux, BSD & macOS)
::: warning
Nu is not intended to be POSIX compliant.
Be aware that some programs on your system (or their documentation) might assume that your login shell is [POSIX](https://en.wikipedia.org/wiki/POSIX) compatible.
Breaking that assumption can lead to unexpected issues. See [Configuration - Login Shell](./configuration.md#configuring-nu-as-a-login-shell) for more details.
:::
To set the login shell you can use the [`chsh`](https://linux.die.net/man/1/chsh) command.
Some Linux distributions have a list of valid shells located in `/etc/shells` and will disallow changing the shell until Nu is in the whitelist.
You may see an error similar to the one below if you haven't updated the `shells` file:
@[code](@snippets/installation/chsh_invalid_shell_error.sh)
You can add Nu to the list of allowed shells by appending your Nu binary to the `shells` file.
The path to add can be found with the command `which nu`, usually it is `$HOME/.cargo/bin/nu`.
book/design_notes.md:
---prev:
text: Nushell operator maplink: /book/nushell_operator_map.mdnext:
text: How Nushell Code Gets Runlink: /book/how_nushell_code_gets_run.md---# Design Notes
This chapter intends to give more in-depth overview of certain aspects of Nushell's design. The topics are not necessary for a basic usage, but reading them will help you understand how Nushell works and why.
We intend to expand this chapter in the future. If there is some topic that you find confusing and hard to understand, let us know. It might be a good candidate for a page here.
[How Nushell Code Gets Run](how_nushell_code_gets_run.md) explains what happens when you run Nushell source code. It explains how Nushell is in many ways closer to classic compiled languages, like C or Rust, than to other shells and dynamic languages and hopefully clears some confusion that stems from that.
book/directory_stack.md:
# Directory Stack
Like some other shells, Nushell provides a Directory Stack feature for easily switching between multiple directories. In Nushell, this feature is part of the [Standard Library](./standard_library.md) and can be accessed in several ways.
::: note
In Nushell, the "stack" is represented as a `list`, but the overall functionality is similar to that of other shells.
:::
[[toc]]## `dirs` Module and Commands
To use the `dirs` command and its subcommands, first import the module using:
```nuuse std/dirs
::: tip
To make the feature available whenever you start Nushell, add the above command to your startup configuration.
:::
This makes several new commands available:
Command
Description
dirs
Lists the directories on the stack
dirs add
Adds one or more directories to the list. The first directory listed becomes the new active directory. Similar to the pushd command in some other shells.
dirs drop
Drops the current directory from the list. The previous directory in the list becomes the new active directory. Similar to the popd command in some other shells.
dirs goto
Jumps to directory by using its index in the list
dirs next
Makes the next directory on the list the active directory. If the current active directory is the last in the list, then cycle to the start of the list.
dirs prev
Makes the previous directory on the list the active directory. If the current active directory is the first in the list, then cycle to the end of the list.
When we start using dirs, there is only one directory in the list, the active one. You can, as always, change this directory using the cd command.
When we drop nu_scripts from the list, the previous directory (reedline) becomes active.
shells Aliases
Some users may prefer to think of this feature as multiple "shells within shells", where each has its own directory.
The Standard Library provides a set of aliases that can be used in place of the dirs commands above.
Import them using:
use std/dirs shells-aliases *
The built-in aliases are:
Alias
Description
shells
in place of dirs to list current "shells"/directories.
enter
in place of dirs add to enter a new "shell"/dir.
dexit
in place of dirs drop to exit a "shell"/dir.
g
as an alias for dirs goto.
n
for dirs next
p
for dirs prev
Of course, you can also define your own aliases if desired.
`book/environment.md`:
```md
# Environment
A common task in a shell is to control the environment that external applications will use. This is often done automatically, as the environment is packaged up and given to the external application as it launches. Sometimes, though, we want to have more precise control over what environment variables an application sees.
You can see the current environment variables in the $env variable:
```nu
$env | table -e
# => ╭──────────────────────────────────┬───────────────────────────────────────────╮
# => │ │ ╭──────┬────────────────────────────────╮ │
# => │ ENV_CONVERSIONS │ │ │ ╭─────────────┬──────────────╮ │ │
# => │ │ │ PATH │ │ from_string │ <Closure 32> │ │ │
# => │ │ │ │ │ to_string │ <Closure 34> │ │ │
# => │ │ │ │ ╰─────────────┴──────────────╯ │ │
# => │ │ │ │ ╭─────────────┬──────────────╮ │ │
# => │ │ │ Path │ │ from_string │ <Closure 36> │ │ │
# => │ │ │ │ │ to_string │ <Closure 38> │ │ │
# => │ │ │ │ ╰─────────────┴──────────────╯ │ │
# => │ │ ╰──────┴────────────────────────────────╯ │
# => │ 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.
To send environment variables to external applications, the values will need to be converted to strings. See Environment variable conversions on how this works.
The environment is initially created from the Nu configuration files and from the environment that Nu is run inside of.
Setting Environment Variables
There are several ways to set an environment variable:
$env.VAR assignment
Using the $env.VAR = "val" is the most straightforward method
$env.FOO= 'BAR'
So, if you want to extend the Windows Path variable, for example, you could do that as follows.
Here we've prepended our folder to the existing folders in the Path, so it will have the highest priority.
If you want to give it the lowest priority instead, you can use the append command.
If you have more than one environment variable you'd like to set, you can use load-env to create a table of name/value pairs and load multiple variables at the same time:
load-env { "BOB": "FOO","JAY": "BAR" }
One-shot Environment Variables
These are defined to be active only temporarily for a duration of executing a code block.
See Single-use environment variables for details.
Alternatively, you can check for the presence of an environmental variable with in:
$env.FOO# => BARif"FOO" in $env {
echo $env.FOO
}
# => BAR
Case sensitivity
Nushell's $env is case-insensitive, regardless of the OS. Although $env behaves mostly like a record, it is special in that it ignores the case when reading or updating. This means, for example, you can use any of $env.PATH, $env.Path, or $env.path, and they all work the same on any OS.
If you want to read $env in a case-sensitive manner, use $env | get --sensitive.
Scoping
When you set an environment variable, it will be available only in the current scope (the block you're in and any block inside of it).
Here is a small example to demonstrate the environment scoping:
A common task in a shell is to change the directory using the cd command. In Nushell, calling cd is equivalent to setting the PWD environment variable. Therefore, it follows the same rules as other environment variables (for example, scoping).
Single-use Environment Variables
A common shorthand to set an environment variable once is available, inspired by Bash and others:
FOO=BAR$env.FOO# => BAR
You can also use with-env to do the same thing more explicitly:
with-env { FOO: BAR } { $env.FOO }
# => BAR
The with-env 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 will run with this new environment variable set.
Permanent Environment Variables
You can also set environment variables at startup so they are available for the duration of Nushell running. To do this, set an environment variable inside the Nu configuration file.
For example:
# In config.nu$env.FOO= 'BAR'
Environment Variable Conversions
You can set the ENV_CONVERSIONS environment variable to convert other environment variables between a string and a value.
For example, the default environment config includes conversion of PATH (and Path used on Windows) environment variables from a string to a list.
After both env.nu and config.nu are loaded, any existing environment variable specified inside ENV_CONVERSIONS will be translated according to its from_string field into a value of any type.
External tools require environment variables to be strings, therefore, any non-string environment variable needs to be converted first.
The conversion of value -> string is set by the to_string field of ENV_CONVERSIONS and is done every time an external command is run.
Let's illustrate the conversions with an example.
Put the following in your config.nu:
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
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
do$env.ENV_CONVERSIONS.FOO.from_string 'a-b-c'
Now, to test the conversion list -> string, run:
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.
Running commands with nu -c does not load the config file, therefore the env conversion for FOO is missing and it is displayed as a plain string -- this way we can verify the translation was successful.
You can also run this step manually by do $env.ENV_CONVERSIONS.FOO.to_string [a b c]
(Important! The environment conversion string -> value happens after the env.nu and config.nu are evaluated. All environment variables in env.nu and config.nu are still strings unless you set them manually to some other values.)
Removing Environment Variables
You can remove an environment variable only if it was set in the current scope via hide-env:
$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:
$env.FOO= 'BAR'
do {
hide-env FOO# $env.FOO does not exist
}
$env.FOO# => BAR
`book/explore.md`:
```md
# `explore`
Explore is a table pager, just like `less` but for table structured data.
## Signature
`> explore --head --index --reverse --peek`
### Parameters
- `--head {bool}`: Show or hide column headers (default true)
- `--index, -i`: Show row indexes when viewing a list
- `--tail, -t`: Start with the viewport scrolled to the bottom
- `--peek, -p`: When quitting, output the value of the cell the cursor was on
## Get Started
```nu
ls | explore -i
So the main point of explore is :table (Which you see on the above screenshot).
You can interact with it via <Left>, <Right>, <Up>, <Down>arrow keys. It also supports the Vim keybindings <h>, <j>, <k>, and <l>, <Ctrl-f> and <Ctrl-b>, and it supports the Emacs keybindings <Ctrl-v>, <Alt-v>, <Ctrl-p>, and <Ctrl-n>.
You can inspect a underlying values by entering into cursor mode. You can press either <i> or <Enter> to do so.
Then using arrow keys you can choose a necessary cell.
And you'll be able to see it's underlying structure.
You can obtain more information about the various aspects of it by :help.
Commands
explore has a list of built in commands you can use. Commands are run through pressing <:> and then a command name.
To find out the comprehensive list of commands you can type :help.
Config
You can configure many things (including styles and colors), via config.
You can find an example configuration in default-config.nu.
Examples
Peeking a Value
$nu| explore --peek
:try Command
There's an interactive environment which you can use to navigate through data using nu.
Keeping the chosen value by $nu
Remember you can combine it with --peek.
`book/externs.md`:
```md
# Externs
Using external commands (a.k.a. binaries or applications) is a fundamental feature of any shell. Nushell allows custom commands to take advantage of many of its features, such as:
- Parse-time type checking
- Completions
- Syntax highlighting
Support for these features is provided using the `extern` keyword, which allows a full signature to be defined for external commands.
Here's a short example for the `ssh` command:
```nu
module "ssh extern" {
def complete_none [] { [] }
def complete_ssh_identity [] {
ls ~/.ssh/id_*
| where {|f|
($f.name | path parse | get extension) != "pub"
}
| get name
}
export extern ssh [
destination?: string@complete_none # Destination Host
-p: int # Destination Port
-i: string@complete_ssh_identity # Identity File
]
}
use "ssh extern" ssh
Notice that the syntax here is similar to that of the def keyword when defining a custom command. You can describe flags, positional parameters, types, completers, and more.
This implementation:
Will provide -p and -i (with descriptions) as possible completions for ssh -.
Will perform parse-time type checking. Attempting to use a non-int for the port number will result in an error (and error-condition syntax highlighting).
Will offer parse-time syntax highlighting based on the shapes of the arguments.
Will offer any private key files in ~/.ssh as completion values for the -i (identity) option
Will not offer completions for the destination host. Without a completer that returns an empty list, Nushell would attempt to use the default "File" completer.
See the Nu_scripts Repository for an implementation that retrieves hosts from the SSH config files.
::: tip Note
A Nushell comment that continues on the same line for argument documentation purposes requires a space before the # pound sign.
:::
Format Specifiers
Positional parameters can be made optional with a ? (as seen above). The remaining (rest) parameters can be matched with ... before the parameter name. For example:
There are a few limitations to the current extern syntax. In Nushell, flags and positional arguments are very flexible—flags can precede positional arguments, flags can be mixed into positional arguments, and flags can follow positional arguments. Many external commands are not this flexible. There is not yet a way to require a particular ordering of flags and positional arguments to the style required by the external.
The second limitation is that some externals require flags to be passed using = to separate the flag and the value. In Nushell, the = is a convenient optional syntax and there's currently no way to require its use.
In addition, externals called via the caret sigil (e.g., ^ssh) are not recognized by extern.
Finally, some external commands support -long arguments using a single leading hyphen. Nushell extern syntax can not yet represent these arguments.
`book/getting_started.md`:
```md
---
prev:
text: Default Shell
link: /book/default_shell.md
next:
text: Quick Tour
link: /book/quick_tour.md
---
# Getting Started
Let's get started! :elephant:
The next sections will give you a [short tour of Nushell by example](quick_tour.md) (including how to get help from within Nushell) and show you how to [move around your file system](moving_around.md).
Then, because Nushell takes some design decisions that are quite different from typical shells or dynamic scripting languages, make sure to check out [Thinking in Nu](thinking_in_nu.md) where we explain some of these concepts.
book/hooks.md:
# Hooks
Hooks allow you to run a code snippet at some predefined situations.
They are only available in the interactive mode ([REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)), they do not work if you run Nushell with a script (`nu script.nu`) or command (`nu -c "print foo"`) argument.
Currently, we support these types of hooks:
-`pre_prompt` : Triggered before the prompt is drawn
-`pre_execution` : Triggered before the line input starts executing
-`env_change` : Triggered when an environment variable changes
-`display_output` : A block that the output is passed to
-`command_not_found` : Triggered when a command is not found
To make it clearer, we can break down Nushell's execution cycle.
The steps to evaluate one line in the REPL mode are as follows:
1. Check for `pre_prompt` hooks and run them
1. Check for `env_change` hooks and run them
1. Display prompt and wait for user input
1. After user typed something and pressed "Enter": Check for `pre_execution` hooks and run them
1. Parse and evaluate user input
1. If a command is not found: Run the `command_not_found` hook. If it returns a string, show it.
1. If `display_output` is defined, use it to print command output
1. Return to 1.
## Basic Hooks
To enable hooks, define them in your [config](configuration.md):
```nu$env.config.hooks = { pre_prompt: [{ print "pre prompt hook" }] pre_execution: [{ print "pre exec hook" }] env_change: { PWD: [{|before, after| print $"changing directory from ($before) to ($after)" }] }}
Try putting the above into your config, running Nushell and moving around your filesystem.
When you change a directory, the PWD environment variable changes and the change triggers the hook with the previous and the current values stored in before and after variables, respectively.
Instead of defining just a single hook per trigger, it is possible to define a list of hooks which will run in sequence:
One feature of the hooks is that they preserve the environment.
Environment variables defined inside the hook block will be preserved in a similar way as def --env.
You can test it with the following example:
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.
pre_execution Hooks
pre_execution hooks can inspect the to-be-executed command through the commandline command.
This won't work because the environment will be active only within the if block.
In this case, you could easily rewrite it as load-env (if $after == ... { ... } else { {} }) but this pattern is fairly common and later we'll see that not all cases can be rewritten like this.
To deal with the above problem, we introduce another way to define a hook - a record:
When the hook triggers, it evaluates the condition block.
If it returns true, the code block will be evaluated.
If it returns false, nothing will happen.
If it returns something else, an error will be thrown.
The condition field can also be omitted altogether in which case the hook will always evaluate.
The pre_prompt and pre_execution hook types also support the conditional hooks but they don't accept the before and after parameters.
Hooks as Strings
So far a hook was defined as a block that preserves only the environment, but nothing else.
To be able to define commands or aliases, it is possible to define the code field as a string.
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
When defining a hook as a string, the $before and $after variables are set to the previous and current environment variable value, respectively, similarly to the previous examples:
You can use the display_output hook to redirect the output of commands.
You should define a block that works on all value types.
The output of external commands is not filtered through display_output.
This hook can display the output in a separate window,
perhaps as rich HTML text. Here is the basic idea of how to do that:
$env.config = ($env.config | upsert hooks {
display_output: { to html --partial --no-color | save --raw /tmp/nu-output.html }
})
You can view the result by opening file:///tmp/nu-output.html in
a web browser.
Of course this isn't very convenient unless you use
a browser that automatically reloads when the file changes.
Instead of the save command, you would normally customize this
to send the HTML output to a desired window.
Changing how Output is Displayed
You can change to default behavior of how output is displayed by using the display_output hook.
Here is an example that changes the default display behavior to show a table 1 layer deep if the terminal is wide enough, or collapse otherwise:
The following hook uses the ftype command, to find program paths in Windows that might be relevant to the user for alias-ing.
$env.config = {
...other config...
hooks: {
...other hooks...
command_not_found: {
|cmd_name| (
try {
let attrs = (
ftype | find $cmd_name| to text | lines | reduce -f [] { |line, acc|$line|parse"{type}={path}"|append$acc
} | group-by path | transpose key value | each { |row|
{ path: $row.key, types: ($row.value | get type | str join ", ") }
}
)
let len = ($attrs| length)
if$len==0 {
return null
} else {
return ($attrs| table --collapse)
}
}
)
}
}
}
`book/how_nushell_code_gets_run.md`:
```md
---
prev:
text: Design Notes
link: /book/design_notes.md
next:
text: (Not so) Advanced
link: /book/advanced.md
---
# How Nushell Code Gets Run
In [Thinking in Nu](./thinking_in_nu.md#think-of-nushell-as-a-compiled-language), we encouraged you to _"Think of Nushell as a compiled language"_ due to the way in which Nushell code is processed. We also covered several code examples that won't work in Nushell due that process.
The underlying reason for this is a strict separation of the **_parsing and evaluation_** stages that **_disallows `eval`-like functionality_**. In this section, we'll explain in detail what this means, why we're doing it, and what the implications are. The explanation aims to be as simple as possible, but it might help if you've programmed in another language before.
[[toc]]
## Interpreted vs. Compiled Languages
### Interpreted Languages
Nushell, Python, and Bash (and many others) are _"interpreted"_ languages.
Let's start with a simple "Hello, World!" Nushell program:
```nu
# hello.nu
print "Hello, World!"
Of course, this runs as expected using nu hello.nu. A similar program written in Python or Bash would look (and behave) nearly the same.
In "interpreted languages" code usually gets handled something like this:
Source Code → Interpreter → Result
Nushell follows this pattern, and its "Interpreter" is split into two parts:
First, the source code is analyzed by the Parser and converted into an intermediate representation (IR), which in Nushell's case is just a collection of data structures. Then, these data structures are passed to the Engine for evaluation and output of the results.
This, as well, is common in interpreted languages. For example, Python's source code is typically converted into bytecode before evaluation.
Compiled Languages
On the other side are languages that are typically "compiled", such as C, C++, or Rust. For example, here's a simple "Hello, World!" in Rust:
The compilation results stored as a binary file on the disk
The first two steps are handled with rustc main.rs.
Then, to produce a result, you need to run the binary (./main), which passes the instructions to the CPU
So:
Source Code ⇒ Compiler ⇒ Machine Code
Machine Code ⇒ CPU ⇒ Result
::: important
You can see that the compile-run sequence is not much different from the parse-evaluate sequence of an interpreter. You begin with source code, parse (or compile) it into some state (e.g., bytecode, IR, machine code), then evaluate (or run) the IR to get a result. You could think of machine code as just another type of IR and the CPU as its interpreter.
One big difference, however, between interpreted and compiled languages is that interpreted languages typically implement an eval function while compiled languages do not. What does this mean?
:::
Dynamic vs. Static Languages
::: tip Terminology
In general, the difference between a dynamic and static language is how much of the source code is resolved during Compilation (or Parsing) vs. Evaluation/Runtime:
"Static" languages perform more code analysis (e.g., type-checking, data ownership) during Compilation/Parsing.
"Dynamic" languages perform more code analysis, including eval of additional code, during Evaluation/Runtime.
For the purposes of this discussion, the primary difference between a static and dynamic language is whether or not it has an eval function.
The argument to an eval is "source code inside of source code", typically conditionally or dynamically computed. This means that, when an interpreted language encounters an eval in source code during Parse/Eval, it typically interrupts the normal Evaluation process to start a new Parse/Eval on the source code argument to the eval.
Here's a simple Python eval example to demonstrate this (potentially confusing!) concept:
When you run the file (python hello_eval.py), you'll see two messages: "Hello, World!" and "Hello, Eval!". Here is what happens:
The entire program is Parsed
(Line 3) print("Hello, World!") is Evaluated
(Line 4) In order to evaluate eval("print('Hello, Eval!')"):
print('Hello, Eval!') is Parsed
print('Hello, Eval!') is Evaluated
::: tip More fun
Consider eval("eval(\"print('Hello, Eval!')\")") and so on!
:::
Notice how the use of eval here adds a new "meta" step into the execution process. Instead of a single Parse/Eval, the eval creates additional, "recursive" Parse/Eval steps instead. This means that the bytecode produced by the Python interpreter can be further modified during the evaluation.
Nushell does not allow this.
As mentioned above, without an eval function to modify the bytecode during the interpretation process, there's very little difference (at a high level) between the Parse/Eval process of an interpreted language and that of the Compile/Run in compiled languages like C++ and Rust.
::: tip Takeaway
This is why we recommend that you "think of Nushell as a compiled language". Despite being an interpreted language, its lack of eval gives it some of the characteristic benefits as well as limitations common in traditional static, compiled languages.
:::
We'll dig deeper into what it means in the next section.
Implications
Consider this Python example:
exec("def hello(): print('Hello eval!')")
hello()
::: note
We're using exec in this example instead of eval because it can execute any valid Python code rather than being limited to eval expressions. The principle is similar in both cases, though.
:::
During interpretation:
The entire program is Parsed
In order to Evaluate Line 1:
def hello(): print('Hello eval!') is Parsed
def hello(): print('Hello eval!') is Evaluated
(Line 2) hello() is evaluated.
Note, that until step 2.2, the interpreter has no idea that a function hello even exists! This makes static analysis of dynamic languages challenging. In this example, the existence of the hello function cannot be checked just by parsing (compiling) the source code. The interpreter must evaluate (run) the code to discover it.
In a static, compiled language, a missing function is guaranteed to be caught at compile-time.
In a dynamic, interpreted language, however, it becomes a possible runtime error. If the eval-defined function is conditionally called, the error may not be discovered until that condition is met in production.
::: important
In Nushell, there are exactly two steps:
Parse the entire source code
Evaluate the entire source code
This is the complete Parse/Eval sequence.
:::
::: tip Takeaway
By not allowing eval-like functionality, Nushell prevents these types of eval-related bugs. Calling a non-existent definition is guaranteed to be caught at parse-time in Nushell.
Furthermore, after parsing completes, we can be certain the bytecode (IR) won't change during evaluation. This gives us a deep insight into the resulting bytecode (IR), allowing for powerful and reliable static analysis and IDE integration which can be challenging to achieve with more dynamic languages.
In general, you have more peace of mind that errors will be caught earlier when scaling Nushell programs.
:::
The Nushell REPL
As with most any shell, Nushell has a "Read→Eval→Print Loop" (REPL) that is started when you run nu without any file. This is often thought of, but isn't quite the same, as the "commandline".
::: tip Note
In this section, the > character at the beginning of a line in a code-block is used to represent the commandline prompt. For instance:
> some code...
Code after the prompt in the following examples is executed by pressing the Enter key. For example:
>print"Hello world!"# => Hello world!> ls
# => prints files and directories...
The above means:
From inside Nushell (launched with nu):
Type print "Hello world!"
Press Enter
Nushell will display the result
Type ls
Press Enter
Nushell will display the result
:::
When you press Enter after typing a commandline, Nushell:
(Read): Reads the commandline input
(Evaluate): Parses the commandline input
(Evaluate): Evaluates the commandline input
(Evaluate): Merges the environment (such as the current working directory) to the internal Nushell state
(Print): Displays the results (if non-null)
(Loop): Waits for another input
In other words, each REPL invocation is its own separate parse-evaluation sequence. By merging the environment back to the Nushell's state, we maintain continuity between the REPL invocations.
Compare a simplified version of the cd example from "Thinking in Nu":
cd spam
source-env foo.nu
There we saw that this cannot work (as a script or other single expression) because the directory will be changed after the parse-time source-env keyword attempts to read the file.
Running these commands as separate REPL entries, however, works:
> cd spam
> source-env foo.nu
# Yay, works!
To see why, let's break down what happens in the example:
Read the cd spam commandline.
Parse the cd spam commandline.
Evaluate the cd spam commandline.
Merge environment (including the current directory) into the Nushell state.
Read and Parse source-env foo.nu.
Evaluate source-env foo.nu.
Merge environment (including any changes from foo.nu) into the Nushell state.
When source-env tries to open foo.nu during the parsing in Step 5, it can do so because the directory change from Step 3 was merged into the Nushell state during Step 4. As a result, it's visible in the following Parse/Eval cycles.
Multiline REPL Commandlines
Keep in mind that this only works for separate commandlines.
In Nushell, it's possible to group multiple commands into one commandline using:
A semicolon:
cd spam; source-env foo.nu
A newline:
> cd span
source-env foo.nu
Notice there is no "prompt" before the second line. This type of multiline commandline is usually created with a keybinding to insert a Newline when Alt+Enter or Shift+ Enter is pressed.
These two examples behave exactly the same in the Nushell REPL. The entire commandline (both statements) are processed a single Read→Eval→Print Loop. As such, they will fail the same way that the earlier script-example did.
::: tip
Multiline commandlines are very useful in Nushell, but watch out for any out-of-order Parser-keywords.
:::
Parse-time Constant Evaluation
While it is impossible to add parsing into the evaluation stage and yet still maintain our static-language benefits, we can safely add a little bit of evaluation into parsing.
::: tip Terminology
In the text below, we use the term "constant" to refer to:
A const definition
The result of any command that outputs a constant value when provide constant inputs.
:::
By their nature, constants and constant values are known at Parse-time. This, of course, is in sharp contrast to variable declarations and values.
As a result, we can utilize constants as safe, known arguments to parse-time keywords like source, use, and related commands.
Let's analyze the Parse/Eval process for this version:
The entire program is Parsed into IR.
Line 1: The const definition is parsed. Because it is a constant assignment (and const is also a parser-keyword), that assignment can also be Evaluated at this stage. Its name and value are stored by the Parser.
Line 2: The source command is parsed. Because source is also a parser-keyword, it is Evaluated at this stage. In this example, however, it can be successfully parsed since its argument is known and can be retrieved at this point.
The source-code of ~/nushell-files/common.nu is parsed. If it is invalid, then an error will be generated, otherwise the IR results will be included in evaluation in the next stage.
The entire IR is Evaluated:
Line 1: The const definition is Evaluated. The variable is added to the runtime stack.
Line 2: The IR result from parsing ~/nushell-files/common.nu is Evaluated.
::: important
An eval adds additional parsing during evaluation
Parse-time constants do the opposite, adding additional evaluation to the parser.
:::
Also keep in mind that the evaluation allowed during parsing is very restricted. It is limited to only a small subset of what is allowed during a regular evaluation.
For example, the following is not allowed:
const foo_contents = (open foo.nu)
Put differently, only a small subset of commands and expressions can generate a constant value. For a command to be allowed:
It must be designed to output a constant value
All of its inputs must also be constant values, literals, or composite types (e.g., records, lists, tables) of literals.
In general, the commands and resulting expressions will be fairly simple and without side effects. Otherwise, the parser could all-too-easily enter an unrecoverable state. Imagine, for instance, attempting to assign an infinite stream to a constant. The Parse stage would never complete!
::: tip
You can see which Nushell commands can return constant values using:
help commands | where is_const
:::
For example, the path join command can output a constant value. Nushell also defines several useful paths in the $nu constant record. These can be combined to create useful parse-time constant evaluations like:
const my_startup_modules =$nu.default-config-dir | path join "my-mods"
use $"($my_startup_modules)/my-utils.nu"
::: note Additional Notes
Compiled ("static") languages also tend to have a way to convey some logic at compile time. For instance:
C's preprocessor
Rust macros
Zig's comptime, which was an inspiration for Nushell's parse-time constant evaluation.
There are two reasons for this:
Increasing Runtime Performance: Logic in the compilation stage doesn't need to be repeated during runtime.
This isn't currently applicable to Nushell, since the parsed results (IR) are not stored beyond Evaluation. However, this has certainly been considered as a possible future feature.
As with Nushell's parse-time constant evaluations, these features help (safely) work around limitations caused by the absence of an eval function.
:::
Conclusion
Nushell operates in a scripting language space typically dominated by "dynamic", "interpreted" languages, such as Python, Bash, Zsh, Fish, and many others. Nushell is also "interpreted" since code is run immediately (without a separate, manual compilation).
However, is not "dynamic" in that it does not have an eval construct. In this respect, it shares more in common with "static", compiled languages like Rust or Zig.
This lack of eval is often surprising to many new users and is why it can be helpful to think of Nushell as a compiled, and static, language.
`book/installation.md`:
```md
---
next:
text: Default Shell
link: /book/default_shell.md
---
# Installing Nu
There are lots of ways to get Nu up and running. You can download pre-built binaries from our [release page](https://github.com/nushell/nushell/releases), [use your favourite package manager](https://repology.org/project/nushell/versions), or build from source.
The main Nushell binary is named `nu` (or `nu.exe` on Windows). After installation, you can launch it by typing `nu`.
@[code](@snippets/installation/run_nu.sh)
[[toc]]
## Pre-built Binaries
Nu binaries are published for Linux, macOS, and Windows [with each GitHub release](https://github.com/nushell/nushell/releases). Just download, extract the binaries, then copy them to a location on your PATH.
## Package Managers
Nu is available via several package managers:
[](https://repology.org/project/nushell/versions)
For macOS and Linux, [Homebrew](https://brew.sh/) is a popular choice (`brew install nushell`).
For Windows:
- [Winget](https://docs.microsoft.com/en-us/windows/package-manager/winget/)
- Machine scope installation: `winget install nushell --scope machine`
- Machine scope upgrade: `winget update nushell`
- User scope installation: `winget install nushell` or `winget install nushell --scope user`
- User scope upgrade: Due to [winget-cli issue #3011](https://github.com/microsoft/winget-cli/issues/3011), running `winget update nushell` will unexpectedly install the latest version to `C:\Program Files\nu`. To work around this, run `winget install nushell` again to install the latest version in the user scope.
- [Scoop](https://scoop.sh/) (`scoop install nu`)
For Debian & Ubuntu:
```sh
curl -fsSL https://apt.fury.io/nushell/gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/fury-nushell.gpg
echo "deb https://apt.fury.io/nushell/ /" | sudo tee /etc/apt/sources.list.d/fury.list
sudo apt update
sudo apt install nushell
echo"https://alpine.fury.io/nushell/"| tee -a /etc/apk/repositories
apk update
apk add --allow-untrusted nushell
Cross Platform installation:
npm (npm install -g nushell Note that nu plugins are not included if you install in this way)
Docker Container Images
Docker images are available from the GitHub Container Registry. An image for the latest release is built regularly
for Alpine and Debian. You can run the image in interactive mode using:
docker run -it --rm ghcr.io/nushell/nushell:<version>-<distro>
Where <version> is the version of Nushell you want to run and <distro> is alpine or the latest supported Debian release, such as bookworm.
To run a specific command, use:
docker run --rm ghcr.io/nushell/nushell:latest-alpine -c "ls /usr/bin | where size > 10KiB"
To run a script from the current directory using Bash, use:
docker run --rm \
-v $(pwd):/work \ ghcr.io/nushell/nushell:latest-alpine \ "/work/script.nu"
Build from Source
You can also build Nu from source. First, you will need to set up the Rust toolchain and its dependencies.
Installing a Compiler Suite
For Rust to work properly, you'll need to have a compatible compiler suite installed on your system. These are the recommended compiler suites:
Make sure to install the "Desktop development with C++" workload
Any Visual Studio edition will work (Community is free)
Installing Rust
If you don't already have Rust on our system, the best way to install it is via rustup. Rustup is a way of managing Rust installations, including managing using different Rust versions.
Nu currently requires the latest stable (1.66.1 or later) version of Rust. The best way is to let rustup find the correct version for you. When you first open rustup it will ask what version of Rust you wish to install:
If you'd rather not install Rust via rustup, you can also install it via other methods (e.g. from a package in a Linux distro). Just be sure to install a version of Rust that is 1.66.1 or later.
Dependencies
Debian/Ubuntu
You will need to install the "pkg-config", "build-essential" and "libssl-dev" packages:
Nushell releases are published as source to the popular Rust package registry crates.io. This makes it easy to build and install the latest Nu release with cargo:
cargo install nu --locked
The cargo tool will do the work of downloading Nu and its source dependencies, building it, and installing it into the cargo bin path.
Note that the default plugins must be installed separately when using cargo. See the Plugins Installation section of the Book for instructions.
Building from the GitHub repository
You can also build Nu from the latest source on GitHub. This gives you immediate access to the latest features and bug fixes. First, clone the repo:
People familiar with Rust may wonder why we do both a "build" and a "run" step if "run" does a build by default. This is to get around a shortcoming of the new default-run option in Cargo, and ensure that all plugins are built, though this may not be required in the future.
`book/line_editor.md`:
```md
# Reedline, Nu's Line Editor
Nushell's line-editor [Reedline](https://github.com/nushell/reedline) is
cross-platform and designed to be modular and flexible. The line-editor is
in charge of controlling the command history, validations, completions, hints,
screen paint, and more.
[[toc]]
## Multi-line Editing
Reedline allows Nushell commandlines to extend across multiple lines. This can be accomplished using several methods:
1. Pressing <kbd>Enter</kbd> when a bracketed expression is open.
For example:
```nu
def my-command [] {
Pressing Enter after the open-bracket will insert a newline. This will also occur with opening (and valid) ( and [ expressions.
This is commonly used to create blocks and closures (as above), but also list, record, and table literals:
It can even be used to continue a single command across multiple lines:
::: details Example
(
tar
-cvz
-f archive.tgz
--exclude='*.temp'
--directory=../project/./)
:::
Pressing Enter at the end of a line with a trailing pipe-symbol (|).
ls |
where name =~ '^[0-9]' |# Comments after a trailing pipe are okay
get name |
mv ...$in./backups/
Manually insert a newline using Alt+Enter or Shift+Enter.
This can be used to create a somewhat more readable version of the previous commandline:
ls
| where name =~ '^[0-9]' # Files starting with a digit| get name
| mv ...$in./backups/
::: tip
It's possible that one or both of these keybindings may be intercepted by the terminal application or window-manager. For instance, Windows Terminal (and most other terminal applications on Windows) assign Alt+Enter to expand the terminal to full-screen. If neither of the above keybindings work in your terminal, you can assign a different keybinding to:
Pressing Ctrl+O opens the current commandline in your editor. Saving the resulting file and exiting the editor will update the commandline with the results.
Setting the Editing Mode
Reedline allows you to edit text using two modes — Vi and Emacs. If not
specified, the default mode is Emacs. To change the mode, use the
edit_mode setting.
$env.config.edit_mode = 'vi'
This can be changed at the commandline or persisted in config.nu.
::: note
Vi is a "modal" editor with "normal" mode and an "insert" mode. We recommend
becoming familiar with these modes through the use of the Vim or Neovim editors
before using Vi mode in Nushell. Each has a built-in tutorial covering the basics
(and more) of modal editing.
:::
Default Keybindings
Each edit mode comes with common keybindings for Vi and Emacs text editing.
Emacs and Vi-insert Keybindings
These keybinding events apply to both Emacs and Vi-insert mode:
Key
Event
Shift+Enter
Insert newline
Alt+Enter
Insert newline
Backspace
Backspace
End
Move to end of line
End
Complete history hint
Home
Move to line start
Ctrl+C
Cancel current line
Ctrl+L
Clear screen
Ctrl+R
Search history
Ctrl+→ (Right Arrow)
Complete history word
Ctrl+→ (Right Arrow)
Move word right
Ctrl+← (Left Arrow)
Move word left
↑ (Up Arrow)
Move up
↓ (Down Arrow)
Move down
← (Left Arrow)
Move left
→ (Right Arrow)
Move right
Ctrl+P
Move up
Ctrl+N
Move down
Ctrl+B
Move left
Ctrl+F
Move right
→ (Right Arrow)
History-hint complete
Ctrl+F
History-hint complete
Alt+F
History-hint complete one word
Alt+← (Left Arrow)
History-hint complete one word less
Vi-insert Keybindings
These keybinding events apply only to Vi-insert mode:
Key
Event
Esc
Switch to Vi-normal mode
Vi-normal Keybindings
These keybinding events apply only to Vi-normal mode:
Key
Event
Ctrl+C
Cancel current line
Ctrl+L
Clear screen
↑ (Up Arrow)
Move up
↓ (Down Arrow)
Move down
← (Left Arrow)
Move left
→ (Right Arrow)
Move right
Ctrl+→ (Right Arrow)
Move right one word
Ctrl+← (Left Arrow)
Move left one word
Vi-normal Motions
As with Vi, many motions and actions can be combined with an optional count in normal-mode. For example, 3dw deletes the next three words.
Key
Motion
w
Move to beginning of next word
e
Move to end of current or next word
b
Move to beginning of current or previous word
0
Move to start of line
$
Move to end of line
h
Move left
l
Move right
j
Move down
k
Move up
f+<char>
Move right to <char>
t+<char>
Move right to before <char>
Shift+F+<char>
Move left to <char>
Shift+T+<char>
Move left to after <char>
Vi-normal Actions
These actions can be combined with many of the motions above.
Key
Action
d
Delete
Shift+D
Delete to end of line
p
Paste after current character
Shift+P
Paste before current character
i
Enter Vi insert-mode (append) at current character
Shift+I
Enter insert-mode at beginning of line
a
Append after current character
Shift+A
Append to end of line
0
Move to start of line
^
Move to start of line
$
Move to end of line
c
Change
r
Replace
s
Substitute character(s)
x
Delete character
u
Undo
Command History
As mentioned before, Reedline manages and stores all the commands that are
edited and sent to Nushell. To configure the max number of records that
Reedline should store you will need to adjust this value in your config file:
$env.config.history.max_size =1000
Customizing the Prompt
The Reedline prompt is configured using a number of environment variables. See Prompt Configuration for details.
Keybindings
Reedline keybindings are powerful constructs that let you build chains of
events that can be triggered with a specific combination of keys.
For example, let's say that you would like to map the completion menu to the
Ctrl + t keybinding (default is tab). You can add the next entry to your
config file.
$env.config.keybindings ++= [{
name: completion_menu
modifier: control
keycode: char_t
mode: emacs
event: { send: menu name: completion_menu }
}]
After loading this new config.nu, your new keybinding (Ctrl + t) will open
the completion command.
Each keybinding requires the next elements:
name: Unique name for your keybinding for easy reference in $config.keybindings
modifier: A key modifier for the keybinding. The options are:
none
control
alt
shift
shift_alt
alt_shift
control_alt
alt_control
control_shift
shift_control
control_alt_shift
control_shift_alt
keycode: This represent the key to be pressed
mode: emacs, vi_insert, vi_normal (a single string or a list. e.g.
[vi_insertvi_normal])
event: The type of event that is going to be sent by the keybinding. The
options are:
send
edit
until
::: tip
All of the available modifiers, keycodes and events can be found with
the command keybindings list
:::
::: tip
The keybindings added to vi_insert mode will be available when the
line editor is in insert mode (when you can write text), and the keybindings
marked with vi_normal mode will be available when in normal (when the cursor
moves using h, j, k or l)
:::
The event section of the keybinding entry is where the actions to be performed
are defined. In this field you can use either a record or a list of records.
Something like this
The first keybinding example shown in this page follows the first case; a
single event is sent to the engine.
The next keybinding is an example of a series of events sent to the engine. It
first clears the prompt, inserts a string and then enters that value
$env.config.keybindings ++= [{
name: change_dir_with_fzf
modifier: CONTROL
keycode: Char_t
mode: emacs
event: [
{ edit: Clear }
{
edit: InsertString,
value: "cd (ls | where type == dir | each { |row| $row.name} | str join (char nl) | fzf | decode utf-8 | str trim)"
}
{ send: Enter }
]
}]
One disadvantage of the previous keybinding is the fact that the inserted text
will be processed by the validator and saved in the history, making the
keybinding a bit slow and populating the command history with the same command.
For that reason there is the executehostcommand type of event. The next
example does the same as the previous one in a simpler way, sending a single
event to the engine
$env.config.keybindings ++= [{
name: change_dir_with_fzf
modifier: CONTROL
keycode: Char_y
mode: emacs
event: {
send: executehostcommand,
cmd: "cd (ls | where type == dir | each { |row| $row.name} | str join (char nl) | fzf | decode utf-8 | str trim)"
}
}]
Before we continue you must have noticed that the syntax changes for edits and
sends, and for that reason it is important to explain them a bit more. A send
is all the Reedline events that can be processed by the engine and an edit
are all the EditCommands that can be processed by the engine.
Send Type
To find all the available options for send you can use
keybindings list| where type == events
And the syntax for send events is the next one
...
event: { send: <NAMEOFEVENTFROMLIST> }
...
::: tip
You can write the name of the events with capital letters. The
keybinding parser is case insensitive
:::
There are two exceptions to this rule: the Menu and ExecuteHostCommand.
Those two events require an extra field to be complete. The Menu needs the
name of the menu to be activated (completion_menu or history_menu)
...
event: {
send: menu
name: completion_menu
}
...
and the ExecuteHostCommand requires a valid command that will be sent to the
engine
It is worth mentioning that in the events list you will also see Edit([]),
Multiple([]) and UntilFound([]). These options are not available for the
parser since they are constructed based on the keybinding definition. For
example, a Multiple([]) event is built for you when defining a list of
records in the keybinding's event. An Edit([]) event is the same as the
edit type that was mentioned. And the UntilFound([]) event is the same as
the until type mentioned later.
Edit Type
The edit type is the simplification of the Edit([]) event. The event type
simplifies defining complex editing events for the keybindings. To list the
available options you can use the next command
keybindings list| where type == edits
The usual syntax for an edit is the next one
...
event: { edit: <NAMEOFEDITFROMLIST> }
...
The syntax for the edits in the list that have a () changes a little bit.
Since those edits require an extra value to be fully defined. For example, if
we would like to insert a string where the prompt is located, then you will
have to use
...
event: {
edit: insertstring
value: "MY NEW STRING"
}
...
As you can see, these two types will allow you to construct any type of
keybinding that you require
Until Type
To complete this keybinding tour we need to discuss the until type for event.
As you have seen so far, you can send a single event or a list of events. And
as we have seen, when a list of events is sent, each and every one of them is
processed.
However, there may be cases when you want to assign different events to the
same keybinding. This is especially useful with Nushell menus. For example, say
you still want to activate your completion menu with Ctrl + t but you also
want to move to the next element in the menu once it is activated using the
same keybinding.
For these cases, we have the until keyword. The events listed inside the
until event will be processed one by one with the difference that as soon as
one is successful, the event processing is stopped.
The previous keybinding will first try to open a completion menu. If the menu
is not active, it will activate it and send a success signal. If the keybinding
is pressed again, since there is an active menu, then the next event it will
send is MenuNext, which means that it will move the selector to the next
element in the menu.
As you can see the until keyword allows us to define two events for the same
keybinding. At the moment of this writing, only the Menu events allow this type
of layering. The other non menu event types will always return a success value,
meaning that the until event will stop as soon as it reaches the command.
For example, the next keybinding will always send a down because that event
is always successful
Your terminal environment may not always propagate your key combinations on to Nushell the way you expect it to. You can use the command keybindings listen to determine if certain keypresses are actually received by Nushell, and how.
Menus
Thanks to Reedline, Nushell has menus that can help you with your day to day
shell scripting. Next we present the default menus that are always available
when using Nushell
Menu Keybindings
When a menu is active, some keybindings change based on the keybinding until specifier discussed above. Common keybindings for menus are:
Key
Event
Tab
Select next item
Shift+Tab
Select previous item
Enter
Accept selection
↑ (Up Arrow)
Move menu up
↓ (Down Arrow)
Move menu down
← (Left Arrow)
Move menu left
→ (Right Arrow)
Move menu right
Ctrl+P
Move menu up
Ctrl+N
Move menu down
Ctrl+B
Move menu left
Ctrl+F
Move menu right
::: note
Menu direction behavior varies based on the menu type (see below). For example,
in a description menu, "Up" and "Down" apply to the "Extra" list, but in a
list menu the directions apply to the selection.
:::
Help Menu
The help menu is there to ease your transition into Nushell. Say you are
putting together an amazing pipeline and then you forgot the internal command
that would reverse a string for you. Instead of deleting your pipe, you can
activate the help menu with F1. Once active just type keywords for the
command you are looking for and the menu will show you commands that match your
input. The matching is done on the name of the commands or the commands
description.
To navigate the menu you can select the next element by using tab, you can
scroll the description by pressing left or right and you can even paste into
the line the available command examples.
The help menu can be configured by modifying the next parameters
$env.config.menus ++= [{
name: help_menu
only_buffer_difference: true # Search is done on the text written after activating the menu
marker: "? "# Indicator that appears with the menu is active
type: {
layout: description # Type of menu
columns: 4# Number of columns where the options are displayed
col_width: 20# Optional value. If missing all the screen width is used to calculate column width
col_padding: 2# Padding between columns
selection_rows: 4# Number of rows allowed to display found options
description_rows: 10# Number of rows allowed to display command description
}
style: {
text: green # Text style
selected_text: green_reverse # Text style for selected option
description_text: yellow # Text style for description
}
}]
Completion Menu
The completion menu is a context sensitive menu that will present suggestions
based on the status of the prompt. These suggestions can range from path
suggestions to command alternatives. While writing a command, you can activate
the menu to see available flags for an internal command. Also, if you have
defined your custom completions for external commands, these will appear in the
menu as well.
The completion menu by default is accessed by pressing tab and it can be configured by
modifying these values from the config object:
$env.config.menus ++= [{
name: completion_menu
only_buffer_difference: false # Search is done on the text written after activating the menu
marker: "| "# Indicator that appears with the menu is active
type: {
layout: columnar # Type of menu
columns: 4# Number of columns where the options are displayed
col_width: 20# Optional value. If missing all the screen width is used to calculate column width
col_padding: 2# Padding between columns
}
style: {
text: green # Text style
selected_text: green_reverse # Text style for selected option
description_text: yellow # Text style for description
}
}]
By modifying these parameters you can customize the layout of your menu to your
liking.
History Menu
The history menu is a handy way to access the editor history. When activating
the menu (default Ctrl+r) the command history is presented in reverse
chronological order, making it extremely easy to select a previous command.
The history menu can be configured by modifying these values from the config object:
$env.config.menus ++= [{
name: history_menu
only_buffer_difference: true # Search is done on the text written after activating the menu
marker: "? "# Indicator that appears with the menu is active
type: {
layout: list# Type of menu
page_size: 10# Number of entries that will presented when activating the menu
}
style: {
text: green # Text style
selected_text: green_reverse # Text style for selected option
description_text: yellow # Text style for description
}
}]
When the history menu is activated, it pulls page_size records from the
history and presents them in the menu. If there is space in the terminal, when
you press Ctrl+x again the menu will pull the same number of records and
append them to the current page. If it isn't possible to present all the pulled
records, the menu will create a new page. The pages can be navigated by
pressing Ctrl+z to go to previous page or Ctrl+x to go to next page.
Searching the History
To search in your history you can start typing key words for the command you
are looking for. Once the menu is activated, anything that you type will be
replaced by the selected command from your history. for example, say that you
have already typed this
let a = ()
you can place the cursor inside the () and activate the menu. You can filter
the history by typing key words and as soon as you select an entry, the typed
words will be replaced
let a = (ls | where size > 10MiB)
Menu Quick Selection
Another nice feature of the menu is the ability to quick select something from
it. Say you have activated your menu and it looks like this
>0: ls | where size > 10MiB
1: ls | where size > 20MiB
2: ls | where size > 30MiB
3: ls | where size > 40MiB
Instead of pressing down to select the fourth entry, you can type !3 and
press enter. This will insert the selected text in the prompt position, saving
you time scrolling down the menu.
History search and quick selection can be used together. You can activate the
menu, do a quick search, and then quick select using the quick selection
character.
User Defined Menus
In case you find that the default menus are not enough for you and you have
the need to create your own menu, Nushell can help you with that.
In order to add a new menu that fulfills your needs, you can use one of the default
layouts as a template. The templates available in nushell are columnar, list or
description.
The columnar menu will show you data in a columnar fashion adjusting the column
number based on the size of the text displayed in your columns.
The list type of menu will always display suggestions as a list, giving you the
option to select values using ! plus number combination.
The description type will give you more space to display a description for some
values, together with extra information that could be inserted into the buffer.
Let's say we want to create a menu that displays all the variables created
during your session, we are going to call it vars_menu. This menu will use a
list layout (layout: list). To search for values, we want to use only the things
that are written after the menu has been activated
(only_buffer_difference: true).
With that in mind, the desired menu would look like this
$env.config.menus ++= [{
name: vars_menu
only_buffer_difference: true
marker: "# "
type: {
layout: list
page_size: 10
}
style: {
text: green
selected_text: green_reverse
description_text: yellow
}
source: { |buffer, position|
scope variables
| where name =~ $buffer| sort-by name
| each { |row| {value: $row.name description: $row.type} }
}
}]
As you can see, the new menu is identical to the history_menu previously
described. The only huge difference is the new field called source. The
source field is a nushell definition of the values you want to display in the
menu. For this menu we are extracting the data from scope variables and we
are using it to create records that will be used to populate the menu.
The required structure for the record is the next one
{
value: # The value that will be inserted in the buffer
description: # Optional. Description that will be display with the selected value
span: { # Optional. Span indicating what section of the string will be replaced by the value
start:
end:
}
extra: [string] # Optional. A list of strings that will be displayed with the selected value. Only works with a description menu
}
For the menu to display something, at least the value field has to be present
in the resulting record.
In order to make the menu interactive, these two variables are available in
the block: $buffer and $position. The $buffer contains the value captured
by the menu, when the option only_buffer_difference is true, $buffer is the
text written after the menu was activated. If only_buffer_difference is
false, $buffer is all the string in line. The $position variable can be
used to create replacement spans based on the idea you had for your menu. The
value of $position changes based on whether only_buffer_difference is true
or false. When true, $position is the starting position in the string where
text was inserted after the menu was activated. When the value is false,
$position indicates the actual cursor position.
Using this information, you can design your menu to present the information you
require and to replace that value in the location you need it. The only thing
extra that you need to play with your menu is to define a keybinding that will
activate your brand new menu.
Menu Keybindings
In case you want to change the default way both menus are activated, you can
change that by defining new keybindings. For example, the next two keybindings
assign the completion and history menu to Ctrl+t and Ctrl+y respectively
`book/loading_data.md`:
```md
# Loading Data
Earlier, we saw how you can use commands like [`ls`](/commands/docs/ls.md), [`ps`](/commands/docs/ps.md), [`date`](/commands/docs/date.md), and [`sys`](/commands/docs/sys.md) to load information about your files, processes, time of day, and the system itself. Each command gives us a table of information that we can explore. There are other ways we can load in a table of data to work with.
## Opening files
One of Nu's most powerful assets in working with data is the [`open`](/commands/docs/open.md) command. It is a multi-tool that can work with a number of different data formats. To see what this means, let's try opening a json file:
@[code](@snippets/loading_data/vscode.sh)
In a similar way to [`ls`](/commands/docs/ls.md), opening a file type that Nu understands will give us back something that is more than just text (or a stream of bytes). Here we open a "package.json" file from a JavaScript project. Nu can recognize the JSON text and parse it to a table of data.
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
Nu currently supports the following formats for loading data directly into tables:
::: tip Did you know?
Under the hood open will look for a from ... subcommand in your scope which matches the extension of your file.
You can thus simply extend the set of supported file types of open by creating your own from ... subcommand.
:::
But what happens if you load a text file that isn't one of these? Let's try it:
open README.md
We're shown the contents of the file.
Below the surface, what Nu sees in these text files is one large string. Next, we'll talk about how to work with these strings to get the data we need out of them.
NUON
Nushell Object Notation (NUON) aims to be for Nushell what JavaScript Object Notation (JSON) is for JavaScript.
That is, NUON code is a valid Nushell code that describes some data structure.
For example, this is a valid NUON (example from the default configuration file):
{
menus: [
# Configuration for default nushell menus# Note the lack of source parameter
{
name: completion_menu
only_buffer_difference: false
marker: "| "
type: {
layout: columnar
columns: 4
col_width: 20# Optional value. If missing all the screen width is used to calculate column width
col_padding: 2
}
style: {
text: green
selected_text: green_reverse
description_text: yellow
}
}
]
}
You might notice it is quite similar to JSON, and you're right.
NUON is a superset of JSON!
That is, any JSON code is a valid NUON code, therefore a valid Nushell code.
Compared to JSON, NUON is more "human-friendly".
For example, comments are allowed and commas are not required.
One limitation of NUON currently is that it cannot represent all of the Nushell data types.
Most notably, NUON does not allow the serialization of blocks.
Handling Strings
An important part of working with data coming from outside Nu is that it's not always in a format that Nu understands. Often this data is given to us as a string.
Let's imagine that we're given this data file:
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.
The first thing we want to do when bringing in the file is to work with it a line at a time:
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 command. split, as the name implies, gives us a way to split a delimited string. We will use split's column subcommand to split the contents across multiple columns. We tell it what the delimiter is, and it does the rest:
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:
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 command using the toml subcommand:
The from command can be used for each of the structured data text formats that Nu can open and understand by passing it the supported format as a subcommand.
Opening in raw mode
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 command can take an optional --raw flag:
open Cargo.toml --raw
# => [package] name = "nu"# => version = "0.1.3"# => authors = ["Yehuda Katz <[email protected]>", "Sophia Turner <[email protected]>"]# => description = "A shell for the GitHub era"# => license = "MIT"
SQLite
SQLite databases are automatically detected by open, no matter what their file extension is. You can open a whole database:
(Note: some older versions of Nu use into db | query instead of query db )
Fetching URLs
In addition to loading files from your filesystem, you can also load URLs by using the http get command. This will fetch the contents of the URL from the internet and return it:
`book/metadata.md`:
```md
# Metadata
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
The error message tells us not only that what we gave from toml wasn't a string, but also where the value originally came from. How would it know that?
Values that flow through a pipeline in Nu often have a set of additional information, or metadata, attached to them. These are known as tags, like the tags on an item in a store. These tags don't affect the data, but they give Nu a way to improve the experience of working with that data.
Let's run the open command again, but this time, we'll look at the tags it gives back:
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.
`book/modules.md`:
```md
# Modules
Like many programming languages, Nushell supports writing and using _modules_ as a way to organize code more efficiently. Modules can be thought of as "containers" that hold various definitions, including:
- Additional custom commands
- Aliases
- Constants
- Externs
- Environment variables
- And even other modules (a.k.a., submodules)
Many users will start off using modules written by others, then progress to writing their own. This chapter covers those two topics:
- [Using Modules](./modules/using_modules.md)
- [Creating Modules](./modules/creating_modules.md)
book/modules/creating_modules.md:
# Creating Modules[[toc]]
::: important
When working through the examples below, it is recommended that you start a new shell before importing an updated version of each module or command. This will help reduce any confusion caused by definitions from previous imports.
:::
## Overview
Modules (and Submodules, to be covered below) are created in one of two ways:
- Most commonly, by creating a file with a series of `export` statements of definitions to be exported from the module.
- For submodules inside a module, using the `module` command
::: tip
While it's possible to use the `module` command to create a module directly at the commandline, it's far more useful and common to store the module definitions in a file for reusability.
:::
The module file can be either:
- A file named `mod.nu`, in which case its _directory_ becomes the module name
- Any other `<module_name>.nu` file, in which case the filename becomes the module name
### Simple Module Example
Create a file named `inc.nu` with the following:
```nuexport def increment []: int -> int { $in + 1}
This is a module! We can now import it and use the increment command:
use inc.nu *5| increment
# => 6
Of course, you can easily distribute a file like this so that others can make use of the module as well.
Exports
We covered the types of definitions that are available in modules briefly in the main Modules Overview above. While this might be enough explanation for an end-user, module authors will need to know how to create the export definitions for:
::: tip
Only definitions marked with export (or export-env for environment variables) are accessible when the module is imported. Definitions not marked with export are only visible from inside the module. In some languages, these would be called "private" or "local" definitions. An example can be found below in Additional Examples.
:::
main Exports
::: important
An export cannot have the same name as that of the module itself.
:::
In the Basic Example above, we had a module named inc with a command named increment. However, if we rename that file to increment.nu, it will fail to import.
mv inc.nu increment.nu
use increment.nu *# => Error: nu::parser::named_as_module# => ...# => help: Module increment can't export command named# => the same as the module. Either change the module# => name, or export `main` command.
As helpfully mentioned in the error message, you can simply rename the export main, in which case it will take on the name of the module when imported. Edit the increment.nu file:
export def main []: int -> int {
$in+1
}
Now it works as expected:
use ./increment.nu2024 | increment# => 2025
::: note
main can be used for both export def and export extern definitions.
:::
::: tip
main definitions are imported in the following cases:
The entire module is imported with use <module> or use <module.nu>
The * glob is used to import all of the modules definitions (e.g., use <module> *, etc.)
The main definition is explicitly imported with use <module> main, use <module> [main], etc.)
Conversely, the following forms do not import the main definition:
use <module><other_definition># or
use <module> [ <other_definitions> ]
:::
::: note
Additionally,`main` has special behavior if used in a script file, regardless of whether it is exported ornot.See the [Scripts](../scripts.html#parameterizing-scripts) chapter for more details.:::## Module FilesAs mentioned briefly in the Overview above, modules can be created either as:1. `<module_name>.nu`: "File-form" - Useful for simple modules2. `<module_name>/mod.nu`: "Directory-form"-Usefulfor organizing larger module projects where submodules can easily map to subdirectories of the main module
The`increment.nu` example above is clearly an example of (1) the file-form.Let's try converting it to the directory-form:
```nu
mkdir increment
mv increment.nu increment/mod.nuuse increment *41 | increment# => 42
Notice that the behavior of the module once imported is identical regardless of whether the file-form or directory-form is used; only its path changes.
::: note
Technically, you can import this either using the directory form above or explicitly with use increment/mod.nu *, but the directory shorthand is preferred when using a mod.nu.
:::
Subcommands
As covered in Custom Commands, subcommands allow us to group commands logically. Using modules, this can be done in one of two ways:
As with any custom command, the command can be defined as "<command> <subcommand>", using a space inside quotes. Let's add an increment by subcommand to the increment module we defined above:
export def main []: int -> int {
$in+1
}
export def "increment by" [amount: int]: int -> int {
$in+$amount
}
It can then be imported with use increment * to load both the increment command and increment by subcommand.
Alternatively, we can define the subcommand simply using the name by, since importing the entire increment module will result in the same commands:
export def main []: int -> int {
$in+1
}
export def by [amount: int]: int -> int {
$in+$amount
}
This module is imported using use increment (without the glob *) and results in the same increment command and increment by subcommand.
::: note
We'll continue to use this version for further examples below, so notice that the import pattern has changed to use increment (rather than use increment *) below.
:::
Submodules
Submodules are modules that are exported from another module. There are two ways to add a submodule to a module:
With export module: Exports (a) the submodule and (b) its definitions as members of the submodule
With export use: Exports (a) the submodule and (b) its definitions as members of the parent module
To demonstrate the difference, let's create a new my-utils module, with our increment example as a submodule. Additionally, we'll create a new range-into-list command in its own submodule.
Create a directory for the new my-utils and move the increment.nu into it
mkdir my-utils
# Adjust the following as needed
mv increment/mod.nu my-utils/increment.nu
rm increment
cd my-utils
In the my-utils directory, create a range-into-list.nu file with the following:
export def main []: range ->list {
# It looks odd, yes, but the following is just# a simple way to convert ranges to lists
each {||}
}
Test it:
use range-into-list.nu
1..5| range-into-list| describe
# => list<int> (stream)
We should now have a my-utils directory with the:
increment.nu module
range-into-list.nu module
The following examples show how to create a module with submodules.
Example: Submodule with export module
The most common form for a submodule definition is with export module.
Create a new module named my-utils. Since we're in the my-utils directory, we will create a mod.nu to define it. This version of my-utils/mod.nu will contain:
We now have a module my-utils with the two submodules. Try it out:
# Go to the parent directory of my-utils
cd ..
use my-utils *5| increment by 4# => 9let file_indices =0..2..<10| range-into-list
ls | select ...$file_indices# => Returns the 1st, 3rd, 5th, 7th, and 9th file in the directory
Before proceeding to the next section, run scope modules and look for the my-utils module. Notice that it has no commands of its own; just the two submodules.
Example: Submodule with export use
Alternatively, we can (re)export the definitions from other modules. This is slightly different from the first form, in that the commands (and other definitions, if they were present) from increment and range-into-list become members of the my-utils module itself. We'll be able to see the difference in the output of the scope modules command.
Let's change my-utils/mod.nu to:
export use ./increment.nuexport use ./range-into-list.nu
Try it out using the same commands as above:
# Go to the parent directory of my-utils
cd ..
use my-utils *5| increment by 4# => 9let file_indices =0..2..<10| range-into-list
ls /| sort-by modified | select ...$file_indices# => Returns the 1st, 3rd, 5th, 7th, and 9th file in the directory, oldest-to-newest
Run scope modules again and notice that all of the commands from the submodules are re-exported into the my-utils module.
::: tip
While export module is the recommended and most common form, there is one module-design scenario in which export use is required -- export use can be used to selectively export definitions from the submodule, something export module cannot do. See Additional Examples - Selective Export for an example.
:::
::: note
module without export defines only a local module; it does not export a submodule.
:::
Documenting Modules
As with custom commands, modules can include documentation that can be viewed with help <module_name>. The documentation is simply a series of commented lines at the beginning of the module file. Let's document the my-utils module:
# A collection of helpful utility functions
export use ./increment.nuexport use ./range-into-list.nu
Now examine the help:
use my-utils *help my-utils
# => A collection of helpful utility functions
Also notice that, because the commands from increment and range-into-list are re-exported with export use ..., those commands show up in the help for the main module as well.
Environment Variables
Modules can define an environment using export-env. Let's extend our my-utils module with an environment variable export for a common directory where we'll place our modules in the future. This directory is (by default) in the $env.NU_LIB_DIRS search path discussed in Using Modules - Module Path.
# A collection of helpful utility functions
export use ./increment.nuexport use ./range-into-list.nu
export-env {
$env.NU_MODULES_DIR= ($nu.default-config-dir | path join "scripts")
}
When this module is imported with use, the code inside the export-env block is run and the its environment merged into the current scope:
use my-utils
$env.NU_MODULES_DIR# => Returns the directory name
cd $env.NU_MODULES_DIR
::: tip
As with any command defined without --env, commands and other definitions in the module use their own scope for environment. This allows changes to be made internal to the module without them bleeding into the user's scope. Add the following to the bottom of my-utils/mod.nu:
export def examine-config-dir [] {
# Changes the PWD environment variable
cd $nu.default-config-dir
ls
}
Running this command changes the directory locally in the module, but the changes are not propagated to the parent scope.
:::
Caveats
export-env runs only when the use call is evaluated
::: note
This scenario is commonly encountered when creating a module that uses std/log.
:::
Attempting to import a module's environment within another environment may not work as expected. Let's create a new module go.nu that creates "shortcuts" to common directories. One of these will be the $env.NU_MODULES_DIR defined above in my-utils.
We might try:
# go.nu, in the parent directory of my-utils
use my-utils
export def --env home [] {
cd ~
}
export def --env modules [] {
cd $env.NU_MODULES_DIR
}
And then import it:
use go.nu
go home
# => Works
go modules
# => Error: $env.NU_MODULES_DIR is not found
This doesn't work because my-utils isn't evaluated in this case; it is only parsed when the go.nu module is imported. While this brings all of the other exports into scope, it does not run the export-env block.
::: important
As mentioned at the start of this chapter, trying this while my-utils (and its $env.NU_MODULES_DIR) is still in scope from a previous import will not fail as expected. Test in a new shell session to see the "normal" failure.
:::
To bring my-utils exported environment into scope for the go.nu module, there are two options:
Import the module in each command where it is needed
By placing use my-utils in the go home command itself, its export-env will be evaluated when the command is. For example:
# go.nu
export def --env home [] {
cd ~
}
export def --env modules [] {
use my-utils
cd $env.NU_MODULES_DIR
}
Import the my-utils environment inside an export-env block in the go.nu module
use my-utils
export-env {
use my-utils []
}
export def --env home [] {
cd ~
}
export def --env modules [] {
cd $env.NU_MODULES_DIR
}
In the example above, go.nu imports my-utils twice:
The first use my-utils imports the module and its definitions (except for the environment) into the module scope.
The second use my-utils [] imports nothing but the environment into go.nu's exported environment block. Because the export-env of go.nu is executed when the module is first imported, the use my-utils [] is also evaluated.
Note that the first method keeps my-utils environment inside the go.nu module's scope. The second, on the other hand, re-exports my-utils environment into the user scope.
Module files and commands cannot be named after parent module
A .nu file cannot have the same name as its module directory (e.g., spam/spam.nu) as this would create an ambiguous condition with the name being defined twice. This is similar to the situation described above where a command cannot have the same name as its parent.
Windows Path Syntax
::: important
Nushell on Windows supports both forward-slashes and back-slashes as the path separator. However, to ensure that they work on all platforms, using only the forward-slash / in your modules is highly recommended.
:::
Additional Examples
Local Definitions
As mentioned above, definitions in a module without the export keyword are only accessible in the module's scope.
To demonstrate, create a new module is-alphanumeric.nu. Inside this module, we'll create a str is-alphanumeric command. If any of the characters in the string are not alpha-numeric, it returns false:
# is-alphanumeric.nu
def alpha-num-range [] {
[
...(seq char 'a''z')
...(seq char 'A''Z')
...(seq 09| each { into string })
]
}
export def "str is-alphanumeric" []: string -> bool {
if ($in== '') {
false
} else {
let chars = (split chars)
$chars| all {|char|$char in (alpha-num-range)}
}
}
Notice that we have two definitions in this module -- alpha-num-range and str is-alphanumeric, but only the second is exported.
use is-alphanumeric.nu *
'Word' | str is-alphanumeric
# => true
'Some punctuation?!' | str is-alphanumeric
# => false'a' in (alpha-num-range)
# => Error:# => help: `alpha-num-range` is neither a Nushell built-in or a known external command
Selective Export from a Submodule
::: note
While the following is a rare use-case, this technique is used by the Standard Library to
make the dirs commands and its aliases available separately.
:::
As mentioned in the Submodules section above, only export use can selectively export definitions from a submodule.
To demonstrate, let's add a modified form of the go.nu module example above to my-utils:
# go.nu, in the my-utils directory
export def --env home [] {
cd ~
}
export def --env modules [] {
cd ($nu.default-config-dir | path join "scripts")
}
export alias h = home
export alias m = modules
This go.nu includes the following changes from the original:
It doesn't rely on the my-utils mod since it will now be a submodule of my-utils instead
It adds "shortcut" aliases:
h: Goes to the home directory (alias of go home)
m: Goes to the modules directory (alias of go modules)
A user could import just the aliases with:
use my-utils/go.nu [h, m]
However, let's say we want to have go.nu be a submodule of my-utils. When a user imports my-utils, they should only get the commands, but not the aliases. Edit my-utils/mod.nu and add:
export use ./go.nu [home, modules]
That almost works -- It selectively exports home and modules, but not the aliases. However, it does so without the go prefix. For example:
use my-utils *
home
# => works
go home
# => Error: command not found
To export them as go home and go modules, make the following change to my-utils/mod.nu:
# Replace the existing `export use` with ...
export module go {
export use ./go.nu [home, modules]}
This creates a new, exported submodule go in my-utils with the selectively (re)exported definitions for go home and go modules.
use my-utils *# => As expected:
go home
# => works
home
# => Error: command not found
`book/modules/using_modules.md`:
```md
# Using Modules
[[toc]]
## Overview
End-users can add new functionality to Nushell by using ("importing") modules written by others.
To import a module and its definitions, we call the [`use`](/commands/docs/use.md) command:
```nu
use <path/to/module> <members...>
For example:
use std/loglog info "Hello, Modules"
::: tip
The example above uses the Standard Library, a collection of modules built-in to Nushell. Because it is readily available to all Nushell users, we'll also use it for several of the examples below.
:::
Installing Modules
Installing a module is simply a matter of placing its files in a directory. This might be done via git clone (or other version control system), a package manager such as nupm, or manually. The module's documentation should provide recommendations.
Importing Modules
Anything after the use keyword forms an import pattern which controls how the definitions are imported.
Notice above that use has two arguments:
A path to the module
(Optional) The definitions to import
The module's documentation will usually tell you the recommended way to import it. However, it can still be useful to understand the options available:
Module Path
The path to the module can be:
An absolute path to a directory containing a mod.nu file:
::: details Example
use ~/nushell/modules/nupm
Note that the module name (i.e., its directory) can end in a / (or \ on Windows), but as with most commands that take paths (e.g., cd), this is completely optional.
:::
A relative path to a directory containing a mod.nu file:
::: details Example
# cd then use the mod.nu in the relative nupm directory
cd ~/nushell/modules
use nupm
# or
use nupm/
Note that the module name (its directory) can end in a / (or \ on Windows), but as with most commands that take a paths (e.g., cd), this is completely optional.
:::
::: important Important! Importing modules from $env.NU_LIB_DIRS
When importing a module via a relative path, Nushell first searches from the current directory. If a matching module is not found at that location, Nushell then searches each directory in the $env.NU_LIB_DIRS list.
This allows you to install modules to a location that is easily accessible via a relative path regardless of the current directory.
:::
An absolute or relative path to a Nushell module file. As above, Nushell will search the $env.NU_LIB_DIRS for a matching relative path.
::: details Example
use ~/nushell/modules/std-rfc/bulk-rename.nu
# Or
cd ~/nushell/modules
use std-rfc/bulk-rename.nu
:::
A virtual directory:
::: details Example
The standard library modules mentioned above are stored in a virtual filesystem with a std directory. Consider this an alternate form of the "absolute path" examples above.
use std/assertassert equal 'string1' "string1"
:::
Less commonly, the name of a module already created with the module command. While it is possible to use this command to create a module at the commandline, this isn't common or useful. Instead, this form is primarily used by module authors to define a submodule. See Creating Modules - Submodules.
Module Definitions
The second argument to the use command is an optional list of the definitions to import. Again, the module documentation should provide recommendations. For example, the Standard Library Chapter covers the recommended imports for each submodule.
Of course, you always have the option to choose a form that works best for your use-case.
Import an entire module/submodule as a command with subcommands
In an earlier example above, we imported the std/log module without specifying the definitions:
use std/loglog info "Hello, std/log Module"
Notice that this imports the log submodule with all of its subcommands (e.g., log info, log error, etc.) into the current scope.
Compare the above to the next version, where the command becomes std log info:
use std
std log info "Hello, std Module"
Import all of the definitions from a module
Alternatively, you can import the definitions themselves into the current scope. For example:
use std/formats *ls | to jsonl
Notice how the to jsonl command is placed directly in the current scope, rather than being a subcommand of formats.
Import one or more definitions from a module
Nushell can also selectively import a subset of the definitions of a module. For example:
use std/math PIlet circle = 2 * $PI * $radius
Keep in mind that the definitions can be:
Commands
Aliases
Constants
Externs
Other modules (as submodules)
Environment variables (always imported)
Less commonly, a list of imports can also be used:
use std/formats [ 'from ndjson' 'to ndjson' ]
::: note Importing submodules
While you can import a submodule by itself using use <module> </submodule> (e.g., use std help), the entire parent module and all of its definitions (and thus submodules) will be parsed when using this form. When possible, loading the submodule as a module will result in faster code. For example:
# Faster
use std/help
:::
Importing Constants
As seen above with the std/math examples, some modules may export constant definitions. When importing the entire module, constants can be accessed through a record with the same name as the module:
# Importing entire module - Record access
use std/math$math.PI# => 3.141592653589793$math# => ╭───────┬──────╮# => │ GAMMA │ 0.58 │# => │ E │ 2.72 │# => │ PI │ 3.14 │# => │ TAU │ 6.28 │# => │ PHI │ 1.62 │# => ╰───────┴──────╯# Or importing all of the module's membersuse std/math *$PI# => 3.141592653589793
Hiding
Any custom command or alias, whether imported from a module or not, can be "hidden" to restore the previous definition using
the hide command.
The hide command also accepts import patterns, similar to use, but interprets them slightly differently. These patterns can be one of the following:
If the name is a custom command, the hide command hides it directly.
If the name is a module name, it hides all of its exports prefixed with the module name
For example, using std/assert:
use std/assertassert equal 1 2# => Assertion failedassert true# => Assertion passeshide assertassert equal 1 1# => Error:# => help: A command with that name exists in module `assert`. Try importing it with `use`assert true# => Error:# => help: A command with that name exists in module `assert`. Try importing it with `use`
Just as you can use a subset of the module's definitions, you can also hide them selectively as well:
use std/asserthide assert mainassert equal 1 1# => assertion passesassert true# => Error:# => help: A command with that name exists in module `assert`. Try importing it with `use`
::: tip
main is covered in more detail in Creating Modules, but for end-users, main simply means "the command named the same as the module." In this case the assert module exports a main command that "masquerades" as the assert command. Hiding main has the effect of hiding the assert command, but not its subcommands.
:::
See Also
To make a module always be available without having to use it in each Nushell session, simply add its import (use) to your startup configuration. See the Configuration Chapter to learn how.
`book/moving_around.md`:
```md
# Moving Around the System
A defining characteristic of a shell is the ability to navigate and interact with the filesystem. Nushell is, of course, no exception. Here are some common commands you might use when interacting with the filesystem:
## Viewing Directory Contents
```nu
ls
As seen in the Quick Tour, the ls command returns the contents of a directory. Nushell's ls will return the contents as a table.
The ls command also takes an optional argument to change what you'd like to view. For example, we can list the files that end in ".md"
The asterisk (*) in the above optional argument *.md is sometimes called a wildcard or a glob. It lets us match anything. You can read this glob *.md as "match any filename, so long as it ends with '.md'."
The most general glob is *, which will match all paths. More often, you'll see this pattern used as part of another pattern, for example *.bak and temp*.
Nushell also supports a double * which will traverse paths that are nested inside of other directories. For example, ls **/* will list all the non-hidden paths nested under the current directory.
ls **/*.md# => ╭───┬───────────────────────────────┬──────┬──────────┬──────────────╮# => │ # │ name │ type │ size │ modified │# => ├───┼───────────────────────────────┼──────┼──────────┼──────────────┤# => │ 0 │ CODE_OF_CONDUCT.md │ file │ 3.4 KiB │ 5 months ago │# => │ 1 │ CONTRIBUTING.md │ file │ 11.0 KiB │ a month ago │# => │ 2 │ README.md │ file │ 12.0 KiB │ a month ago │# => │ 3 │ SECURITY.md │ file │ 2.6 KiB │ 5 hours ago │# => │ 4 │ benches/README.md │ file │ 249B │ 2 months ago │
# => │ 5 │ crates/README.md │ file │ 795 B │ 5 months ago │# => │ 6 │ crates/nu-cli/README.md │ file │ 388 B │ 5 hours ago │# => │ 7 │ crates/nu-cmd-base/README.md │ file │ 262 B │ 5 hours ago │# => │ 8 │ crates/nu-cmd-extra/README.md │ file │ 669 B │ 2 months ago │# => │ 9 │ crates/nu-cmd-lang/README.md │ file │ 1.5 KiB │ a month ago │# => ╰───┴───────────────────────────────┴──────┴──────────┴──────────────╯
Here, we're looking for any file that ends with ".md". The double-asterisks further specify "in any directory starting from here."
Escaping the *, ?, and [] patterns works by enclosing them in a single-quoted, double-quoted, or
raw string. For example, to show the contents of a directory named
[slug], use ls "[slug]" or ls '[slug]'.
However, backtick quoted strings do not escape globs. For example, compare the following scenarios:
Unquoted: Glob pattern
An unquoted bare word string with glob characters is interpreted as a glob pattern, so the following will remove all files in the current directory that contain
myfile as any part of the filename:
rm *myfile*
Quoted: String literal with asterisks
When quoting with single or double quotes, or using a raw string, a string with the literal, escaped asterisks (or other glob characters) is passed to the command. The result is not a glob. The following command will only remove a file literally named *myfile* (including the asterisks). Other files with myfile in the name are not affected:
rm "*myfile*"
Backtick-quoted: Glob pattern
Asterisks (and other glob patterns) within a backtick-quoted string are interpreted as a glob pattern. Notice that this is the same behavior as that of the bare-word string example in #1 above.
The following, as with that first example, removes all files in the current directory that contain myfile as part of the filename
rm `*myfile*`
::: tip
Nushell also includes a dedicated glob command with support for more complex globbing scenarios.
:::
Converting Strings to Globs
The quoting techniques above are useful when constructing glob-literals, but you may need to construct globs programmatically. There are several techniques available for this purpose:
into glob
The into glob command can be used to convert a string (and other types) into a glob. For instance:
# Find files whose name includes the current month in the form YYYY-mmlet current_month = (date now | format date '%Y-%m')
let glob_pattern = ($"*($current_month)*"| into glob)
ls $glob_pattern
The spread operator combined with the glob command:
The glob command (note: not the same as into glob) produces a list of filenames that match the glob pattern. This list can be expanded and passed to filesystem commands using the spread operator:
# Find files whose name includes the current month in the form YYYY-mmlet current_month = (date now | format date '%Y-%m')
ls ...(glob $"*($current_month)*")
Force glob type via annotation:
# Find files whose name includes the current month in the form YYYY-mmlet current_month = (date now | format date '%Y-%m')
let glob_pattern: glob = ($"*($current_month)*")
ls $glob_pattern
Creating a Directory
As with most other shells, the mkdir command is used to create new directories. One subtle difference is that Nushell's internal mkdir command operates like the Unix/Linux mkdir -p by default, in that it:
Will create multiple directory levels automatically. For example:
mkdir modules/my/new_module
This will create all three directories even if none of them currently exists. On Linux/Unix, this requires mkdir -p.
Will not error if the directory already exists. For example:
mkdir modules/my/new_module
mkdir modules/my/new_module
# => No error
::: tip
A common mistake when coming to Nushell is to attempt to use mkdir -p <directory> as in the native Linux/Unix version. However, this will generate an Unknown Flag error on Nushell.
Just repeat the command without the -p to achieve the same effect.
:::
Changing the Current Directory
cd cookbook
To change from the current directory to a new one, use the cd command.
Changing the current working directory can also be done if cd is omitted and a path by itself is given:
cookbook/
Just as in other shells, you can use either the name of the directory, or if you want to go up a directory you can use the .. shortcut.
You can also add additional dots to go up additional directory levels:
# Change to the parent directory
cd ..# or..# Go up two levels (parent's parent)
cd ...# or...# Go up three levels (parent of parent's parent)
cd ....# Etc.
::: tip
Multi-dot shortcuts are available to both internal Nushell filesystem commands as well as to external commands. For example, running ^stat .... on a Linux/Unix system will show that the path is expanded to ../../..
:::
You can combine relative directory levels with directory names as well:
cd ../sibling
::: tip IMPORTANT TIP
Changing the directory with cd changes the PWD environment variable. This means that a change of a directory is kept to the current scope (e.g. block or closure). Once you exit the block, you'll return to the previous directory. You can learn more about this in the Environment chapter.
:::
Filesystem Commands
Nu also provides some basic filesystem commands that work cross-platform such as:
mv to rename or move a file or directory to a new location
::: tip NOTE
Under Bash and many other shells, most filesystem commands (other than cd) are actually separate binaries in the system. For instance, on a Linux system, cp is the /usr/bin/cp binary. In Nushell, these commands are built-in. This has several advantages:
They work consistently on platforms where a binary version may not be available (e.g. Windows). This allows the creation of cross-platform scripts, modules, and custom commands.
They are more tightly integrated with Nushell, allowing them to understand Nushell types and other constructs
As mentioned in the Quick Tour, they are documented in the Nushell help system. Running help <command> or <command> --help will display the Nushell documentation for the command.
While the use of the Nushell built-in versions is typically recommended, it is possible to access the Linux binaries. See Running System Commands for details.
`book/navigating_structured_data.md`:
```md
# Navigating and Accessing Structured Data
Given Nushell's strong support for structured data, some of the more common tasks involve navigating and accessing that data.
## Index to this Section
- [Background and Definitions](#background)
- [Cell-paths](#cell-paths)
- [With Records](#records)
- [With Lists](#lists)
- [With Tables](#tables)
- Sample Data
- Example - Access a Table Row
- Example - Access a Table Column
- [With Nested Data](#nested-data)
- [Using `get` and `select`](#using-get-and-select)
- Example - `get` vs. `select` with a Table Row
- Example - `select` with multiple rows and columns
- [Handling missing data using the optional operator](#the-optional-operator)
- [Key/Column names with spaces](#keycolumn-names-with-spaces)
- [Other commands for navigating structured data](#other-commands-for-accessing-structured-data)
## Background
For the examples and descriptions below, keep in mind several definitions regarding structured data:
- **_List:_** Lists contain a series of zero or more values of any type. A list with zero values is known as an "empty list"
- **_Record:_** Records contain zero or more pairs of named keys and their corresponding value. The data in a record's value can also be of any type. A record with zero key-value pairs is known as an "empty record"
- **_Nested Data:_** The values contained in a list, record, or table can be either of a basic type or structured data themselves. This means that data can be nested multiple levels and in multiple forms:
- List values can contain tables, records, and even other lists
- **_Table:_** Tables are a list of records
- Record values can contain tables, lists, and other records
- This means that the records of a table can also contain nested tables, lists, and other records
::: tip
Because a table is a list of records, any command or syntax that works on a list will also work on a table. The converse is not necessarily the case; there are some commands and syntax that work on tables but not lists.
:::
## Cell-paths
A cell-path is the primary way to access values inside structured data. This path is based on a concept similar to that of a spreadsheet, where columns have names and rows have numbers. Cell-path names and indices are separated by dots.
### Records
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 = {
a: 5
b: 42
}
$my_record.b + 5
# => 47
Lists
For a list, the cell-path specifies the position (index) of the value in the list. This is an int:
Example - Access a List Value:
Remember, list indices are 0-based.
let scoobies_list = [ VelmaFredDaphneShaggyScooby ]
$scoobies_list.2# => Daphne
Tables
To access a column, a cell-path uses the name of the column, which is a string
To access a row, it uses the index number of the row, which is an int
To access a single cell, it uses a combination of the column name with the row index.
The next few examples will use the following table:
let data = [
[date temps condition ];
[2022-02-01T14:30:00+05:00, [38.24,38.50,37.99,37.98,39.10], 'sunny' ],
[2022-02-02T14:30:00+05:00, [35.24,35.94,34.91,35.24,36.65], 'sunny' ],
[2022-02-03T14:30:00+05:00, [35.17,36.67,34.42,35.76,36.52], 'cloudy' ],
[2022-02-04T14:30:00+05:00, [39.24,40.94,39.21,38.99,38.80], 'rain' ]
]
::: details Expand for a visual representation of this data
Since data can be nested, a cell-path can contain references to multiple names or indices.
Example - Accessing Nested Table Data
To obtain the temperature at the second weather station on the third day:
$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.
Using get and select
In addition to the cell-path literal syntax used above, Nushell also provides several commands that utilize cell-paths. The most important of these are:
get is equivalent to using a cell-path literal but with support for variable names and expressions. get, like the cell-path examples above, returns the value indicated by the cell-path.
select is subtly, but critically, different. It returns the specified data structure itself, rather than just its value.
Using select on a table will return a table of equal or lesser size
Using select on a list will return a list of equal or lesser size
Using select on a record will return a record of equal or lesser size
get returns the same record as the $data.1 example above
select returns a new, single-row table, including column names and row indices
::: tip
The row indices of the table resulting from select are not the same as that of the original. The new table has its own, 0-based index.
To obtain the original index, you can use the enumerate command. For example:
$data| enumerate | select 1
:::
Example - select with multiple rows and columns
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:
$data| select date condition 01# => ╭───┬─────────────┬───────────╮# => │ # │ date │ condition │# => ├───┼─────────────┼───────────┤# => │ 0 │ 2 years ago │ sunny │# => │ 1 │ 2 years ago │ sunny │# => ╰───┴─────────────┴───────────╯
Key/Column names with spaces
If a key name or column name contains spaces or other characters that prevent it from being accessible as a bare-word string, then the key name may be quoted.
Example:
let record_example = {
"key x":12"key y":4
}
$record_example."key x"# => 12# or$record_example| get "key x"# => 12
Quotes are also required when a key name may be confused for a numeric value.
Example:
let record_example = {
"1": foo
"2": baz
"3": far
}
$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).
Handling Missing Data
The Optional Operator
By default, cell path access will fail if it can't access the requested row or column. To suppress these errors, you can add a ? to a cell path member to mark it as optional:
Example - The Optional Operator
Using the temp data from above:
let cp: cell-path = $.temps?.1# only get the 2nd location from the temps column# Ooops, we've removed the temps column$data| reject temps | get $cp
By default missing cells will be replaced by null when accessed via the optional operator.
Assigning a default for missing or null data
The default command can be used to apply a default value to missing or null column result.
reject is the opposite of select, removing the specified rows and columns
slice specifies the rows of a list or table to select using a range type
`book/nu_as_a_shell.md`:
```md
---
prev:
text: Best Practices
link: /book/style_guide.md
next:
text: Configuration
link: /book/configuration.md
---
# Nu as a Shell
The [Nu Fundamentals](nu_fundamentals.md) and [Programming in Nu](programming_in_nu.md) chapter focused mostly on the language aspects of Nushell.
This chapter sheds the light on the parts of Nushell that are related to the Nushell interpreter (the Nushell [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)).
Some of the concepts are directly a part of the Nushell programming language (such as environment variables) while others are implemented purely to enhance the interactive experience (such as hooks) and thus are not present when, for example, running a script.
Many parameters of Nushell can be [configured](configuration.md).
The config itself is stored as an environment variable.
Furthermore, Nushell has several different configuration files that are run on startup where you can put custom commands, aliases, etc.
A big feature of any shell are [environment variables](environment.md).
In Nushell, environment variables are scoped and can have any type supported by Nushell.
This brings in some additional design considerations so please refer to the linked section for more details.
The other sections explain how to work with [stdout, stderr and exit codes](stdout_stderr_exit_codes.md), how to [run an external command when there is a built-in with the same name](./running_externals.md), and how to [configure 3rd party prompts](3rdpartyprompts.md) to work with Nushell.
An interesting feature of Nushell is the [Directory Stack](directory_stack.md) which let you work in multiple directories simultaneously.
Nushell also has its own line editor [Reedline](line_editor.md).
With Nushell's config, it is possible to configure some of the Reedline's features, such as the prompt, keybindings, history, or menus.
It is also possible to define [custom signatures for external commands](externs.md) which lets you define [custom completions](custom_completions.md) for them (the custom completions also work for Nushell custom commands).
[Coloring and Theming in Nu](coloring_and_theming.md) goes into more detail about how to configure Nushell's appearance.
If you want to schedule some commands to run in the background, [Background jobs](background_jobs.md) provides simple guidelines for you to follow.
Finally, [hooks](hooks.md) allow you to insert fragments of Nushell code to run at certain events.
book/nu_fundamentals.md:
---prev:
text: Nushell Cheat Sheetlink: cheat_sheet.mdnext:
text: Types of Datalink: /book/types_of_data.md---# Nu Fundamentals
This chapter explains some of the fundamentals of the Nushell programming language.
After going through it, you should have an idea how to write simple Nushell programs.
Nushell has a rich type system.
You will find typical data types such as strings or integers and less typical data types, such as cell paths.
Furthermore, one of the defining features of Nushell is the notion of _structured data_ which means that you can organize types into collections: lists, records, or tables.
Contrary to the traditional Unix approach where commands communicate via plain text, Nushell commands communicate via these data types.
All of the above is explained in [Types of Data](types_of_data.md).
[Loading Data](loading_data.md) explains how to read common data formats, such as JSON, into _structured data_. This includes our own "NUON" data format.
Just like Unix shells, Nushell commands can be composed into [pipelines](pipelines.md) to pass and modify a stream of data.
Some data types have interesting features that deserve their own sections: [strings](working_with_strings.md), [lists](working_with_lists.md), and [tables](working_with_tables.md).
Apart from explaining the features, these sections also show how to do some common operations, such as composing strings or updating values in a list.
Finally, [Command Reference](/commands/) lists all the built-in commands with brief descriptions.
Note that you can also access this info from within Nushell using the [`help`](/commands/docs/help.md) command.
book/nushell_map.md:
# Nu map from other shells and domain specific languages
The idea behind this table is to help you understand how Nu builtins and plugins relate to other known shells and domain specific languages. We've tried to produce a map of relevant Nu commands and what their equivalents are in other languages. Contributions are welcome.
| Nushell | SQL | .Net LINQ (C#) | PowerShell (without external modules) | Bash || ---------------------------------------------------------- | ----------------------------- | ---------------------------------------------------- | ------------------------------------------ | ----------------------------------------------- ||[`alias`](/commands/docs/alias.md)|||`alias`|`alias`||[`append`](/commands/docs/append.md)||`Append`|`-Append`|||[`math avg`](/commands/docs/math_avg.md)|`avg`|`Average`|`Measure-Object`, `measure`|||[Operators](operators.md) and [`math`](/commands/docs/math.md)| Math operators |`Aggregate`, `Average`, `Count`, `Max`, `Min`, `Sum`||`bc`||[`cd`](/commands/docs/cd.md)|||`Set-Location`, `cd`|`cd`||[`clear`](/commands/docs/clear.md)<br /><kbd>Ctrl/⌘</kbd>+<kbd>L</kbd> |||`Clear-Host`<br /><kbd>Ctrl/⌘</kbd>+<kbd>L</kbd> |`clear`<br /><kbd>Ctrl/⌘</kbd>+<kbd>L</kbd> ||[`config`](/commands/docs/config.md)<br />`$nu.default-config-dir`|||`$Profile`|`~/.bashrc`, `~/.profile`||[`cp`](/commands/docs/cp.md)|||`Copy-Item`, `cp`, `copy`|`cp`||[`date`](/commands/docs/date.md)|`NOW()`, `getdate()`|`DateTime` class |`Get-Date`|`date`||[`du`](/commands/docs/du.md)<br />[`ls --du`](/commands/docs/ls.md)||||`du`||[`each`](/commands/docs/each.md)| Cursors ||`ForEach-Object`, `foreach`, `for`|`for`||[`exit`](/commands/docs/exit.md)<br /><kbd>Ctrl/⌘</kbd>+<kbd>D</kbd> |||`exit`<br /><kbd>Ctrl/⌘</kbd>+<kbd>D</kbd> |`exit`<br /><kbd>Ctrl/⌘</kbd>+<kbd>D</kbd> ||[`http`](/commands/docs/http.md)||`HttpClient`, `WebClient`, `HttpWebRequest/Response`|`Invoke-WebRequest`|`wget`, `curl`||[`first`](/commands/docs/first.md)|`top`, `limit`|`First`, `FirstOrDefault`|`Select-Object -First`|`head`||[`format`](/commands/docs/format.md), [`str`](/commands/docs/str.md)||`String.Format`|`String.Format`|`printf`||[`from`](/commands/docs/from.md)|`import flatfile,``openjson`, `cast(variable as xml) `||`Import/ConvertFrom-{Csv,Xml,Html,Json}`|||[`get`](/commands/docs/get.md)||`Select`|`(cmd).column`|||[`group-by`](/commands/docs/group-by.md)|`group by`|`GroupBy`, `group`|`Group-Object`, `group`|||[`help`](/commands/docs/help.md)|`sp_help`||`Get-Help`, `help`, `man`|`man`||[`history`](/commands/docs/history.md)|||`Get-History`, `history`|`history`||[`is-empty`](/commands/docs/is-empty.md)|`is null`|`String.IsNullOrEmpty`|`String.IsNullOrEmpty`|||[`kill`](/commands/docs/kill.md)|||`Stop-Process`, `kill`|`kill`||[`last`](/commands/docs/last.md)||`Last`, `LastOrDefault`|`Select-Object -Last`|`tail`||[`str stats`](/commands/docs/str_stats.md)<br />[`length`](/commands/docs/length.md)<br />[`str length`](/commands/docs/str_length.md)|`count`|`Count`|`Measure-Object`, `measure`|`wc`||[`lines`](/commands/docs/lines.md)|||`File.ReadAllLines`|||[`ls`](/commands/docs/ls.md)|||`Get-ChildItem`, `dir`, `ls`|`ls`||[`mkdir`](/commands/docs/mkdir.md)|||`mkdir`, `md`, `New-Item -ItemType Directory`|`mkdir`||[`mv`](/commands/docs/mv.md)|||`Move-Item`, `mv`, `move`, `mi`|`mv`||[`open`](/commands/docs/open.md)|||`Get-Content`, `gc`, `cat`, `type`|`cat`||[`print`](/commands/docs/print.md)|`print`, `union all`||`Write-Output`, `write`|`echo`, `print`||[`transpose`](/commands/docs/transpose.md)|`pivot`|||||[`ps`](/commands/docs/ps.md)|||`Get-Process`, `ps`, `gps`|`ps`||[`pwd`](/commands/docs/pwd.md)|||`Get-Location`, `pwd`|`pwd`||[`range`](types_of_data.html#ranges)||`Range`|`1..10`, `'a'..'f'`|||[`reduce`](/commands/docs/reduce.md)||`Aggregate`||||[`rename`](/commands/docs/rename.md)|||`Rename-Item`, `ren`, `rni`|`mv`||[`reverse`](/commands/docs/reverse.md)||`Reverse`|`[Array]::Reverse($var)`|||[`rm`](/commands/docs/rm.md)|||`Remove-Item`, `del`, `erase`, `rd`, `ri`, `rm`, `rmdir`|`rm`||[`save`](/commands/docs/save.md)|||`Write-Output`, `Out-File`|`> foo.txt` redirection ||[`select`](/commands/docs/select.md)|`select`|`Select`|`Select-Object`, `select`|||[`shuffle`](/commands/docs/shuffle.md)||`Random`|`Sort-Object {Get-Random}`|||[`skip`](/commands/docs/skip.md)|`where row_number()`|`Skip`|`Select-Object -Skip`|||[`skip until`](/commands/docs/skip_until.md)||`SkipWhile`||||[`skip while`](/commands/docs/skip_while.md)||`SkipWhile`||||[`slice`](/commands/docs/slice.md)|`limit x offset y`, `rownumber`|`ElementAt`|`[x]`, indexing operator, `ElementAt`|||[`sort-by`](/commands/docs/sort-by.md)|`order by`|`OrderBy`, `OrderByDescending`, `ThenBy`, `ThenByDescending`|`Sort-Object`, `sort`|`sort`||[`str`](/commands/docs/str.md)| String functions |`String` class |`String` class |||[`str join`](/commands/docs/str_join.md)|`concat_ws`|`Join`|`Join-String`|||[`str trim`](/commands/docs/str_trim.md)|`rtrim`, `ltrim`|`Trim`, `TrimStart`, `TrimEnd`|`Trim`|||[`math sum`](/commands/docs/math_sum.md)| ``sum` |`Sum`|`Measure-Object`, `measure`|||[`uname`](/commands/docs/uname.md)<br />[`sys host`](/commands/docs/sys_host.md)|||`Get-ComputerInfo`|`uname`||[`sys disks`](/commands/docs/sys_disks.md)|||`Get-ComputerInfo`|`lsblk`||[`sys mem`](/commands/docs/sys_mem.md)|||`Get-ComputerInfo`|`free`||[`table`](/commands/docs/table.md)|||`Format-Table`, `ft`, `Format-List`, `fl`|||[`take`](/commands/docs/take.md)|`top`, `limit`|`Take`|`Select-Object -First`|`head`||[`take until`](/commands/docs/take_until.md)||`TakeWhile`||||[`take while`](/commands/docs/take_while.md)||`TakeWhile`||||[`timeit`](/commands/docs/timeit.md)|||`Measure-Command`|`time`||[`to`](/commands/docs/to.md)|||`Export`/`ConvertTo-{Csv,Xml,Html,Json}`|||[`touch`](/commands/docs/touch.md)|||`Set-Content`|`touch`||[`uniq`](/commands/docs/uniq.md)|`distinct`|`Distinct`|`Get-Unique`, `gu`|`uniq`||[`update`](/commands/docs/update.md)|||`ForEach-Object`|||[`upsert`](/commands/docs/upsert.md)|`As`||`ForEach-Object`|||[`version`](/commands/docs/version.md)|`select @@version`||`$PSVersionTable`|||`$env.FOO = "bar"`<br />[`with-env`](/commands/docs/with-env.md)|||`$env:FOO = 'bar'`|`export FOO "bar"`||[`where`](/commands/docs/where.md)|`where`|`Where`|`Where-Object`, `where`, `?` operator |||[`which`](/commands/docs/which.md)|||`Get-Command`|`which`|
book/nushell_map_functional.md:
# Nu Map from Functional Languages
The idea behind this table is to help you understand how Nu builtins and plugins relate to functional languages. We've tried to produce a map of relevant Nu commands and what their equivalents are in other languages. Contributions are welcome.
Note: this table assumes Nu 0.43 or later.
| Nushell | Clojure | Tablecloth (Ocaml / Elm) | Haskell || ------------ | ---------------------------- | ------------------------------- | ------------------------ || append | conj, into, concat | append, (++), concat, concatMap | (++) || into binary | Integer/toHexString || showHex || count | count | length, size | length, size || date | java.time.LocalDate/now |||| each | map, mapv, iterate | map, forEach | map, mapM || exit | System/exit |||| first | first | head | head || format | format || Text.Printf.printf || group-by | group-by || group, groupBy || help | doc |||| is-empty | empty? | isEmpty ||| last | last, peek, take-last | last | last || lines ||| lines, words, split-with || match || match (Ocaml), case (Elm) | case || nth | nth | Array.get | lookup || open | with-open |||| transpose | (apply mapv vector matrix) || transpose || prepend | cons | cons, :: | :: || print | println || putStrLn, print || range, 1..10 | range | range | 1..10, 'a'..'f' || reduce | reduce, reduce-kv | foldr | foldr || reverse | reverse, rseq | reverse, reverseInPlace | reverse || select | select-keys |||| shuffle | shuffle |||| size | count || size, length || skip | rest | tail | tail || skip until | drop-while |||| skip while | drop-while | dropWhile | dropWhile, dropWhileEnd || sort-by | sort, sort-by, sorted-set-by | sort, sortBy, sortWith | sort, sortBy || split row | split, split-{at,with,lines} | split, words, lines | split, words, lines || str | clojure.string functions | String functions ||| str join | join | concat | intercalate || str trim | trim, triml, trimr | trim, trimLeft, trimRight | strip || sum | apply + | sum | sum || take | take, drop-last, pop | take, init | take, init || take until | take-while | takeWhile | takeWhile || take while | take-while | takeWhile | takeWhile || uniq | set | Set.empty | Data.Set || where | filter, filterv, select | filter, filterMap | filter |
book/nushell_map_imperative.md:
# Nu Map from Imperative Languages
The idea behind this table is to help you understand how Nu built-ins and plugins relate to imperative languages. We've tried to produce a map of programming-relevant Nu commands and what their equivalents are in other languages. Contributions are welcome.
Note: this table assumes Nu 0.94 or later.
| Nushell | Python | Kotlin (Java) | C++ | Rust || -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------------------------------------------------------- | --------------------------- | ---------------------------------------------------- ||[`append`](/commands/docs/append.md)|`list.append`, `set.add`|`add`|`push_back`, `emplace_back`|`push`, `push_back`||[`math avg`](/commands/docs/math_avg.md)|`statistics.mean`|||||[`math`](/commands/docs/math.md), [Math Operators](nushell_operator_map.md)| Math operators | Math operators | Math operators | Math operators ||[`cp`](/commands/docs/cp.md)|`shutil.copy`|||`fs::copy`||[`date`](/commands/docs/date.md)|`datetime.date.today`|`java.time.LocalDate.now`||||[`drop`](/commands/docs/drop.md)|`list[:-3]`|||||[`du`](/commands/docs/du.md), [`ls --du`](/commands/docs/ls.md)|`shutil.disk_usage`|||||[`each`](/commands/docs/each.md)<br />[`for`](/commands/docs/for.md)|`for`|`for`|`for`|`for`||[`exit`](/commands/docs/exit.md)|`exit()`|`System.exit`, `kotlin.system.exitProcess`|`exit`|`exit`||[`http get`](/commands/docs/http_get.md)|`urllib.request.urlopen`|||||[`first`](/commands/docs/first.md)|`list[:x]`|`List[0]`, `peek`|`vector[0]`, `top`|`Vec[0]`||[`format`](/commands/docs/format.md)|`format`|`format`|`format`|`format!`||[`from`](/commands/docs/from.md)|`csv`, `json`, `sqlite3`|||||[`get`](/commands/docs/get.md)|`dict[\"key\"]`|`Map[\"key\"]`|`map[\"key\"]`|`HashMap["key"]`, `get`, `entry`||[`group-by`](/commands/docs/group-by.md)|`itertools.groupby`|`groupBy`||`group_by`||[`headers`](/commands/docs/headers.md)|`keys`|||||[`help`](/commands/docs/help.md)|`help()`|||||[`insert`](/commands/docs/insert.md)|`dict[\"key\"] = val`||`map.insert({ 20, 130 })`|`map.insert(\"key\", val)`||[`is-empty`](/commands/docs/is-empty.md)|`is None`, `is []`|`isEmpty`|`empty`|`is_empty`||[`take`](/commands/docs/take.md)|`list[:x]`|||`&Vec[..x]`||[`take until`](/commands/docs/take_until.md)|`itertools.takewhile`|||||[`take while`](/commands/docs/take_while.md)|`itertools.takewhile`|||||[`kill`](/commands/docs/kill.md)|`os.kill`|||||[`last`](/commands/docs/last.md)|`list[-x:]`|||`&Vec[Vec.len()-1]`||[`length`](/commands/docs/length.md)|`len`|`size`, `length`|`length`|`len`||[`lines`](/commands/docs/lines.md)|`split`, `splitlines`|`split`|`views::split`|`split`, `split_whitespace`, `rsplit`, `lines`||[`ls`](/commands/docs/ls.md)|`os.listdir`|||`fs::read_dir`||[`match`](/commands/docs/match.md)|`match`|`when`||`match`||[`merge`](/commands/docs/merge.md)|`dict.append`|||`map.extend`||[`mkdir`](/commands/docs/mkdir.md)|`os.mkdir`|||`fs::create_dir`||[`mv`](/commands/docs/mv.md)|`shutil.move`|||`fs::rename`||[`get`](/commands/docs/get.md)|`list[x]`|`List[x]`|`vector[x]`|`Vec[x]`||[`open`](/commands/docs/open.md)|`open`|||||[`transpose`](/commands/docs/transpose.md)|`zip(\*matrix)`|||||[`http post`](/commands/docs/http_post.md)|`urllib.request.urlopen`|||||[`prepend`](/commands/docs/prepend.md)|`deque.appendleft`|||||[`print`](/commands/docs/print.md)|`print`|`println`|`printf`|`println!`||[`ps`](/commands/docs/ps.md)|`os.listdir('/proc')`|||||[`pwd`](/commands/docs/pwd.md)|`os.getcwd`|||`env::current_dir`||[`range`](types_of_data.html#ranges) type |`range`|`..`, `until`, `downTo`, `step`|`iota`|`..`||[`reduce`](/commands/docs/reduce.md)|`functools.reduce`|`reduce`|`reduce`|`fold`, `rfold`, `scan`||[`reject`](/commands/docs/reject.md)|`del`|||||[`rename`](/commands/docs/rename.md)|`dict[\"key2\"] = dict.pop(\"key\")`|||`map.insert(\"key2\", map.remove(\"key\").unwrap())`||[`reverse`](/commands/docs/reverse.md)|`reversed`, `list.reverse`|`reverse`, `reversed`, `asReversed`|`reverse`|`rev`||[`rm`](/commands/docs/rm.md)|`os.remove`|||||[`save`](/commands/docs/save.md)|`io.TextIOWrapper.write`|||||[`select`](/commands/docs/select.md)|`{k:dict[k] for k in keys}`|||||[`shuffle`](/commands/docs/shuffle.md)|`random.shuffle`|||||[`str stats`](/commands/docs/str_stats.md)<br />[`str length`](/commands/docs/str_length.md)<br />[`length`](/commands/docs/length.md)|`len`|||`len`||[`skip`](/commands/docs/skip.md)|`list[x:]`|||`&Vec[x..]`, `skip`||[`skip until`](/commands/docs/skip_until.md)|`itertools.dropwhile`|||||[`skip while`](/commands/docs/skip_while.md)|`itertools.dropwhile`|||`skip_while`||[`sort-by`](/commands/docs/sort-by.md)|`sorted`, `list.sort`|`sortedBy`, `sortedWith`, `Arrays.sort`, `Collections.sort`|`sort`|`sort`||[`split row`](/commands/docs/split_row.md)|`str.split{,lines}`, `re.split`|`split`|`views::split`|`split`||[`str`](/commands/docs/str.md)|`str` functions | String functions | String functions |`&str`, String functions ||[`str join`](/commands/docs/str_join.md)|`str.join`|`joinToString`||`join`||[`str trim`](/commands/docs/str_trim.md)|`strip`, `rstrip`, `lstrip`|`trim`, `trimStart`, `trimEnd`| Regex |`trim`, `trim*{start,end}`, `strip*{suffix,prefix}`||[`math sum`](/commands/docs/math_sum.md)|`sum`|`sum`|`reduce`|`sum`||[`to`](/commands/docs/to.md)|`import csv`, `json`, `sqlite3`|||||[`touch`](/commands/docs/touch.md)|`open(path, 'a').close()`|||||[`uniq`](/commands/docs/uniq.md)|`set`| Set |`set`|`HashSet`||[`upsert`](/commands/docs/upsert.md)|`dict[\"key\"] = val`|||||[`version`](/commands/docs/version.md)|`sys.version`, `sys.version_info`|||||[`with-env`](/commands/docs/with-env.md)<br />`$env.FOO = "bar"`|`os.environ`|||||[`where`](/commands/docs/where.md)|`filter`|`filter`|`filter`|`filter`||[`which`](/commands/docs/which.md)|`shutil.which`|||||[`wrap`](/commands/docs/wrap.md)|`{ "key" : val }`||||
book/nushell_operator_map.md:
---next:
text: Design Noteslink: /book/design_notes.md---# Nushell operator map
The idea behind this table is to help you understand how Nu operators relate to other language operators. We've tried to produce a map of all the nushell operators and what their equivalents are in other languages. Contributions are welcome.
Note: this table assumes Nu 0.14.1 or later.
| Nushell | SQL | Python | .NET LINQ (C#) | PowerShell | Bash || ------- | -------- | ------------------ | -------------------- | ---------------------- | ------------------ || == | = | == | == | -eq, -is | -eq || != | !=, <> | != | != | -ne, -isnot | -ne || < | < | < | < | -lt | -lt || <= | <= | <= | <= | -le | -le || > | > | > | > | -gt | -gt || >= | >= | >= | >= | -ge | -ge || =~| like | re, in, startswith | Contains, StartsWith | -like, -contains | =~|| !~| not like | not in | Except | -notlike, -notcontains | ! "str1" =~ "str2" || + | + | + | + | + | + || - | - | - | - | - | - ||\*|\*|\*|\*|\*|\*|| / | / | / | / | / | / ||\*\*| pow |\*\*| Power | Pow |\*\*|| in | in | re, in, startswith | Contains, StartsWith | -In | case in || not-in | not in | not in | Except | -NotIn ||| and | and | and | && | -And, && | -a, && || or | or | or |\|\|| -Or, \|\|| -o, \|\||
book/operators.md:
# Operators
Nushell supports the following operators for common math, logic, and string operations:
| Operator | Description || ------------------ | ------------------------------------------------------- ||`+`| add ||`-`| subtract ||`*`| multiply ||`/`| divide ||`//`| floor division ||`mod`| modulo ||`**`| exponentiation (power) ||`==`| equal ||`!=`| not equal ||`<`| less than ||`<=`| less than or equal ||`>`| greater than ||`>=`| greater than or equal ||`=~` or `like`| regex match / string contains another ||`!~` or `not-like`| inverse regex match / string does *not* contain another ||`in`| value in list ||`not-in`| value not in list ||`has`| list has value ||`not-has`| list does not have value ||`not`| logical not ||`and`| and two Boolean expressions (short-circuits) ||`or`| or two Boolean expressions (short-circuits) ||`xor`| exclusive or two boolean expressions ||`bit-or`| bitwise or ||`bit-xor`| bitwise xor ||`bit-and`| bitwise and ||`bit-shl`| bitwise shift left ||`bit-shr`| bitwise shift right ||`starts-with`| string starts with ||`ends-with`| string ends with ||`++`| append lists |
Parentheses can be used for grouping to specify evaluation order or for calling commands and using the results in an expression.
## Order of Operations
To understand the precedence of operations, you can run the command: `help operators | sort-by precedence -r`.
Presented in descending order of precedence, the article details the operations as follows:
- Parentheses (`()`)
- Exponentiation/Power (`**`)
- Multiply (`*`), Divide (`/`), Integer/Floor Division (`//`), and Modulo (`mod`)
- Add (`+`) and Subtract (`-`)
- Bit shifting (`bit-shl`, `bit-shr`)
- Comparison operations (`==`, `!=`, `<`, `>`, `<=`, `>=`), membership tests (`in`, `not-in`, `starts-with`, `ends-with`), regex matching (`=~`, `!~`), and list appending (`++`)
- Bitwise and (`bit-and`)
- Bitwise xor (`bit-xor`)
- Bitwise or (`bit-or`)
- Logical and (`and`)
- Logical xor (`xor`)
- Logical or (`or`)
- Assignment operations
- Logical not (`not`)
```nu3 * (1 + 2)# => 9
Types
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:
"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.
Regular Expression / string-contains Operators
The =~ and !~ operators provide a convenient way to evaluate regular expressions. You don't need to know regular expressions to use them - they're also an easy way to check whether 1 string contains another.
string =~ pattern returns true if string contains a match for pattern, and false otherwise.
string !~ pattern returns false if string contains a match for pattern, and true otherwise.
For example:
foobarbaz =~ bar # returns true
foobarbaz !~ bar # returns false
ls | where name =~ ^nu # returns all files whose names start with "nu"
Use the str contains command's --ignore-case flag:
"FOO"| str contains --ignore-case"foo"
Convert strings to lowercase with str downcase before comparing:
("FOO"| str downcase) == ("Foo"| str downcase)
Spread operator
Nushell has a spread operator (...) for unpacking lists and records. You may be familiar with it
if you've used JavaScript before. Some languages use * for their spread/splat operator. It can
expand lists or records in places where multiple values or key-value pairs are expected.
There are three places you can use the spread operator:
Suppose you have multiple lists you want to concatenate together, but you also want to intersperse
some individual values. This can be done with append and prepend, but the spread
operator can let you do it more easily.
Note that each call to append results in the creation of a new list, meaning that in this second
example, 3 unnecessary intermediate lists are created. This is not the case with the spread operator,
so there may be (very minor) performance benefits to using ... if you're joining lots of large
lists together, over and over.
You may have noticed that the last item of the resulting list above is "...Nemo". This is because
inside list literals, it can only be used to spread lists, not strings. As such, inside list literals, it can
only be used before variables (...$foo), subexpressions (...(foo)), and list literals (...[foo]).
The ... also won't be recognized as the spread operator if there's any whitespace between it and
the next expression:
This is mainly so that ... won't be confused for the spread operator in commands such as mv ... $dir.
In Record literals
Let's say you have a record with some configuration information and you want to add more fields to
this record:
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.
Similarly to lists, inside record literals, the spread operator can only be used before variables (...$foo),
subexpressions (...(foo)), and record literals (...{foo:bar}). Here too, there needs to be no
whitespace between the ... and the next expression for it to be recognized as the spread operator.
In Command calls
You can also spread arguments to a command, provided that it either has a rest parameter or is an
external command.
Here is an example custom command that has a rest parameter:
It has one flag (--flag), one required positional parameter (req), one optional positional parameter
(opt?), and rest parameter (args).
If you have a list of arguments to pass to args, you can spread it the same way you'd spread a list
inside a list literal. The same rules apply: the spread operator is only
recognized before variables, subexpressions, and list literals, and no whitespace is allowed in between.
foo "bar""baz"...[123] # With ..., the numbers are treated as separate arguments# => { flag: false, req: bar, opt: baz, args: [1, 2, 3] }
foo "bar""baz" [123] # Without ..., [1 2 3] is treated as a single argument# => { flag: false, req: bar, opt: baz, args: [[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:
def bar [ ...args ] { foo --flag "bar""baz"...$args }
bar 123# => { flag: true, req: bar, opt: baz, args: [1, 2, 3] }
You can spread multiple lists in a single call, and also intersperse individual arguments:
foo "bar""baz"1...[23] 45...(6..9| take 2) last
# => { flag: false, req: bar, opt: baz, args: [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:
If a spread argument comes before an optional positional parameter, that optional parameter is treated
as being omitted:
foo "bar"...[12] "not opt"# The null means no argument was given for opt# => { flag: false, req: bar, opt: null, args: [1, 2, "not opt"] }
`book/overlays.md`:
```md
# Overlays
Overlays act as "layers" of definitions (custom commands, aliases, environment variables) that can be activated and deactivated on demand.
They resemble virtual environments found in some languages, such as Python.
_Note: To understand overlays, make sure to check [Modules](modules.md) first as overlays build on top of modules._
## Basics
First, Nushell comes with one default overlay called `zero`.
You can inspect which overlays are active with the [`overlay list`](/commands/docs/overlay_list.md) command.
You should see the default overlay listed there.
To create a new overlay, you first need a module:
```nu
module spam {
export def foo [] {
"foo"
}
export alias bar = echo "bar"
export-env {
load-env { BAZ: "baz" }
}
}
We'll use this module throughout the chapter, so whenever you see overlay use spam, assume spam is referring to this module.
::: tip
The module can be created by any of the three methods described in Modules:
It brought the module's definitions into the current scope and evaluated the export-env block the same way as use command would (see Modules chapter).
::: tip
In the following sections, the > prompt will be preceded by the name of the last active overlay.
(spam)> some-command means the spam overlay is the last active overlay when the command was typed.
:::
Removing an Overlay
If you don't need the overlay definitions anymore, call overlay hide:
(spam)> overlay hide spam
(zero)> foo
Error: Can't run executable...
(zero)> overlay list
───┬──────
0 │ zero
───┴──────
The overlays are also scoped.
Any added overlays are removed at the end of the scope:
(zero)>do { overlay use spam; foo } # overlay is active only inside the block
foo
(zero)> overlay list
───┬──────
0 │ zero
───┴──────
The last way to remove an overlay is to call overlay hide without an argument which will remove the last active overlay.
Overlays Are Recordable
Any new definition (command, alias, environment variable) is recorded into the last active overlay:
Now, the eggs command belongs to the spam overlay.
If we remove the overlay, we can't call it anymore:
(spam)> overlay hide spam
(zero)> eggs
Error: Can't run executable...
But we can bring it back!
(zero)> overlay use spam
(spam)> eggs
eggs
Overlays remember what you add to them and store that information even if you remove them.
This can let you repeatedly swap between different contexts.
::: tip
Sometimes, after adding an overlay, you might not want custom definitions to be added into it.
The solution can be to create a new empty overlay that would be used just for recording the custom changes:
(zero)> overlay use spam
(spam)> module scratchpad { }
(spam)> overlay use scratchpad
(scratchpad)> def eggs [] { "eggs" }
The eggs command is added into scratchpad while keeping spam intact.
To make it less verbose, you can use the overlay new command:
(zero)> overlay use spam
(spam)> overlay new scratchpad
(scratchpad)> def eggs [] { "eggs" }
:::
Prefixed Overlays
The overlay use command would take all commands and aliases from the module and put them directly into the current namespace.
However, you might want to keep them as subcommands behind the module's name.
That's what --prefix is for:
This can be useful if you have a generic script name, such as virtualenv's activate.nu but you want a more descriptive name for your overlay.
Preserving Definitions
Sometimes, you might want to remove an overlay, but keep all the custom definitions you added without having to redefine them in the next active overlay:
The overlays are arranged as a stack.
If multiple overlays contain the same definition, say foo, the one from the last active one would take precedence.
To bring an overlay to the top of the stack, you can call overlay use again:
(zero)> def foo [] { "foo-in-zero" }
(zero)> overlay use spam
(spam)> foo
foo
(spam)> overlay use zero
(zero)> foo
foo-in-zero
(zero)> overlay list
───┬──────
0 │ spam
1 │ zero
───┴──────
Now, the zero overlay takes precedence.
`book/parallelism.md`:
```md
# Parallelism
Nushell now has early support for running code in parallel. This allows you to process elements of a stream using more hardware resources of your computer.
You will notice these commands with their characteristic `par-` naming. Each corresponds to a non-parallel version, allowing you to easily write code in a serial style first, and then go back and easily convert serial scripts into parallel scripts with a few extra characters.
## par-each
The most common parallel command is [`par-each`](/commands/docs/par-each.md), a companion to the [`each`](/commands/docs/each.md) command.
Like [`each`](/commands/docs/each.md), [`par-each`](/commands/docs/par-each.md) works on each element in the pipeline as it comes in, running a block on each. Unlike [`each`](/commands/docs/each.md), [`par-each`](/commands/docs/par-each.md) will do these operations in parallel.
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|
{ name: $row.name, len: (ls $row.name | length) }
}
We create a record for each entry, and fill it with the name of the directory and the count of entries in that sub-directory.
On your machine, the times may vary. For this machine, it took 21 milliseconds for the current directory.
Now, since this operation can be run in parallel, let's convert the above to parallel by changing each to par-each:
ls | where type == dir | par-each { |row|
{ name: $row.name, len: (ls $row.name | length) }
}
On this machine, it now runs in 6ms. That's quite a difference!
ls | where type == dir | par-each { |row|
{ name: $row.name, len: (cd $row.name; ls | length) }
}
You'll notice, if you look at the results, that they come back in different orders each run (depending on the number of hardware threads on your system). As tasks finish, and we get the correct result, we may need to add additional steps if we want our results in a particular order. For example, for the above, we may want to sort the results by the "name" field. This allows both each and par-each versions of our script to give the same result.
`book/pipelines.md`:
```md
# Pipelines
One of the core designs of Nu is the pipeline, a design idea that traces its roots back decades to some of the original philosophy behind Unix. Just as Nu extends from the single string data type of Unix, Nu also extends the idea of the pipeline to include more than just text.
## Basics
A pipeline is composed of three parts: the input, the filter, and the output.
```nu
open Cargo.toml | update workspace.dependencies.base64 0.24.2 | save Cargo_new.toml
The first command, open Cargo.toml, is an input (sometimes also called a "source" or "producer"). This creates or loads data and feeds it into a pipeline. It's from input that pipelines have values to work with. Commands like ls are also inputs, as they take data from the filesystem and send it through the pipelines so that it can be used.
The second command, update workspace.dependencies.base64 0.24.2, is a filter. Filters take the data they are given and often do something with it. They may change it (as with the update command in our example), or they may perform other operations, like logging, as the values pass through.
The last command, save Cargo_new.toml, is an output (sometimes called a "sink"). An output takes input from the pipeline and does some final operation on it. In our example, we save what comes through the pipeline to a file as the final step. Other types of output commands may take the values and view them for the user.
The $in variable will collect the pipeline into a value for you, allowing you to access the whole stream as a parameter:
[123] |$in.1*$in.2# => 6
Multi-line pipelines
If a pipeline is getting a bit long for one line, you can enclose it within parentheses ():
let year = (
"01/22/2021"|parse"{month}/{day}/{year}"|
get year
)
Semicolons
Take this example:
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.
As there is a semicolon after line1, the command will run to completion and get displayed on the screen.
line2 | line3 is a normal pipeline. It runs, and its contents are displayed after line1's contents.
Pipeline Input and the Special $in Variable
Much of Nu's composability comes from the special $in variable, which holds the current pipeline input.
$in is particular useful when used in:
Command or external parameters
Filters
Custom command definitions or scripts that accept pipeline input
$in as a Command Argument or as Part of an Expression
Compare the following two command-lines that create a directory with tomorrow's date as part of the name. The following are equivalent:
Using subexpressions:
mkdir $'((date now) + 1day | format date '%F') Report'
or using pipelines:
date now # 1: today|$in+ 1day # 2: tomorrow| format date '%F' # 3: Format as YYYY-MM-DD| $'($in) Report' # 4: Format the directory name| mkdir $in# 5: Create the directory
While the second form may be overly verbose for this contrived example, you'll notice several advantages:
It can be composed step-by-step with a simple ↑ (up arrow) to repeat the previous command and add the next stage of the pipeline.
Let's examine the contents of $in on each line of the above example:
On line 2, $in refers to the results of line 1's date now (a datetime value).
On line 4, $in refers to tomorrow's formatted date from line 3 and is used in an interpolated string
On line 5, $in refers to the results of line 4's interpolated string, e.g. '2024-05-14 Report'
Pipeline Input in Filter Closures
Certain filter commands may modify the pipeline input to their closure in order to provide more convenient access to the expected context. For example:
1..10| each {$in*2}
Rather than referring to the entire range of 10 digits, the each filter modifies $in to refer to the value of the current iteration.
In most filters, the pipeline input and its resulting $in will be the same as the closure parameter. For the each filter, the following example is equivalent to the one above:
1..10| each {|value|$value*2}
However, some filters will assign an even more convenient value to their closures' input. The update filter is one example. The pipeline input to the update command's closure (as well as $in) refers to the column being updated, while the closure parameter refers to the entire record. As a result, the following two examples are also equivalent:
ls | update name {|file|$file.name | str upcase}
ls | update name {str upcase}
With most filters, the second version would refer to the entire file record (with name, type, size, and modified columns). However, with update, it refers specifically to the contents of the column being updated, in this case name.
Pipeline Input in Custom Command Definitions and Scripts
Rule 1: When used in the first position of a pipeline in a closure or block, $in refers to the pipeline (or filter) input to the closure/block.
Example:
defecho_me [] {
print$in
}
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.
Example:
[ a b c ] | each {
print$inprint$in$in
}
All three of the $in values are the same on each iteration, so this outputs:
a
a
b
b
c
c
╭───┬───╮
│ 0 │ a │
│ 1 │ b │
│ 2 │ c │
╰───┴───╯
Rule 2: When used anywhere else in a pipeline (other than the first position), $in refers to the previous expression's result:
Example:
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
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.
Example:
4|do {
print$in# closure-scope $in is 4letp= ( # explicit sub-expression, but one will be created regardless$in*$in# initial-pipeline position $in is still 4 here|$in/2# $in is now 16
) # $p is the result, 8 - Sub-expression scope endsprint$in# At the closure-scope, the "original" $in is still 4print$p
}
So the output from the 3 print statements is:
448
Again, this would hold true even if the command above used the more compact, implicit sub-expression form:
Example:
4|do {
print$in# closure-scope $in is 4letp=$in*$in|$in/2# Implicit let sub-expressionprint$in# At the closure-scope, $in is still 4print$p
}
448
Rule 4: In a multi-statement line separated by semicolons, $in cannot be used to capture the results of the previous statement.
This is the same as having no-input:
ls/|getname; $in|describe# => nothing
Instead, simply continue the pipeline:
ls/|getname|$in|describe# => list<string>
Best practice for $in in Multiline Code
While $in can be reused as demonstrated above, assigning its value to another variable in the first line of your closure/block will often aid in readability and debugging.
Example:
def "date info" [] {
let day =$inprint ($day| format date '%v')
print $'... was a ($day| format date '%A')'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
Collectability of $in
Currently, the use of $in on a stream in a pipeline results in a "collected" value, meaning the pipeline "waits" on the stream to complete before handling $in with the full results. However, this behavior is not guaranteed in future releases. To ensure that a stream is collected into a single variable, use the collect command.
Likewise, avoid using $in when normal pipeline input will suffice, as internally $in forces a conversion from PipelineData to Value and may result in decreased performance and/or increased memory usage.
Working with External Commands
Nu commands communicate with each other using the Nu data types (see types of data), but what about commands outside of Nu? Let's look at some examples of working with external commands:
internal_command | external_command
Data will flow from the internal_command to the external_command. This data will get converted to a string, so that they can be sent to the stdin of the external_command.
external_command | internal_command
Data coming from an external command into Nu will come in as bytes that Nushell will try to automatically convert to UTF-8 text. If successful, a stream of text data will be sent to internal_command. If unsuccessful, a stream of binary data will be sent to internal command. Commands like lines help make it easier to bring in data from external commands, as it gives discrete lines of data to work with.
external_command_1 | external_command_2
Nu works with data piped between two external commands in the same way as other shells, like Bash would. The stdout of external_command_1 is connected to the stdin of external_command_2. This lets data flow naturally between the two commands.
Command Input and Output Types
The Basics section above describes how commands can be combined in pipelines as input, filters, or output.
How you can use commands depends on what they offer in terms of input/output handling.
You can check what a command supports with help <command name>, which shows the relevant Input/output types.
For example, through help first we can see that the first command supports multiple input and output types:
helpfirst# => […]# => Input/output types:# => ╭───┬───────────┬────────╮# => │ # │ input │ output │# => ├───┼───────────┼────────┤# => │ 0 │ list<any> │ any │# => │ 1 │ binary │ binary │# => │ 2 │ range │ any │# => ╰───┴───────────┴────────╯
[a b c] |first took 1ms
# => a1..4|first took 21ms
# => 1
As another example, the ls command supports output but not input:
This means, for example, that attempting to pipe into ls (echo .. | ls) leads to unintended results.
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:
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<string> to string.
Other commands without default behavior may fail in different ways, and with explicit errors.
For example, help sleep tells us that sleep supports no input and no output types:
While there is no steadfast rule, Nu generally tries to copy established conventions in command behavior,
or do what 'feels right'.
The sleep behavior of not supporting an input stream matches Bash sleep behavior for example.
Many commands do have piped input/output however, and if it's ever unclear, check their help documentation as described above.
Rendering Display Results
In interactive mode, when a pipeline ends, the display_output hook configuration defines how the result will be displayed.
The default configuration uses the table command to render structured data as a visual table.
The following example shows how the display_output hook can render
an expanded table with table -e
an unexpanded table with table
an empty closure {||} and empty string '' lead to simple output
null can be assigned to clear any customization, reverting back to default behavior
Sometimes you want to output Nushell structured data to an external command for further processing. However, Nushell's default formatting options for structured data may not be what you want.
For example, you want to find a file named "tutor" under "/usr/share/vim/runtime" and check its ownership
ls /usr/share/nvim/runtime/# => ╭────┬───────────────────────────────────────┬──────┬─────────┬───────────────╮# => │ # │ name │ type │ size │ modified │# => ├────┼───────────────────────────────────────┼──────┼─────────┼───────────────┤# => │ 0 │ /usr/share/nvim/runtime/autoload │ dir │ 4.1KB │ 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 the result to external ^ls
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:
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)
ls /usr/share/nvim/runtime/| get name | find tutor | ansi strip | ^ls -al ...$in
Command Output in Nushell
Unlike external commands, Nushell commands are akin to functions. Most Nushell commands do not print anything to stdout and instead just return data.
do { ls; ls; ls; "What?!" }
This means that the above code will not display the files under the current directory three times.
In fact, running this in the shell will only display "What?!" because that is the value returned by the do command in this example. However, using the system ^ls command instead of ls would indeed print the directory thrice because ^ls does print its result once it runs.
Knowing when data is displayed is important when using configuration variables that affect the display output of commands such as table.
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
do { $env.config.table.mode ="none"; ls } | table
Because Nushell $env variables are scoped, this means that the table command in the example is not affected by the
environment modification inside the do block and the data will not be shown with the applied configuration.
When displaying data early is desired, it is possible to explicitly apply | table inside the scope, or use the print command.
do { $env.config.table.mode ="none"; ls | table }do { $env.config.table.mode ="none"; print (ls) }
`book/plugins.md`:
```md
# Plugins
Nu can be extended using plugins. Plugins behave much like Nu's built-in commands, with the added benefit that they can be added separately from Nu itself.
::: warning Important
Plugins communicate with Nushell using the `nu-plugin` protocol. This protocol is versioned, and plugins must use the same `nu-plugin` version provided by Nushell.
When updating Nushell, please make sure to also update any plugins that you have registered.
:::
[[toc]]
## Overview
- In order to use a plugin, it needs to be:
- Installed
- Added
- Imported
There are two types of plugins:
- "Core plugins" are officially maintained and are usually installed with Nushell, in the same directory as the Nushell executable.
- Third-party plugins are also available from many sources.
The `$NU_LIB_DIRS` constant or `$env.NU_LIB_DIRS` environment variable can be used to set the search-path for plugins.
### Core Plugin Quickstart
To begin using the Polars plugin:
1. Most package managers will automatically install the core plugins with Nushell. A notable exception, however, is `cargo`. If you installed
Nushell using `cargo`, see [Installing Core Plugins](#core-plugins) below.
2. (Recommended) Set the plugin search path to include the directory where Nushell and its plugins are installed. Assuming the core plugins are installed
in the same directory as the Nushell binary, the following can be added to your startup config:
```nu
const NU_PLUGIN_DIRS = [
($nu.current-exe | path dirname)
...$NU_PLUGIN_DIRS
]
Add the plugin to the plugin registry. This only needs to be done one time. The name is the name of the plugin file, including its extension:
# On Unix/Linux platforms:
plugin add nu_plugin_polars
# Or on Windows
plugin add nu_plugin_polars.exe
plugin list# Confirm it was added to the registry
Alternatively, if you did not add the binary directory to the plugin path in Step 2, you can still use an absolute path:
Import the plugin (to begin using it immediately) or restart Nushell. All plugins in the registry are automatically imported when Nushell starts:
# The name of the plugin, without the leading `nu_plugin` nor any extension
plugin use polars
Confirm the plugin is working:
ls | polars into-df | describe
# => NuDataFrame
Installing Plugins
Core Plugins
Nushell ships with a set of officially maintained plugins which includes:
polars: Extremely fast columnar operations using DataFrames via the Polars Library. See the DataFrames Chapter for more details.
formats: Support for several additional data formats - EML, ICS, INI, plist, and VCF.
gstat: Returns information on the status of a Git repository as Nushell structured data.
query: Support for querying SQL, XML, JSON, HTML (via selector), and WebPage Metadata
inc: Increment a value or version (e.g., semver). This plugin acts as both an end-user plugin as well as a simple developer example of how to create a plugin.
Nushell also ships with several plugins that serve as examples or tools for plugin developers. These include nu_plugin_example, nu_plugin_custom_values, and nu_plugin_stress_internals.
Core plugins are typically distributed with the Nushell release and should already be installed in the same directory as the Nushell executable. If this is the case on your system, core plugins should be using correct nu-plugin protocol version. If your package management system installs them separately, please make sure to update the core plugins whenever Nushell itself is updated.
::: tip Installing using Cargo
For example, when installing or upgrading Nushell directly from crates.io using cargo install nu --locked, the corresponding core plugins for that version may also be installed or updated using cargo install nu_plugin_<plugin_name> --locked.
To install all of the default (non-developer) plugins, from within Nushell run:
You can find third-party plugins on crates.io, online Git repositories, awesome-nu, and other sources. As with any third-party code you run on your system, please make sure you trust its source.
To install a third-party plugin on your system, you first need to make sure the plugin uses the same version of Nu as your system:
Confirm your Nushell version with the version command
Confirm the version the plugin requires by checking its Cargo.toml file
To install a plugin by name from crates.io, run:
cargo install nu_plugin_<plugin_name>--locked
When installing from a repository (e.g., GitHub), run the following from inside the cloned repository:
cargo install --path .--locked
This will create a binary file that can be used to add the plugin.
::: tip Cargo installation location
By default, binaries installed with cargo install are placed in your home directory under .cargo/bin.
However, this can change depending on how your system is configured.
:::
Registering Plugins
To add a plugin to the plugin registry file, call the plugin add command to tell Nu where to find it.
::: tip Note
The plugin file name must start with nu_plugin_, Nu uses this filename prefix to identify plugins.
:::
Communicates via the plugin protocol in order to ensure compatibility and to get a list of all of the commands it supports
This plugin information is then saved to the plugin registry file ($nu.plugin-path), which acts as a cache
Importing Plugins
Once added to the registry, the next time nu is started, the plugin will be imported and available in that session.
You can also immediately import (or reload) a plugin in the current session by calling plugin use. In this case, the name of the plugin (rather than the filename) is used without the nu_plugin prefix:
plugin use cool
It is not necessary to add plugin use statements to your config file. All previously registered plugins are automatically loaded at startup.
::: tip Note
plugin use is a parser keyword, so when evaluating a script, it will be evaluated first. This means that while you can execute plugin add and then plugin use at the REPL on separate lines, you can't do this in a single script. If you need to run nu with a specific plugin or set of plugins without preparing a cache file, you can pass the --plugins option to nu with a list of plugin executable files:
nu --plugins '[./my_plugins/nu_plugin_cool]'
:::
Plugin Search Path
Nushell includes two list variables that can be used to set a search path for plugins. This only applies when registering plugins with plugin add, but it can be a nice shortcut
if you commonly add and remove plugins.
const NU_PLUGIN_DIRS: A constant which takes effect immediately when set. However, as a constant, only certain commands may be used with it. It can be updated, for example, as seen in the QuickStart above.
$env.NU_PLUGIN_DIRS: An environment variable which is mutable and can accept any command that updates its list. However, changes to it will not take effect until the next expression is parsed.
Updating Plugins
When updating a plugin, it is important to run plugin add again just as above to load the new signatures from the plugin and allow Nu to rewrite them to the plugin file ($nu.plugin-path). You can then plugin use to get the updated signatures within the current session.
Managing Plugins
Installed plugins are displayed using plugin list:
All of the commands from installed plugins are available in the current scope:
scope commands | where type =="plugin"
Plugin Lifecycle
Plugins stay running while they are in use, and are automatically stopped by default after a period of time of inactivity. This behavior is managed by the plugin garbage collector. To manually stop a plugin, call plugin stop with its name:
For example, run the gstat command from the corresponding plugin, then check its is_running status:
gstat
# => gstat output
plugin list| where name == gstat | select name is_running
# =>
╭───┬───────┬────────────╮
│ # │ name │ is_running │
├───┼───────┼────────────┤
│ 0 │ gstat │ true │
╰───┴───────┴────────────╯
Now stop the plugin manually, and we can see that it is no longer running:
plugin stop gstat
plugin list| where name == gstat | select name is_running
# =>
╭───┬───────┬────────────╮
│ # │ name │ is_running │
├───┼───────┼────────────┤
│ 0 │ gstat │ false │
╰───┴───────┴────────────╯
Plugin Garbage Collector
As mentioned above, Nu comes with a plugin garbage collector which automatically stops plugins that are not actively in use after a period of time (by default, 10 seconds). This behavior is fully configurable:
$env.config.plugin_gc = {
# Settings for plugins not otherwise specified:
default: {
enabled: true # set to false to never automatically stop plugins
stop_after: 10sec # how long to wait after the plugin is inactive before stopping it
}
# Settings for specific plugins, by plugin name# (i.e. what you see in `plugin list`):
plugins: {
gstat: {
stop_after: 1min
}
inc: {
stop_after: 0sec # stop as soon as possible
}
example: {
enabled: false # never stop automatically
}
}
}
To remove a plugin, call plugin rm <plugin_name>. Note that this is the plugin name, rather than the filename. For example, if you previously added the plugin ~/.cargo/bin/nu_plugin_gstat, its name would be gstat. To remove it:
plugin rm gstat
You can confirm the name of a plugin by running plugin list.
Running plugin rm removes the plugin from the registry so that it will not be loaded the next time Nushell starts. However, any commands created by the plugin remain in scope until the current Nushell session ends.
For Plugin Developers
Nu plugins are executables; Nu launches them as needed and communicates with them over stdin and stdout or local sockets. Nu plugins can use either JSON or MessagePack as their communication encoding.
Examples
Nu's main repo contains example plugins that are useful for learning how the plugin protocol works:
The simplest way to debug a plugin is to print to stderr; plugins' standard error streams are redirected through Nu and displayed to the user.
Tracing
The Nu plugin protocol message stream may be captured for diagnostic purposes using trace_nu_plugin.
::: warning
Trace output will accumulate for as long as the plugin is installed with the trace wrapper. Large files are possible. Be sure to remove the plugin with plugin rm when finished tracing, and reinstall without the trace wrapper.**
:::
Developer Help
Nu's plugin documentation is a work in progress. If you're unsure about something, the #plugins channel on the Nu Discord is a great place to ask questions!
`book/programming_in_nu.md`:
```md
---
prev:
text: Special Variables
link: /book/special_variables.md
next:
text: Custom Commands
link: /book/custom_commands.md
---
# Programming in Nu
This chapter goes into more detail of Nushell as a programming language.
Each major language feature has its own section.
Just like most programming languages allow you to define functions, Nushell uses [custom commands](custom_commands.md) for this purpose.
From other shells you might be used to [aliases](aliases.md).
Nushell's aliases work in a similar way and are a part of the programming language, not just a shell feature.
Common operations, such as addition or regex search, can be done with [operators](operators.md).
Not all operations are supported for all data types, and Nushell will make sure to let you know when there is a mismatch.
You can store intermediate results to [variables](variables.md).
Variables can be immutable, mutable, or a parse-time constant.
The last three sections are aimed at organizing your code:
[Scripts](scripts.md) are the simplest form of code organization: You just put the code into a file and source it.
However, you can also run scripts as standalone programs with command line signatures using the "special" `main` command.
With [modules](modules.md), just like in many other programming languages, it is possible to compose your code from smaller pieces.
Modules let you define a public interface vs. private commands and you can import custom commands, aliases, and environment variables from them.
[Overlays](overlays.md) build on top of modules.
By defining an overlay, you bring in module's definitions into its own swappable "layer" that gets applied on top of other overlays.
This enables features like activating virtual environments or overriding sets of default commands with custom variants.
The standard library also has a [testing framework](testing.md) if you want to prove your reusable code works perfectly.
book/quick_tour.md:
---prev:
text: Getting Startedlink: /book/getting_started.md---# Quick Tour[[toc]]## Nushell Commands Output _Data_
The easiest way to see what Nu can do is to start with some examples, so let's dive in.
The first thing you'll notice when you run a command like [`ls`](/commands/docs/ls.md) is that instead of a block of text coming back, you get a structured table.
```nu:no-line-numbersls# => ╭────┬─────────────────────┬──────┬───────────┬──────────────╮# => │ # │ name │ type │ size │ modified │# => ├────┼─────────────────────┼──────┼───────────┼──────────────┤# => │ 0 │ CITATION.cff │ file │ 812 B │ 2 months ago │# => │ 1 │ CODE_OF_CONDUCT.md │ file │ 3.4 KiB │ 9 months ago │# => │ 2 │ CONTRIBUTING.md │ file │ 11.0 KiB │ 5 months ago │# => │ 3 │ Cargo.lock │ file │ 194.9 KiB │ 15 hours ago │# => │ 4 │ Cargo.toml │ file │ 9.2 KiB │ 15 hours ago │# => │ 5 │ Cross.toml │ file │ 666 B │ 6 months ago │# => │ 6 │ LICENSE │ file │ 1.1 KiB │ 9 months ago │# => │ 7 │ README.md │ file │ 12.0 KiB │ 15 hours ago │# => ...
This table does more than just format the output nicely. Like a spreadsheet, it allows us to work with the data interactively.
Acting on Data
Next, let's sort this table by each file's size. To do this, we'll take the output from ls and feed it into a command that can sort tables based on the values in a column.
Notice that we didn't pass commandline arguments or switches to ls. Instead, we used Nushell's built-in sort-by command to sort the output of the ls command. Then, to see the largest files on top, we used reverse on the output of sort-by.
::: tip Cool!
If you compare the sort order closely, you might realize that the data isn't sorted alphabetically. It's not even sorted by the numerical values. Instead, since the size column is a filesize type, Nushell knows that 1.1 KiB (kibibytes) is larger than 812 B (bytes).
:::
Finding Data Using the where Command
Nu provides many commands that can operate on the structured output of the previous command. These are usually categorized as "Filters" in Nushell.
For example, we can use where to filter the contents of the table so that it only shows files over 10 kilobytes:
Of course, this isn't limited to the ls command. Nushell follows the Unix philosophy where each command does one thing well and you can typically expect the output of one command to become the input of another. This allows us to mix-and-match commands in many different combinations.
You may be familiar with the Linux/Unix ps command. It provides a list of all of the current processes running in the system along with their current status. As with ls, Nushell provides a cross-platform, built-in ps command that returns its results as structured data.
::: note
The traditional Unix ps only shows the current process and its parents by default. Nushell's implementation shows all of the processes on the system by default.
Normally, running ps in Nushell uses its internal, cross-platform command. However, it is still possible to run the external, system-dependent version on Unix/Linux platforms by prefacing it with the caret sigil. For example:
^ps aux # run the Unix ps command with all processes in user-oriented form
What if we wanted to just show the processes that are actively running? As with ls above, we can also work with the table that psoutputs:
ps | where status ==Running# => ╭───┬──────┬──────┬──────┬─────────┬──────┬──────────┬─────────╮# => │ # │ pid │ ppid │ name │ status │ cpu │ mem │ virtual │# => ├───┼──────┼──────┼──────┼─────────┼──────┼──────────┼─────────┤# => │ 0 │ 6585 │ 6584 │ nu │ Running │ 0.00 │ 31.9 MiB │ 1.2 GiB │# => ╰───┴──────┴──────┴──────┴─────────┴──────┴──────────┴─────────╯
::: tip
Remember above, where the size column from the ls command was a filesize? Here, status is really just a string, and you can use all the normal string operations and commands with it, including (as above) the == comparison.
You can examine the types for the table's columns using:
The describe command can be used to display the output type of any command or expression.
:::
Command Arguments in a Pipeline
Sometimes, a command takes an argument instead of pipeline input. For this scenario, Nushell provides the $in variable that let's you use the previous command's output in variable-form. For example:
ls
| sort-by size
| reverse
| first
| get name
| cp $in ~
::: tip Nushell Design Note
Whenever possible, Nushell commands are designed to act on pipeline input. However, some commands, like cp in this example, have two (or more)
arguments with different meanings. In this case, cp needs to know both the path to copy as well as the target path. As a result, this command is
more ergonomic with two positional parameters.
:::
::: tip
Nushell commands can extend across multiple lines for readability. The above is the same as:
ls | sort-by size | reverse |first| get name | cp $in ~
The first three lines are the same commands we used in the second example above, so let's examine the last three:
The first command simply returns the first value from the table. In this case, that means the file with the largest size. That's the Cargo.lock file if using the directory listing from the second example above. This "file" is a record from the table which still contains its name, type, size, and modified columns/fields.
get name returns the value of the name field from the previous command, so "Cargo.lock" (a string). This is also a simple example of a cell-path that can be used to navigate and isolate structured data.
The last line uses the $in variable to reference the output of line 5. The result is a command that says "Copy 'Cargo.lock' to the home directory"
::: tip
get and its counterpart select are two of the most used filters in Nushell, but it might not be easy to
spot the difference between them at first glance. When you're ready to start using them more extensively, see Using get and select for a guide.
:::
Getting Help
Nushell provides an extensive, in-shell Help system. For example
# help <command>help ls
# Or
ls --help# Alsohelp operators
help escapes
::: tip Cool!
Press the F1 key to access the Help menu. Search for the ps command here, but don't press Enter just yet!
Instead, press the Down Arrow key, and notice that you are scrolling through the Examples section. Highlight an example, then press Enter and
the example will be entered at the commandline, ready to run!
This can be a great way to explore and learn about the extensive set of Nushell commands.
:::
The Help system also has a "search" feature:
help--find filesize
# orhelp-f filesize
It may not surprise you by now that the Help system itself is based on structured data! Notice that the output of help -f filesize is a table.
The Help for each command is stored as a record with the:
Name
Category
Type (built-in, plugin, custom)
Parameters it accepts
Signatures showing what types of data it can accept as well as output
And more
You can view all commands (other than externals) as a single large table using:
help commands
::: tip
Notice that the params and input_output columns of the output above are nested tables. Nushell allows arbitrarily nested data structures.
:::
explore'ing from Here
That help commands output is quite long. You could send it to a pager like less or bat, but Nushell includes a built-in explore command that lets you not only scroll, but also telescope-in to nested data. Try:
help commands | explore
Then press the Enter key to access the data itself. Use the arrow keys to scroll to the cp command, and over to the params column. Hit Enter again to
telescope in to the complete list of parameters available to the cp command.
::: note
Pressing Esc one time returns from Scroll-mode to the View; Pressing it a second time returns to the previous view (or exits, if already at the top view level).
:::
::: tip
You can, of course, use the explore command on any structured data in Nushell. This might include JSON data coming from a Web API, a spreadsheet or CSV file, YAML, or anything that can be represented as structured data in Nushell.
Try $env.config | explore for fun!
:::
`book/regular_expressions.md`:
```md
# Regular Expressions
Regular expressions in Nushell's commands are handled by the `rust-lang/regex` crate. If you want to know more, check the crate documentation: "[regex](https://github.com/rust-lang/regex)".
book/running_externals.md:
# Running System (External) Commands
Nu provides a set of commands that you can use across different operating systems ("internal" commands) and having this consistency is helpful when creating cross-platform code. Sometimes, though, you want to run an external command that has the same name as an internal Nu command. To run the external [`ls`](/commands/docs/ls.md) or [`date`](/commands/docs/date.md) command, for example, preface it with the caret (^) sigil. Prefacing with the caret calls the external command found in the user's `PATH` (e.g. `/bin/ls`) instead of Nu's internal [`ls`](/commands/docs/ls.md) command).
Nu internal command:
```nuls
External command (typically /usr/bin/ls):
^ls
::: note
On Windows, ls is a PowerShell alias by default, so ^ls will not find a matching system command.
:::
Additional Windows Notes
When running an external command on Windows,
Nushell forwards some CMD.EXE internal commands to cmd instead of attempting to run external commands.
Coming from CMD.EXE contains a list of these commands and describes the behavior in more detail.
`book/scripts.md`:
```md
# Scripts
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
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:
A script file defines the definitions for custom commands as well as the main script itself, which will run after the custom commands are defined.
In the above example, first greet is defined by the Nushell interpreter. This allows us to later call this definition. We could have written the above as:
greet "world"
def greet [name] {
["hello"$name]
}
There is no requirement that definitions have to come before the parts of the script that call the definitions, allowing you to put them where you feel comfortable.
How Scripts are Processed
In a script, definitions run first. This allows us to call the definitions using the calls in the script.
After the definitions run, we start at the top of the script file and run each group of commands one after another.
Script Lines
To better understand how Nushell sees lines of code, let's take a look at an example script:
a
b; c | d
When this script is run, Nushell will first run the a command to completion and view its results. Next, Nushell will run b; c | d following the rules in the "Semicolons" section.
Parameterizing Scripts
Script files can optionally contain a special "main" command. main will be run after any other Nu code, and is primarily used to allow positional parameters and flags in scripts. You can pass arguments to scripts after the script name (nu <script name> <script args>).
For example:
# myscript.nu
def main [x: int] {
$x+10
}
nu myscript.nu 100# => 110
Argument Type Interpretation
By default, arguments provided to a script are interpreted with the type Type::Any, implying that they are not constrained to a specific data type and can be dynamically interpreted as fitting any of the available data types during script execution.
In the previous example, main [x: int] denotes that the argument x should possess an integer data type. However, if arguments are not explicitly typed, they will be parsed according to their apparent data type.
You can then execute the script's subcommands when calling it:
nu myscript.nu
# => hello from myscript!
nu myscript.nu build
# => building
nu myscript.nu run
# => running
Unlike modules, main does not need to be 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.
It is important to note that you must define a main command in order for subcommands of main to be correctly exposed. For example, if we had just defined the run and build subcommands, they wouldn't be accessible when running the script:
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:
def main [] {}
Shebangs (#!)
On Linux and macOS you can optionally use a shebang to tell the OS that a file should be interpreted by Nu. For example, with the following in a file named myscript:
#!/usr/bin/env nu"Hello World!"
./myscript# => Hello World!
For script to have access to standard input, nu should be invoked with --stdin flag:
#!/usr/bin/env -S nu --stdin
def main [] {
echo $"stdin: ($in)"
}
`book/sorting.md`:
```md
# Sorting
Nushell offers many ways of sorting data, and which method you reach for will depend on the problem and what kind of data you're working with. Let's take a look at some of the ways you might wish to sort data.
## Basic sorting
### Lists
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 │
# => ╰───┴───╯
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:
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.
::: tip
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 sort option:
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.
Records
Records can be sorted two ways: by key, and by value. By default, passing a record to sort will sort in order of its keys:
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.
In this example, the id column for all items is equal. Then, the two items with quantity 5 are sorted before the item with quantity 10. Finally, the item with price 1 is sorted before the item with price 8.
Sorting structured data
Cell path
In order to sort more complex types, such as tables, you can use the sort-by command. sort-by can order its input by a cell path.
Here's an example directory, sorted by filesize:
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:
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.
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, which will transform each value into a sorting keywithout 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:
In addition to key closures, sort-by also supports closures which specify a custom sort order. The --custom, or -c, flag will tell sort-by to interpret closures as custom sort closures. A custom sort closure has two parameters, and returns a boolean. The closure should return true if the first parameter comes before the second parameter in the sort order.
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":
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
The parameters are also passed to the custom closure as a two element list, so the following are equivalent:
{|a, b| $a < $b }
{ $in.0 < $in.1 }
:::
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.
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|
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
[_,0] => false,# only b has 0 work time, so a comes after b in the sort order
_ => ($a.priority >$b.priority) # both have non-zero work time, sort by priority
}
}
$queue| sort-by -c $my_sort
Special sorts
Case insensitive sort
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:
The natural sort option 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:
Under some circumstances, you might need to sort data containing mixed types. There are a couple things to be aware of when sorting mixed types:
Generally, values of the same type will appear next to each other in the sort order. For example, sorted numbers come first, then sorted strings, then sorted lists.
Some types will be intermixed in the sort order. These are:
Integers and floats. For example, [2.2, 1, 3] will be sorted as [1, 2.2, 3].
Strings and globs. For example, [("b" | into glob) a c] will be sorted as [a b c] (where b is still a glob).
If using natural sort, integers, floats, and strings will be intermixed as described in that section.
The ordering between non-intermixed types is not guaranteed, except for null values, which will always be sorted to the end of a list.
Within the same Nushell version the ordering should always be the same, but this should not be relied upon. If you have code which is sensitive to the ordering across types, consider using a custom sort which better expresses your requirements.
If you need to sort data which may contain mixed types, consider one of the following strategies:
Strict sort to disallow sorting of incompatible types
Natural sort to sort intermixed numbers and numeric strings
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:
Special handling is required for null values, since comparison between any value and null returns null. To instead reject null values, try the following:
let baddata = [83.2 null 582]
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"}),# => ╰────
`book/special_variables.md`:
```md
---
next:
text: Programming in Nu
link: /book/programming_in_nu.md
---
# Special Variables
Nushell makes available and uses a number of special variables and constants. Many of these are mentioned or documented in other places in this Book, but this page
should include _all_ variables for reference.
[[toc]]
## `$nu`
The `$nu` constant is a record containing several useful values:
- `default-config-dir`: The directory where the configuration files are stored and read.
- `config-path`: The path of the main Nushell config file, normally `config.nu` in the config directory.
- `env-path`: The optional environment config file, normally `env.nu` in the config directory.
- `history-path`: The text or SQLite file storing the command history.
- `loginshell-path`: The optional config file which runs for login shells, normally `login.nu` in the config directory.
- `plugin-path`: The plugin registry file, normally `plugin.msgpackz` in the config directory.
- `home-path`: The user's home directory which can be accessed using the shorthand `~`.
- `data-dir`: The data directory for Nushell, which includes the `./vendor/autoload` directories loaded at startup and other user data.
- `cache-dir`: A directory for non-essential (cached) data.
- `vendor-autoload-dirs`: A list of directories where third-party applications should install configuration files that will be auto-loaded during startup.
- `user-autoload-dirs`: A list of directories where the user may create additional configuration files which will be auto-loaded during startup.
- `temp-path`: A path for temporary files that should be writeable by the user.
- `pid`: The PID of the currently running Nushell process.
- `os-info`: Information about the host operating system.
- `startup-time`: The amount of time (in duration) that it took for Nushell to start and process all configuration files.
- `is-interactive`: A boolean indicating whether Nushell was started as an interactive shell (`true`) or is running a script or command-string. For example:
```nu
$nu.is-interactive
# => true
nu -c "$nu.is-interactive"
# => false
# Force interactive with --interactive (-i)
nu -i -c "$nu.is-interactive"
# => true
Note: When started as an interactive shell, startup config files are processed. When started as a non-interactive shell, no config files are read unless explicitly called via flag.
is-login: Indicates whether or not Nushell was started as a login shell.
history-enabled: History may be disabled via nu --no-history, in which case this constant will be false.
current-exe: The full path to the currently-running nu binary. Can be combined with path dirname (which is constant) to determine the directory where the binary is located.
$env
$env is a special mutable variable containing the current environment variables. As with any process, the initial environment is inherited from the parent process which started nu.
There are also several environment variables that Nushell uses for specific purposes:
$env.CMD_DURATION_MS
The amount of time in milliseconds that the previous command took to run.
$env.config
$env.config is the main configuration record used in Nushell. Settings are documented in config nu --doc.
$env.CURRENT_FILE
Inside a script, module, or sourced-file, this variable holds the fully-qualified filename. Note that this
information is also available as a constant through the path self command.
$env.ENV_CONVERSIONS
Allows users to specify how to convert certain environment variables to Nushell types. See ENV_CONVERSIONS.
$env.FILE_PWD
Inside a script, module, or sourced-file, this variable holds the fully qualified name of the directory in which
the file resides. Note that this value is also available as a constant through:
path self| path dirname
$env.LAST_EXIT_CODE
The exit code of the last command, usually used for external commands — Equivalent to $? from POSIX. Note that this information is also made available to the catch block in a try expression for external commands. For instance:
The standard library offers logging in std/log. The NU_LOG_LEVEL environment variable is used to define the log level being used for custom commands, modules, and scripts.
nu -c '1|print; use std/log; log debug 1111; 9 | print'# => 1# => 9
nu -c '1|print; use std/log; NU_LOG_LEVEL=debug log debug 1111; 9 | print'# => 1# => 2025-07-12T21:27:30.080|DBG|1111# => 9
nu -c '1|print; use std/log; $env.NU_LOG_LEVEL = "debug"; log debug 1111; 9 | print'# => 1# => 2025-07-12T21:27:57.888|DBG|1111# => 9
Note that $env.NU_LOG_LEVEL is different from nu --log-level, which sets the log level for built-in native Rust Nushell commands. It does not influence the std/log logging used in custom commands and scripts.
nu --log-level 'debug' -c '1|print; use std/log; log debug 1111; 9 | print'# => … a lot more log messages, with references to the Nushell command Rust source files# and without our own `log debug` message# => 1# => 9# => …
$env.NU_PLUGIN_DIRS
A list of directories which will be searched when registering plugins with plugin add. See also:
The current Nushell version. The same as (version).version, but, as an environment variable, it is exported to and can be read by child processes.
$env.PATH
The search path for executing other applications. It is initially inherited from the parent process as a string, but converted to a Nushell list at startup for easy access.
It is converted back to a string before running a child-process.
$env.PROCESS_PATH
When executing a script, this variable represents the name and relative path of the script. Unlike the two variables
above, it is not present when sourcing a file or importing a module.
Note: Also unlike the two variables above, the exact path (including symlinks) that was used to invoke the file is returned.
$env.PROMPT_* and $env.TRANSIENT_PROMPT_*
A number of variables are available for configuring the Nushell prompt that appears on each commandline. See also:
SHLVL is incremented by most shells when entering a new subshell. It can be used to determine the number of nested shells. For instance,
if $env.SHLVL == 2 then typing exit should return you to a parent shell.
$it is a special variable that is only available in a where "row condition" — a convenient shorthand which simplifies field access. See help where or where for more information.
$NU_LIB_DIRS
A constant version of $env.NU_LIB_DIRS - a list of directories which will be searched when using the source, use, or overlay use commands. See also:
`book/standard_library.md`:
```md
---
prev:
text: (Not so) Advanced
link: /book/advanced.md
---
# Standard Library (Preview)
Nushell ships with a standard library of useful commands written in native Nu. By default, the standard library is loaded into memory (but not automatically imported) when Nushell starts.
[[toc]]
## Overview
The standard library currently includes:
- Assertions
- An alternative `help` system with support for completions.
- Additional JSON variant formats
- XML Access
- Logging
- And more
To see a complete list of the commands available in the standard library, run the following:
```nu
nu -c "
use std
scope commands
| where name =~ '^std '
| select name description extra_description
| wrap 'Standard Library Commands'
| table -e
"
::: note
The use std command above loads the entire standard library so that you can see all of the commands at once. This is typically not how it will be used (more info below). It is also run in a separate Nu subshell simply so that it is not loaded into scope in the shell you are using.
:::
Importing the Standard Library
The Standard Library modules and submodules are imported with the use command, just as any other module. See Using Modules for more information.
While working at the commandline, it can be convenient to load the entire standard library using:
use std *
However, this form should be avoided in custom commands and scripts since it has the longest load time.
::: important Optimal Startup when Using the Standard Library
See the notes below on how to ensure that your configuration isn't loading the entire Standard Library.
:::
Importing Submodules
Each submodule of the standard library can be loaded separately. Again, for best performance, load only the submodule(s) that you need in your code.
See Importing Modules for general information on using modules. The recommended import for each of the Standard Library submodules is listed below:
1. Submodules with <command> <subcommand> form
These submodules are normally imported with use std/<submodule> (without a glob/*):
use std/assert: assert and its subcommands
use std/bench: The benchmarking command bench
use std/dirs: The directory stack command dirs and its subcommands
use std/input: The input display command
use std/help: An alternative version of the help command and its subcommands which supports completion and other features
use std/iters: Additional iters-prefixed iteration commands.
use std/log: The log <subcommands> such as log warning <msg>
use std/math: Mathematical constants such as $math.E. These can also be imported as definitions as in Form #2 below.
2. Import the definitions (contents) of the module directly
Some submodules are easier to use when their definitions (commands, aliases, constants, etc.) are loaded into the current scope. For instance:
use std/formats *ls | to jsonl
Submodules that are normally imported with use std/<submodule> * (with a glob/*):
use std/dt *: Additional commands for working with date values
use std/formats *: Additional to and from format conversions
use std/math *: The math constants without a prefix, such as $E. Note that the prefixed form #1 above is likely more understandable when reading and maintaining code.
use std/xml *: Additional commands for working with XML data
3. use std <submodule>
It is possible to import Standard Library submodules using a space-separated form:
use std log
use std formats *
::: important
As mentioned in Using Modules, this form (like use std *) first loads the entire Standard Library into scope and then imports the submodules. In contrast, the slash-separated versions in #1 and #2 above only import the submodule and will be much faster as a result.
:::
The Standard Library Candidate Module
std-rfc, found in the nushell Repository, serves as a staging ground for possible Standard Library additions.
If you are interested in adding to the Standard Library, please submit your code via PR to the std-rfc module in that repository. We also encourage you to install this module and provide feedback on upcoming candidate commands.
::: details More details
Candidate commands for the Standard Library should, in general:
Have broad appeal - Be useful to a large number of users or use cases
Be well-written and clearly commented for future maintainers
Implement help comments with example usage
Have a description that explains why you feel the command should be a part of the standard library. Think of this as an "advertisement" of sorts to convince people to try the command and provide feedback so that it can be promoted in the future.
In order for a command to be graduated from RFC to the Standard Library, it must have:
Positive feedback
Few (or no) outstanding issues and, of course, no significant issues
A PR author for the std submission. This does not necessarily have to be the original author of the command.
Test cases as part of the std submission PR
Ultimately a member of the core team will decide when and if to merge the command into std based on these criteria.
Of course, if a candidate command in std-rfc no longer works or has too many issues, it may be removed from or disabled in std-rfc.
:::
Disabling the Standard Library
To disable the standard library, you can start Nushell using:
nu --no-std-lib
This can be especially useful to minimize overhead when running a command in a subshell using nu -c. For example:
nu --no-std-lib -n -c "$nu.startup-time"# => 1ms 125µs 10ns
nu -n -c "$nu.startup-time"# => 4ms 889µs 576ns
You will not be able to import the library, any of its submodules, nor use any of its commands, when it is disabled in this way.
Using std/log in Modules
::: warning Important!
std/log exports environment variables. To use the std/log module in your own module, please see this caveat in the "Creating Modules" Chapter.
:::
Optimal Startup
If Nushell's startup time is important to your workflow, review your startup configuration in config.nu, env.nu, and potentially others for inefficient use of the standard library. The following command should identify any problem areas:
view files
| enumerate | flatten
| where filename !~ '^std'
| where filename !~ '^entry'
| where {|file|
(view span $file.start $file.end) =~ 'use\W+std[^\/]' }
Edit those files to use the recommended syntax in the Importing Submodules section above.
::: note
If a Nushell library (e.g., from the nu_scripts repository), example, or doc is using this syntax, please report it via an issue or PR. These will be updated over time after Nushell 0.99.0 is released.
If a third-party module is using this syntax, please report it to the author/maintainers to update.
:::
`book/stdout_stderr_exit_codes.md`:
```md
# Stdout, Stderr, and Exit Codes
An important piece of interop between Nushell and external commands is working with the standard streams of data coming from the external.
The first of these important streams is stdout.
## 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
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.
Without the pipeline, Nushell will not do any redirection, allowing it to print directly to the screen.
Stderr
Another common stream that external applications often use to print error messages is stderr. By default, Nushell does not do any redirection of stderr, which means that by default it will print to the screen.
But you can do pass stderr to a command or a file if you want to:
use e>| to pass stderr to next command.
use e> file to redirect stderr to a file.
use do -i { cmd } | complete to capture stderr message.
Exit Code
Finally, external commands have an "exit code". These codes help give a hint to the caller whether the command ran successfully.
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.
The echo command is mainly for pipes. It returns its arguments, ignoring the piped-in value. There is usually little reason to use this over just writing the values as-is.
In contrast, the print command prints the given values to stdout as plain text. It can be used to write to standard error output, as well. Unlike echo, this command does not return any value (print | describe will return "nothing"). Since this command has no output, there is no point in piping it with other commands.
The standard library has commands to write out messages in different logging levels. For example:
The log level for output can be set with the NU_LOG_LEVEL environment variable:
NU_LOG_LEVEL=DEBUG nu std_log.nu
File Redirections
If you want to redirect stdout of an external command to a file, you can use out> followed by a file path. Similarly, you can use err> to redirect stderr:
cat unknown.txt out> out.log err> err.log
If you want to redirect both stdout and stderr to the same file, you can use out+err>:
cat unknown.txt out+err> log.log
Note that out can be shortened to just o, and err can be shortened to just e. So, the following examples are equivalent to the previous ones above:
Also, any expression can be used for the file path, as long as it is a string value:
use std
cat unknown.txt o+e> (std null-device)
Note that file redirections are scoped to an expression and apply to all external commands in the expression. In the example below, out.txt will contain hello\nworld:
let text ="hello\nworld"
($text|head-n 1; $text | tail -n 1) o> out.txt
Pipes and additional file redirections inside the expression will override any file redirections applied from the outside.
Pipe Redirections
If a regular pipe | comes after an external command, it redirects the stdout of the external command as input to the next command. To instead redirect the stderr of the external command, you can use the stderr pipe, err>| or e>|:
cat unknown.txt e>| str upcase
Of course, there is a corresponding pipe for combined stdout and stderr, out+err>| or o+e>|:
nu -c 'print output; print -e error' o+e>| str upcase
Unlike file redirections, pipe redirections do not apply to all commands inside an expression. Rather, only the last command in the expression is affected. For example, only cmd2 in the snippet below will have its stdout and stderr redirected by the pipe.
(cmd1; cmd2) o+e>| cmd3
Raw Streams
Both stdout and stderr are represented as "raw streams" inside of Nushell. These are streams of bytes rather than the structured data used by internal Nushell commands.
Because streams of bytes can be difficult to work with, especially given how common it is to use output as if it was text data, Nushell attempts to convert raw streams into text data. This allows other commands to pull on the output of external commands and receive strings they can further process.
Nushell attempts to convert to text using UTF-8. If at any time the conversion fails, the rest of the stream is assumed to always be bytes.
If you want more control over the decoding of the byte stream, you can use the decode command. The decode 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:
0x[8a 4c] | decode shift-jis
# => 貝
`book/style_guide.md`:
```md
---
next:
text: Nu as a Shell
link: /book/nu_as_a_shell.md
---
# Best Practices
This page is a working document collecting syntax guidelines and best practices we have discovered so far.
The goal of this document is to eventually land on a canonical Nushell code style, but as for now it is still work in
progress and subject to change. We welcome discussion and contributions.
Keep in mind that these guidelines are not required to be used in external repositories (not ours), you can change them in the
way you want, but please be consistent and follow your rules.
All escape sequences should not be interpreted literally, unless directed to do so. In other words,
treat something like `\n` like the new line character and not a literal slash followed by `n`.
## Formatting
### Defaults
**It's recommended to** assume that by default no spaces or tabs allowed, but the following rules define where they are allowed.
### Basic
- **It's recommended to** put one space before and after pipe `|` symbol, commands, subcommands, their options and arguments.
- **It's recommended to** never put several consecutive spaces unless they are part of string.
- **It's recommended to** omit commas between list items.
Correct:
```nu
'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff'
Incorrect:
# - too many spaces after "|": 2 instead of 1
'Hello,Nushell!This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff'
One-line Format
One-line format is a format for writing all commands in one line.
It's recommended to default to this format:
unless you are writing scripts
in scripts for lists and records unless they either:
more than 80 characters long
contain nested lists or records
for pipelines less than 80 characters long not containing items should be formatted with
a long format
Rules:
parameters:
It's recommended to put one space after comma , after block or closure parameter.
It's recommended to put one space after pipe | symbol denoting block or closure parameter list end.
block and closure bodies:
It's recommended to put one space after opening block or closure curly brace { if no explicit parameters defined.
It's recommended to put one space before closing block or closure curly brace }.
records:
It's recommended to put one space after : after record key.
It's recommended to put one space after comma , after key value.
lists:
It's recommended to put one space after comma , after list value.
surrounding constructs:
It's recommended to put one space before opening square [, curly brace {, or parenthesis ( if preceding symbol is not the same.
It's recommended to put one space after closing square ], curly brace }, or parenthesis ) if following symbol is not the same.
# too many spaces before "|el|": no space is allowed
[[status]; [UP] [UP]] | all { |el| $el.status == UP }# too many spaces before ",": no space is allowed
[1234] | reduce {|elt , acc|$elt+$acc }
# too many spaces before "x": no space is allowed
{ x: 1, y: 2}
# too many spaces before "[3": one space is required
[12] | zip [34]
# too many spaces before "]": no space is allowed
[ ]
# too many spaces before ")": no space is allowed
(1+2 ) *3
Multi-line Format
Multi-line format is a format for writing all commands in several lines. It inherits all rules from one-line format
and modifies them slightly.
It's recommended to default to this format:
while you are writing scripts
in scripts for lists and records while they either:
more than 80 characters long
contain nested lists or records
for pipelines more 80 characters long
Rules:
general:
It's required to omit trailing spaces.
block and closure bodies:
It's recommended to put each body pipeline on a separate line.
records:
It's recommended to put each record key-value pair on separate line.
lists:
It's recommended to put each list item on separate line.
surrounding constructs:
It's recommended to put one \n before opening square [, curly brace {, or parenthesis ( if preceding symbol is not the and applying this rule produce line with a singular parenthesis.
It's recommended to put one \n after closing square ], curly brace }, or parenthesis ) if following symbol is not the same and applying this rule produce line with a singular parenthesis.
Correct:
[[status]; [UP] [UP]] | all {|el|$el.status ==UP
}
[1234] | reduce {|elt, acc|$elt+$acc
}
{x: 1, y: 2}
[
{name: "Teresa", age: 24},
{name: "Thomas", age: 26}
]
let selectedProfile = (for it in ($credentials| transpose name credentials) {
echo $it.name
})
Incorrect:
# too many spaces before "|el|": no space is allowed (like in one-line format)
[[status]; [UP] [UP]] | all { |el|# too few "\n" before "}": one "\n" is required$el.status ==UP}
# too many spaces before "2": one space is required (like in one-line format)
[1234] | reduce {|elt, acc|$elt+$acc
}
{
# too many "\n" before "x": one-line format required as no nested lists or record exist
x: 1,
y: 2
}
# too few "\n" before "{": multi-line format required as there are two nested records
[{name: "Teresa", age: 24},
{name: "Thomas", age: 26}]
let selectedProfile = (
# too many "\n" before "foo": no "\n" is allowedfor it in ($credentials| transpose name credentials) {
echo $it.name
})
Naming Convention
Abbreviations and Acronyms
It's recommended to use full concise words over abbreviations and acronyms, unless they are well-known and/or
commonly used.
Correct:
query-user --id 123$user.name | str downcase
Incorrect:
qry-usr --id 123$user.name | string downcase
Case
Commands
It's recommended to use kebab-case for command names with multiple words.
Sub commands are commands that are logically grouped under a parent command and separated by a space.
It's recommended to use kebab-case for the sub-command name.
Correct:
date now
date list-timezone
def "login basic-auth" [username: string password: string] {
# ...
}
It's recommended to keep count of all positional parameters less than or equal to 2, for remaining inputs use options. Assume that command can expect source and destination parameter, like mv: source and target file or directory.
It's recommended to use positional parameters unless they can't be used due to rules listed here or technical restrictions.
For instance, when there are several kinds of optional parameters (but at least one parameter should be provided)
use options. Great example of this is ansi gradient command where at least foreground or background must be passed.
It's recommended to provide both long and short options.
Documentation
It's recommended to provide documentation for all exported entities (like custom commands) and their
inputs (like custom command parameters and options).
`book/table_of_contents.md`:
```md
# Table of Contents
- [Installation](installation.md) - Installing Nushell
- [Introduction](README.md) - Getting started
- [Thinking in Nu](thinking_in_nu.md) - Thinking in Nushell
- [Moving around](moving_around.md) - Moving around in Nushell
- [Types of data](types_of_data.md) - Types of data in Nushell
- [Loading data](loading_data.md) - Loading data and using it
- [Strings](working_with_strings.md) - Strings, escape characters, and string interpolation
- [Working with lists](working_with_lists.md) - Working with Nu lists
- [Working with tables](working_with_tables.md) - Working with Nu tables
- [Pipelines](pipelines.md) - How the pipeline works
- [Configuration](configuration.md) - How to configure Nushell
- [3rd Party Prompts](3rdpartyprompts.md) - How to configure 3rd party prompts
- [Custom commands](custom_commands.md) - Creating your own commands
- [Aliases](aliases.md) - How to alias commands
- [Operators](operators.md) - Operators supported by Nushell
- [Variables](variables.md) - Working with variables
- [Control flow](control_flow.md) - Working with the control flow commands
- [Environment](environment.md) - Working with environment variables
- [Stdout, stderr, and exit codes](stdout_stderr_exit_codes.md) - Working with stdout, stderr, and exit codes
- [Modules](modules.md) - Creating and using your own modules
- [Hooks](hooks.md) - Adding code snippets to be run automatically
- [Scripts](scripts.md) - Creating your own scripts
- [Metadata](metadata.md) - An explanation of Nu's metadata system
- [Creating your own errors](creating_errors.md) - Creating your own error messages
- [Directory Stack](directory_stack.md) - Working with multiple locations
- [Running External (System) Commands](./running_externals.md) - Running external commands with a naming conflict
- [Plugins](plugins.md) - Enhancing Nushell with more features using plugins
- [Parallelism](parallelism.md) - Running your code in parallel
- [Line editor](line_editor.md) - Nushell's line editor
- [Dataframes](dataframes.md) - Working with dataframes in Nushell
- [Explore](explore.md) - Using the Nushell TUI
- [Coloring and Theming](coloring_and_theming.md) - How to change the colors and themes in Nushell
- [Regular Expressions](regular_expressions.md) - Guide to use regex
- [Coming from Bash](coming_from_bash.md) - Guide for those coming to Nushell from Bash
- [Nushell map from shells/DSL](nushell_map.md) - Guide to show how Nushell compares with SQL, LINQ, PowerShell, and Bash
- [Nushell map from imperative languages](nushell_map_imperative.md) - Guide to show how Nushell compares with Python, Kotlin, C++, C#, and Rust
- [Nushell map from functional languages](nushell_map_functional.md) - Guide to show how Nushell compares with Clojure, Tablecloth (OCaml / Elm) and Haskell
- [Nushell operator map](nushell_operator_map.md) - Guide to show how Nushell operators compare with those in general purpose programming languages
- [Command Reference](/commands/) - List of all Nushell's commands
book/testing.md:
# Testing your Nushell Code## Assert Commands
Nushell provides a set of "assertion" commands in the standard library.
One could use built-in equality / order tests such as `==` or `<=` or more complex commands and throw errors manually when an expected condition fails, but using what the standard library has to offer is arguably easier!
In the following, it will be assumed that the `std assert` module has been imported inside the current scope
```nuuse std/assert
The foundation for every assertion is the std assert command. If the condition is not true, it makes an error.
assert (1==2)
Error:
× Assertion failed.
╭─[entry #13:1:1]
1 │ assert (1 == 2)
· ───┬──
· ╰── It is not true.
╰────
Optionally, a message can be set to show the intention of the assert command, what went wrong or what was expected:
let a =0
assert ($a==19) $"The lockout code is wrong, received: ($a)"
Error:
× The lockout code is wrong, received: 13
╭─[entry #25:1:1]
1 │ let a = 0
2 │ assert ($a == 19) $"The lockout code is wrong, received: ($a)"
· ────┬───
· ╰── It is not true.
╰────
There are many assert commands, which behave exactly as the base one with the proper operator. The additional value for them is the ability for better error messages.
For example this is not so helpful without additional message:
let a ="foo"let b ="bar"
assert ($b| str contains $a)
Error: × Assertion failed.
╭─[entry #5:3:8]
2 │ let b = "bar"
3 │ assert ($b | str contains $a)
· ───────────┬──────────
· ╰── It is not true.
╰────
While with using assert str contains:
let a ="a needle"let b ="haystack"
assert str contains $b$a
Error: × Assertion failed.
╭─[entry #7:3:21]
2 │ let b = "bar"
3 │ assert str contains $b $a
· ──┬──
· ╰─┤ This does not contain 'a needle'.
· │ value: "haystack"
╰────
In general for base assert command it is encouraged to always provide the additional message to show what went wrong. If you cannot use any built-in assert command, you can create a custom one with passing the label for error make for the assert command:
def "assert even" [number: int] {
assert ($number mod 2==0) --error-label {
text: $"($number) is not an even number",
span: (metadata $number).span,
}
}
Then you'll have your detailed custom error message:
let$a=13
assert even $a
Error:
× Assertion failed.
╭─[entry #37:1:1]
1 │ assert even $a
· ─┬
· ╰── 13 is not an even number
╰────
Running the Tests
Now that we are able to write tests by calling commands from std assert, it would be great to be able to run them and see our tests fail when there is an issue and pass when everything is correct :)
Nupm Package
In this first case, we will assume that the code you are trying to test is part of a Nupm package.
In that case, it is as easy as following the following steps
create a tests/ directory next to the nupm.nuon package file of your package
make the tests/ directory a valid module by adding a mod.nu file into it
write commands inside tests/
call nupm test
The convention is that any command fully exported from the tests module will be run as a test, e.g.
export def some-test in tests/mod.nu will run
def just-an-internal-cmd in tests/mod.nu will NOT run
export def another-test in tests/spam.nu will run if and only if there is something like export use spam.nu * in tests/mod.nu
Standalone Tests
If your Nushell script or module is not part of a Nupm package, the simplest way is to write tests in standalone scripts and then call them, either from a Makefile or in a CI:
Let's say we have a simple math.nu module which contains a simple Fibonacci command:
# `fib n` is the n-th Fibonacci number
export def fib [n: int] [ nothing -> int ] {
if$n==0 {
return0
} elseif$n==1 {
return1
}
(fib ($n-1)) + (fib ($n-2))
}
then a test script called tests.nu could look like
use math.nu fib
use std/assertfor t in [ [input, expected]; [0, 0], [1, 1], [2, 1], [3, 2], [4, 3], [5, 5], [6, 8], [7, 13],] { assert equal (fib $t.input) $t.expected}
and be invoked as nu tests.nu
Basic Test Framework
It is also possible to define tests in Nushell as functions with descriptive names and discover
them dynamically without requiring a Nupm package. The following uses scope commands and a
second instance of Nushell to run the generated list of tests.
use std/assertsource fib.nudef main [] { print "Running tests..." let test_commands = ( scope commands | where ($it.type == "custom") and ($it.name | str starts-with "test ") and not ($it.description | str starts-with "ignore") | get name | each { |test| [$"print 'Running test: ($test)'", $test] } | flatten | str join "; " ) nu --commands $"source ($env.CURRENT_FILE); ($test_commands)" print "Tests completed successfully"}def "test fib" [] { for t in [ [input, expected]; [0, 0], [1, 1], [2, 1], [3, 2], [4, 3], [5, 5], [6, 8], [7, 13] ] { assert equal (fib $t.input) $t.expected }}# ignoredef "test show-ignored-test" [] { print "This test will not be executed"}
This is a simple example but could be extended to include many of the things you might expect from
a testing framework, including setup and tear down functions and test discovery across files.
`book/thinking_in_nu.md`:
```md
# Thinking in Nu
Nushell is different! It's common (and expected!) for new users to have some existing "habits" or mental models coming from other shells or languages.
The most common questions from new users typically fall into one of the following topics:
[[toc]]
## Nushell isn't Bash
### It can sometimes look like Bash
Nushell is both a programming language and a shell. Because of this, it has its own way of working with files, directories, websites, and more. You'll find that some features in Nushell work similar to those you're familiar with in other shells. For instance, pipelines work by combining two (or more) commands together, just like in other shells.
For example, the following commandline works the same in both Bash and Nushell on Unix/Linux platforms:
```nu
curl -s https://api.github.com/repos/nushell/nushell/contributors | jq -c '.[] | {login,contributions}'
# => returns contributors to Nushell, ordered by number of contributions
Nushell has many other similarities with Bash (and other shells) and many commands in common.
::: tip
Bash is primarily a command interpreter which runs external commands. Nushell provides many of these as cross-platform, built-in commands.
While the above commandline works in both shells, in Nushell there's just no need to use the curl and jq commands. Instead, Nushell has a built-in http get command and handles JSON data natively. For example:
http get https://api.github.com/repos/nushell/nushell/contributors | select login contributions
:::
::: warning Thinking in Nushell
Nushell borrows concepts from many shells and languages. You'll likely find many of Nushell's features familiar.
:::
But it's not Bash
Because of this, however, it's sometimes easy to forget that some Bash (and POSIX in general) style constructs just won't work in Nushell. For instance, in Bash, it would be normal to write:
# Redirect using >echo"hello"> output.txt
# But compare (greater-than) using the test commandtest 4 -gt 7
echo$?# => 1
In Nushell, however, the > is used as the greater-than operator for comparisons. This is more in line with modern programming expectations.
4>10# => false
Since > is an operator, redirection to a file in Nushell is handled through a pipeline command that is dedicated to saving content - save:
"hello"| save output.txt
::: warning Thinking in Nushell
We've put together a list of common Bash'isms and how to accomplish those tasks in Nushell in the Coming from Bash Chapter.
:::
Implicit Return
Users coming from other shells will likely be very familiar with the echo command. Nushell's
echo might appear the same at first, but it is very different.
First, notice how the following output looks the same in both Bash and Nushell (and even PowerShell and Fish):
echo "Hello, World"# => Hello, World
But while the other shells are sending Hello, World straight to standard output, Nushell's echo is
simply returning a value. Nushell then renders the return value of a command, or more technically, an expression.
More importantly, Nushell implicitly returns the value of an expression. This is similar to PowerShell or Rust in many respects.
::: tip
An expression can be more than just a pipeline. Even custom commands (similar to functions in many languages, but we'll cover them more in depth in a later chapter) automatically, implicitly return the last value. There's no need for an echo or even a return command to return a value - It just happens.
:::
In other words, the string "Hello, World" and the output value from echo "Hello, World" are equivalent:
"Hello, World"== (echo "Hello, World")
# => true
Here's another example with a custom command definition:
def latest-file [] {
ls | sort-by modified | last
}
The output of that pipeline (its "value") becomes the return value of the latest-file custom command.
::: warning Thinking in Nushell
Most anywhere you might write echo <something>, in Nushell, you can just write <something> instead.
:::
Single Return Value per Expression
It's important to understand that an expression can only return a single value. If there are multiple subexpressions inside an expression, only the last value is returned.
A common mistake is to write a custom command definition like this:
def latest-file [] {
echo "Returning the last file"
ls | sort-by modified | last
}
latest-file
New users might expect:
Line 2 to output "Returning the last file"
Line 3 to return/output the file
However, remember that echoreturns a value. Since only the last value is returned, the Line 2 value is discarded. Only the file will be returned by line 3.
To make sure the first line is displayed, use the print command:
def latest-file [] {
print"Returning last file"
ls | sort-by modified | last
}
Also compare:
40; 50; 60
::: tip
A semicolon is the same as a newline in a Nushell expression. The above is the same as a file or multi-line command:
The first value is evaluated as the integer 40 but is not returned
The second value is evaluated as the integer 50 but is not returned
The third value is evaluated as the integer 60, and since it is the last
value, it is is returned and displayed (rendered).
::: warning Thinking in Nushell
When debugging unexpected results, be on the lookout for:
Subexpressions (e.g., commands or pipelines) that ...
... output a (non-null) value ...
... where that value isn't returned from the parent expression.
These can be likely sources of issues in your code.
:::
Every Command Returns a Value
Some languages have the concept of "statements" which don't return values. Nushell does not.
In Nushell, every command returns a value, even if that value is null (the nothing type). Consider the following multiline expression:
let p = 7
print $p
$p * 6
Line 1: The integer 7 is assigned to $p, but the return value of the
let command itself is null. However, because it is not the last
value in the expression, it is not displayed.
Line 2: The return value of the print command itself is null, but the print command
forces its argument ($p, which is 7) to be displayed. As with Line 1, the null return value
is discarded since this isn't the last value in the expression.
Line 3: Evaluates to the integer value 42. As the last value in the expression, this is the return
result, and is also displayed (rendered).
::: warning Thinking in Nushell
Becoming familiar with the output types of common commands will help you understand how
to combine simple commands together to achieve complex results.
help <command> will show the signature, including the output type(s), for each command in Nushell.
:::
Think of Nushell as a Compiled Language
In Nushell, there are exactly two, separate, high-level stages when running code:
Stage 1 (Parser): Parse the entire source code
Stage 2 (Engine): Evaluate the entire source code
It can be useful to think of Nushell's parsing stage as compilation in static languages like Rust or C++. By this, we mean that all of the code that will be evaluated in Stage 2 must be known and available during the parsing stage.
::: important
However, this also means that Nushell cannot currently support an eval construct as with dynamic languages such as Bash or Python.
:::
Features Built on Static Parsing
On the other hand, the static results of Parsing are key to many features of Nushell its REPL, such as:
Accurate and expressive error messages
Semantic analysis for earlier and robust detection of error conditions
IDE integration
The type system
The module system
Completions
Custom command argument parsing
Syntax highlighting
Real-time error highlighting
Profiling and debugging commands
(Future) Formatting
(Future) Saving IR (Intermediate Representation) "compiled" results for faster execution
Limitations
The static nature of Nushell often leads to confusion for users coming to Nushell from languages where an eval is available.
Consider a simple two-line file:
<line1 code>
<line2 code>
Parsing:
Line 1 is parsed
Line 2 is parsed
If parsing was successful, then Evaluation:
Line 1 is evaluated
Line 2 is evaluated
This helps demonstrate why the following examples cannot run as a single expression (e.g., a script) in Nushell:
::: note
The following examples use the source command, but similar conclusions apply to other commands that parse Nushell source code, such as use, overlay use, hide or source-env.
:::
Example: Dynamically Generating Source
Consider this scenario:
"print Hello"| save output.nu
source output.nu
# => Error: nu::parser::sourced_file_not_found# =># => × File not found# => ╭─[entry #5:2:8]# => 1 │ "print Hello" | save output.nu# => 2 │ source output.nu# => · ────┬────# => · ╰── File not found: output.nu# => ╰────# => help: sourced files need to be available before your script is run
This is problematic because:
Line 1 is parsed but not evaluated. In other words, output.nu is not created during the parsing stage, but only during evaluation.
Line 2 is parsed. Because source is a parser-keyword, resolution of the sourced file is attempted during Parsing (Stage 1). But output.nu doesn't even exist yet! If it does exist, then it's probably not even the correct file! This results in the error.
::: note
Typing these as two separate lines in the REPL will work since the first line will be parsed and evaluated, then the second line will be parsed and evaluated.
The limitation only occurs when both are parsed together as a single expression, which could be part of a script, block, closure, or other expression.
See the REPL section in "How Nushell Code Gets Run" for more explanation.
:::
Example: Dynamically Creating a Filename to be Sourced
Another common scenario when coming from another shell might be attempting to dynamically create a filename that will be sourced:
let my_path ="~/nushell-files"
source $"($my_path)/common.nu"# => Error:# => × Error: nu::shell::not_a_constant# => │# => │ × Not a constant.# => │ ╭─[entry #6:2:11]# => │ 1 │ let my_path = "~/nushell-files"# => │ 2 │ source $"($my_path)/common.nu"# => │ · ────┬───# => │ · ╰── Value is not a parse-time constant# => │ ╰────# => │ help: Only a subset of expressions are allowed constants during parsing. Try using the 'const' command or typing the value literally.# => │# => ╭─[entry #6:2:8]# => 1 │ let my_path = "~/nushell-files"# => 2 │ source $"($my_path)/common.nu"# => · ───────────┬───────────# => · ╰── Encountered error during parse-time evaluation# => ╰────
Because the let assignment is not resolved until evaluation, the parser-keyword source will fail during parsing if passed a variable.
::: details Comparing Rust and C++
Imagine that the code above was written in a typical compiled language such as C++:
let my_path = "foo";use format!("{}::common", my_path);
If you've ever written a simple program in any of these languages, you can see these examples aren't valid in those languages. Like Nushell, compiled languages require that all of the source code files are ready and available to the compiler beforehand.
:::
::: tip See Also
As noted in the error message, however, this can work if my_path can be defined as a constant since constants can be (and are) resolved during parsing.
Example: Change to a different directory (cd) and source a file
Here's one more — Change to a different directory and then attempt to source a file in that directory.
if ('spam/foo.nu' | path exists) {
cd spam
source-env foo.nu
}
Based on what we've covered about Nushell's Parse/Eval stages, see if you can spot the problem with that example.
::: details Solution
In line 3, during Parsing, the source-env attempts to parse foo.nu. However, cd doesn't occur until Evaluation. This results in a parse-time error, since the file is not found in the current directory.
To resolve this, of course, simply use the full-path to the file to be sourced.
::: warning Thinking in Nushell
Nushell is designed to use a single Parsing stage for each expression or file. This Parsing stage occurs before and is separate from Evaluation. While this enables many of Nushell's features, it also means that users need to understand the limitations it creates.
:::
Variables are Immutable by Default
Another common surprise when coming from other languages is that Nushell variables are immutable by default. While Nushell has optional mutable variables, many of Nushell's commands are based on a functional-style of programming which requires immutability.
Immutable variables are also key to Nushell's par-each command, which allows you to operate on multiple values in parallel using threads.
::: warning Thinking in Nushell
If you're used to relying on mutable variables, it may take some time to relearn how to code in a more functional style. Nushell has many functional features and commands that operate on and with immutable variables. Learning them will help you write code in a more Nushell-idiomatic style.
A nice bonus is the performance increase you can realize by running parts of your code in parallel with par-each.
:::
Nushell's Environment is Scoped
Nushell takes multiple design cues from compiled languages. One such cue is that languages should avoid global mutable state. Shells have commonly used global mutation to update the environment, but Nushell attempts to steer clear of this approach.
In Nushell, blocks control their own environment. Changes to the environment are scoped to the block where they occur.
In practice, this lets you write (as just one example) more concise code for working with subdirectories. Here's an example that builds each sub-project in the current directory:
ls | each { |row|
cd $row.name
make
}
The cd command changes the PWD environment variables, but this variable change does not survive past the end of the block. This allows each iteration to start from the current directory and then enter the next subdirectory.
Having a scoped environment makes commands more predictable, easier to read, and when the time comes, easier to debug. It's also another feature that is key to the par-each command we discussed above.
Nushell also provides helper commands like load-env as a convenient way of loading multiple updates to the environment at once.
::: note
def --env is an exception to this rule. It allows you to create a command that changes the parent's environment.
:::
::: warning Thinking in Nushell
Use scoped-environment to write more concise scripts and prevent unnecessary or unwanted global environment mutation.
:::
`book/types_of_data.md`:
```md
---
prev:
text: Nu Fundamentals
link: /book/nu_fundamentals.md
---
# Types of Data
Traditional Unix shell commands communicate with each other using strings of text -- One command writes text to standard output (often abbreviated `stdout`) and the other reads text from standard input (or `stdin`). This allows multiple commands to be combined together to communicate through what is called a "pipeline".
Nushell embraces this approach and expands it to include other types of data in addition to strings.
Like many programming languages, Nu models data using a set of simple, structured data types. Simple data types include integers, floats, strings, and booleans. There are also special types for dates, file sizes, and time durations.
The [`describe`](/commands/docs/describe.md) command returns the type of a data value:
```nu
42 | describe
# => int
::: tip
You can also easily create lists of characters with a form similar to ranges with the command seq char as well as with dates using the seq date command.
:::
Cell Paths
Description:
An expression that is used to navigated to an inner value in a structured value.
Annotation:
cell-path
Literal syntax:
A dot-separated list of row (int) and column (string) IDs. E.g., name.4.5.
Optionally, use a leading $. when needed for disambiguation, such as when assigning a cell-path to a variable
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:
open nushell_logo.jpg
| into binary
|first2|$in==0x[ff d8]
# => true
Structured Data Types
Nushell includes a collection of structured data types that can contain the primitive types above. For example, instead of a single float, structured data gives us a way to represent multiple float values, such as a list of temperature readings, in the same value. Nushell supports the following structured data types:
Lists
Description:
Ordered sequence of zero or more values of any type
The table is a core data structure in Nushell. As you run commands, you'll see that many of them return tables as output. A table has both rows and columns.
:::tip
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:
[{x:12, y:5}, {x:3, y:6}] | get 0# => ╭───┬────╮# => │ x │ 12 │# => │ y │ 5 │# => ╰───┴────╯
:::
Other Data Types
Any
Description:
When used in a type annotation or signature, matches any type. In other words, a "superset" of other types.
Annotation:
any
Literal syntax:
N/A - Any literal value can be assigned to an any type
`book/variables.md`:
```md
# Variables
Nushell values can be assigned to named variables using the `let`, `const`, or `mut` keywords.
After creating a variable, we can refer to it using `$` followed by its name.
## Types of Variables
### Immutable Variables
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
# => ╰────
However, immutable variables can be 'shadowed'. Shadowing means that they are redeclared and their initial value cannot be used anymore within the same scope.
let val =42# declare a variabledo { let val =101; $val } # in an inner scope, shadow the variable# => 101$val# in the outer scope the variable remains unchanged# => 42let 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
A mutable variable is allowed to change its value by assignment. These are declared using the mut keyword.
mut val =42$val+=27$val# => 69
There are a couple of assignment operators used with mutable variables
Operator
Description
=
Assigns a new value to the variable
+=
Adds a value to the variable and makes the sum its new value
-=
Subtracts a value from the variable and makes the difference its new value
*=
Multiplies the variable by a value and makes the product its new value
/=
Divides the variable by a value and makes the quotient its new value
++=
Appends a list or a value to a variable
::: tip Note
+=, -=, *= and /= are only valid in the contexts where their root operations are expected to work. For example, += uses addition, so it can not be used for contexts where addition would normally fail
++= requires that either the variable or the argument is a list.
:::
More on Mutability
Closures and nested defs cannot capture mutable variables from their environment. For example
# naive method to count number of elements in a list
mut x =0
[123] | each { $x+=1 } # error: $x is captured in a closure
To use mutable variables for such behaviour, you are encouraged to use the loops
Constant Variables
A constant variable is an immutable variable that can be fully evaluated at parse-time. These are useful with commands that need to know the value of an argument at parse time, like source, use and plugin use. See how nushell code gets run for a deeper explanation. They are declared using the const keyword
Try to use immutable variables for most use-cases.
You might wonder why Nushell uses immutable variables by default. For the first few years of Nushell's development, mutable variables were not a language feature. Early on in Nushell's development, we decided to see how long we could go using a more data-focused, functional style in the language. This experiment showed its value when Nushell introduced parallelism. By switching from each to par-each in any Nushell script, you're able to run the corresponding block of code in parallel over the input. This is possible because Nushell's design leans heavily on immutability, composition, and pipelining.
Many, if not most, use-cases for mutable variables in Nushell have a functional solution that:
Only uses immutable variables, and as a result ...
Has better performance
Supports streaming
Can support additional features such as par-each as mentioned above
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 with enumerate:
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 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:
While reduce processes lists, the generate command can be used with arbitrary sources such as external REST APIs, also without requiring mutable variables. Here's an example that retrieves local weather data every hour and generates a continuous list from that data. The each command can be used to consume each new list item as it becomes available.
generate {|weather_station|let res =try {
http get -ef $'https://api.weather.gov/stations/($weather_station)/observations/latest'
} catch {
null
}
sleep 1hr
match $res {
null => {
next: $weather_station
}
_ => {
out: ($res.body? | default '' | from json)
next: $weather_station
}
}
} khot
| each {|weather_report|
{
time: ($weather_report.properties.timestamp | into datetime)
temp: $weather_report.properties.temperature.value
}
}
Performance Considerations
Using filter commands with immutable variables is often far more performant than mutable variables with traditional flow-control statements such as for and while. For example:
Using a for statement to create a list of 50,000 random numbers:
timeit {
mut randoms = []
for _ in 1..50_000 {
$randoms= ($randoms|append (random int))
}
}
Result: 1min 4sec 191ms 135µs 90ns
Using each to do the same:
timeit {
let randoms = (1..50_000 | each {random int})
}
Result: 19ms 314µs 205ns
Using each with 10,000,000 iterations:
timeit {
let randoms = (1..10_000_000 | each {random int})
}
Result: 4sec 233ms 865µs 238ns
As with many filters, the each statement also streams its results, meaning the next stage of the pipeline can continue processing without waiting for the results to be collected into a variable.
For tasks which can be optimized by parallelization, as mentioned above, par-each can have even more drastic performance gains.
Variable Names
Variable names in Nushell come with a few restrictions as to what characters they can contain. In particular, they cannot contain these characters:
. [ ( { + - * ^ / = ! < > & |
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.
let$var=42# identical to `let var = 42`
`book/working_with_lists.md`:
```md
# Working with Lists
:::tip
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 │
# => ╰───┴──────╯
:::
Creating lists
A list is an ordered collection of values.
A list is created using square brackets surrounding values separated by spaces, linebreaks, and/or commas.
For example, [foo bar baz] or [foo, bar, baz].
::: tip
Nushell lists are similar to JSON arrays. The same [ "Item1", "Item2", "Item3" ] that represents a JSON array can also be used to create a Nushell list.
:::
Updating lists
We can insert values into lists as they flow through the pipeline, for example let's insert the value 10 into the middle of a list:
[1,2,3,4] | insert 210# => [1, 2, 10, 3, 4]
We can also use update to replace the 2nd element with the value 10.
[1,2,3,4] | update 110# => [1, 10, 3, 4]
Removing or Adding Items from List
In addition to insert and update, we also have prepend and append. These let you insert to the beginning of a list or at the end of the list, respectively.
For example:
let colors = [yellow green]
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]
In case you want to remove items from list, there are many ways. skip allows you skip first rows from input, while drop allows you to skip specific numbered rows from end of list.
let colors = [red yellow green purple]
let colors = ($colors| skip 1)
let colors = ($colors| drop 2)
$colors# => [yellow]
We also have last and first which allow you to take from the end or beginning of the list, respectively.
let colors = [red yellow green purple black magenta]
let colors = ($colors| last 3)
$colors# => [purple black magenta]
And from the beginning of a list,
let colors = [yellow green purple]
let colors = ($colors|first2)
$colors# => [yellow green]
Using the Spread Operator
To append one or more lists together, optionally with values interspersed in between, you can also use the
spread operator (...):
To iterate over the items in a list, use the each command with a block
of Nu code that specifies what to do to each item. The block parameter (e.g. |elt| in { |elt| print $elt }) is the current list
item, but the enumerate filter can be used to provide index and item values if needed. For example:
let names = [MarkTamiAmandaJeremy]
$names| each { |elt| $"Hello, ($elt)!" }
# Outputs "Hello, Mark!" and three more similar lines.$names| enumerate | each { |elt| $"($elt.index + 1) - ($elt.item)" }
# Outputs "1 - Mark", "2 - Tami", etc.
The where command can be used to create a subset of a list, effectively filtering the list based on a condition.
The following example gets all the colors whose names end in "e".
let colors = [red orange yellow green blue purple]
$colors| where ($it| str ends-with 'e')
# The block passed to `where` must evaluate to a boolean.# This outputs the list [orange blue purple].
In this example, we keep only values higher than 7.
let scores = [710867]
$scores| where $it>7# [10 8]
The reduce command computes a single value from a list.
It uses a block which takes 2 parameters: the current item (conventionally named elt) and an accumulator
(conventionally named acc). To specify an initial value for the accumulator, use the --fold (-f) flag.
To change elt to have index and item values, use the enumerate filter.
For example:
To access a list item at a given index, use the $name.index form where $name is a variable that holds a list.
For example, the second element in the list below can be accessed with $names.1.
let names = [MarkTamiAmandaJeremy]
$names.1# gives Tami
If the index is in some variable $index we can use the get command to extract the item from the list.
let names = [MarkTamiAmandaJeremy]
let index =1$names| get $index# gives Tami
The length command returns the number of items in a list.
For example, [red green blue] | length outputs 3.
The is-empty command determines whether a string, list, or table is empty.
It can be used with lists as follows:
let colors = [red green blue]
$colors| is-empty # falselet colors = []
$colors| is-empty # true
The in and not-in operators are used to test whether a value is in a list. For example:
let colors = [red green blue]
'blue' in $colors# true
'yellow' in $colors# false
'gold' not-in $colors# true
The any command determines if any item in a list
matches a given condition.
For example:
let colors = [red green blue]
# Do any color names end with "e"?$colors| any {|elt|$elt| str ends-with "e" } # true# Is the length of any color name less than 3?$colors| any {|elt| ($elt| str length) <3 } # falselet scores = [384]
# Are any scores greater than 7?$scores| any {|elt|$elt>7 } # true# Are any scores odd?$scores| any {|elt|$elt mod 2==1 } # true
The all command determines if every item in a list
matches a given condition.
For example:
let colors = [red green blue]
# Do all color names end with "e"?$colors| all {|elt|$elt| str ends-with "e" } # false# Is the length of all color names greater than or equal to 3?$colors| all {|elt| ($elt| str length) >=3 } # truelet scores = [384]
# Are all scores greater than 7?$scores| all {|elt|$elt>7 } # false# Are all scores even?$scores| all {|elt|$elt mod 2==0 } # false
Converting the List
The flatten command creates a new list from an existing list
by adding items in nested lists to the top-level list.
This can be called multiple times to flatten lists nested at any depth.
For example:
The wrap command converts a list to a table. Each list value will
be converted to a separate row with a single column:
let zones = [UTCCETEurope/Moscow Asia/Yekaterinburg]
# Show world clock for selected time zones$zones| wrap 'Zone' | upsert Time {|row| (date now | date to-timezone $row.Zone| format date '%Y.%m.%d %H:%M')}
`book/working_with_records.md`:
```md
# Working with Records
:::tip
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 │
# => ╰──────┴─────╯
Note that the my_recordvariable is immutable. The updated record resulting from the pipeline is printed as seen in the code block. The my_record variable still holds the original value - $my_record.age is still 30.
:::
Creating records
A record is a collection of zero or more key-value pair mappings. It is similar to a JSON object, and can be created using the same syntax:
In Nushell, the key-value pairs of a record can also be separated using spaces or line-breaks.
::: tip
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:
let first_record = { name: "Sam", rank: 10 }
$first_record| merge { title: "Mayor" }
# => ╭───────┬───────╮# => │ name │ Sam │# => │ rank │ 10 │# => │ title │ Mayor │# => ╰───────┴───────╯
Use the spread operator (...) to expand the first record inside a new record:
let first_record = { name: "Sam", rank: 10 }
{
...$first_record
title: "Mayor"
}
# => ╭───────┬───────╮# => │ name │ Sam │# => │ rank │ 10 │# => │ title │ Mayor │# => ╰───────┴───────╯
Iterating over a Record
Use the items command to iterate over each pair of key and value:
{ "apples": 543,"bananas": 411,"oranges": 0 } | items {|fruit, count| $"We have ($fruit) ($count)" }
# => ╭───┬─────────────────────╮# => │ 0 │ We have apples 543 │# => │ 1 │ We have bananas 411 │# => │ 2 │ We have oranges 0 │# => ╰───┴─────────────────────╯
Alternatively, you can transpose the record into a table with columns, and then iterate over rows:
{ "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 │# => ╰───┴─────────────────────╯
See Working with Tables - Remember, commands that operate on table rows will usually operate the same way on records.
`book/working_with_strings.md`:
```md
# Working with Strings
As with most languages, strings are a collection of 0 or more characters that represent text. This can include file names, file paths, names of columns,
and much more. Strings are so common that Nushell offers multiple string formats to match your use-case:
## String Formats at a Glance
| Format of string | Example | Escapes | Notes |
| ---------------------------------------------------- | ----------------------- | ------------------------- | ---------------------------------------------------------------------- |
| [Single-quoted string](#single-quoted-strings) | `'[^\n]+'` | None | Cannot contain single quotes within the string |
| [Double-quoted string](#double-quoted-strings) | `"The\nEnd"` | C-style backslash escapes | All literal backslashes must be escaped |
| [Raw strings](#raw-strings) | `r#'Raw string'#` | None | May include single quotes |
| [Bare word string](#bare-word-strings) | `ozymandias` | None | Can only contain "word" characters; Cannot be used in command position |
| [Backtick string](#backtick-quoted-strings) | <code>\`[^\n]+\`</code> | None | Bare string that can include whitespace. Cannot contain any backticks |
| [Single-quoted interpolation](#string-interpolation) | `$'Captain ($name)'` | None | Cannot contain any `'` or unmatched `()` |
| [Double-quoted interpolation](#string-interpolation) | `$"Captain ($name)"` | C-style backslash escapes | All literal backslashes and `()` must be escaped |
## Single-quoted Strings
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
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.
Double-quoted Strings
For more complex strings, Nushell also offers double-quoted strings. These strings use the " character to surround text. They also support the ability escape characters inside the text using the \ character.
For example, we could write the text hello followed by a new line and then world, using escape characters and a double-quoted string:
"hello\nworld"# => hello# => world
Escape characters let you quickly add in a character that would otherwise be hard to type.
Nushell currently supports the following escape characters:
\" - double-quote character
\' - single-quote character
\\ - backslash
\/ - forward slash
\b - backspace
\f - formfeed
\r - carriage return
\n - newline (line feed)
\t - tab
\u{X...} - a single unicode character, where X... is 1-6 hex digits (0-9, A-F)
Raw strings behave the same as a single quoted strings, except that raw strings
may also contain single quotes. This is possible because raw strings are enclosed
by a starting r#' and a closing '#. This syntax should look familiar to users
of Rust.
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
one less than the same number of # symbols next to a ' symbol in the string. This can
be used to nest raw strings:
r###'r##'This is an example of a raw string.'##'#### => r##'This is an example of a raw string.'##
Bare Word Strings
Like other shell languages (but unlike most other programming languages) strings consisting of a single 'word' can also be written without any quotes:
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:
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:
So, while bare strings are useful for informal command line usage, when programming more formally in nu, you should generally use quotes.
Backtick-quoted Strings
Bare word strings, by their nature, cannot include spaces or quotes. As an alternative, Nushell also includes backtick-quoted
strings using the ` character. In most cases, these should operate the same as a bare word string.
For instance, as with a bare word, a backtick-quoted string in the first position of an expression will be interpreted as a command or path.
For example:
# Run the external ls binary found on the path`ls`# Move up one directory`..`# Change to the "my dir" subdirectory, if it exists`./my dir`
Backtick-quoted strings can be useful for combining globs with files or directories which include spaces:
ls `./my dir/*`
Backtick-quoted strings cannot contain unmatched backticks in the string itself. For example:
echo ``````
echo ```# Unterminated string which will start a new line in the CLI
Strings as external commands
You can place the ^ sigil in front of any string (including a variable) to have Nushell execute the string as if it was an external command:
^'C:\ProgramFiles\exiftool.exe'
let foo = 'C:\ProgramFiles\exiftool.exe'
^$foo
You can also use the run-external command for this purpose, which provides additional flags and options.
Appending and Prepending to strings
There are various ways to pre, or append strings. If you want to add something to the beginning of each string closures are a good option:
['foo', 'bar'] | each {|s| '~/' ++ $s} # ~/foo, ~/bar['foo', 'bar'] | each {|s| '~/' +$s} # ~/foo, ~/bar
You can also use a regex to replace the beginning or end of a string:
Though in the cases of strings, especially if you don't have to operate on the strings, it's usually easier and more correct (notice the extra + at the end in the example above) to use str join.
Finally you could also use string interpolation, but that is complex enough that it is covered in its own subsection below.
String interpolation
More complex string use cases also need a new form of string: string interpolation. This is a way of building text from both raw text and the result of running expressions. String interpolation combines the results together, giving you a new string.
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:
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.
String interpolation has both a single-quoted, $' ', and a double-quoted, $" ", form. These correspond to the single-quoted and double-quoted strings: single-quoted string interpolation doesn't support escape characters while double-quoted string interpolation does.
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:
$"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
on your configuration and your config.nu hasn't been loaded yet, they will use the default configuration.
So if you have something like this in your config.nu, x will be "2.0 KB" even if your config says to use
MB for all file sizes (datetimes will similarly use the default config).
const x = $"(2kb)"
Splitting Strings
The split row command creates a list from a string based on a delimiter.
"red,green,blue"| split row ","# => ╭───┬───────╮# => │ 0 │ red │# => │ 1 │ green │# => │ 2 │ blue │# => ╰───┴───────╯
The split column command will create a table from a string based on a delimiter. This applies generic column names to the table.
"red,green,blue"| split column ","# => ╭───┬─────────┬─────────┬─────────╮# => │ # │ column1 │ column2 │ column3 │# => ├───┼─────────┼─────────┼─────────┤# => │ 0 │ red │ green │ blue │# => ╰───┴─────────┴─────────┴─────────╯
Finally, the split chars command will split a string into a list of characters.
'aeiou' | split chars
# => ╭───┬───╮# => │ 0 │ a │# => │ 1 │ e │# => │ 2 │ i │# => │ 3 │ o │# => │ 4 │ u │# => ╰───┴───╯
Many string functions are subcommands of the str command. You can get a full list using help str.
For example, you can look if a string contains a particular substring using str contains:
"hello world"| str contains "o wo"# => true
(You might also prefer, for brevity, the =~ operator (described below).)
Trimming Strings
You can trim the sides of a string with the str trim command. By default, the str trim commands trims whitespace from both sides of the string. For example:
' 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)
To trim a specific character, use --char <Character> or -c <Character> to specify the character to trim.
Here's an example of all the options in action:
'===Nu shell ===' | str trim -r -c '='# => === Nu shell
Substrings
Substrings are slices of a string. They have a startpoint and an endpoint. Here's an example of using a substring:
You can color strings with the ansi command. For example:
$'(ansi purple_bold)This text is a bold purple!(ansi reset)'
ansi purple_bold makes the text a bold purple
ansi reset resets the coloring to the default.
::: tip
You should always end colored strings with ansi reset
:::
`book/working_with_tables.md`:
```md
# Working with Tables
[[toc]]
## Overview
One of the common ways of seeing data in Nu is through a table. Nu comes with a number of commands for working with tables to make it convenient to find what you're looking for, and for narrowing down the data to just what you need.
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
# => ───┴───────────────┴──────┴─────────┴────────────
::: tip Changing how tables are displayed
Nu will try to expands all table's structure by default. You can change this behavior by changing the display_output hook.
See hooks for more information.
:::
Sorting the Data
We can sort a table by calling the sort-by 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:
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.
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 command using its row number:
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
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 command:
These look very similar! Let's see if we can spell out the difference between these two commands to make it clear:
select - creates a new table which includes only the columns specified
get - returns the values inside the column specified as a list
:::tip
The arguments provided to select and get are cell-paths, a fundamental part of Nu's query language. For a more in-depth discussion of cell-paths and other navigation topics, see the next chapter, Navigating and Accessing Structured Data.
:::
Changing Data in a Table
In addition to selecting data from a table, we can also update what the table has. We may want to combine tables, add new columns, or edit the contents of a cell. In Nu, rather than editing in place, each of the commands in the section will return a new table in the pipeline.
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:
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 command:
open rustfmt.toml | insert next_edition 2021| save rustfmt2.toml
open rustfmt2.toml
# => ──────────────┬──────# => edition │ 2018# => next_edition │ 2021# => ──────────────┴──────
Updating a Column
In a similar way to the insert command, we can also use the update command to change the contents of a column to a new value. To see it in action let's open the same file:
You can also use the upsert command to insert or update depending on whether the column already exists.
Moving Columns
You can use move to move columns in the table. For example, if we wanted to move the "name" column from ls after the "size" column, we could do:
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
You can also rename columns in a table by passing it through the rename command. If we wanted to run ls and rename the columns, we can use this example:
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
You can also reject columns in a table by passing it through the reject command. If we wanted to run ls and delete the columns, we can use this example:
You've noticed that every table, by default, starts with a column with the heading #. This column can operate in one of two modes:
Internal #
The default mode
Nushell provides a 0-based, consecutive index
Always corresponds to the cell-path row-number, where select 0 will return the first item in the list, and select <n-1> returns the nth item
Is a display of an internal representation only. In other words, it is not accessible by column name. For example, get index will not work, nor get #
"Index"-Renamed #
When a column named "index" is created, either directly or as a side-effect of another command, then this index column takes the place of the # column in the table display. In the table output, the column header is still #, but the name of the column is now index.
Example:
ls | each { insert index { 1000 }} |first5# => ╭──────┬─────────────────┬──────┬─────────┬──────────────╮# => │ # │ name │ type │ size │ modified │# => ├──────┼─────────────────┼──────┼─────────┼──────────────┤# => │ 1000 │ CNAME │ file │ 15 B │ 9 months ago │# => │ 1000 │ CONTRIBUTING.md │ file │ 4.3 KiB │ 9 hours ago │# => │ 1000 │ LICENSE │ file │ 1.0 KiB │ 9 months ago │# => │ 1000 │ README.md │ file │ 2.2 KiB │ 3 weeks ago │# => │ 1000 │ assets │ dir │ 4.0 KiB │ 9 months ago │# => ╰──────┴─────────────────┴──────┴─────────┴──────────────╯
If an index key is added to each row in the table, then it can be accessed via select and get:
ls | each { insert index { 1000 }} |first5| select index name
# => ╭──────┬─────────────────╮# => │ # │ name │# => ├──────┼─────────────────┤# => │ 1000 │ CNAME │# => │ 1000 │ CONTRIBUTING.md │# => │ 1000 │ LICENSE │# => │ 1000 │ README.md │# => │ 1000 │ assets │# => ╰──────┴─────────────────╯
On the other hand, if some rows have an index key and others don't, the result is no longer a table; it is a list<any> due to the different record types:
This can be useful when you need to store the rendered view of structured data as a string. For example, to remove all ANSI formatting (colors) from a table:
ls | table | ansi strip
The table command also has multiple options for changing the rendering of a table, such as:
-e to expand data that would normally be collapsed when rendering. Compare scope modules | table to scope modules | table -e.
-i false to hide the index/# column
-a 5 to abbreviate the table to just the first and last 5 entries
And more
`commands/README.md`:
```md
# Command Reference
If you're new to Nushell, [the quick tour](/book/quick_tour.md) can show you the most important commands. You don't need to know them all!
To see all commands from inside Nushell, run [`help commands`](/commands/docs/help.md).
<script>
import pages from '@temp/pages'
export default {
computed: {
commands() {
return pages
.filter(p => p.path.indexOf('/commands/docs/') >= 0)
.sort((a,b) => (a.title > b.title) ? 1 : ((b.title > a.title) ? -1 : 0));
}
}
}
</script>
<table>
<tr>
<th>Command</th>
<th>Categories</th>
<th>Description</th>
<th>Feature</th>
</tr>
<tr v-for="command in commands">
<td><a :href="$withBase(command.path)">{{ command.title }}</a></td>
<td style="white-space: pre-wrap;">{{ command.frontmatter.categories }}</td>
<td style="white-space: pre-wrap;">{{ command.frontmatter.usage }}</td>
</tr>
</table>
---title: aliascategories: | coreversion: 0.107.0core: | Alias a command (with optional flags) to a new name.usage: | Alias a command (with optional flags) to a new name.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `alias` for [core](/commands/categories/core.md)
<divclass='command-title'>Alias a command (with optional flags) to a new name.</div>
## Signature```> alias {flags} (name) (initial_value)```## Parameters-`name`: Name of the alias.
-`initial_value`: Equals sign followed by value.
## Input/output types:| input | output || ------- | ------- || nothing | nothing |## Examples
Alias ll to ls -l
```nu> alias ll = ls -l
`commands/docs/all.md`:
```md
---
title: all
categories: |
filters
version: 0.107.0
filters: |
Test if every element of the input fulfills a predicate expression.
usage: |
Test if every element of the input fulfills a predicate expression.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `all` for [filters](/commands/categories/filters.md)
<div class='command-title'>Test if every element of the input fulfills a predicate expression.</div>
## Signature
```> all {flags} (predicate)```
## Parameters
- `predicate`: A closure that must evaluate to a boolean.
## Input/output types:
| input | output |
| --------- | ------ |
| list<any> | bool |
## Examples
Check if a list contains only true values
```nu
> [false true true false] | all {}
false
Check if each row's status is the string 'UP'
> [[status]; [UP] [UP]] | all {|el| $el.status == UP }
true
Check that each item is a string
> [foo bar 2 baz] | all {|| ($in| describe) == 'string' }
false
Check that all values are equal to twice their index
Check that all of the values are even, using a stored closure
>letcond= {|el| ($el mod 2) ==0 }; [2 4 6 8] | all $cond
true
`commands/docs/ansi.md`:
```md
---
title: ansi
categories: |
platform
version: 0.107.0
platform: |
Output ANSI codes to change color and style of text.
usage: |
Output ANSI codes to change color and style of text.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `ansi` for [platform](/commands/categories/platform.md)
<div class='command-title'>Output ANSI codes to change color and style of text.</div>
## Signature
```> ansi {flags} (code)```
## Flags
- `--escape, -e`: escape sequence without the escape character(s) ('\x1b[' is not required)
- `--osc, -o`: operating system command (osc) escape sequence without the escape character(s) ('\x1b]' is not required)
- `--list, -l`: list available ansi code names
## Parameters
- `code`: The name of the code to use (from `ansi -l`).
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | any |
## Examples
Change color to green (see how the next example text will be green!)
```nu
> ansi green
Avoid resetting color when setting/resetting different style codes
> $'Set color to (ansi g)GREENthen style to (ansi bo)BOLD(ansi rst_bo) or (ansi d)DIMMED(ansi rst_d) or (ansi i)ITALICS(ansi rst_i) or (ansi u)UNDERLINE(ansi rst_u) or (ansi re)REVERSE(ansi rst_re) or (ansi h)HIDDEN(ansi rst_h) or (ansi s)STRIKE(ansi rst_s) then (ansi rst)reset everything'
Set color to GREENthen style to BOLDorDIMMEDorITALICSorUNDERLINEorREVERSEorHIDDENorSTRIKEthen reset everything
Use escape codes, without the '\x1b['
> $"(ansi --escape '3;93;41m')Hello(ansi reset)"# italic bright yellow on red backgroundHello
Use simple hex string
> $"(ansi '#4169E1')Hello(ansi reset)"# royal blue foreground colorHello
Use structured escape codes
>let bold_blue_on_red = { # `fg`, `bg`, `attr` are the acceptable keys, all other keys are considered invalid and will throw errors.
fg: '#0000ff'
bg: '#ff0000'
attr: b
}
$"(ansi --escape $bold_blue_on_red)Hello, Nu World!(ansi reset)"Hello,NuWorld!
Notes
An introduction to what ANSI escape sequences are can be found in the
�]8;;https://en.wikipedia.org/wiki/ANSI_escape_code�\ANSI escape code�]8;;�\ Wikipedia page.
Escape sequences usual values:
╭────┬────────────┬────────┬────────┬─────────╮
│ # │ type │ normal │ bright │ name │
├────┼────────────┼────────┼────────┼─────────┤
│ 0 │ foreground │ 30 │ 90 │ black │
│ 1 │ foreground │ 31 │ 91 │ red │
│ 2 │ foreground │ 32 │ 92 │ green │
│ 3 │ foreground │ 33 │ 93 │ yellow │
│ 4 │ foreground │ 34 │ 94 │ blue │
│ 5 │ foreground │ 35 │ 95 │ magenta │
│ 5 │ foreground │ 35 │ 95 │ purple │
│ 6 │ foreground │ 36 │ 96 │ cyan │
│ 7 │ foreground │ 37 │ 97 │ white │
│ 8 │ foreground │ 39 │ │ default │
│ 9 │ background │ 40 │ 100 │ black │
│ 10 │ background │ 41 │ 101 │ red │
│ 11 │ background │ 42 │ 102 │ green │
│ 12 │ background │ 43 │ 103 │ yellow │
│ 13 │ background │ 44 │ 104 │ blue │
│ 14 │ background │ 45 │ 105 │ magenta │
│ 14 │ background │ 45 │ 105 │ purple │
│ 15 │ background │ 46 │ 106 │ cyan │
│ 16 │ background │ 47 │ 107 │ white │
│ 17 │ background │ 49 │ │ default │
╰────┴────────────┴────────┴────────┴─────────╯
Escape sequences style attributes:
╭────┬────┬──────────────┬─────────────────────────────────────────╮
│ # │ id │ abbreviation │ description │
├────┼────┼──────────────┼─────────────────────────────────────────┤
│ 0 │ 0 │ rst │ reset / normal display │
│ 1 │ 1 │ bo │ bold on │
│ 2 │ 2 │ d │ dimmed on │
│ 3 │ 3 │ i │ italic on (non-mono font) │
│ 4 │ 4 │ u │ underline on │
│ 5 │ 5 │ bl │ blink on │
│ 6 │ 6 │ bf │ fast blink on │
│ 7 │ 7 │ r │ reverse video on │
│ 8 │ 8 │ h │ hidden (invisible) on │
│ 9 │ 9 │ s │ strike-through on │
│ 10 │ 21 │ rst_bo │ bold or dimmed off │
│ 11 │ 22 │ du │ double underline (not widely supported) │
│ 12 │ 23 │ rst_i │ italic off (non-mono font) │
│ 13 │ 24 │ rst_u │ underline off │
│ 14 │ 25 │ rst_bl │ blink off │
│ 15 │ 26 │ │ <reserved> │
│ 16 │ 27 │ rst_r │ reverse video off │
│ 17 │ 28 │ rst_h │ hidden (invisible) off │
│ 18 │ 29 │ rst_s │ strike-through off │
╰────┴────┴──────────────┴─────────────────────────────────────────╯
Operating system commands:
╭───┬─────┬───────────────────────────────────────╮
│ # │ id │ description │
├───┼─────┼───────────────────────────────────────┤
│ 0 │ 0 │ Set window title and icon name │
│ 1 │ 1 │ Set icon name │
│ 2 │ 2 │ Set window title │
│ 3 │ 4 │ Set/read color palette │
│ 4 │ 9 │ iTerm2 Grown notifications │
│ 5 │ 10 │ Set foreground color (x11 color spec) │
│ 6 │ 11 │ Set background color (x11 color spec) │
│ 7 │ ... │ others │
╰───┴─────┴───────────────────────────────────────╯
`commands/docs/ansi_gradient.md`:
```md
---
title: ansi gradient
categories: |
platform
version: 0.107.0
platform: |
Add a color gradient (using ANSI color codes) to the given string.
usage: |
Add a color gradient (using ANSI color codes) to the given string.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `ansi gradient` for [platform](/commands/categories/platform.md)
<div class='command-title'>Add a color gradient (using ANSI color codes) to the given string.</div>
## Signature
```> ansi gradient {flags} ...rest```
## Flags
- `--fgstart, -a {string}`: foreground gradient start color in hex (0x123456)
- `--fgend, -b {string}`: foreground gradient end color in hex
- `--bgstart, -c {string}`: background gradient start color in hex
- `--bgend, -d {string}`: background gradient end color in hex
## Parameters
- `...rest`: For a data structure input, add a gradient to strings at the given cell paths.
## Input/output types:
| input | output |
| ------------ | ------------ |
| string | string |
| list<string> | list<string> |
| table | table |
| record | record |
## Examples
draw text in a gradient with foreground start and end colors
```nu
> 'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff'
draw text in a gradient with foreground start and end colors and background start and end colors
> 'Hello,Nushell!This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff' --bgstart '0xe81cff' --bgend '0x40c9ff'
draw text in a gradient by specifying foreground start color - end color is assumed to be black
> 'Hello,Nushell!This is a gradient.' | ansi gradient --fgstart '0x40c9ff'
draw text in a gradient by specifying foreground end color - start color is assumed to be black
> 'Hello,Nushell!This is a gradient.' | ansi gradient --fgend '0xe81cff'
`commands/docs/ansi_link.md`:
```md
---
title: ansi link
categories: |
platform
version: 0.107.0
platform: |
Add a link (using OSC 8 escape sequence) to the given string.
usage: |
Add a link (using OSC 8 escape sequence) to the given string.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `ansi link` for [platform](/commands/categories/platform.md)
<div class='command-title'>Add a link (using OSC 8 escape sequence) to the given string.</div>
## Signature
```> ansi link {flags} ...rest```
## Flags
- `--text, -t {string}`: Link text. Uses uri as text if absent. In case of
tables, records and lists applies this text to all elements
## Parameters
- `...rest`: For a data structure input, add links to all strings at the given cell paths.
## Input/output types:
| input | output |
| ------------ | ------------ |
| string | string |
| list<string> | list<string> |
| table | table |
| record | record |
## Examples
Create a link to open some file
```nu
> 'file:///file.txt' | ansi link --text 'Open Me!'
Open Me!
> [[url text]; [https://example.com Text]] | ansi link url
`commands/docs/ansi_strip.md`:
```md
---
title: ansi strip
categories: |
platform
version: 0.107.0
platform: |
Strip ANSI escape sequences from a string.
usage: |
Strip ANSI escape sequences from a string.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `ansi strip` for [platform](/commands/categories/platform.md)
<div class='command-title'>Strip ANSI escape sequences from a string.</div>
## Signature
```> ansi strip {flags} ...rest```
## Parameters
- `...rest`: For a data structure input, remove ANSI sequences from strings at the given cell paths.
## Input/output types:
| input | output |
| ------------ | ------------ |
| string | string |
| list<string> | list<string> |
| table | table |
| record | record |
## Examples
Strip ANSI escape sequences from a string
```nu
> $'(ansi green)(ansi cursor_on)hello' | ansi strip
hello
`commands/docs/any.md`:
```md
---
title: any
categories: |
filters
version: 0.107.0
filters: |
Tests if any element of the input fulfills a predicate expression.
usage: |
Tests if any element of the input fulfills a predicate expression.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `any` for [filters](/commands/categories/filters.md)
<div class='command-title'>Tests if any element of the input fulfills a predicate expression.</div>
## Signature
```> any {flags} (predicate)```
## Parameters
- `predicate`: A closure that must evaluate to a boolean.
## Input/output types:
| input | output |
| --------- | ------ |
| list<any> | bool |
## Examples
Check if a list contains any true values
```nu
> [false true true false] | any {}
true
Check if any row's status is the string 'DOWN'
> [[status]; [UP] [DOWN] [UP]] | any {|el| $el.status == DOWN }
true
Check if any of the values are odd, using a stored closure
>letcond= {|e|$e mod 2==1 }; [2 4 1 6 8] | any $cond
true
`commands/docs/append.md`:
```md
---
title: append
categories: |
filters
version: 0.107.0
filters: |
Append any number of rows to a table.
usage: |
Append any number of rows to a table.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `append` for [filters](/commands/categories/filters.md)
<div class='command-title'>Append any number of rows to a table.</div>
## Signature
```> append {flags} (row)```
## Parameters
- `row`: The row, list, or table to append.
## Input/output types:
| input | output |
| ----- | --------- |
| any | list<any> |
## Examples
Append one int to a list
```nu
> [0 1 2 3] | append 4
╭───┬───╮
│ 0 │ 0 │
│ 1 │ 1 │
│ 2 │ 2 │
│ 3 │ 3 │
│ 4 │ 4 │
╰───┴───╯
Be aware that this command 'unwraps' lists passed to it. So, if you pass a variable to it,
and you want the variable's contents to be appended without being unwrapped, it's wise to
pre-emptively wrap the variable in a list, like so: append [$val]. This way, append will
only unwrap the outer list, and leave the variable's contents untouched.
`commands/docs/ast.md`:
```md
---
title: ast
categories: |
debug
version: 0.107.0
debug: |
Print the abstract syntax tree (ast) for a pipeline.
usage: |
Print the abstract syntax tree (ast) for a pipeline.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `ast` for [debug](/commands/categories/debug.md)
<div class='command-title'>Print the abstract syntax tree (ast) for a pipeline.</div>
## Signature
```> ast {flags} (pipeline)```
## Flags
- `--json, -j`: Serialize to json
- `--minify, -m`: Minify the nuon or json output
- `--flatten, -f`: An easier to read version of the ast
## Parameters
- `pipeline`: The pipeline to print the ast for.
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | table |
| nothing | record |
| nothing | string |
## Examples
Print the ast of a string
```nu
> ast 'hello'
Print the ast of a pipeline
> ast 'ls | where name =~ README'
Print the ast of a pipeline with an error
> ast 'for x in 1..10 { echo $x '
Print the ast of a pipeline with an error, as json, in a nushell table
> ast 'for x in 1..10 { echo $x ' --json | get block | from json
Print the ast of a pipeline with an error, as json, minified
`commands/docs/attr.md`:
```md
---
title: attr
categories: |
core
version: 0.107.0
core: |
Various attributes for custom commands.
usage: |
Various attributes for custom commands.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `attr` for [core](/commands/categories/core.md)
<div class='command-title'>Various attributes for custom commands.</div>
## Signature
```> attr {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | string |
## Notes
You must use one of the following subcommands. Using this command as-is will only produce this help message.
## Subcommands:
| name | description | type |
| ---------------------------------------------------------- | ------------------------------------------------------ | -------- |
| [`attr category`](/commands/docs/attr_category.md) | Attribute for adding a category to custom commands. | built-in |
| [`attr deprecated`](/commands/docs/attr_deprecated.md) | Attribute for marking a command or flag as deprecated. | built-in |
| [`attr example`](/commands/docs/attr_example.md) | Attribute for adding examples to custom commands. | built-in |
| [`attr search-terms`](/commands/docs/attr_search-terms.md) | Attribute for adding search terms to custom commands. | built-in |
commands/docs/attr_category.md:
---title: attr categorycategories: | coreversion: 0.107.0core: | Attribute for adding a category to custom commands.usage: | Attribute for adding a category to custom commands.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `attr category` for [core](/commands/categories/core.md)
<divclass='command-title'>Attribute for adding a category to custom commands.</div>
## Signature```> attr category {flags} (category)```## Parameters-`category`: Category of the custom command.
## Input/output types:| input | output || ------- | ------------ || nothing | list<string>|## Examples
Add a category to a custom command
```nu> # Double numbers @category math def double []: [number -> number] { $in * 2 }
`commands/docs/attr_deprecated.md`:
```md
---
title: attr deprecated
categories: |
core
version: 0.107.0
core: |
Attribute for marking a command or flag as deprecated.
usage: |
Attribute for marking a command or flag as deprecated.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `attr deprecated` for [core](/commands/categories/core.md)
<div class='command-title'>Attribute for marking a command or flag as deprecated.</div>
## Signature
```> attr deprecated {flags} (message)```
## Flags
- `--flag {string}`: Mark a flag as deprecated rather than the command
- `--since, -s {string}`: Denote a version when this item was deprecated
- `--remove, -r {string}`: Denote a version when this item will be removed
- `--report {string}`: How to warn about this item. One of: first (default), every
## Parameters
- `message`: Help message to include with deprecation warning.
## Input/output types:
| input | output |
| ------- | ------- |
| nothing | nothing |
| nothing | string |
## Examples
Add a deprecation warning to a custom command
```nu
> @deprecated
def outdated [] {}
Mark a command (default) or flag/switch (--flag) as deprecated. By default, only the first usage will trigger a deprecation warning.
A help message can be included to provide more context for the deprecation, such as what to use as a replacement.
Also consider setting the category to deprecated with @category deprecated
`commands/docs/attr_example.md`:
```md
---
title: attr example
categories: |
core
version: 0.107.0
core: |
Attribute for adding examples to custom commands.
usage: |
Attribute for adding examples to custom commands.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `attr example` for [core](/commands/categories/core.md)
<div class='command-title'>Attribute for adding examples to custom commands.</div>
## Signature
```> attr example {flags} (description) (example)```
## Flags
- `--result {any}`: Expected output of example.
## Parameters
- `description`: Description of the example.
- `example`: Example code snippet.
## Input/output types:
| input | output |
| ------- | -------------------------------------------- |
| nothing | record<description: string, example: string> |
## Examples
Add examples to custom command
```nu
> # Double numbers
@example "double an int" { 2 | double } --result 4
@example "double a float" { 0.25 | double } --result 0.5
def double []: [number -> number] { $in * 2 }
`commands/docs/attr_search-terms.md`:
```md
---
title: attr search-terms
categories: |
core
version: 0.107.0
core: |
Attribute for adding search terms to custom commands.
usage: |
Attribute for adding search terms to custom commands.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `attr search-terms` for [core](/commands/categories/core.md)
<div class='command-title'>Attribute for adding search terms to custom commands.</div>
## Signature
```> attr search-terms {flags} ...rest```
## Parameters
- `...rest`: Search terms.
## Input/output types:
| input | output |
| ------- | ------------ |
| nothing | list<string> |
## Examples
Add search terms to a custom command
```nu
> # Double numbers
@search-terms multiply times
def double []: [number -> number] { $in * 2 }
`commands/docs/banner.md`:
```md
---
title: banner
categories: |
default
version: 0.107.0
default: |
Print a banner for Nushell with information about the project
usage: |
Print a banner for Nushell with information about the project
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `banner` for [default](/commands/categories/default.md)
<div class='command-title'>Print a banner for Nushell with information about the project</div>
## Signature
```> banner {flags} ```
## Flags
- `--short`: Only show startup time
commands/docs/bits.md:
---title: bitscategories: | bitsversion: 0.107.0bits: | Various commands for working with bits.usage: | Various commands for working with bits.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `bits` for [bits](/commands/categories/bits.md)
<divclass='command-title'>Various commands for working with bits.</div>
## Signature```> bits {flags} ```## Input/output types:| input | output || ------- | ------ || nothing | string |## Notes
You must use one of the following subcommands. Using this command as-is will only produce this help message.
## Subcommands:| name | description | type || ---------------------------------------- | ----------------------------------------------- | -------- ||[`bits and`](/commands/docs/bits_and.md)| Performs bitwise and for ints or binary values. | built-in ||[`bits not`](/commands/docs/bits_not.md)| Performs logical negation on each bit. | built-in ||[`bits or`](/commands/docs/bits_or.md)| Performs bitwise or for ints or binary values. | built-in ||[`bits rol`](/commands/docs/bits_rol.md)| Bitwise rotate left for ints or binary values. | built-in ||[`bits ror`](/commands/docs/bits_ror.md)| Bitwise rotate right for ints or binary values. | built-in ||[`bits shl`](/commands/docs/bits_shl.md)| Bitwise shift left for ints or binary values. | built-in ||[`bits shr`](/commands/docs/bits_shr.md)| Bitwise shift right for ints or binary values. | built-in ||[`bits xor`](/commands/docs/bits_xor.md)| Performs bitwise xor for ints or binary values. | built-in |
commands/docs/bits_and.md:
---title: bits andcategories: | bitsversion: 0.107.0bits: | Performs bitwise and for ints or binary values.usage: | Performs bitwise and for ints or binary values.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `bits and` for [bits](/commands/categories/bits.md)
<divclass='command-title'>Performs bitwise and for ints or binary values.</div>
## Signature```> bits and {flags} (target)```## Flags-`--endian, -e {string}`: byte encode endian, available options: native(default), little, big
## Parameters-`target`: Right-hand side of the operation.
## Input/output types:| input | output || ------------ | ------------ || int | int || binary | binary || list<int>| list<int>|| list<binary>| list<binary>|## Examples
Apply bitwise and to two numbers
```nu> 2 | bits and 22
`commands/docs/bits_not.md`:
```md
---
title: bits not
categories: |
bits
version: 0.107.0
bits: |
Performs logical negation on each bit.
usage: |
Performs logical negation on each bit.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bits not` for [bits](/commands/categories/bits.md)
<div class='command-title'>Performs logical negation on each bit.</div>
## Signature
```> bits not {flags} ```
## Flags
- `--signed, -s`: always treat input number as a signed number
- `--number-bytes, -n {int}`: the size of unsigned number in bytes, it can be 1, 2, 4, 8, auto
## Input/output types:
| input | output |
| ------------ | ------------ |
| int | int |
| binary | binary |
| list<int> | list<int> |
| list<binary> | list<binary> |
## Examples
Apply logical negation to a list of numbers
```nu
> [4 3 2] | bits not
╭───┬─────╮
│ 0 │ 251 │
│ 1 │ 252 │
│ 2 │ 253 │
╰───┴─────╯
Apply logical negation to a list of numbers, treat input as 2 bytes number
`commands/docs/bits_rol.md`:
```md
---
title: bits rol
categories: |
bits
version: 0.107.0
bits: |
Bitwise rotate left for ints or binary values.
usage: |
Bitwise rotate left for ints or binary values.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bits rol` for [bits](/commands/categories/bits.md)
<div class='command-title'>Bitwise rotate left for ints or binary values.</div>
## Signature
```> bits rol {flags} (bits)```
## Flags
- `--signed, -s`: always treat input number as a signed number
- `--number-bytes, -n {int}`: the word size in number of bytes. Must be `1`, `2`, `4`, or `8` (defaults to the smallest of those that fits the input number)
## Parameters
- `bits`: Number of bits to rotate left.
## Input/output types:
| input | output |
| ------------ | ------------ |
| int | int |
| binary | binary |
| list<int> | list<int> |
| list<binary> | list<binary> |
## Examples
Rotate left a number with 2 bits
```nu
> 17 | bits rol 2
68
`commands/docs/bits_ror.md`:
```md
---
title: bits ror
categories: |
bits
version: 0.107.0
bits: |
Bitwise rotate right for ints or binary values.
usage: |
Bitwise rotate right for ints or binary values.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bits ror` for [bits](/commands/categories/bits.md)
<div class='command-title'>Bitwise rotate right for ints or binary values.</div>
## Signature
```> bits ror {flags} (bits)```
## Flags
- `--signed, -s`: always treat input number as a signed number
- `--number-bytes, -n {int}`: the word size in number of bytes. Must be `1`, `2`, `4`, or `8` (defaults to the smallest of those that fits the input number)
## Parameters
- `bits`: Number of bits to rotate right.
## Input/output types:
| input | output |
| ------------ | ------------ |
| int | int |
| binary | binary |
| list<int> | list<int> |
| list<binary> | list<binary> |
## Examples
rotate right a number with 2 bits
```nu
> 17 | bits ror 2
68
`commands/docs/bits_shl.md`:
```md
---
title: bits shl
categories: |
bits
version: 0.107.0
bits: |
Bitwise shift left for ints or binary values.
usage: |
Bitwise shift left for ints or binary values.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bits shl` for [bits](/commands/categories/bits.md)
<div class='command-title'>Bitwise shift left for ints or binary values.</div>
## Signature
```> bits shl {flags} (bits)```
## Flags
- `--signed, -s`: always treat input number as a signed number
- `--number-bytes, -n {int}`: the word size in number of bytes. Must be `1`, `2`, `4`, or `8` (defaults to the smallest of those that fits the input number)
## Parameters
- `bits`: Number of bits to shift left.
## Input/output types:
| input | output |
| ------------ | ------------ |
| int | int |
| binary | binary |
| list<int> | list<int> |
| list<binary> | list<binary> |
## Examples
Shift left a number by 7 bits
```nu
> 2 | bits shl 7
0
`commands/docs/bits_shr.md`:
```md
---
title: bits shr
categories: |
bits
version: 0.107.0
bits: |
Bitwise shift right for ints or binary values.
usage: |
Bitwise shift right for ints or binary values.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bits shr` for [bits](/commands/categories/bits.md)
<div class='command-title'>Bitwise shift right for ints or binary values.</div>
## Signature
```> bits shr {flags} (bits)```
## Flags
- `--signed, -s`: always treat input number as a signed number
- `--number-bytes, -n {int}`: the word size in number of bytes. Must be `1`, `2`, `4`, or `8` (defaults to the smallest of those that fits the input number)
## Parameters
- `bits`: Number of bits to shift right.
## Input/output types:
| input | output |
| ------------ | ------------ |
| int | int |
| binary | binary |
| list<int> | list<int> |
| list<binary> | list<binary> |
## Examples
Shift right a number with 2 bits
```nu
> 8 | bits shr 2
2
break can only be used in while, loop, and for loops. It can not be used with each or other filter commands
`commands/docs/bytes.md`:
```md
---
title: bytes
categories: |
bytes
version: 0.107.0
bytes: |
Various commands for working with byte data.
usage: |
Various commands for working with byte data.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bytes` for [bytes](/commands/categories/bytes.md)
<div class='command-title'>Various commands for working with byte data.</div>
## Signature
```> bytes {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | string |
## Notes
You must use one of the following subcommands. Using this command as-is will only produce this help message.
## Subcommands:
| name | description | type |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------- |
| [`bytes add`](/commands/docs/bytes_add.md) | Add specified bytes to the input. | built-in |
| [`bytes at`](/commands/docs/bytes_at.md) | Get bytes defined by a range. | built-in |
| [`bytes build`](/commands/docs/bytes_build.md) | Create bytes from the arguments. | built-in |
| [`bytes collect`](/commands/docs/bytes_collect.md) | Concatenate multiple binary into a single binary, with an optional separator between each. | built-in |
| [`bytes ends-with`](/commands/docs/bytes_ends-with.md) | Check if bytes ends with a pattern. | built-in |
| [`bytes index-of`](/commands/docs/bytes_index-of.md) | Returns start index of first occurrence of pattern in bytes, or -1 if no match. | built-in |
| [`bytes length`](/commands/docs/bytes_length.md) | Output the length of any bytes in the pipeline. | built-in |
| [`bytes remove`](/commands/docs/bytes_remove.md) | Remove bytes. | built-in |
| [`bytes replace`](/commands/docs/bytes_replace.md) | Find and replace binary. | built-in |
| [`bytes reverse`](/commands/docs/bytes_reverse.md) | Reverse the bytes in the pipeline. | built-in |
| [`bytes split`](/commands/docs/bytes_split.md) | Split input into multiple items using a separator. | built-in |
| [`bytes starts-with`](/commands/docs/bytes_starts-with.md) | Check if bytes starts with a pattern. | built-in |
commands/docs/bytes_add.md:
---title: bytes addcategories: | bytesversion: 0.107.0bytes: | Add specified bytes to the input.usage: | Add specified bytes to the input.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `bytes add` for [bytes](/commands/categories/bytes.md)
<divclass='command-title'>Add specified bytes to the input.</div>
## Signature```> bytes add {flags} (data) ...rest```## Flags-`--index, -i {int}`: index to insert binary data
-`--end, -e`: add to the end of binary
## Parameters-`data`: The binary to add.
-`...rest`: For a data structure input, add bytes to the data at the given cell paths.
## Input/output types:| input | output || ------------ | ------------ || binary | binary || list<binary>| list<binary>|| table | table || record | record |## Examples
Add bytes `0x[AA]` to `0x[1F FF AA AA]````nu> 0x[1F FF AA AA] | bytes add 0x[AA]Length: 5 (0x5) bytes | printable whitespace ascii_other non_ascii00000000: aa 1f ff aa aa ו×××
Add bytes 0x[AA BB] to 0x[1F FF AA AA] at index 1
>0x[1FFFAAAA] | bytes add 0x[AABB] --index 1Length: 6 (0x6) bytes | printable whitespace ascii_other non_ascii
00000000: 1f aa bb ff aa aa •×××××
`commands/docs/bytes_at.md`:
```md
---
title: bytes at
categories: |
bytes
version: 0.107.0
bytes: |
Get bytes defined by a range.
usage: |
Get bytes defined by a range.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bytes at` for [bytes](/commands/categories/bytes.md)
<div class='command-title'>Get bytes defined by a range.</div>
## Signature
```> bytes at {flags} (range) ...rest```
## Parameters
- `range`: The range to get bytes.
- `...rest`: For a data structure input, get bytes from data at the given cell paths.
## Input/output types:
| input | output |
| ------------ | ------------ |
| binary | binary |
| list<binary> | list<binary> |
| table | table |
| record | record |
## Examples
Extract bytes starting from a specific index
```nu
> { data: 0x[33 44 55 10 01 13 10] } | bytes at 3.. data
╭──────┬─────────────────╮
│ data │ [16, 1, 19, 16] │
╰──────┴─────────────────╯
`commands/docs/bytes_ends-with.md`:
```md
---
title: bytes ends-with
categories: |
bytes
version: 0.107.0
bytes: |
Check if bytes ends with a pattern.
usage: |
Check if bytes ends with a pattern.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bytes ends-with` for [bytes](/commands/categories/bytes.md)
<div class='command-title'>Check if bytes ends with a pattern.</div>
## Signature
```> bytes ends-with {flags} (pattern) ...rest```
## Parameters
- `pattern`: The pattern to match.
- `...rest`: For a data structure input, check if bytes at the given cell paths end with the pattern.
## Input/output types:
| input | output |
| ------ | ------ |
| binary | bool |
| table | table |
| record | record |
## Examples
Checks if binary ends with `0x[AA]`
```nu
> 0x[1F FF AA AA] | bytes ends-with 0x[AA]
true
Checks if binary ends with 0x[FF AA AA]
>0x[1FFFAAAA] | bytes ends-with 0x[FFAAAA]
true
Checks if binary ends with 0x[11]
>0x[1FFFAAAA] | bytes ends-with 0x[11]
false
`commands/docs/bytes_index-of.md`:
```md
---
title: bytes index-of
categories: |
bytes
version: 0.107.0
bytes: |
Returns start index of first occurrence of pattern in bytes, or -1 if no match.
usage: |
Returns start index of first occurrence of pattern in bytes, or -1 if no match.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bytes index-of` for [bytes](/commands/categories/bytes.md)
<div class='command-title'>Returns start index of first occurrence of pattern in bytes, or -1 if no match.</div>
## Signature
```> bytes index-of {flags} (pattern) ...rest```
## Flags
- `--all, -a`: returns all matched index
- `--end, -e`: search from the end of the binary
## Parameters
- `pattern`: The pattern to find index of.
- `...rest`: For a data structure input, find the indexes at the given cell paths.
## Input/output types:
| input | output |
| ------ | ------ |
| binary | any |
| table | table |
| record | record |
## Examples
Returns index of pattern in bytes
```nu
> 0x[33 44 55 10 01 13 44 55] | bytes index-of 0x[44 55]
1
`commands/docs/bytes_length.md`:
```md
---
title: bytes length
categories: |
bytes
version: 0.107.0
bytes: |
Output the length of any bytes in the pipeline.
usage: |
Output the length of any bytes in the pipeline.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bytes length` for [bytes](/commands/categories/bytes.md)
<div class='command-title'>Output the length of any bytes in the pipeline.</div>
## Signature
```> bytes length {flags} ...rest```
## Parameters
- `...rest`: For a data structure input, find the length of data at the given cell paths.
## Input/output types:
| input | output |
| ------------ | --------- |
| binary | int |
| list<binary> | list<int> |
| table | table |
| record | record |
## Examples
Return the length of a binary
```nu
> 0x[1F FF AA AB] | bytes length
4
`commands/docs/bytes_starts-with.md`:
```md
---
title: bytes starts-with
categories: |
bytes
version: 0.107.0
bytes: |
Check if bytes starts with a pattern.
usage: |
Check if bytes starts with a pattern.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `bytes starts-with` for [bytes](/commands/categories/bytes.md)
<div class='command-title'>Check if bytes starts with a pattern.</div>
## Signature
```> bytes starts-with {flags} (pattern) ...rest```
## Parameters
- `pattern`: The pattern to match.
- `...rest`: For a data structure input, check if bytes at the given cell paths start with the pattern.
## Input/output types:
| input | output |
| ------ | ------ |
| binary | bool |
| table | table |
| record | record |
## Examples
Checks if binary starts with `0x[1F FF AA]`
```nu
> 0x[1F FF AA AA] | bytes starts-with 0x[1F FF AA]
true
Checks if binary starts with 0x[1F]
>0x[1FFFAAAA] | bytes starts-with 0x[1F]
true
Checks if binary starts with 0x[1F]
>0x[1FFFAAAA] | bytes starts-with 0x[11]
false
`commands/docs/cal.md`:
```md
---
title: cal
categories: |
generators
version: 0.107.0
generators: |
Display a calendar.
usage: |
Display a calendar.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `cal` for [generators](/commands/categories/generators.md)
<div class='command-title'>Display a calendar.</div>
## Signature
```> cal {flags} ```
## Flags
- `--year, -y`: Display the year column
- `--quarter, -q`: Display the quarter column
- `--month, -m`: Display the month column
- `--as-table, -t`: output as a table
- `--full-year {int}`: Display a year-long calendar for the specified year
- `--week-start {string}`: Display the calendar with the specified day as the first day of the week
- `--month-names`: Display the month names instead of integers
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | string |
| nothing | table |
## Examples
This month's calendar
```nu
> cal
The calendar for all of 2012
> cal --full-year 2012
This month's calendar with the week starting on Monday
> cal --week-start mo
How many 'Friday the Thirteenths' occurred in 2015?
> cal --as-table --full-year 2015| where fr ==13| length
`commands/docs/cd.md`:
```md
---
title: cd
categories: |
filesystem
version: 0.107.0
filesystem: |
Change directory.
usage: |
Change directory.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `cd` for [filesystem](/commands/categories/filesystem.md)
<div class='command-title'>Change directory.</div>
## Signature
```> cd {flags} (path)```
## Flags
- `--physical, -P`: use the physical directory structure; resolve symbolic links before processing instances of ..
## Parameters
- `path`: The path to change to.
## Input/output types:
| input | output |
| ------- | ------- |
| nothing | nothing |
## Examples
Change to your home directory
```nu
> cd ~
Change to the previous working directory (same as "cd $env.OLDPWD")
> cd -
Changing directory with a custom command requires 'def --env'
> def --env gohome [] { cd ~ }
Move two directories up in the tree (the parent directory's parent). Additional dots can be added for additional levels.
> cd ...
The cd command itself is often optional. Simply entering a path to a directory will cd to it.
>/home
`commands/docs/char.md`:
```md
---
title: char
categories: |
strings
version: 0.107.0
strings: |
Output special characters (e.g., 'newline').
usage: |
Output special characters (e.g., 'newline').
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `char` for [strings](/commands/categories/strings.md)
<div class='command-title'>Output special characters (e.g., 'newline').</div>
## Signature
```> char {flags} (character) ...rest```
## Flags
- `--list, -l`: List all supported character names
- `--unicode, -u`: Unicode string i.e. 1f378
- `--integer, -i`: Create a codepoint from an integer
## Parameters
- `character`: The name of the character to output.
- `...rest`: Multiple Unicode bytes.
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | any |
## Examples
Output newline
```nu
> char newline
List available characters
> char --list
Output prompt character, newline and a hamburger menu character
chunk-by applies the given closure to each value of the input list, and groups
consecutive elements that share the same closure result value into lists.
`commands/docs/chunks.md`:
```md
---
title: chunks
categories: |
filters
version: 0.107.0
filters: |
Divide a list, table or binary input into chunks of `chunk_size`.
usage: |
Divide a list, table or binary input into chunks of `chunk_size`.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `chunks` for [filters](/commands/categories/filters.md)
<div class='command-title'>Divide a list, table or binary input into chunks of `chunk_size`.</div>
## Signature
```> chunks {flags} (chunk_size)```
## Parameters
- `chunk_size`: The size of each chunk.
## Input/output types:
| input | output |
| --------- | --------------- |
| table | list<table> |
| list<any> | list<list<any>> |
| binary | list<binary> |
## Examples
Chunk a list into pairs
```nu
> [1 2 3 4] | chunks 2
╭───┬───────────╮
│ 0 │ ╭───┬───╮ │
│ │ │ 0 │ 1 │ │
│ │ │ 1 │ 2 │ │
│ │ ╰───┴───╯ │
│ 1 │ ╭───┬───╮ │
│ │ │ 0 │ 3 │ │
│ │ │ 1 │ 4 │ │
│ │ ╰───┴───╯ │
╰───┴───────────╯
This command will error if chunk_size is negative or zero.
`commands/docs/clear.md`:
```md
---
title: clear
categories: |
platform
version: 0.107.0
platform: |
Clear the terminal.
usage: |
Clear the terminal.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `clear` for [platform](/commands/categories/platform.md)
<div class='command-title'>Clear the terminal.</div>
## Signature
```> clear {flags} ```
## Flags
- `--keep-scrollback, -k`: Do not clear the scrollback history
## Input/output types:
| input | output |
| ------- | ------- |
| nothing | nothing |
## Examples
Clear the terminal
```nu
> clear
Clear the terminal but not its scrollback history
> clear --keep-scrollback
Notes
By default clears the current screen and the off-screen scrollback buffer.
`commands/docs/collect.md`:
```md
---
title: collect
categories: |
filters
version: 0.107.0
filters: |
Collect a stream into a value.
usage: |
Collect a stream into a value.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `collect` for [filters](/commands/categories/filters.md)
<div class='command-title'>Collect a stream into a value.</div>
## Signature
```> collect {flags} (closure)```
## Flags
- `--keep-env`: let the closure affect environment variables
## Parameters
- `closure`: The closure to run once the stream is collected.
## Input/output types:
| input | output |
| ----- | ------ |
| any | any |
## Examples
Use the second value in the stream
```nu
> [1 2 3] | collect { |x| $x.1 }
2
Read and write to the same file
> open file.txt | collect | save -f file.txt
Notes
If provided, run a closure with the collected value as input.
The entire stream will be collected into one value in memory, so if the stream
is particularly large, this can cause high memory usage.
`commands/docs/columns.md`:
```md
---
title: columns
categories: |
filters
version: 0.107.0
filters: |
Given a record or table, produce a list of its columns' names.
usage: |
Given a record or table, produce a list of its columns' names.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `columns` for [filters](/commands/categories/filters.md)
<div class='command-title'>Given a record or table, produce a list of its columns' names.</div>
## Signature
```> columns {flags} ```
## Input/output types:
| input | output |
| ------ | ------------ |
| table | list<string> |
| record | list<string> |
## Examples
Get the columns from the record
```nu
> { acronym:PWD, meaning:'Print Working Directory' } | columns
╭───┬─────────╮
│ 0 │ acronym │
│ 1 │ meaning │
╰───┴─────────╯
This is a counterpart to values, which produces a list of columns' values.
`commands/docs/commandline.md`:
```md
---
title: commandline
categories: |
core
version: 0.107.0
core: |
View the current command line input buffer.
usage: |
View the current command line input buffer.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `commandline` for [core](/commands/categories/core.md)
<div class='command-title'>View the current command line input buffer.</div>
## Signature
```> commandline {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | string |
## Subcommands:
| name | description | type |
| -------------------------------------------------------------------- | --------------------------------------------- | -------- |
| [`commandline edit`](/commands/docs/commandline_edit.md) | Modify the current command line input buffer. | built-in |
| [`commandline get-cursor`](/commands/docs/commandline_get-cursor.md) | Get the current cursor position. | built-in |
| [`commandline set-cursor`](/commands/docs/commandline_set-cursor.md) | Set the current cursor position. | built-in |
commands/docs/commandline_edit.md:
---title: commandline editcategories: | coreversion: 0.107.0core: | Modify the current command line input buffer.usage: | Modify the current command line input buffer.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `commandline edit` for [core](/commands/categories/core.md)
<divclass='command-title'>Modify the current command line input buffer.</div>
## Signature```> commandline edit {flags} (str)```## Flags-`--append, -a`: appends the string to the end of the buffer
-`--insert, -i`: inserts the string into the buffer at the cursor position
-`--replace, -r`: replaces the current contents of the buffer (default)
-`--accept, -A`: immediately executes the result after edit
## Parameters-`str`: The string to perform the operation with.
## Input/output types:| input | output || ------- | ------- || nothing | nothing |
commands/docs/commandline_get-cursor.md:
---title: commandline get-cursorcategories: | coreversion: 0.107.0core: | Get the current cursor position.usage: | Get the current cursor position.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `commandline get-cursor` for [core](/commands/categories/core.md)
<divclass='command-title'>Get the current cursor position.</div>
## Signature```> commandline get-cursor {flags} ```## Input/output types:| input | output || ------- | ------ || nothing | int |
commands/docs/commandline_set-cursor.md:
---title: commandline set-cursorcategories: | coreversion: 0.107.0core: | Set the current cursor position.usage: | Set the current cursor position.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `commandline set-cursor` for [core](/commands/categories/core.md)
<divclass='command-title'>Set the current cursor position.</div>
## Signature```> commandline set-cursor {flags} (pos)```## Flags-`--end, -e`: set the current cursor position to the end of the buffer
## Parameters-`pos`: Cursor position to be set.
## Input/output types:| input | output || ------- | ------- || nothing | nothing |
commands/docs/compact.md:
---title: compactcategories: | filtersversion: 0.107.0filters: | Creates a table with non-empty rows.usage: | Creates a table with non-empty rows.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `compact` for [filters](/commands/categories/filters.md)
<divclass='command-title'>Creates a table with non-empty rows.</div>
## Signature```> compact {flags} ...rest```## Flags-`--empty, -e`: also compact empty items like "", {}, and []## Parameters-`...rest`: The columns to compact from the table.
## Input/output types:| input | output || --------- | --------- || list<any>| list<any>|## Examples
Filter out all records where 'Hello' is null
```nu> [["Hello" "World"]; [null 3]] | compact Hello╭────────────╮│ empty list │╰────────────╯
`commands/docs/complete.md`:
```md
---
title: complete
categories: |
system
version: 0.107.0
system: |
Capture the outputs and exit code from an external piped in command in a nushell table.
usage: |
Capture the outputs and exit code from an external piped in command in a nushell table.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `complete` for [system](/commands/categories/system.md)
<div class='command-title'>Capture the outputs and exit code from an external piped in command in a nushell table.</div>
## Signature
```> complete {flags} ```
## Input/output types:
| input | output |
| ----- | ------ |
| any | record |
## Examples
Run the external command to completion, capturing stdout, stderr, and exit_code
```nu
> ^external arg1 | complete
Notes
In order to capture stdout, stderr, and exit_code, externally piped in commands need to be wrapped with do
`commands/docs/config.md`:
```md
---
title: config
categories: |
env
version: 0.107.0
env: |
Edit nushell configuration files.
usage: |
Edit nushell configuration files.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `config` for [env](/commands/categories/env.md)
<div class='command-title'>Edit nushell configuration files.</div>
## Signature
```> config {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | string |
## Notes
You must use one of the following subcommands. Using this command as-is will only produce this help message.
## Subcommands:
| name | description | type |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| [`config env`](/commands/docs/config_env.md) | Edit nu environment configurations. | built-in |
| [`config flatten`](/commands/docs/config_flatten.md) | Show the current configuration in a flattened form. | built-in |
| [`config nu`](/commands/docs/config_nu.md) | Edit nu configurations. | built-in |
| [`config reset`](/commands/docs/config_reset.md) | Reset nushell environment configurations to default, and saves old config files in the config location as oldconfig.nu and oldenv.nu. | built-in |
| [`config use-colors`](/commands/docs/config_use-colors.md) | Get the configuration for color output. | built-in |
commands/docs/config_env.md:
---title: config envcategories: | envversion: 0.107.0env: | Edit nu environment configurations.usage: | Edit nu environment configurations.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `config env` for [env](/commands/categories/env.md)
<divclass='command-title'>Edit nu environment configurations.</div>
## Signature```> config env {flags} ```## Flags-`--default, -d`: Print the internal default `env.nu` file instead.
-`--doc, -s`: Print a commented `env.nu` with documentation instead.
## Input/output types:| input | output || ------- | ------ || nothing | any |## Examples
open user's env.nu in the default editor
```nu> config env
pretty-print a commented env.nu that explains common settings
> config env --doc | nu-highlight,
pretty-print the internal env.nu file which is loaded before the user's environment
> config env --default | nu-highlight,
`commands/docs/config_flatten.md`:
```md
---
title: config flatten
categories: |
debug
version: 0.107.0
debug: |
Show the current configuration in a flattened form.
usage: |
Show the current configuration in a flattened form.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `config flatten` for [debug](/commands/categories/debug.md)
<div class='command-title'>Show the current configuration in a flattened form.</div>
## Signature
```> config flatten {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | record |
## Examples
Show the current configuration in a flattened form
```nu
> config flatten
`commands/docs/config_nu.md`:
```md
---
title: config nu
categories: |
env
version: 0.107.0
env: |
Edit nu configurations.
usage: |
Edit nu configurations.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `config nu` for [env](/commands/categories/env.md)
<div class='command-title'>Edit nu configurations.</div>
## Signature
```> config nu {flags} ```
## Flags
- `--default, -d`: Print the internal default `config.nu` file instead.
- `--doc, -s`: Print a commented `config.nu` with documentation instead.
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | any |
## Examples
open user's config.nu in the default editor
```nu
> config nu
pretty-print a commented config.nu that explains common settings
> config nu --doc | nu-highlight
pretty-print the internal config.nu file which is loaded before user's config
> config nu --default | nu-highlight
`commands/docs/config_reset.md`:
```md
---
title: config reset
categories: |
env
version: 0.107.0
env: |
Reset nushell environment configurations to default, and saves old config files in the config location as oldconfig.nu and oldenv.nu.
usage: |
Reset nushell environment configurations to default, and saves old config files in the config location as oldconfig.nu and oldenv.nu.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `config reset` for [env](/commands/categories/env.md)
<div class='command-title'>Reset nushell environment configurations to default, and saves old config files in the config location as oldconfig.nu and oldenv.nu.</div>
## Signature
```> config reset {flags} ```
## Flags
- `--nu, -n`: reset only nu config, config.nu
- `--env, -e`: reset only env config, env.nu
- `--without-backup, -w`: do not make a backup
## Input/output types:
| input | output |
| ------- | ------- |
| nothing | nothing |
## Examples
reset nushell configuration files
```nu
> config reset
`commands/docs/config_use-colors.md`:
```md
---
title: config use-colors
categories: |
env
version: 0.107.0
env: |
Get the configuration for color output.
usage: |
Get the configuration for color output.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `config use-colors` for [env](/commands/categories/env.md)
<div class='command-title'>Get the configuration for color output.</div>
## Signature
```> config use-colors {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | bool |
## Notes
Use this command instead of checking `$env.config.use_ansi_coloring` to properly handle the "auto" setting, including environment variables that influence its behavior.
commands/docs/const.md:
---title: constcategories: | coreversion: 0.107.0core: | Create a parse-time constant.usage: | Create a parse-time constant.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `const` for [core](/commands/categories/core.md)
<divclass='command-title'>Create a parse-time constant.</div>
## Signature```> const {flags} (const_name) (initial_value)```## Parameters-`const_name`: Constant name.
-`initial_value`: Equals sign followed by constant value.
## Input/output types:| input | output || ------- | ------- || nothing | nothing |## Examples
Create a new parse-time constant.
```nu> const x = 10
`commands/docs/continue.md`:
```md
---
title: continue
categories: |
core
version: 0.107.0
core: |
Continue a loop from the next iteration.
usage: |
Continue a loop from the next iteration.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `continue` for [core](/commands/categories/core.md)
<div class='command-title'>Continue a loop from the next iteration.</div>
## Signature
```> continue {flags} ```
## Input/output types:
| input | output |
| ------- | ------- |
| nothing | nothing |
## Examples
Continue a loop from the next iteration
```nu
> for i in 1..10 { if $i == 5 { continue }; print $i }
continue can only be used in while, loop, and for loops. It can not be used with each or other filter commands
`commands/docs/cp.md`:
```md
---
title: cp
categories: |
filesystem
version: 0.107.0
filesystem: |
Copy files using uutils/coreutils cp.
usage: |
Copy files using uutils/coreutils cp.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `cp` for [filesystem](/commands/categories/filesystem.md)
<div class='command-title'>Copy files using uutils/coreutils cp.</div>
## Signature
```> cp {flags} ...rest```
## Flags
- `--recursive, -r`: copy directories recursively
- `--verbose, -v`: explicitly state what is being done
- `--force, -f`: if an existing destination file cannot be opened, remove it and try
again (this option is ignored when the -n option is also used).
currently not implemented for windows
- `--interactive, -i`: ask before overwriting files
- `--update, -u`: copy only when the SOURCE file is newer than the destination file or when the destination file is missing
- `--progress, -p`: display a progress bar
- `--no-clobber, -n`: do not overwrite an existing file
- `--preserve {list<string>}`: preserve only the specified attributes (empty list means no attributes preserved)
if not specified only mode is preserved
possible values: mode, ownership (unix only), timestamps, context, link, links, xattr
- `--debug`: explain how a file is copied. Implies -v
## Parameters
- `...rest`: Copy SRC file/s to DEST.
## Input/output types:
| input | output |
| ------- | ------- |
| nothing | nothing |
## Examples
Copy myfile to dir_b
```nu
> cp myfile dir_b
Recursively copy dir_a to dir_b
> cp -r dir_a dir_b
Recursively copy dir_a to dir_b, and print the feedbacks
> cp -r -v dir_a dir_b
Move many files into a directory
> cp *.txt dir_a
Copy only if source file is newer than target file
> cp -u myfile newfile
Copy file preserving mode and timestamps attributes
Copy file to a directory three levels above its current location
> cp myfile ....
`commands/docs/date.md`:
```md
---
title: date
categories: |
date
version: 0.107.0
date: |
Date-related commands.
usage: |
Date-related commands.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `date` for [date](/commands/categories/date.md)
<div class='command-title'>Date-related commands.</div>
## Signature
```> date {flags} ```
## Input/output types:
| input | output |
| ------- | ------ |
| nothing | string |
## Notes
You must use one of the following subcommands. Using this command as-is will only produce this help message.
## Subcommands:
| name | description | type |
| ------------------------------------------------------------ | --------------------------------------------------------- | -------- |
| [`date format`](/commands/docs/date_format.md) | Removed command: use `format date` instead. | built-in |
| [`date from-human`](/commands/docs/date_from-human.md) | Convert a human readable datetime string to a datetime. | built-in |
| [`date humanize`](/commands/docs/date_humanize.md) | Print a 'humanized' format for the date, relative to now. | built-in |
| [`date list-timezone`](/commands/docs/date_list-timezone.md) | List supported time zones. | built-in |
| [`date now`](/commands/docs/date_now.md) | Get the current date. | built-in |
| [`date to-timezone`](/commands/docs/date_to-timezone.md) | Convert a date to a given time zone. | built-in |
commands/docs/date_format.md:
---title: date formatcategories: | removedversion: 0.107.0removed: | Removed command: use `format date` instead.usage: | Removed command: use `format date` instead.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `date format` for [removed](/commands/categories/removed.md)
<divclass='command-title'>Removed command: use `format date` instead.</div>
## Signature```> date format {flags} (format string)```## Flags-`--list, -l`: lists strftime cheatsheet
## Parameters-`format string`: The desired date format.
## Input/output types:| input | output || -------- | ------ || datetime | string || string | string |
commands/docs/date_from-human.md:
---title: date from-humancategories: | dateversion: 0.107.0date: | Convert a human readable datetime string to a datetime.usage: | Convert a human readable datetime string to a datetime.editLink: falsecontributors: false---<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. --># `date from-human` for [date](/commands/categories/date.md)
<divclass='command-title'>Convert a human readable datetime string to a datetime.</div>
## Signature```> date from-human {flags} ```## Flags-`--list, -l`: Show human-readable datetime parsing examples
## Input/output types:| input | output || ------- | -------- || string | datetime || nothing | table |## Examples
Parsing human readable datetime
```nu> 'Today at 18:30' | date from-human
Parsing human readable datetime
> 'LastFriday at 19:45' | date from-human
Parsing human readable datetime
> 'In5 minutes and30 seconds' | date from-human
PShow human-readable datetime parsing examples
> date from-human --list
`commands/docs/date_humanize.md`:
```md
---
title: date humanize
categories: |
date
version: 0.107.0
date: |
Print a 'humanized' format for the date, relative to now.
usage: |
Print a 'humanized' format for the date, relative to now.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `date humanize` for [date](/commands/categories/date.md)
<div class='command-title'>Print a 'humanized' format for the date, relative to now.</div>
## Signature
```> date humanize {flags} ```
## Input/output types:
| input | output |
| -------- | ------ |
| datetime | string |
| string | string |
## Examples
Print a 'humanized' format for the date, relative to now.
```nu
> "2021-10-22 20:00:12 +01:00" | date humanize
`commands/docs/date_list-timezone.md`:
```md
---
title: date list-timezone
categories: |
date
version: 0.107.0
date: |
List supported time zones.
usage: |
List supported time zones.
editLink: false
contributors: false
---
<!-- This file is automatically generated. Please edit the command in https://github.com/nushell/nushell instead. -->
# `date list-timezone` for [date](/commands/categories/date.md)