command_line_options

This library provides command-line parsing predicates where command-line options are defined as objects that import the command_line_option category. Predicates are also provided for generating help text.

Parsed options are returned by default as a list of Name(Value) terms. A parser option, output_functor(Functor), allows returning options as Functor(Key, Value) terms instead.

Adapted with significant changes from the SWI-Prolog optparse library by Marcus Uneson. Most documentation, parsing options, and help options retained from the original library. Command line options specification changed to an object-based representation. Parsing simplified, no longer using DCGs. Comprehensive set of tests added, based on documentation examples. Full portability to all supported backends.

API documentation

Open the ../../apis/library_index.html#command_line_options file in a web browser.

Loading

To load all entities in this library, load the loader.lgt utility file:

| ?- logtalk_load(command_line_options(loader)).

Testing

To test this library predicates, load the tester.lgt file:

| ?- logtalk_load(command_line_options(tester)).

Terminology

The terminology is partly borrowed from Python (see http://docs.python.org/library/optparse.html#terminology). Arguments are what you provide on the command line and for many Prolog systems show up as a list of atoms Args in current_prolog_flag(argv, Args). They can be divided into:

  • Runtime arguments, which control the Prolog runtime; conventionally terminated by --.

  • Options, which are key-value pairs (with a boolean value possibly implicit) intended to control your program.

  • Positional arguments, which are what remains after all runtime arguments and options have been removed (with implicit arguments true/false for booleans filled in).

Positional arguments are used for mandatory arguments without sensible defaults (e.g., input file names). Options offer flexibility by letting you change a default setting. This library has no notion of mandatory or required options.

Defining option objects

Define command-line options by creating objects that import the command_line_option category. Each object represents one command-line option and overrides the predicates to specify its properties.

Create an object that imports command_line_option and override the following predicates:

  • key/1: The key used to identify this option in the result. This predicate must be overridden.

  • short_flags/1: List of single-character short flags (e.g., [v] for -v). Default: [].

  • long_flags/1: List of long flags (e.g., [verbose] for --verbose). Default: [].

  • type/1: Option value type. One of boolean, atom, integer, float, or term. Default: term.

  • default/1: Default value. Optional.

  • meta/1: Metasyntactic variable name for help text. Default: ''.

  • help/1: Help text (atom or list of atoms for pre-broken lines). Default: ''.

Validating option definitions

Option objects provide two predicates for validating their definitions:

  • check/0: Validates the option definition, throwing an error if invalid. The validation checks:

    • The key/1 predicate is defined (not just using the default).

    • All short flags are single characters.

    • The type is a known type (supported by the type library).

    • If a default value is defined and the type is not term, the default value matches the declared type.

  • valid/0: Succeeds deterministically if the option definition is valid, fails otherwise. This is useful when you want to check validity without handling exceptions.

The parse/4-5 and help/2-3 predicates automatically call check/0 on all option objects before processing, ensuring invalid definitions are caught early with clear error messages.

Example:

| ?- verbose_option::check.
yes

| ?- verbose_option::valid.
yes

Example option objects

:- object(verbose_option,
    imports(command_line_option)).

    key(verbose).
    short_flags([v]).
    long_flags([verbosity]).
    type(integer).
    default(2).
    meta('V').
    help('verbosity level, 1 <= V <= 3').

:- end_object.


:- object(mode_option,
    imports(command_line_option)).

    key(mode).
    short_flags([m]).
    long_flags([mode]).
    type(atom).
    default('SCAN').
    help(['data gathering mode, one of',
          '  SCAN: do this',
          '  READ: do that',
          '  MAKE: fabricate numbers',
          '  WAIT: do nothing']).

:- end_object.


:- object(cache_option,
    imports(command_line_option)).

    key(cache).
    short_flags([r]).
    long_flags(['rebuild-cache']).
    type(boolean).
    default(true).
    help('rebuild cache in each iteration').

:- end_object.


:- object(outfile_option,
    imports(command_line_option)).

    key(outfile).
    short_flags([o]).
    long_flags(['output-file']).
    type(atom).
    meta('FILE').
    help('write output to FILE').

:- end_object.


% Configuration parameter without command-line flags
:- object(path_option,
    imports(command_line_option)).

    key(path).
    default('/some/file/path/').

:- end_object.

Parsing command-line arguments

Use the command_line_options object parse/4-5 predicates:

| ?- command_line_options::parse(
         [verbose_option, mode_option, cache_option, outfile_option],
         ['-v', '5', '-m', 'READ', '-ooutput.txt', 'input.txt'],
         Options,
         PositionalArguments
     ).

Options = [verbose(5), mode('READ'), cache(true), outfile('output.txt')],
PositionalArguments = ['input.txt'].

Generating help text

Use the command_line_options::help/2 predicate for default formatting:

| ?- command_line_options::help([verbose_option, mode_option, cache_option], Help).

Or use command_line_options::help/3 with custom help options:

| ?- command_line_options::help([verbose_option, mode_option], Help, [line_width(100)]).

Help options

The help/3 predicate supports the following help options:

  • line_width(Width): Maximum line width for help text. Default: 80.

  • min_help_width(Width): Minimum width for help text column. Default: 40.

  • break_long_flags(Boolean): If true, break long flags across multiple lines. Default: false.

  • suppress_empty_meta(Boolean): If true (default), suppress empty metasyntactic variables in help output.

Parse options

The parse/5 predicate supports the following parse options:

  • output_functor(Functor): When defined, options are returned as Functor(Key, Value) terms instead of Key(Value) terms. No default.

  • duplicated_flags(Keep): How to handle duplicate options. One of keepfirst, keeplast, keepall. Default: keeplast.

  • allow_empty_flag_spec(Boolean): If true (default), options without flags are allowed (useful for configuration parameters). Set to false to raise errors on empty flags.

Notes and tips

  • The default type is term, which subsumes integer, float, and atom. However, always specifying types is recommended for reliable parsing and clear error messages.

  • -sbar is taken as -s bar, not as -s -b -a -r (no clustering).

  • -s=foo is disallowed.

  • Duplicate flags default to keeplast (controllable via the duplicated_flags parse option).

  • Unknown flags (not in the specification) will raise errors.