Options
A command-line interface can be composed of subcommands and options (also known as flags). The options allow a calling application or user to configure the command that will run. tsargp offers a selection of option types that should suit most applications. In the next sections, we present the available types and describe them in detail.
Option types
There are seven types of options, as summarized in the table below:
Type | Parameters | Attribute classes |
---|---|---|
help | niladic | basic, message |
version | niladic | basic, message |
command | niladic1 | basic, value, template |
flag | niladic | basic, value, environment |
single | positional, inline, monadic | basic, value, environment, template, parameter, selection |
array | positional, inline, variadic, delimited, appended | basic, value, environment, template, parameter, selection |
function | positional, inline, configurable | basic, value, environment, template, parameter |
Glossary
The next sub-sections cover some concepts that may be used throughout this page.
Option definition
An option is configured through a definition object, whose properties we shall denote as attributes. Also, in a hierarchical set of definitions, a level constitutes the list of options from the same subcommand or main command.
Option type
The type
attribute of an option definition indicates the type of the option. It is the only required attribute of any option, and is used as a discriminant for determining the available attributes for a specific option.
Option parameters
Each type of option expects a different number of parameters on the command line:
- niladic — no parameter
- monadic — single parameter
- variadic — variable number of parameters
- delimited — values can be delimited with a parameter separator and/or parameter marker
- appended — can be supplied multiple times and have values appended
- configurable — can be configured with a parameter count
- inline — allows parameters to be inlined with option names
Option value
The option value (also called parsed value) appears in the resulting object. Its data type depends on the option type. You can check the effective data type of the values for a set of option definitions by inspecting IntelliSense hints. For example, consider the following script:
const = {
: { : 'help' },
: { : 'flag' },
: { : 'single', : ['one', 'two'] },
: { : 'array', : ['one', 'two'], : { : 1 }, : true },
: { : 'function', : , : null },
: { : 'command', : { : { : 'version' } } },
} as satisfies ;
Hover over the assigned valuesconst = await ();
const = ();
type = <typeof >;
Notice that the properties in the resulting object are readonly
. This is intentional: the parsed values should never be modified, because they reflect the command line. Generally, you can do any necessary transformation inside the parsing callback and return arbitrary values, such as class
instances, which should be enough for most purposes.
A few additional remarks:
- the initial value of any valued option is
undefined
- the final value of any valued option can be
undefined
, unless it is always required or has a default value - if an array option declares a default value that is not an array, that value is converted to a single-element tuple
- help and version options without the save message attribute do not have a value
Option requirements
An option can be configured with requirements, which are specifications of inter-dependencies between options and/or option values in the same definition level.
Option constraints
Non-niladic options can be configured with constraint attributes, which may be of two kinds:
- parameter constraint — a restriction applied to option parameter(s)
- value constraint — a restriction applied to the parsed value(s)
Option supply
An option is considered supplied if it either appears on the command line or has data coming from the environment.
When an option is supplied multiple times, its value gets replaced each time. The only exception is an array option configured with append values.
Attribute classes
This section classifies some attributes according to the subset of option types to which they apply. The options themselves will be explained later in this page.
Basic attributes
All options share a set of attributes in addition to their type. They are described below.
Option names
The names
attribute lists the option names as they may appear on the command line (e.g., -h
or --help
). The following rules apply to option names:
- A name must not contain the equals sign
'='
, since the latter is used as option-parameter separator. - A name should not contain styles, but may contain any other Unicode character (including whitespace) or even be the empty string.
- A name can be
null
, in which case the corresponding name slot will be skipped in the help message.
Names can be omitted if the option may be supplied through positional arguments or the environment.
Preferred name
The preferredName
attribute is used for informational purposes. It is displayed in messages in cases where a name is not available, e.g., when evaluating option requirements or processing positional arguments. If not specified, the first name from option names will be used.
This attribute is not validated, so it can be any string.
Option synopsis
The synopsis
attribute, if present, specifies a brief summary of the option’s purpose. It will be formatted in the help message according to text formatting rules.
Deprecation notice
The deprecated
attribute, if present, specifies the reason for the option being deprecated. It will be formatted in the help message according to text formatting rules.
Note that the library does not provide a deprecation mechanism for specific values within attributes, such as option names, parameter choices or data sources. For that effect, you will have to clarify it in the option synopsis.
Group | hide
The group
attribute, if present, specifies the name of a group under which the option should appear in the help message. If absent, the option will belong to the default group, which is also denoted by the empty string. Alternatively, you can use the value null
to completely hide it from the help message.
Display styles
The styles
attribute, if present, specifies custom styling attributes for each of the option’s help columns. It has the following optional properties:
names
— the style of option namesparam
— the style of option parameterdescr
— the style of option description
Layout settings
The layout
attribute, if present, specifies option-specific help layout settings for presentation in help messages.
Media hyperlink
The link
attribute, if present, specifies the URL of an external resource or media. It will be included in the option’s description in the help message.
Message attributes
Both the help and version options share the attribute described below.
Save message
By default, the option will throw the generated message, as a convenient way for the application to print it in the terminal. However, this behavior can be changed with the saveMessage
attribute. If present, it indicates that the message should be saved as the option value instead of being thrown.
The reason why the library does not itself print the message is to allow client code to choose the output medium. For example, in browser environments, one may want to display the message in a dialog or an embedded terminal instead of printing in the browser console.
Value attributes
All options that may have a value share a set of attributes, which are described below.
Cluster letters
The cluster
attribute, if present, specifies letters that can be used to combine options into a single command-line argument. This feature is also known as short-option style, and can be enabled via the cluster prefix parsing flag.
Cluster letters should not be included in the list of option names, although they share the same restrictions.
Here is an example that illustrates how it works. Suppose we have the following options:
- flag option, with name
'--flag'
and letters'fF'
- single option, with name
'--str'
and letters'sS'
- array option, with name
'--num'
and letters'nN'
Given these definitions, the following invocations would be equivalent:
cli -fSN 'my string' 1 2 3
cli -Fsn 'my string' 1 2 3
And would be transformed into their “canonical” form, i.e.:
cli --flag --str 'my string' --num 1 2 3
Cluster parsing rules
The following rules apply to cluster arguments:
- the order of options in a cluster is preserved when converting to the canonical form
- variadic options and subcommands are supported, but they must come last in a cluster
- if word completion is attempted for a cluster, the default completion message is thrown
- if a nameless positional option appears in a cluster, its argument will be treated as positional
Cluster inline parameters
Cluster arguments may be considered to have inline parameters if they contain at least one unknown letter that is not the first. For example, using the previous definitions, the command line cli -s'my str' -n123
would be parsed as cli --str 'my str' --num 123
.
Notice how the parameters appear “glued” to the cluster letter (i.e., with no intervening space), and they contain characters that are not valid cluster letters. However, the first letter must be valid for the argument to be considered a cluster.
This feature is affected by the inline constraint.
Always required
The required
attribute, if present, indicates that the option is always required, regardless of other options.
Mutually exclusive with default value and conditional requirements.
When using this attribute, we recommend also setting preferred name to some explanatory name.
Forward requirements
The requires
attribute, if present, specifies requirements that must be satisfied if the option is supplied. Its value can be any of the following:
string
— an option key;object
— a record that maps option keys to required values;- an instance of a requirement expression; or
- a requirement callback
An option key means that the referenced option must also be supplied. In the case of a record, every referenced option must have the corresponding value, which can be any value accepted by that option, or one of the special values:
undefined
— to signify presence; ornull
— to signify absence
Options from a subcommand (whether parent or child) cannot be referenced in a requirement. Option keys must always refer to options in the same definition level.
Requirement expression
You can specify requirements as an expression, in which case it is evaluated as follows:
allOf
— an expression that is satisfied when all requirements are satisfiedoneOf
— an expression that is satisfied when at least one requirement is satisfiednot
— an expression that is satisfied when the requirement is not satisfied
Requirement callback
You can specify a custom callback to evaluate requirements. It receives a single parameter containing the parsed values, and should return a boolean
(or a promise thereof) indicating whether the requirements were satisfied. It may perform any kind of verification, such as inspect parsed values, check the environment, etc.
It may also be configured with a custom toString
method, so it can be displayed in messages. For example:
options.flag.requires.toString = () => 'this and that ...';
Conditional requirements
The requiredIf
attribute is reciprocal to the previous one: if present, it specifies requirements that must be satisfied for the affected option to be considered required. It accepts the same kinds of value as the former.
An example might help elucidate the distinction. Suppose we have these requirements:
allOf(
'option1',
oneOf({ option2: null }, not({ option3: [2] })),
(values) => values['option1'] === values['option3'],
);
If they were declared in the requires
attribute, they would mean:
If this option is supplied, then the following must hold true:
option1
must be present AND (option2
must be absent ORoption3
must have a value different than[2]
) ANDoption1
must have the same value asoption3
.
And if they were declared in the requiredIf
attribute, they would mean:
If
option1
is present AND (option2
is absent ORoption3
has a value different than[2]
) ANDoption1
has the same value asoption3
, then this option is considered required and must be supplied.
Mutually exclusive with always required.
Default value
The default
attribute, if present, specifies a value (or a promise thereof) to be used at the end of the parsing loop, in case the option is not supplied.
Mutually exclusive with always required.
Default value callback
In case the default value is not known beforehand, you can use a callback. It receives a single parameter containing the parsed values, and should return the default value (or a promise thereof).
When rendering a help message, the formatter disregards any value returned by the callback, as it may depend on the values parsed from command-line arguments (which are not available when processing the help option). On the other hand, the callback may be configured with a custom toString
method, so it can be displayed in messages, e.g.:
options.flag.default.toString = () => 'this and that ...';
Parsing callback
The parse
attribute, if present, specifies a custom callback to parse the option parameter(s). It receives two parameters:
param
— depends on the option type (see below)info
— the current sequence information
The param
will be of a different kind for each option:
- parsed values — for the command option
- null value — for the flag option
- string value — for the single and array options
- string array — for the function option
The callback should return the parsed value (or a promise thereof). To throw an error from within it, we recommend instantiating the error message class.
You can check whether an option has been supplied before by comparing its value with undefined
. This works because default values and values from the environment are only set at the end of the parsing loop.
Environment attributes
Options that may read data from the environment share some attributes, as described below.
Data sources
The sources
attribute, if present, lists names of environment data sources from which the option value should be read, in case it is not supplied on the command line. Its elements can be either of:
string
— an environment variable; orURL
— the path of a local file (to be used withimport.meta.resolve
)
The reason why we did not use a dedicated env
attribute for environment variables was a design choice: since the sources are tried in the specified order, you can mix the two types of values in order of priority.
This attribute has precedence over standard input.
Variable names should not be included in the list of option names, although they share the same restrictions.
If data is found in a source, the affected option will be considered supplied, which has implications for evaluating option requirements.
Standard input
The stdin
attribute, if present, indicates that the option may read data from the standard input. It only has effect if:
- the option is not supplied; and
- the option pertains to the command or subcommand being executed (i.e., not a parent one); and
- the option is always required; or
- the terminal is non-interactive (i.e., the data comes from a redirected output)
Otherwise, the input stream will remain untouched.
You can omit the option names or hide the option from the help message, if you want its value to be read exclusively from the standard input.
In the case of interactive terminals, the parser will block to wait for new input. If you need more sophisticated handling of interactive terminals, do yourself a favor and use a third-party prompting library in conjunction with a default value callback.
Break loop
The break
attribute indicates whether the parser should exit the parsing loop after returning from a parsing callback.
When setting this attribute, the requirements of all options supplied up to the current argument will be verified. Hence, you should make it clear in the help message that any options required by the affected one must be supplied either before it or through the environment.
Template attributes
Non-niladic options and subcommands share a set of attributes, which are described below.
Example value
The example
attribute, if present, specifies a value to display in place of option parameter(s) in help messages. It will appear in the parameter column and, when a parameter name is not present, in the usage statement as well.
Parameter name
The paramName
attribute, if present, specifies a name to to display in place of option parameter(s) in help messages. It will appear in the usage statement and, when an example value is not present, in the parameter column as well.
Overrides example value in usage statements.
Usage parameter name
The usageParamName
attribute, if present, specifies a name to to display in place of option parameter(s), but only in a usage statement. It does not appear in the parameter column.
Overrides example value and parameter name in usage statements.
Parameter attributes
Non-niladic options share a set of attributes, which are described below.
Positional
The positional
attribute, if present, indicates that the option accepts positional arguments. An argument is considered positional if it is not recognized as an option name or is supplied through the positional marker.
If there are multiple positional options, their declaration order determines their relative position in the command line. A variadic option will take all remaining positional arguments. Otherwise, if there are more arguments than options, the last such option will take the excess.
When using this attribute, we recommend also setting preferred name to some explanatory name.
You can assign a unique group to positional options and declare them first in the definitions, so as to highlight them in the help message.
Inline constraint
The inline
attribute, if present, indicates the option’s treatment of inline parameters. Its value can be either of:
false
— to disallow inline parameters;'always'
— to require inline parameters; orobject
— a record that maps option names to one of the above, indicating the constraint for specific names
By default, parameters are allowed (but not required) to be inlined with any option name.
Completion callback
The complete
attribute, if present, specifies a custom callback for word completion, which can be used to make better suggestions than the built-in algorithm would for the option. It receives two parameters:
param
— the word being completedinfo
— the current sequence information
It should return the list of completion words or suggestions (or a promise thereof). If an error is thrown, it will be ignored and the default completion message will be thrown instead.
Parameter marker
The marker
attribute, if present, specifies marker(s) to delimit the option parameters. It has the same semantics as the positional marker, except that it does not appear in help messages and the parameters are not treated as positional.
This attribute is not available for the single option.
Marker(s) should not be included in the list of option names, although they share the same restrictions.
Here is an example that illustrates how it works. Suppose we have the following option:
const = {
: {
: 'array',
: ['-a'],
: ['[', ']'],
},
} as satisfies ;
Given these definitions, the following invocations would be equivalent:
cli -a abc 1 2 3
cli [ abc 1 2 3
cli [ abc 1 2 3 ]
However, the last two invocations would allow passing option names as parameters (e.g., '-a'
), whereas the first would not. Additionally, the last invocation would allow more arguments to come after.
Selection attributes
Both the single and array options can have additional parameter constraints, for which they share the set of attributes described below.
Regular expression
The regex
attribute, if present, specifies a regular expression that the option parameter(s) should match. A parameter that does not match the regex (after applying any configured normalization) will cause an error to be raised.
Mutually exclusive with parameter choices.
Parameter choices
The choices
attribute, if present, specifies string values that the option accepts as parameter(s). A parameter that does not match any of these values (after applying any configured normalization) will cause an error to be raised. These values are also considered by the completion algorithm when a parameter is being completed.
Mutually exclusive with regular expression.
Parameter mapping
The mapping
attribute, if present, specifies a record that maps parameter values to option values. In this case, if a parameter matches one of the given keys (after applying any configured normalization), it will get mapped to the corresponding value; otherwise it will be forwarded to the parsing callback, if one is specified.
Parameter normalization
The normalize
attribute, if present, specifies a normalization function to be applied to parameters before they get validated and/or parsed. This includes parsing of option parameters and performing word completion.
Niladic options
Niladic options do not expect any parameter on the command line.
Help option
The help option uses the formatter to generate a help message. Internally, it calls the format
function with the provided configuration, obtains the formatted message and throws it. The application is responsible for catching this message and printing it in a terminal.
When word completion is in effect, this option will be skipped.
This option has the following sets of attributes: basic, message and the ones described below.
Help sections
The sections
attribute specifies help sections to be rendered in the help message. By default, a single groups section is included.
Enable subcommand
The useCommand
attribute, if present, indicates that the option may use the next argument as the name of a subcommand for which the message should be generated. For example, the following invocations would be equivalent:
cli --help cmd
cli cmd --help
And would throw the help of the cmd
subcommand, if it exists.
If a subcommand with the specified name does not exist or does not have its own help, the argument may still be subject to enable option filter.
Enable option filter
The useFilter
attribute, if present, indicates that the option may use the remaining arguments as option filter. If enabled, an invocation like cli --help flag
would only include options whose names, synopsis or environment variable names contain the pattern flag
(case-insensitive).
This feature can be combined with enable subcommand. For example, the following invocations would be equivalent:
cli --help cmd -f
cli cmd --help -f
And would throw the help message of the cmd
subcommand, filtered by option -f
.
Version option
The version option throws a version message. The application is responsible for catching this message and printing it in a terminal.
When word completion is in effect, this option will be skipped.
This option has the following sets of attributes: basic, message and the one described below.
Version info
The version
attribute, if present, specifies the version information. Its value is supposed to be a semantic version, but can be any kind of unstructured text data and is not interpreted or validated.
You can get the version
field from a JSON module through the getVersion
function.
Command option
The command option, also known as subcommand, can be configured with a set of option definitions for which the remaining arguments should be parsed. It will forward the parsed values to the parsing callback and subsequently break the parsing loop.
The option value will be either the result of the callback, if one is specified, or the parsed values themselves. Values of ancestor commands (i.e. non-immediate parents) cannot be accessed from within the callback. For this purpose, you will need to wait until the parsing procedure returns.
When word completion is in effect, the callback will not be called, since completion will have occurred before it has a chance to execute.
This option has the following sets of attributes: basic, value, template and the ones described below.
Nested options
The options
attribute, if present, specifies a set of option definitions for the subcommand. Its value can be either of:
object
— a record containing the option definitions (or a promise thereof); or- a callback that returns the option definitions (or a promise thereof)
A callback is useful for various reasons, but especially because it allows:
- the implementation of recursive commands
- the use of a dynamic import
In either case, the callback is only evaluated once the affected option is parsed from the command line.
Remaining arguments will be parsed according to the definitions from this attribute, not from the parent command. Hence, you should make it clear in the help message that all arguments pertaining to the subcommand must be supplied either after it or through the environment.
Cluster prefix
The clusterPrefix
attribute, if present, indicates whether the subcommand accepts cluster arguments. It must be used in conjunction with the cluster letters of the nested options.
This attribute is analogous to the cluster prefix parsing flag, and has precedence over the attribute below.
Option prefix
The optionPrefix
attribute, if present, specifies the prefix for option names within the subcommand. If set, then arguments starting with this prefix will be considered an option name, regardless of their position respective to other arguments in the command line.
This attribute is analogous to the option prefix parsing flag.
Flag option
The flag option accepts no parameter, but has a value that will be either the result of the parsing callback, if one is specified, or true
. The callback receives the value null
as its first parameter.
If you need a boolean-valued option that accepts a single parameter, use the single option instead. To make the parameter optional, use the function option with a parameter count of [0, 1]
.
This option has the following sets of attributes: basic, value and environment.
Old library versions provided an attribute to indicate alternate option names to turn the option value false
(e.g., —no-flag). This can now be achieved by inspecting the name
property of the sequence information.
Non-niladic options
Non-niladic options accept one or more parameters on the command line.
Single-valued option
The single option accepts a single parameter. Its value can be either the result of the parsing callback, one of the parameter choices, one of the parameter mapping values or the parameter itself (by default).
The callback receives the option parameter as its first parameter, and should return the parsed value.
This option has the following sets of attributes: basic, value, environment, template, parameter and selection.
Array-valued option
The array option accepts multiple (zero or more) parameters. Its value is an array whose elements can be either the result of the parsing callback, one of the parameter choices, one of the parameter mapping values or the parameters themselves (by default).
The callback receives a single option parameter as its first parameter, and should likewise return the parsed value of a single array element. The resulting array may be subject to value constraints.
This option has the following sets of attributes: basic, value, environment, template, parameter, selection and the ones described below.
Parameter separator
The separator
attribute, if present, specifies a delimiter by which to split the option parameters. It can be either a string or a regular expression.
When not using this attribute, we recommend setting the inline constraint to false
.
Remove duplicates
The unique
attribute, if present, indicates that duplicate elements will be removed from the option value. This normalization is applied before checking the element count limit. The remaining elements are left in the order in which they were parsed.
Append values
The append
attribute, if present, indicates that the option allows appending elements to its value when supplied multiple times. Any duplicates are removed after appendage, if enabled.
Element count limit
The limit
attribute, if present, indicates the maximum allowed number of elements. Any argument sequence that causes the array length to exceed the given limit (after removing any duplicates) will cause an error to be raised.
Function option
The function option exists for the sole purpose of being configured with an expected parameter count, and is the only option that can accept between zero and one parameter. Its value will be either the result of the parsing callback, if one is specified, or the parameters themselves.
The callback receives the list of option parameters as its first parameter, and should return the parsed value. As a special case, this list may contain all the remaining command-line arguments (see parameter count below).
This option has the following sets of attributes: basic, value, environment, template, parameter and the ones described below.
Parameter count
The paramCount
attribute, if present, specifies the number of parameters that the option expects on the command line. Its value can be either of:
- unspecified or
Infinity
— the option accepts unlimited parameters; - zero — the option accepts unknown number of parameters (see below);
- positive — the option expects exactly this amount; or
- range — the option expects between a minimum and a maximum count
In case of a numeric range, the minimum should be strictly less than the maximum, but not less than zero. In the special case of zero, the parsing callback will receive a copy of all remaining command-line arguments. This feature should be used in conjunction with the skip count attribute.
If the data comes from the environment, then the callback will receive a single-element tuple as parameter, which may be less than the expected count. To check if this is the case, you should inspect the index
property of the sequence information, which should have the value NaN
.
Note that this option cannot have a parameter separator, since it would conflict with the parameter count. To see why, consider the case with a minimum count of 2. Then, the second subsequent argument would always be treated as a parameter, regardless of whether it is an option name, even if the previous argument had two or more delimited parameters. This is because the parser does not look for delimiters when forming an argument sequence.
Skip count
The skipCount
attribute indicates the number of remaining arguments to skip, after returning from the parsing callback. This value is meant to be changed by the callback, and only works when the parameter count is zero.
It is useful in cases where the number of parameters is not known beforehand, and the callback wants to have control over where an argument sequence ends. Note that this is different from unlimited parameters, where the parser must detect the end of a sequence based on the occurrence of option names in the command line.
Here is an example of how it might be used inside the callback:
{
// other attributes...
parse(params) {
const index = params.findIndex((val) => !val.startsWith('{')); // find first non-JSON param
const count = index >= 0 ? index : params.length; // count how many there are
this.skipCount = count; // <<-- tell the parser to skip them
return params.slice(0, count).map((val) => JSON.parse(val)); // return the parsed values
},
}
When word completion is in effect, the last argument will be the word to complete. If the latter pertains to the current sequence, you can throw a completion message from the callback. (See also the completing
property of the sequence information.)
Footnotes
-
Rather than accepting parameters, it starts a new parsing context with the remaining arguments. ↩