ArgumentParser

Usage

use ArgumentParser;

or

import ArgumentParser;

Warning

ArgumentParser is unstable.

A module to be used for defining and parsing command line arguments.

Note

You must declare your main method to take an array of string arguments in order to get values from the command line. See the quickstart example below or the technote about getting arguments from main().

Note

Chapel programs can make use of configuration constants and variables. The ArgumentParser module can be used in place of, or in addition to, configuration variables and constants. In particular, it is common for Chapel programs to rely solely upon configuration variables and for such programs the ArgumentParser is not needed.

Note

This module is in the initial stages of development and should be expected to change in future releases.

Terminology

Descriptions of each argument type are given below.

Arguments

These are also known as positional values and do not have any identifiers aside from the relative order and count of values entered.

Example:

$ myExecutable filename1 filename2 filename3

Options

These are values that follow some indicator, typically --option is used as a long option and -o might be the short indicator. Typically, 0 or more arguments may follow.

Examples:

$ myExecutable --foo value1
$ myExecutable -f value1

Flags

These are boolean indicators whose presence alone can be used to derive a true/false value.

Example:

$ myExecutable --debug
$ myExecutable -d

Subcommands

These are values that can be used to trigger execution of other methods which take their own arguments. A subcommand typically consumes the remaining values from the command line.

Example:

$ myExecutable build --force otherProgram

PassThrough

This is a delimiter value which designates that all the values which follow should be collected for later use by the developer. Typically this value is a double dash --.

Example:

$ myExecutable build --force otherProgram -- --flags --for --compiling otherProgram

Quickstart Example

module M {
  use ArgumentParser;
  proc main(args:[]string) throws {
    var parser = new argumentParser();
    var simpleArg = parser.addArgument(name="positional");
    var optionArg = parser.addOption(name="optional");
    var flagArg = parser.addFlag(name="debug", defaultValue=false);
    parser.parseArgs(args);

    var debug = flagArg.valueAsBool();
    // we are assured a value here or else the parser would have thrown an error
    var foo = simpleArg.value();
    var bar:string;
    if optionArg.hasValue() then bar = optionArg.value();
  }
}

This program would accept any of the following command line arguments (and other combinations):

$ quickStart myFile
$ quickStart myFile --optional valueA
$ quickStart myFile --debug
$ quickStart myFile --optional valueA --debug
$ quickStart --optional val1 --debug myFile

And will not accept any of the following (reason given below):

$ quickStart --debug
positional argument is missing

$ quickStart myFile --debug=true
debug flag does not accept values

$ quickStart myFile --debug --optional
optional expects 1 value

If a user asks for help with either -h or --help, the following output would be automatically generated and displayed:

$ quickStart -h
USAGE: quickStart <POSITIONAL> [-h, --help] [--debug] [--optional <OPTIONAL>]

ARGUMENTS:
        POSITIONAL

OPTIONS:
        -h, --help      Display this message and exit
        --debug
        --optional <OPTIONAL>

Customizing Help Output

There are various levels of support for help handling that you can request when initializing an argumentParser.

By default, an argumentParser handles help requests in the form of -h and --help, builds a help message, builds a usage message, prints the combined help and usage message when either invalid input or help request is detected, and then exits.

These actions are mostly customizable through arguments set when initializing an argumentParser or individual arguments, options, and flags.

The text that describes each argument can be defined by setting a value for the help argument in the various add methods on the argumentParser.

Example usage:

// to set the help text on an argument, flag, etc.
var myArg = parser.addArgument(name="myArg",
                               help="This text describes myArg for the user");

To take full control over what happens when a user requests help, create a new class that inherits the HelpHandler and override the printHelp() method. Then, create a new instance of your custom class and set it as the helpHandler argument when initializing the argumentParser. This is designed to ease adoption when a program has existing functions to print its help messages.

Example usage:

class MyHelpHandler : HelpHandler {
  override proc printHelp() {
    // call some custom functions like ...
    // printMyCustomHelp();
    // maybe other things?
  }
}
var parser = new argumentParser(helpHandler=new MyHelpHandler());

