Skip to Content
Nextra 4.0 is released 🎉

Parser

The parser module handles parsing of command-line arguments. It provides functions that accept a set of option definitions and parse arguments into option values. They may also produce error messages, which can be customized via message configuration.

Option values

The result of argument parsing is a record containing one option value for each option. There are two ways to obtain these values, as explained below.

Obtaining a fresh object

The parse function returns a promise that resolves to a frozen  object containing the option values. It accepts the following parameters:

  • options — the option definitions (required)
  • cmdLine — the command line or list of command-line arguments (optional)
  • flags — an object containing the parsing flags (optional)

Normally you can leave the optional parameters undefined, as they have sensible default values. The command line defaults to the value of either the COMP_LINE or BUFFER environment variables (whichever is present) or to the process arguments:

process.env['COMP_LINE'] ?? process.env['BUFFER'] ?? process.argv.slice(2);

If you feel the need to configure the parsing procedure, make sure to first understand how word completion works.

Using an existing object

The parseInto function is more flexible, as it allows you to pass an existing object or class instance, which will be filled with the parsed values. It accepts the same parameters as the previous one, except for an additional parameter:

  • values — the option values to parse into (required)

Existing values are preserved until they get overridden by the parsing procedure. When using TypeScript, this object will be type-checked against the expected type of option values for a given set of definitions. You can use the valuesFor function to create an object for just this purpose.

This function returns a promise that resolves to a ParsingResult object containing the following property:

  • warning — a list of warnings encountered in the parsing procedure, if any

Parsing flags

The parsing procedure can be configured via a ParsingFlags object that has some optional properties, as described below.

Program name

The programName property is a custom name for the main command. It may be used in two places: the process title and in usage statements. It defaults to the basename of the executing script, and can be suppressed by setting it to an empty string.

This flag is ignored when word completion is in effect.

Completion index

The completionIndex property is the cursor position in a command line for which the user pressed <Tab>. It defaults to the value of the COMP_POINT or CURSOR environment variables, or to the length of the BUFFER variable (whichever is present, otherwise undefined):

Number(process.env['COMP_POINT'] ?? process.env['CURSOR']) || process.env['BUFFER']?.length;

When invoking the parsing procedure with a raw command line, and this flag is set, the parser will perform word completion for the argument overlapping this position.

Cluster prefix

The clusterPrefix property specifies the prefix for cluster arguments. If set, then eligible arguments starting with this prefix may be considered a cluster. This must be used in conjunction with the cluster letters attribute.

Option names have precedence over the cluster prefix. For example, if the prefix is a single dash and there is an option named '-flag', then arguments matching this name will not be considered a cluster. On the other hand, the cluster prefix has precedence over the option prefix.

💡

The prefix can be the empty string, in which case it behaves similarly to GNU’s tar command.

Option prefix

The optionPrefix property specifies the prefix for option names. 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.

Standard input symbol

The stdinSymbol property specifies a symbol for the standard input (for informational purposes). If not present, the standard input will not appear in usage statements.

Positional marker

The positionalMarker attribute, if present, specifies the marker(s) to delimit positional arguments. If set, then all arguments appearing after or within the marker(s) will be considered positional. Its value can be either of:

  • string — a starting marker (e.g. '--')
  • pair of string — starting and ending markers

The starting marker has precedence over option names and parameter marker. It is also considered by the completion algorithm, although the ending marker is not. Both markers may appear in usage statements.

Similarity threshold

The similarity property indicates the similarity threshold for option name suggestions in case of an unknown option error. Values are given in percentage (e.g., 0.6). Zero or NaN means disabled.

This is different from completion suggestions.

Formatting function

The format property specifies the formatting function for help messages. Use the format function.

Injection is necessary for tree-shaking of the formatter component.

Parsing features

The set of features supported by the parser are described below.

Custom callbacks

Custom parsing operations are supported through the following types of callbacks:

All of these can be asynchronous, in which case the parser awaits their resolution, either because it needs the result or to avoid data races when reading and modifying the option values.

Note that there is no synchronous version of the parsing procedure. This is a design choice: in order to support a fully synchronous parse function using the same code base, the parser would have to deal with returned promises in a way that would make it hard to maintain — remember the classic callback hell .

Besides, the asynchronous version has the benefit of allowing us to perform some operations, such as requirements checking, concurrently. This should not be a drawback for most applications, since argument parsing is usually done at the top-level of a module or script, where the await primitive is readily available.

Argument sequence

An argument sequence is the occurrence of an option in the command line with possible parameters. To determine the start and end of a sequence, the parser looks for option names or positional arguments once it finishes parsing the previous option, or if the latter is variadic.

For example, if the option initiating a sequence is array-valued, the parser starts looking for a new option as soon as it advances to the next argument, since that may be either an option parameter or the start of a new sequence.

The same is true for variadic function options. For example, if the option expects between 1 and 3 parameters, the parser treats the next argument as a parameter to the option, regardless of whether it is an option name. Once the first parameter is saved, the parser resumes searching for options until 3 parameters are accumulated, after which it must find an option specification (even if it is a new occurrence of the same option).

Sequence information

The information gathered by the parser is saved in an object that is passed as parameter to some of the custom callbacks. It contains details about the current argument sequence in the parsing loop, as described below.

