Home Explore Blog CI



nushell

7th chunk of `book/custom_commands.md`
c8387a51a2eacfeda25e0af60a27ef5f35bf67f98ea2ad7a000000010000100a
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:

```nu
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 Rahul Priya Arjun Anjali Vikram
# => 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](/book/operators#spread-operator) (`...`). Using the `vip-greet` command definition above:

```nu
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:

```nu
eza commands
# => categories  docs  README.md
```

We can define a new command `ezal` which will always display a long-listing, adding icons:

```nu
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`.

```nu
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`:

```nu
def --wrapped ezal [...rest] {
  if '-G' in $rest {
    eza ...$rest
  } else {
    eza -l --icons ...$rest
  }
}

ezal -G commands
# => categories  docs  README.md
```

## Pipeline Input-Output Signature

By default, custom commands accept [`<any>` type](./types_of_data.md#any) 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`](/commands/docs/str_stats.md) looks like this:

```nu
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`](/commands/docs/str_join.md):

```nu
def "str join" [separator?: string]: [
  list -> string
  string -> string
] { }
```

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`](/commands/docs/rm.md) or [`hide`](/commands/docs/hide.md)):

```nu
def xhide [module: string, members?]: nothing -> nothing { }
```

::: tip Note
The example above is renamed `xhide` so that copying it to the REPL will not shadow the built-in `hide` command.

Title: Rest Parameters with Wrapped External Commands and Pipeline Input-Output Signature in Nushell
Summary
This section explains how custom commands can wrap external commands using rest parameters and the `--wrapped` flag. It also shows how to check for certain parameters within the custom command and modify the behavior of the wrapped external command accordingly. Additionally, it covers how to define explicit input and output signatures for custom commands, specifying the allowed data types for pipeline input and output. It discusses how to define multiple input/output types and how to use `<nothing>` when a command does not accept or require pipeline input or output.