All help requests will now execute whatever is defined in printHelp() and then exit, as the parser’s exitOnError is true by default.

For existing programs where the help text is defined in a string, the argumentParser can accept a value in the helpMessage argument during initialization.

Example usage:

const myHelpMessage = "A customized message that should be displayed\n" +
                      "instead of the usual help  and usage message.\n"
var parser = new argumentParser(helpMessage=myHelpMessage);

To turn off help handling completely, set the addHelp argument to false when initializing the argumentParser.

record argumentParser

A parser that performs the following functions:

  1. Stores definitions of valid arguments/flags/options

  2. Parses an array of arguments as passed from the command line (where args[0] is typically the name of the executable)

  3. Throws an ArgumentError if invalid or unrecognized arguments are encountered

The parser can process command line arguments that include or omit an equals sign =, with short - or long -- indicators.

We can declare a new argumentParser like so:

var parser = new argumentParser();

Limitations

  • Cannot place short flags together. That is, if a parser has defined short flags -c, -a and -t, we cannot handle -cat.

  • Short options must be separated from their values with an equals sign or spaces. That is, -cValue is not supported and should be entered as either -c Value or -c=Value.

  • Numeric types are not supported and will be passed as strings.

  • Chapel programs currently do config variable processing on the arguments. If you have arguments that conflict with config variables, you can place them after -- on the command line in order to skip the config variable processing. If a passthrough is also specified as --, then these arguments will also be captured by the passthrough. If that is not desired, you can create a different passthrough delimiter, e.g. ++.

  • Counting the number of times a flag is found on the command line is not supported.

  • The argument parser doesn’t support checking for mutually exclusive arguments or arguments that are conditionally required. Instead, you can check after parsing the arguments that the provided arguments are acceptable.

proc init(addHelp = true, exitOnError = true, exitAfterHelp = true, in helpHandler: ?h = none, helpMessage: ?t = none)

Initialize an instance of argumentParser.

Arguments:
  • addHelp – Determines if the ArgumentParser adds help flags and handles their presence in the command line arguments. Flag values are set to -h and --help. Defaults to true.

  • exitOnError – Determines if ArgumentParser exits with error info when an error occurs. Defaults to true.

  • exitAfterHelp – Determines if ArgumentParser exits after it finds a help flag and prints the help message. Defaults to true.

  • helpHandler – Allows a user to define a custom HelpHandler to perform printing of the help message and additional operations. Defaults to a new instance of HelpHandler. Cannot be set in conjunction with helpMessage.

  • helpMessage – Allows a user to set a customized message to display as help output. Defaults to a help message generated by the argumentParser. Cannot be used in conjunction with helpHandler.

proc ref addArgument(name: string, numArgs = 1, defaultValue: ?t = none, help = "", visible = true, valueName: ?v = none) : shared Argument throws

Add an argument to the parser. Arguments are also commonly known as “positional arguments” and are not indicated by anything other than a value.

For example, defining an argument like this:

var fileArg = parser.addArgument(name="filename");

we would expect command line arguments like this:

$ programName myFile.ext
Arguments:
  • name – a friendly name to give this argument. This would typically be displayed in the help or usage message.

  • numArgs – an exact number of values expected from the command line. An ArgumentError will be thrown if more or fewer values are entered.

  • defaultValue – a value to assign the argument when it is not provided on the command line. If numArgs is greater than 1, an array or list may be passed. Defaults to none.

  • help – a message to display for this argument when help is requested

  • visible – determines if this argument should be displayed in the help and usage messages. Defaults to true.

  • valueName – an alternative display name for the value in the help and usage messages for this argument. Defaults to the uppercase representation of the name field.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError in any of the following conditions:

  • name is already defined for this parser

  • defaultValue is something other than a string, array or list of strings.

proc ref addArgument(name: string, numArgs: range(?), defaultValue: ?t = none, help = "", visible = true, valueName: ?v = none) : shared Argument throws

