6.1. kink/ARGV_PARSER

Parses command line arguments, org argv, into option switches, option arguments, and non-option elements. Parsing is done in the style of glibc getopt_long.

Example

# filename: voxxx.kn

:ARGV_PARSER.require_from('kink/')
:PROCESS.require_from('kink/')

:parse_argv <- {(:Argv)
  :Depot = new_val('Loglevel' 'ERROR')
  :Non_opts = ARGV_PARSER.parse(Argv){(:P)
    P.no_arg(['-h' '--help']){
      stdout.print_line('USAGE: kink voxxx.kn [Options...] [--] [Args...]')
      PROCESS.exit(0)
    }
    P.req_arg(['-L' '--loglevel']){(:Arg)
      Depot:Loglevel <- Arg
    }
    P.on_error{(:Msg)
      stderr.print_line('voxxx: {}'.format(Msg))
      PROCESS.exit(64)
    }
  }
  [Depot.Loglevel Non_opts]
}

:main <- {(:Argv)
  [:Loglevel :Non_opts] = parse_argv(Argv)
  stdout.print_line('loglevel={} non-option-elements={}'.format(Loglevel Non_opts.repr))
}

# $ kink voxxx.kn --log INFO foo bar
# loglevel=INFO non-option-elements=["foo" "bar"]
#
# $ kink voxxx.kn --LDEBUG foo bar
# loglevel=DEBUG non-option-elements=["foo" "bar"]
#
# $ kink voxxx.kn foo bar
# loglevel=ERROR non-option-elements=["foo" "bar"]
#
# $ kink voxxx.kn --help
# USAGE: kink voxxx.kn [Options...] [--] [Args...]

Option switches

There are two types of option switches:

• short switch: consists of leading `-` and one other code point, excluding `--`. Ex. `-h`

• long switch: consists of leading `--` and one or more code points. The switch must not include `=`. Ex. `--help`

Each option switch can be grouped to three categories depending on how it takes an argument.

• req_arg: takes one option argument

• opt_arg: takes zero or one option argument

• no_arg: takes no option argument

An argv element consisting of two hyphens `--` is not an option switch, but can be used as a separator between options and non-option elements.

Short req_arg option switch

Assume a short req_arg switch `-p` is defined. This option switch can be used in the following ways.

• -pkink/ → option argument = `kink/`

• -p kink/ → option argument = `kink/`

Long req_arg option switch

Assuem a long req_arg switch `--prefix` is defined. This option switch can be used in the following ways.

• --prefix=kink/ → option argument = `kink/`

• --prefix kink/ → option argument = `kink/`

The option switch can be abbreviated like `--pat`, `--pa`, or `--p`, if it is not ambiguous. See the later section for details.

Short opt_arg option switch

Assume a short opt_arg switch `-b` is defined. This option switch can be used in the following ways.

• -b4096 → option argument = `4096`

• -b → option argument = an empty string ``

Long opt_arg option switch

Assume a long opt_arg switch `--buffer` is defined. This option switch can be used in the following ways.

• --buffer=4096 → option argument = `4096`

• --buffer → option argument = an empty string ``

Short no_arg option switch

Assume a short no_arg switch `-h` is defined. This option switch can be used in the following way.

• -h

When there is one or more code points after the option switch, the following code points are handled as separate options. For example, if no_arg option switches `-x` and `-z` are defined, and a req_arg switch `-f` is defined, argv `-xzf./archive.tgz` is parsed as follows:

• -x with no option argument

• -z with no option argument

• -f with option argument `./archive.tgz`

Long no_arg option switch

Assume a long no_arg switch `--help` is defined. This option switch can be used in the following way.

• --help

Abbreviation of long option switches

A long option switch can be abbreviated to its prefix when it is not ambiguous. For example, if long options switches `--verbose` and `--version` are defined, they can be abbreviated as follows:

• --verbose: --verbos, --verbo, --verb

• --version: --versio, --versi, --vers