The command line may change from its original form due to parsing. More specifically, cluster arguments are canonicalized and the positional marker is removed.

Parsed values

The values property holds the previously parsed values. It it passed as an opaque object and should be cast to OptionValues<typeof your_options>.

Sequence index

The index property specifies the starting index of the sequence. It will point to one of the following:

Sequence position

The position property specifies the sequence number relative to positional arguments (1-based), or NaN if it is not positional.

Option name

The name property specifies the option name. It can be either of:

Completion flag

The completing property indicates whether word completion is in effect.

Only available for the parsing callback.

Previous parameters

The prev property holds the option parameters preceding the word being completed, if any.

Only available for the completion callback. Will be empty for single-valued options.

Word completion

Quoting the Bash docs :

When word completion is attempted for an argument to a command for which a completion specification (a compspec) has been defined using the complete builtin (see Programmable Completion Builtins), the programmable completion facilities are invoked.

The parser does not use the completion facilities, because it relies on the raw command line and the cursor position into that line, which can be retrieved from the following environment variables:

  • COMP_LINE or BUFFER — the current command line
  • COMP_POINT or CURSOR — the index of the cursor position relative to the beginning of the command line

When these variables are available, the parser enters into completion mode: it truncates the command line at the cursor position and performs completion of the last argument. The result is either a text message or a JSON message, which should be printed in the terminal so that the completion builtins can perform the final completion step.

Completion algorithm

The completion algorithm implemented by the library is explained below. In what follows, comp is the word being completed, i.e., the command-line argument ending at the completion index (it may be an empty string):

  1. If comp is expected to be an option name:
    • If comp is a known option name, that name is returned; else
    • If there is no positional option, the available option names are filtered by the prefix comp and returned; else
    • comp is treated as a parameter of the positional option; go to step 2
  2. Else, comp is the parameter of a non-niladic option. Then, either of the following is executed and its result combined with that of step 3:
  3. If the option was supplied neither through the positional marker nor as an inline parameter, then, if either of the following holds true, the available option names are filtered by the prefix comp and returned:
    • It is the first argument in a sequence of positional arguments; or
    • It is not short of the minimum expected parameter count of an option

If all of the above results in an empty list, the default completion (usually file completion, if enabled) will be attempted by the completion engine.

Altered parsing behavior

Since completion builtins always expect a word list as a result, the parser must suppress all errors that occur in the parsing procedure until completion is done. Furthermore, it does not make sense to perform some operations that may throw errors. Therefore, when completion is in effect, the parsing behavior changes in the following ways:

💡

Other arguments are processed as usual, which means that a completion callback can inspect the previously parsed values, in order to make better suggestions based on those values.

If an error is thrown by a completion callback, the default completion message will be thrown instead.

Completion suggestions

Depending on the value of the COMP_JSON environment variable, the parser may emit an enhanced version of completion words, called suggestions. They are produced as an instance of the JSON message. From the parser perspective, a suggestion is a ParserSuggestion object with the following properties:

  • name — the suggestion name (or the value used for traditional shell completion)
  • type — the type of argument being suggested (either the option type, 'parameter', or 'marker' for the positional marker)
  • synopsis — the option synopsis, if any
  • displayName — the supplied option name, in case the suggestion pertains to an option parameter

From the client code perspective, suggestions are the result of a completion callback. Each of which can be a plain string or an object extending ICompletionSuggestion. It will be injected with the above properties by the parser, but overridden by client properties. We recommend extending the Suggestion type from autocomplete-types .

Requirements checking

When the parser evaluates option requirements, it compares an option value against any value required by other options. Generally, this analysis is performed after all arguments have been parsed, but it may be performed in two additional situations:

As has been mentioned previously, requirements are not checked when word completion is in effect.

Name suggestions

When the parser expects an option name and the current argument is not a valid one (and there is no positional option), it may select option names that are similar to the current argument using the Gestalt  algorithm, and include them in the error message.

Inline parameters

An option parameter may be passed on the command line using the syntax <name>=<param>. In the case of array options, the parameter can also be a series of values delimited with a separator.

This syntax cannot be used with the positional marker or parameter marker.

As is the case with standalone parameters, inlined ones do not conflict with option names, and so they may contain any number of equals signs. They may even start with one (e.g., -opt=='my val' would be parsed as '=my val').

Cluster arguments may also have inline parameters, but their syntax is different. A cluster argument is considered to have an inline parameter if it contains an unknown letter that is not the first one in the cluster. In this case, the first letter must correspond to an option and the rest to its parameter. See cluster inline parameters for further details.

Process title

The process title will be updated to reflect the command being executed. This includes the main script and any subcommands. For example, if the command line is:

path/to/main/script.js -flag0 cmd1 -flag1 cmd2 args...

The process title would be updated in the following way:

  1. node — the starting title, before any updates
  2. node script.js — at the beginning of the parsing loop
  3. node script.js cmd1 — as soon as the cmd1 subcommand is parsed
  4. node script.js cmd1 cmd2 — as soon as the cmd2 subcommand is parsed

The title will remain in changed state after the parsing procedure returns.

Other option names are not used, not only because they would pollute the output of process management utilities (such as Linux’s ps), but also because the process title reflects the current value of program name, which appears in usage statements.

Last updated on