An overload of addArgument, described above, that accepts a range for numArgs.

For example, defining an argument like this:

var filesArg = parser.addArgument(name="filenames", numArgs=1..);

we would expect command line arguments like either of these:

$ programName myFile1.ext myFile2.ext myFile3.ext ...
$ programName myFile1.ext
Arguments:
  • name – a friendly name to give this argument. This would typically be displayed in the help or usage message.

  • numArgs – a range of values expected from the command line. If using a range, the argument must be the only positional that accepts a range, and must be specified last relative to other positional arguments to avoid ambiguity. An ArgumentError will be thrown if more or fewer values are entered.

  • defaultValue – a value to assign the argument when it is not provided on the command line. If numArgs is greater than 1, an array or list may be passed. Defaults to none.

  • help – a message to display for this argument when help is requested

  • visible – determines if this argument should be displayed in the help and usage messages. Defaults to true.

  • valueName – an alternative display name for the value in the help and usage messages for this argument. Defaults to the uppercase representation of the name field.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError in any of the following conditions:

  • name is already defined for this parser

  • defaultValue is something other than a string, array or list of strings.

  • numArgs is neither low-bound nor fully-bound

proc ref addOption(name: string, opts: [] string = _processNameToOpts(name), numArgs = 1, required = false, defaultValue: ?t = none, help = "", visible = true, valueName: ?v = none) : shared Argument throws

Add an option to the parser. Options are typically indicated by one or two leading dashes - and may be followed by 0 or more values.

For example, defining an option like this:

var fileArg = parser.addOption(name="filename");

we would expect command line arguments like either of these:

$ programName --filename=myFile1.ext
$ programName --filename myFile1.ext
Arguments:
  • name – a friendly name to give this option, or a pattern to use to indicate this option from the command line. If providing a pattern, use a leading single dash - or double dash --.

  • opts – an array of string values that can be used to indicate this option. Defaults to a long version of the name field with leading double dashes --.

  • numArgs – the exact number of values expected to follow the option on the command line. An ArgumentError will be thrown if more or fewer values are entered.

  • required – a bool to set this option as a required command line argument. If set to true, an ArgumentError will be thrown if the user fails to enter the option on the command line. Defaults to false.

  • defaultValue – a value to assign the argument when an option is not required, and a is not entered on the command line. If numArgs is greater than 1, an array or list may be passed. Defaults to none.

  • help – a message to display for this option when help is requested

  • visible – determines if this option should be displayed in the help and usage messages. Defaults to true.

  • valueName – an alternative display name for the value in the help and usage messages when an option accepts values. Defaults to the uppercase representation of the name field.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError in any of the following conditions:

  • name or opts are already defined for this parser

  • values in opts do not begin with a dash -

  • defaultValue is something other than a string, array or list of strings.

proc ref addOption(name: string, opts: [] string = _processNameToOpts(name), numArgs: range(?), required = false, defaultValue: ?t = none, help = "", visible = true, valueName: ?v = none) : shared Argument throws

An overload of addOption described above that accepts a range of expected values for numArgs.

For example, defining an option like this:

var filesArg = parser.addOption(name="filenames", numArgs=1..);

we would expect command line arguments like any of these:

$ programName --filenames myFile1.ext myFile2.ext myFile3.ext ...
$ programName --filenames=myFile1.ext
$ programName --filenames myFile1.ext --filenames myFile2.ext ...
Arguments:
  • name – a friendly name to give this option, or a pattern to use to indicate this option from the command line. If providing a pattern, use a leading single dash - or double dash --.

  • opts – an array of string values that can be used to indicate this option. Defaults to a long version of the name field with leading double dashes --.

  • numArgs – a range of values expected to follow the option on the command line. This may be a fully-bound range like 1..10 or a lower-bound range like 1... An ArgumentError will be thrown if more or fewer values are entered.

  • required – a bool to set this option as a required command line argument. If set to true, an ArgumentError will be thrown if the user fails to enter the option on the command line. Defaults to false.

  • defaultValue – a value to assign the argument when an option is not required, and a is not entered on the command line. If numArgs is greater than 1, an array or list may be passed. Defaults to none.

  • help – a message to display for this option when help is requested

  • visible – determines if this option should be displayed in the help and usage messages. Defaults to true.

  • valueName – an alternative display name for the value in the help and usage messages when an option accepts values. Defaults to the uppercase representation of the name field.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError in any of the following conditions:

  • name or opts are already defined for this parser

  • values in opts do not begin with a dash -

  • defaultValue is something other than a string, array or list of strings.

  • numArgs does not have a low-bound

