Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

args

import args

This module provides a complete, batteries-included framework for building command-line interfaces. It supports options (flags), positional arguments, sub-commands with their own option sets, automatic help generation, type coercion, required arguments, deprecation warnings, choice validation, abbreviated long-option matching, -- end-of-options, and @file argument expansion.

How a value reaches an option

A long option takes its value either as the next argument or attached with =; both spellings mean the same thing:

$ zuri run myprogram.zu --name Alice
$ zuri run myprogram.zu --name=Alice

The split is on the first =, so --path=a=b sets path to a=b. The attached form is the only way to pass a value that begins with a dash, since --name -5 reads -5 as an option:

$ zuri run myprogram.zu --offset=-5

A short option takes its value as the next argument only. -n Alice works; -n=Alice does not, because a short token is a bundle of single-character flags and = is not one of them. Every character in such a bundle has to name an option, so a typo in -vq is an error rather than a silently dropped flag.

Quick start

import args

var parser = args.Parser('myprogram')
parser.description = 'A friendly CLI tool.'

parser.add_option('name', 'Person to greet', {short_name: 'n', type: args.STRING})
parser.add_option('count', 'Number of greetings', {short_name: 'c', type: args.INT, value: 1})

var cmd = parser.add_command('call', 'Make a phone call')
cmd.add_option('verbose', 'Enable verbose output', {short_name: 'v'})

parser.parse()

Running the following command:

zuri run myprogram.zu -h

Prints the following help output:

Usage: myprogram [OPTIONS] [COMMAND]

  A friendly CLI tool.

OPTIONS:
  -h, --help           Show this help message and exit
  -n, --name <name>    Person to greet
  -c, --count <count>  Number of greetings (default: 1)

COMMANDS:
  call  Make a phone call

Run "myprogram --help [COMMAND]" for help on a specific command.

Typical invocations:

$ zuri run myprogram.zu -h
$ zuri run myprogram.zu --name Alice --count 3
$ zuri run myprogram.zu call --verbose
$ zuri run myprogram.zu call --help

If we change the last line of the program to echo parser.parse() so that we can see the result of the parsing, the following CLI call will yield the given result.

$ zuri run myprogram.zu --name "Kirk"
{options: {name: Kirk, count: 1}, command: nil, indexes: []}

$ zuri run myprogram.zu call
{options: {count: 1}, command: {name: call, value: nil}, indexes: []}

$ zuri run myprogram.zu call -v
{options: {verbose: true, count: 1}, command: {name: call, value: nil}, indexes: []}

Calling name without an option will yield the following result/error:

$ zuri run myprogram.zu --name
error: option --name expects <name>

You may even get help on a command directly like below:

$ zuri run myprogram.zu --help call
Usage: myprogram call [OPTIONS]

  Make a phone call

OPTIONS:
  -v, --verbose  Enable verbose output

GLOBAL OPTIONS:
  -h, --help           Show this help message and exit
  -n, --name <name>    Person to greet
  -c, --count <count>  Number of greetings (default: 1)

Options declared on the parser itself are global: they are accepted before a command and after it alike, and a command’s help lists them under GLOBAL OPTIONS. When a command declares an option of the same name, that option is the one its arguments reach.

Return value of parse() is in the format:

{
  options: {name: 'Alice', count: 3},
  command: {name: 'call', value: nil},
  indexes: []
}

The args API

Every public name in args, wherever it is declared. Each links to the page that documents it.

NameKindSummary
args.ArgsErrorclassError raised for argument parsing errors.
args.BOOLconstantvalue type boolean (accepts 1/0, true/false, yes/no, on/off).
args.CHOICEconstantvalue type choice: value must be one of the choices list/dict
args.INTconstantvalue type integer (accepts numbers, floors to integer)
args.LISTconstantvalue type list: the option may be supplied multiple times
args.NONEconstantvalue type none: the option is a boolean flag
args.NUMBERconstantvalue type number
args.OPTIONALconstantvalue type optional: value is consumed if the next token is not a flag
args.ParserclassA configurable command-line parser.
args.STRINGconstantvalue type string

Constants

NONE

args.NONE = 0

value type none: the option is a boolean flag

INT

args.INT = 1

value type integer (accepts numbers, floors to integer)

NUMBER

args.NUMBER = 2

value type number

BOOL

args.BOOL = 3

value type boolean (accepts 1/0, true/false, yes/no, on/off).

STRING

args.STRING = 4

value type string

LIST

args.LIST = 5

value type list: the option may be supplied multiple times

CHOICE

args.CHOICE = 6

