Search results

There are no results.

std.optparse

Parsing of command-line options and arguments.

This module provides an opinionated and lightweight command-line argument and option, inspired by getopts, with full support for Unicode options.

Both short and long options are supported, using the syntax -o and --option for short and long options respectively. Long option pairs (--option=value) are also supported. Short option pairs (-o=v) are parsed such that the value includes the =, so -o=v is parsed the same way as -o "=v". There are no plans to support parsing these in such a way that the value doesn't include the = (i.e. parsing -o=v as -o v).

Short option names are restricted to single extended grapheme clusters ("characters"), meaning -foo isn't a valid option. Long option names must contain at least two characters, so --h isn't a valid option.

The optparse module supports parsing -- as an argument. Upon encountering this argument, all arguments that follow are kept as-is. This allows passing these arguments to subcommands or other processes.

Usage

The Options type is used to define options, using the methods Options.flag for flags (e.g. -h/--help), Options.single for options that require a single value (e.g. --config=foo.json), and Options.multiple for options that accept multiple values (e.g. --include=foo --include=bar).

Once your options are defined, you can parse a list of arguments (e.g. the return value of std.env.arguments) into a Matches type using Options.parse:

import std.env
import std.optparse (Options)

class async Main {
  fn async main {
    let opts = Options.new

    opts.flag('h', 'help', 'Show this help message')

    let matches = opts.parse(env.arguments).get
  }
}

Using Matches.contains? you can check if an option is specified, using either the short or long name. Matches.value returns the first argument of an option (provided it accepts arguments), while Matches.values returns all the arguments specified. Any remaining arguments are stored in Matches.remaining.

By default, Options parses any options it encounters and will throw an error for any invalid options. The option Options.stop_at_first_non_option can be used to customize this behaviour: when set to true, the first value encountered that isn't an option argument results in it and any arguments that follow it being stored in Matches.remaining:

import std.env
import std.fmt (fmt)
import std.optparse (Options)
import std.stdio (STDOUT)

class async Main {
  fn async main {
    let opts = Options.new

    opts.flag('h', 'help', 'Show this help message')
    opts.stop_at_first_non_option = true

    let matches = opts.parse(env.arguments).get

    STDOUT.new.print(fmt(matches.remaining))
  }
}

When run with the command-line arguments ['foo', '--bar'], instead of producing an error (or panic in the case of this example, due to the get), the output is ['foo', '--bar']. This is useful if you want to support subcommands with their own options, using the syntax root-command --root-option [...] sub-command --sub-option [...].

Help messages

Help messages are generated using the Help type:

import std.env
import std.fmt (fmt)
import std.optparse (Help, Options)
import std.stdio (STDERR, STDOUT)
import std.sys

class async Main {
  fn async main {
    let opts = Options.new

    opts.flag('h', 'help', 'Show this help message')
    opts.single('c', 'config', 'PATH', 'Use a custom configuration file')
    opts.multiple('i', 'include', 'DIR', 'Add the directory')
    opts.multiple('I', 'ignore', '', 'Ignore something')
    opts.flag('', 'verbose', 'Use verbose output,\nlorem ipsum')
    opts.flag('', 'example', '')
    opts.flag('x', '', 'Foo')

    let matches = match opts.parse(env.arguments) {
      case Ok(v) -> v
      case Error(e) -> {
        STDERR.new.print('test: ${e}')
        sys.exit(1)
      }
    }

    if matches.contains?('help') {
      let help = Help
        .new('test')
        .description(
          'This is an example program to showcase the optparse library.',
        )
        .section('Examples')
        .line('test --help')
        .section('Options')
        .options(opts)
        .to_string

      STDOUT.new.write_string(help)
    } else {
      STDOUT.new.print(fmt(matches.remaining))
    }
  }
}

When running this program with the --help option, the output is as follows:

Usage: test [OPTIONS]

This is an example program to showcase the optparse library.

Examples:

  test --help

Options:

  -h, --help           Show this help message
  -c, --config=PATH    Use a custom configuration file
  -i, --include=DIR    Add the directory
  -I, --ignore         Ignore something
      --verbose        Use verbose output,
                       lorem ipsum
      --example
  -x                   Foo

Classes

Error

A type that describes a parsing error.

Help

A type for generating help messages easily.

Matches

A type containing the parsed options and any remaining arguments.

Options

A type that describes the options to parse.