proc ref addFlag(name: string, opts: [?optsD] = _processNameToOpts(name), required = false, defaultValue: ?t = none, flagInversion = false, numArgs = 0, help = "", visible = true, valueName: ?v = none) : shared Argument throws

Add a flag to the parser. Flags may be setup in several ways depending on the user’s needs.

For example, defining a flag like this:

var debugArg = parser.addFlag(name="debug");

we would expect command line arguments like this:

$ programName --debug
Arguments:
  • name – a friendly name to give this flag, or a pattern to use to indicate this flag from the command line. If providing a pattern, use a leading single dash - or double dash --.

  • opts – an array of string values that can be used to indicate this flag. Defaults to a long version of the name field with leading double dashes --.

  • required – a bool to set this flag as a required command line argument. If set to true, an ArgumentError will be thrown if the user fails to enter the flag on the command line. Defaults to false.

  • defaultValue – a value to assign the argument when a flag is not required, and a is not entered on the command line. Defaults to none.

  • flagInversion – a bool to indicate if the parser should automatically create a --no- version of this flag to mean false when entered from the command line. i.e. --[no-]build

  • numArgs – the number of values expected to follow the flag on the command line. Defaults to 0 and has a max value of 1. when 0, then --flag is accepted while --flag=true is rejected when 1, then --flag is rejected while --flag=true is accepted

  • help – a message to display for this flag when help is requested

  • visible – determines if this flag should be displayed in the help and usage messages. Defaults to true.

  • valueName – an alternative display name for the value in the help and usage messages when a flag accepts a value. Defaults to the uppercase representation of the name field.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError in any of the following conditions:

  • name or opts are already defined for this parser

  • numArgs > 1

  • flagInversion is true and numArgs > 0

  • flagInversion is false and defaultValue is true and flag is required and numArgs < 1 (in this case the flag is meaningless because it will always be true)

  • values in opts do not begin with a dash -

proc ref addFlag(name: string, opts: [?optsD] = _processNameToOpts(name), required = false, defaultValue: ?t = none, flagInversion = false, numArgs: range, help = "", visible = true, valueName: ?v = none) : shared Argument throws

An overload of addFlag described above, which accepts a range for numArgs. If a range of 0..1 is used, then either --flag true or --flag is acceptable from the command line.

For example, defining a flag like this:

var debugArg = parser.addFlag(name="debug",
                              numArgs=0..1,
                              defaultValue=false);

we would expect command line arguments like either of these:

$ programName --debug
$ programName --debug=true
Arguments:
  • name – a friendly name to give this flag, or a pattern to use to indicate this flag from the command line. If providing a pattern, use a leading single dash - or double dash --.

  • opts – an array of string values that can be used to indicate this flag. Defaults to a long version of the name field with leading double dashes --.

  • required – a bool to set this flag as a required command line argument. If set to true, an ArgumentError will be thrown if the user fails to enter the flag on the command line. Defaults to false.

  • defaultValue – a value to assign the argument when a flag is not required, and a is not entered on the command line. Defaults to none.

  • flagInversion – a bool to indicate if the parser should automatically create a –no- version of this flag to mean false when entered from the command line. i.e. (–[no-]build)

  • numArgs – the range of values expected to follow the flag on the command line. when 0..1, then --flag or --flag=true are accepted

  • help – a message to display for this flag when help is requested

  • visible – determines if this flag should be displayed in the help and usage messages. Defaults to true.

  • valueName – an alternative display name for the value in the help and usage messages when a flag accepts a value. Defaults to the uppercase representation of the name field.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError in any of the following conditions:

  • name or opts are already defined for this parser

  • numArgs high-bound > 1

  • flagInversion is true and numArgs > 0

  • flagInversion is false and defaultValue is true and flag is required and numArgs < 1 (in this case the flag is meaningless because it will always be true)

  • numArgs does not have a lower-bound or lower-bound < 0

  • values in opts do not begin with a dash -

