Defining nur tasks
I highly recommend reading nu custom commands for more details, but I will try to show you the most important bits right here. I will use the term “nur task” to talk about subcommands to nur in the following section. If you know about nu, just know that the tasks are actually really only normal subcommands.
This means you define nur tasks like def "nur something" - which you can then call by using nur something. nur tasks can call any other nu commands or system command.
The most basic nur task could look like this:
def "nur hello-world" [] {
print "Hello world"
}
nu commands are defined using the def keyword. The command name ("nur hello-world" in this case) is followed by the arguments. Those are written in square brackets ([ and ]), see next chapter for some details on arguments. The command body is then put into curly brackets and can contain any nu script code.
For the most tasks this means your nur task will just execute some system commands like poetry install or npm ci or cargo publish or something similar - but you can also create more complex tasks, however you like. You may look into the nurfile of nur itself for some examples.
Task output (return value)
nu commands will use the result of the last line in the command body as the command return value. nur will then automatically print the return values of the task. The important thing to understand is that nu will see the output of a command as its return value. So this is also true for any command output written to stdout. The output of the last line in your command will be used as the command result/output and thus printed by nur. Any other commands that have been run in your command function will be eaten by nu, unless you actively use print (command | print or print (command)).
This behaviour of nu commands may be strange at first glance, but makes a lot of sense when working with pipelines the way nu does. Having any output produced by each line in a command definition be redirected mixed output and result in errors handling the results. When using nu scripts for nur tasks you need to know about this behaviour and handle any additional output you want to produce accordingly.
An example using print:
def "nur do-something-useful" [] {
print "We will do something useful now:"
run-command-1 | print
print "Now more useful stuff:"
run-command-2 | print # you can also skip the `print` here, as it is the last line
}
If your command should not produce any output you can return null by putting null in your command body as the last line.
Adding some arguments to your tasks
nur tasks can receive three different kinds of arguments:
Named, positional arguments
def "nur taskname" [
argument1,
argument2,
] {
# ...
}
Details:
- Above example provides the variables
$argument1and$argument2in the task - Adding a
?after the parameter name makes it optional
Flags as parameters
def "nur taskname" [
--argument1: string,
--argument-number2: int,
] {
# ...
}
Details:
- If you want to have named flags that can actually receive any values, you need to add a type (see below for typing)
- Flags are always optional, default value will be
nullunless defined otherwise (see below for default values) - Above example provides the variables
$argument1and$argument_number2in the task- Flags will provide variable names without the leading
-- - Flags will be available in your task code as variables with all
-replaced by_
- Flags will provide variable names without the leading
- You may provide short version of flags by using
--flag (-f)
Boolean/switch flags
def "nur taskname" [
--switch,
] {
# ...
}
Details:
- Boolean/switch flags must NOT be typed, they still will be of type
bool - Those can only receive the values
true/false, withfalsebeing the default - Above example provides the variable
$switchin the task
Parameter details
Arguments typing
Arguments can (and should) be typed, you can use argument_name: type for doing so. A typed argument could look like this:
def "nur taskname" [
argument1: string,
argument2: int,
] {
# ...
}
See parameter types for a full list of available types.
Default values
Also arguments can have a default value, you can use argument_name = "value" to set the default value. An example using a default value could look like this:
def "nur taskname" [
argument1 = "value",
argument2 = 10,
] {
# ...
}
Rest parameters
Rest parameters might consume the rest of the arguments:
def "nur taskname" [
...rest
] {
# ...
}
Details:
- Above example provides the variable
$restin the task - The rest of the arguments will not consume any arguments starting with
-, as this would conflict with flags- You may use
def --wrapped ...to also consume unknown flags as rest arguments
- You may use
Full example
Example with different kinds of arguments:
def "nur something" [
name: string
optional?: string
--age (-a): int = 23
--switch (-s)
] {
null # nothing here
}
nu will take care that all arguments are provided and that the types are correct.
Adding documentation to your command
You may add documentation by adding commands to your nur tasks. See the usage example above and the nu command documentation section.
Basic rule is that the command right above your task will be used as a description for that task. Comments next to any argument will be used to document that argument.
Example task documentation:
# This is the documentation used for your task
# you may use multiple lines
#
# and use empty lines to structure the documentation (as long as it is one comment block)
def "nur something" [
name: string # This is used to document the argument "name"
--age: int # This is used to document the argument "age"
] {
null # nothing here
}
The above example will generate the following documentation when running nur --help something or nur something --help:
❯ nur --help something
This is the documentation used for your task
you may use multiple lines
and use empty lines to structure the documentation (as long as it is one comment block)
Usage:
> nur something {flags} <name>
Flags:
--age <Int> - This is used to document the argument "age"
-h, --help - Display the help message for this command
Parameters:
name <string>: This is used to document the argument "name"