Argparse module

A small, declarative argument parser for console commands, in the shape of Python's argparse.

A parser both reads a command's arguments and offers completions for them, from one declaration. Every command written with trx.console.register has one; a command shapes it through the trx.console.register.spec.args function it hands over, and trx.console.register.spec.run then receives a table of parsed values. A command that shapes nothing takes no arguments, and is told so when given one.

Every parser answers -h and --help on its own, printing what it accepts.

How a positional reads a token is its matcher: a type to coerce to, a set of choices, or a function of its own. These do not combine on one positional; a value that is a number or a name is two matchers, declared with trx.argparse.Parser:any_of.

Positionals are read in order, and an optional one a token does not fit is passed over: the token goes to the next positional, and the one skipped stays nil. That is what lets a command take a leading argument it can also be used without - a verb before a value, a count before a name. Completion follows the same path, so a slot offers what every argument reachable from it takes. A token nothing takes is reported against the first argument that refused it.

A choice is either a bare string, where the key and value are the same, or a { key, value } pair, where the key is matched and shown and the value is what trx.argparse.Parser:parse gives back. Matching is forgiving, through trx.strings.fuzzy_match.

Structures

  • trx.argparse.Parser

    An argument parser, built up a call at a time. Every method hands the parser back, so the calls chain.

    Methods:

    • parser:any_of(name, alternatives, [opts])
      Adds a positional whose value is the first of several matchers to take the token, for an argument that is a number or a name.

      Parameters:

      • name (string). What the parsed value is keyed by.

      • alternatives (a list of table). The ways the token may read, tried in order.

        Each entry:

        • type (string, optional). As for positional.
        • choices (any, optional). As for positional.
        • match (function, optional). As for positional.
        • metavar (string, optional). Names this alternative, which earns it a line of its own in the help.
        • help (string, optional). What this alternative is for.
      • opts (table, optional). How the argument behaves.

        Keys:

        • optional (boolean, optional). Lets the argument be left out.
        • greedy (boolean, optional). Reads the rest of the line as one token, so a value with spaces in it still arrives whole.
        • metavar (string, optional). What the argument is called in messages and in the synopsis. Its own name by default.
        • suggest (function, optional). Completions to offer, without restricting what is accepted or being shown in errors. For a free value with a long list behind it, like a setting name.
        • help (string, optional). What the argument is for, shown in the help.

      Returns: trx.argparse.Parser. The same parser, so declarations chain.

    • parser:complete([text], [caret])
      The candidate completions for the token the caret sits in. Matching is against the text before the caret.

      Parameters:

      • text (string, optional). The line so far.
      • caret (integer, optional). Where the caret sits, as a byte offset. The end of the line by default.

      Returns:

      • a list of string. The best match comes first.
      • integer. Where the run they replace starts. The run is the token, or the whole tail a greedy argument swallows; in whitespace it is empty, at the caret.
      • integer. Where that run ends.
    • parser:flag(name, [opts])
      Adds a boolean flag, which may sit anywhere in the line.

      Parameters:

      • name (string). What the parsed value is keyed by. help is reserved.

      • opts (table, optional). How it is spelled and what it is for.

        Keys:

        • short (string, optional). The short spelling, such as "-f".
        • long (string, optional). The long spelling, such as "--force".
        • help (string, optional). What the flag is for, shown in the help.

      Returns: trx.argparse.Parser. The same parser, so declarations chain.

    • parser:format_error(err)
      Turns what a refused line reported into a localized line naming what was wrong and what was expected.

      Parameters:

      • err (table). What parse handed back.

      Returns: string. The line, ready to print.

    • parser:parse([args])
      Reads an argument line. A value carried by a { key, value } choice comes back as its value, and -h/--help comes back as { help = true }.

      Parameters:

      • args (string, optional). The line as the player typed it.

      Returns:

      • table or nil. The values, keyed by argument name, or nil where the line was refused.
      • table or nil. What was wrong, for format_error to put into words.
    • parser:positional(name, [opts])
      Adds a positional argument, read one way.

      Parameters:

      • name (string). What the parsed value is keyed by.

      • opts (table, optional). How it reads its token, and how it behaves. It reads a token one way: name at most one of opts.type, opts.choices and opts.match, and use any_of for several.

        Keys:

        • type (string, optional). Coerce the token: "integer", "number", "string" or "boolean".
        • choices (any, optional). The allowed set: a list of values, or a function of the values parsed so far returning one. The token must match one; the set is shown in errors and completes.
        • match (function, optional). A function of the token and the values parsed so far, returning the value and whether it took, for a shape of its own.
        • optional (boolean, optional). Lets the argument be left out.
        • greedy (boolean, optional). Reads the rest of the line as one token, so a value with spaces in it still arrives whole.
        • metavar (string, optional). What the argument is called in messages and in the synopsis. Its own name by default.
        • suggest (function, optional). Completions to offer, without restricting what is accepted or being shown in errors. For a free value with a long list behind it, like a setting name.
        • help (string, optional). What the argument is for, shown in the help.

      Returns: trx.argparse.Parser. The same parser, so declarations chain.

    • parser:rest(name, [opts])
      Adds an argument taking the rest of the line from here on, verbatim as one string, or nil where an optional one is absent. Always the last argument.

      Parameters:

      • name (string). What the parsed value is keyed by.

      • opts (table, optional). How the argument behaves.

        Keys:

        • optional (boolean, optional). Lets the argument be left out.
        • greedy (boolean, optional). Reads the rest of the line as one token, so a value with spaces in it still arrives whole.
        • metavar (string, optional). What the argument is called in messages and in the synopsis. Its own name by default.
        • suggest (function, optional). Completions to offer, without restricting what is accepted or being shown in errors. For a free value with a long list behind it, like a setting name.
        • help (string, optional). What the argument is for, shown in the help.

      Returns: trx.argparse.Parser. The same parser, so declarations chain.

    • parser:usage()
      A short description of what the command accepts.

      Returns: string. The synopsis, and a line per argument.

Functions

  • trx.argparse.new([spec])
    Creates an argument parser.

    Parameters:

    • spec (table, optional). What the parser calls itself in messages.

      Keys:

      • prog (string, optional). The command word.
      • description (string, optional). What the command does.

    Returns: trx.argparse.Parser. A parser, with no arguments declared on it yet.

    Example:

    local p = trx.argparse.new({ prog = "weather" })
    p:positional("state", { choices = { "snow", "rain", "none" } })
    local parsed = p:parse("snow")  -- { state = "snow" }