Extra Features

On this section, we've outlined some extra features exposed by Rargs that add some quality of life improvements, and take you scrtipts to the next level.

Long Help Output

Most Rargs decorators can be used to improve the usage output of you script. Nonetheless there may be times where you want to include more than a single line of information, or split the lines between other configuration to better explain the logic behind it.

You can use the @@ decorator to do exactly this. Every commend decorated with this operator will be parsed as a single value of the help message, and will be appended appropriately in the usage output.

#!/usr/bin/env bash

# @name minimal
# @version 0.0.1
# @description Flags examples

# @@ You can use the @help decorator to split the output of your usage
# @@ message into multiple lines.
# @@
# @@ You can also interleave these lines with other decorators.
# @arg name="World" Name of the entity to greet
#
## Double '#' Can be used to add comments that won't be treated as part
## of the usage output.
#
# @@
# @@ You can continue with the usage text here. Notice how you can implement
# @@ empty new lines by using only the @@ decorator.
root() {
  echo "Hello $rargs_name"
}

Examples

A typical thing to add to a script is some inline examples on how to run the application. Rargs exposes an @example decorator that allows you define ways to call your script and a brief explanation of what they do.

The @example decorator expects a brief description of what the example is for and the command itself, separated by a $ operator. This value will be replaced in the usage output with the name of the command, or script depending of the scope.

# @example Directory command $ dir
# @example Directory help command $ dir -h
# @example Directory file command $ file -h
# @example List directory sub-command $ dir list
# @example List directory sub-command help $ dir list -h

These examples will have the following text appear on the usage output, assuming the script is called examples.

Examples:
  examples dir
    Directory command
  examples dir -h
    Directory help command
  examples file -h
    Directory file command
  examples dir list
    List directory sub-command
  examples dir list -h
    List directory sub-command help

Any parameters

Use the @any decorator to configure the script or a command to parse a dynamic list of additional arguments. This can be useful when we want to handle parsing the arguments ourselves, or when we need to pass them to a different script or binary.

You can reference the additional arguments inside your scripts through the rargs_other_args variable, defined as an array of values.

cat <<-'EOF' | rargs run - -h
# @help Show how to use the @any decorator.
# @any <GIT_ARGUMENTS> Git command arguments and options.
root() {
	echo "Pass the additional arguments to an external app like git."
	git ${rargs_other_args[@]}
}
EOF

Just as other arguments decorators, the @any decorator accepts a value notation script and a description to include in the usage output.

Environment Variables

Rargs can help you enforce the existence of pre-defined environment variables, and allows you to overwrite options and arguments with the values of environment variables.

To use this feature use @env decorator at the script or command scope.

Required Environment Variable

Use the ! operator to mark an environment variable as required.

# @env REQUIRED_ENVIRONMENT_VARIABLE!

Assign an environment variable to a command or argument

To assign the value of an environment variable to a positional argument or an option, use the : operator followed by the name of the variable you want to assign the value to.

# @arg positional-argument! Positional argument
# @option -e --example Example Option
# @env POSITIONAL_ARGUMENT:positional-argument
# @env EXAMPLE:example

You can't mark an environment variable as required with the ! operator when assigning its value to another variable. If you need to enforce the requirement of this value use the ! operator on the @arg or @option definition.

Dependencies

Most script require external dependencies to be available in the $PATH during its execution. This could be binaries or other scripts. Rargs exposes the @dep decorator to ensure that all the required binaries or scripts are available on runtime. It also allows you to set an error message, which you can use to give the user instructions on how to install the missing dependency.

# @dep curl Please install curl with brew install curl or apt install curl

If you want to add some colors, add the appropriate ANSI escape codes to the message.

# @dep curl Please install \e[32mcurl\e[0m with \e[32mbrew install curl\e[0m or \e[32mapt install curl\e[0m

You can also provide a list of dependencies as strings separated by a comma (,) and can personalize the message by referring to the missing dependency as $dep when writing your help message.

# @dep curl,jo Please install \e[32m$dep\e[0m with \e[32mbrew\e[0m or \e[32maapt-get\e[0m

Rules

Even though Rargs has a lot of opinions on how to write CLI applications, it still offer some escape hatches that you can use to tune your script just how you want. Rules are one big way to do this.

Basically, setting up a rule changes a core behavior of Rargs either at the root or command scope. You can use it to disable the --help flags, or change the way that it should trigger.

To set a rule use the @rule operator followed by the name of the rule you want to enforce. If you set this inside the scope of an @cmd command, then the rule will only be applied to the command, and not to the entire script.

On this section, we'll outline all the rules available.

No first option help

By default, Rargs expects the --help option to be passed as the first argument of the call. If you add any argument before you'll get an error message like this:

Invalid option: --help

The no-first-option-help rule disable this behavior, allowing you to provide the --help option at any place, avorting the execution of the script, to present the script usage information.

# @rule no-first-option-help

No force default

This rule disable the default assigning mechanics of Rargs, letting you mark an option or argument as having a default value, yet letting you decide on your own how this value will be set.

# @rule no-force-default

Use global deps for root.

Allow the usage of the @dep decorator at the global scope to work for scripts with a single root command.

# @rule use-global-deps-for-root

Use gloable envs for root

Allow the usage of the @env decorator at the global scope to work for sciprs with a single root command.

# @rule use-global-envs-for-root

External Sub-Commands

Important: This is a WIP and it may suffer changes in the future.

Bash scripts tend to be fairly long when we add all this functionality, so it makes sense that we might want to split the code into more manageable chunks. The @sub decorator attempts to simplify the process of writing a CLI app in Bash, defined on multiple files.

It works by declaring the @sub decorator, followed by a relative path to the script that should be called instead. This next script can be another Rargs powered script, a normal Bash script, a script written on a different language, or a binary. This script (and all the others defined in the same manner) will be bundled together, and deployed along the main file in the directory defined in the rargs build command. All the sub files will be placed following the same relative directory structure they had before.

The next step is to define how the relative script should be called. To do this, you can leverage other Rargs decorators to parse the inputs before calling script. You do this by using a special $sub variable that will be populated with the right path to the relative file. It's up to you to define how it should be called and what parameters should be provided.

The @sub decorator is meant to be used at the command level, after a @cmd decorator.

./commands-nested.sh

#!/usr/bin/env bash
# @name commands-nested
# @version 0.0.1
# @description Sample application with nested commands

# @cmd Directory commands
# @sub ./commands-nested/dir.sh
# @flag --dry-run Output the command to `stodut` instead of calling the relative script.
dir() {
  if [[ -n "$rargs_dry_run" ]]; then
    echo "$sub ${rargs_input[*]}"
  fi

	"$sub" ${rargs_input[@]}
}

You can use the $rargs_input variable to refer to all the arguments parsed by Rargs.

./commands-nested/dir.sh:

#!/usr/bin/env bash
# @name dir
# @version 0.0.1
# @description Directory commands

# @cmd Show files in the directory
# @arg path! Directory path
list() {
	echo "${rargs_input[*]}"
}

# @cmd Remove directory
# @arg path! Directory path
# @flag -f --force Remove even if not empty
remove() {
	echo "${rargs_input[*]}"
}

You've now seen all the features provided by Rargs. Next, we'll go over some examples that show the tool in action, that you can also use as inspiration for your scripts.

Show me the examples →