value type choice: value must be one of the choices list/dict

OPTIONAL

args.OPTIONAL = 7

value type optional: value is consumed if the next token is not a flag

Classes

ArgsError

class args.ArgsError < Error

Error raised for argument parsing errors.

Parser

class args.Parser < _Optionable

A configurable command-line parser.

Properties you can set after construction
  • description (string): paragraph shown between USAGE and OPTIONS.
  • epilog (string): paragraph shown after all sections.
  • allow_abbrev (bool): allow unambiguous long-option prefix matching. Defaults to true, like Python’s argparse.
  • allow_atfile (bool): expand @filename tokens by reading arguments from that file. Defaults to true.

Fields

FieldTypeDescription
commandsList of sub-commands registered with add_command.
indexesList of positional arguments registered with add_index.
description
epilog
allow_abbrev
allow_atfile
terminal_widthThe column width help text wraps to.

Constructor

args.Parser(name, default_help)

Creates a new parser instance.

Parameters

  • name (string) — The program name shown in usage lines.
  • default_help (?bool) — Show help when invoked with no arguments. Defaults to true.

Parser.set_terminal_width()

args.Parser.set_terminal_width(width)

Overrides the column width help text wraps to, in place of the terminal_width this parser auto-detected at construction time (a real query of the terminal, the COLUMNS environment variable, or 80, in that order of preference; see _terminal_width()). Useful both for a program that wants a fixed layout regardless of environment, and for tests that need deterministic wrapping independent of whatever terminal actually ran them.

Equivalent to setting terminal_width directly; this exists purely for discoverability and to validate its argument.

Parameters

  • width (number)

Parser.add_option()

args.Parser.add_option(name, help, opts)

Adds an option (flag) to the top-level parser.

opts keys can include any of:

  • short_name (string): single-character alias (-x).
  • type (int): one of the type constants; default NONE.
  • value (any): default value when the option is absent.
  • choices (list|dict): restrict allowed values.
  • required (bool): error if the option is absent.
  • metavar (string): placeholder shown in help, defaulting to the option’s own name, lower-cased.
  • deprecated (bool): print a warning when the option is used.

Parameters

  • name (string)
  • help (?string)
  • opts (?dict)

Parser.add_command()

args.Parser.add_command(name, help, opts)

Adds a sub-command.

opts keys: - type {int}: expected type for the command’s value argument - action {function}: called with (options [, value]) after parsing - choices {list|dict}— restrict allowed values when type is CHOICE - metavar {string}: placeholder shown in help for the command’s value, e.g. 'message' for git commit -m <message> (default: the value type’s name, lower-cased)

Returns the _Command object so you can chain add_option calls:

parser.add_command('push', 'Push changes').
       add_option('force', 'Force push', {short_name: 'f'})

Parameters

  • name (string)
  • help (?string)
  • opts (?dict)

Returns — _Command

Parser.add_index()

args.Parser.add_index(name, help, opts)

Adds a positional (index-based) argument.

opts keys: - type {int}: coercion type; default STRING - value {any}: default when argument is absent - choices {list|dict}: restrict allowed values - required {bool}: error if argument is absent (default false) - metavar {string}: display name in help

Without a value, a positional nobody supplied is simply missing from parse()’s indexes rather than sitting there as nil.

A positional of type LIST takes every positional word from where it starts to the end of the command line, flags in between or not, and arrives in indexes as one list. It has to be the last positional declared, since nothing after it could ever receive a word.

Parameters

  • name (string)
  • help (?string)
  • opts (?dict)

Raises ArgsError when a positional is added after a LIST one.

Parser.parse()

args.Parser.parse(custom_args: ?list) -> dict

Parses command-line arguments and returns a dictionary of command, options, and indexes.

By default this reads the real process arguments (os.args, skipping the interpreter and script path). Pass custom_args (a list of strings) to parse something else instead, e.g. a config-driven argument list, or a fixed list in a test.

Result shape:

{
  options: dict,                # collected option values
  command: nil | {name, value}, # command name and value (if any)
  indexes: list                 # collected positional values
}

indexes holds one entry per positional that has a value, in the order they were declared: what the user supplied, then the declared default of any that follow. A positional that was not supplied and has no default is absent rather than nil, so indexes.is_empty() and indexes.length() answer what they look like they answer, and a program that wants its own fallback can reach for it:

var path = parsed.indexes.is_empty() ? os.cwd() : parsed.indexes[0]

Parameters

  • custom_args (?list)

Returns dict

Parser.help()

args.Parser.help()

Print the full help text and exit(0).


2021, Richard Ore and Zuri contributors