proc ref addSubCommand(cmd: string, help = "", visible = true) : shared Argument throws

Add a subcommand to the parser. A subcommand is typically indicated with an action word, like commit in git commit. The subcommand name and all values after the subcommand are collected in the returned shared Argument object.

For example, a defining a subcommand like this:

var subCmdRun = parser.addSubCommand("run");

we would expect command line arguments like this:

$ programName <any args for programName> run <any args for run>
Arguments:
  • cmd – a keyword that is recognized as indicating the subcommand from the command line. For example, commit in git commit.

  • help – a message to display for this subcommand when help is requested

  • visible – determines if this subcommand should be displayed in the help and usage messages. Defaults to true.

Returns:

a shared Argument where parsed values will be placed

Throws:

ArgumentError if cmd is already defined for this parser

proc ref addPassThrough(delimiter = "--") : shared Argument throws

Add a delimiter to indicate all following values should not be parsed, but collected for later use by the developer. Convention dictates this is a double-dash --, but the developer may choose to use something else.

For example, defining a passthrough delimiter like this:

var passedArgs = parser.addPassThrough();

we would expect command line arguments like this:

$ programName <any args for programName> -- --preserved-flags --options etc
Arguments:

delimiter – the pattern to use as the passthrough indicator

Returns:

a shared Argument where collected values will be placed for use by the developer

Throws:

ArgumentError if delimiter is already defined for this parser

proc ref parseArgs(arguments: [?argsD] string) throws

Parses an array of arguments as collected from the command line

Example usage:

proc main(args:[]string) throws {
  // after parser and arguments defined
  parser.parseArgs(args);
}
Arguments:

arguments – The array of values passed from the command line to main(args:[]string)

Throws:

ArgumentError if argumentParser is initialized with exitOnError=false, and invalid or undefined command line arguments are found in arguments.

proc helpFlagPresent() : (bool, string)

Check if the parser identified a help flag from the command line

Returns:

a tuple with the first component being a boolean indicating if a help flag was found and the second element being the flag found. Second element will be the empty string if no help flag was found.

class Argument

Stores the result of argument parsing.

proc value() : string

Return the single value collected from the command line, if any. If no value was collected, the program will halt as result of calling list.first on an empty list.

Warning

This can only be called safely if you are sure a value was collected, either because the argument was required or there was a default value set. Calling value() when no argument was collected will cause the program to halt. To be safe, check the return of hasValue() before calling value().

Example usage:

var argVal:string;
if myArg.hasValue() then argVal = myArg.value();
Returns:

The string value for this argument as parsed from the command line

iter values() : string

Return an iterator over the values collected from the command line, if any. Typically collect these into a new list or var them into an array.

Example usage:

// to get an array of strings
var argValues = myArg.values();
// create a list of strings
var argList = new list(myArg.values());
Returns:

An iterator over the parsed values

proc hasValue() : bool

Check to see if a value was collected from the command line

Returns:

  • true – when at least one value was parsed

  • false – when the argument wasn’t provided and no default was defined

proc valueAsBool() : bool throws

Interpret the value collected from the command line as a bool

Returns:

  • true – for true, 1, yes, y

  • false – for false, 0, no, n

Throws:

ArgumentError if value cannot be interpreted as a bool

class HelpHandler

The HelpHandler class is meant to be inheritable so a user can implement their own behavior when the help flag is recognized by the parser. Typically, there is no need to make a custom version of HelpHandler, as a default is supplied.

proc printHelp()

Prints the help message by default. Inherit this class and override this method to customize the operations.