The exact match always takes precedence over abbreviation. For example, if long option switches `--time` and `--time-style` are defined, argv `--time` is parsed as the option switch `--time`, rather than abbreviation of `--time-style`.

Non-option elements

Argv elements which are neither option switches, option arguments, nor separator `--` are non-option elements.

Two hyphens `--` can be used to separate between options and non-option elements. For example, if no_arg switches `-x`, `-y`, and `-z` are defined, argv `-x -y -- -z a b c` is parsed as follows:

• options: -x, -y

• non-option elements: -z, a, b, c

If strict_order mode is not specified, options can appear after non-option elements. For example, if no_arg switches `-x`, `-y`, and `-z` are defined, argv `-x a b c -y -z` is parsed as follows:

• options: -x, -y, -z

• non-option elements: a b c

If strict_order mode is turned on, all the elements after the first non-option element are parsed as non-option elements. This corresponds to the behavior of getopt_long when POSIXLY_CORRECT is set. For example, if no_arg switches `-x`, `-y`, and `-z` are defined, argv `-x a b c -y -z` is parsed as follows:

• option: -x

• non-option elements: a, b, c, -y, -z

Difference from getopt_long

1. getopt_long assumes argv[0] is the name of the program, while ARGV_PARSER handles the arguments after the program name.

2. getopt_long has a feature to handle `-W foo` as `--foo`, while ARGV_PARSER has no such feature.

6.1.1. ARGV_PARSER.parse(Argv ...[$config={}])

`parse` method parses `Argv` into options and non-option elements, as configured by $config.

If the parsing completes without an error, `parse` tail-calls the success continuation (see C.on_success) with a `vec` of `str` values of non-option elements.

If the parsing results in an error, `parse` tail-calls the error continuation (see C.on_error) with a `str` value of the error message.

Precondition

`Argv` must be a `vec` of `str` values.

$config must be a function which takes a `argv_parser_config`.

6.1.2. type argv_parser_config

`argv_parser_config` is a config value of ARGV_PARSER.parse.

6.1.2.1. C.req_arg(Switches $action)

`req_arg` method defines req_arg option switches in `Switches`.

When an option switch in `Switches` is parsed, $action is called with a `str` value of the corresponding option argument.

Preconditions

`Switches` must be a `vec` of `str` values which are long or short option switches.

`Switches` must not be empty.

Option switches must be unique within an invocation of ARGV_PARSER.parse.

$action must be a function which takes a `str`.

6.1.2.2. C.opt_arg(Switches $action)

`opt_arg` method defines opt_arg option switches in `Switches`.

When an option switch in `Switches` is parsed, $action is called with a `str` value of the corresponding option argument. If the option argument is omitted, an empty `str` is passed to $action.

Preconditions

`Switches` must be a `vec` of `str` values which are long or short option switches.

`Switches` must not be empty.

Option switches must be unique within an invocation of ARGV_PARSER.parse.

$action must be a function which takes a `str`.

6.1.2.3. C.no_arg(Switches $action)

`no_arg` method defines no_arg option switches in `Switches`.

When an option switch in `Switches` is parsed, $action is called with no arg.

Preconditions

`Switches` must be a `vec` of `str` values which are long or short option switches.

`Switches` must not be empty.

Option switches must be unique within an invocation of ARGV_PARSER.parse.

$action must be a thunk.

6.1.2.4. C.strict_order

`strict_order` method specifies that parsing is done in strict_order mode.

This corresponds to setting POSIXLY_CORRECT to getopt_long.

6.1.2.5. C.on_success($success)

`on_success` specifies that $success be used as the success continuation of ARGV_PARSER.parse.

If `on_success` is not called, VAL.identity is used as the default.

Precondition

$success must be a function which takes a `vec` of `str` values, which are non-option elements of argv.

6.1.2.6. C.on_error($error)

`on_error` specifies that $error be used as the error continuation of ARGV_PARSER.parse.

If `on_error` is not called, `raise` is used as the default.

Precondition

$error must be a function which takes a `str` value, which is an error message.