package windtrap

  1. Overview
  2. Docs

Module Private.CliSource

Command-line and environment resolution into the run configuration.

parse reads an argument vector into the parsed flags, settings resolves them with the environment and the defaults into a Run.config, and help is the help page. help also lists the settings that only the environment spells, which nothing here reads.

Nothing here prints or exits. An error is returned as an error, and --help and --version come back as fields of parsed for the caller to act on.

Mirrors. A mirror is the WINDTRAP_* variable of a flag. Under dune runtest an executable gets no command line, and the mirrors are its command line. A mirror is named WINDTRAP_ then the long flag in capitals, with _ for -, except that of --arm, which is WINDTRAP_MUTATE_ARM.

A mirror reaches every executable of a project alike, and a suite that cannot honour one is not in error. settings therefore keeps the source of a value where it changes the outcome of a run.

A mirror is read by the parser of its flag, so a variable accepts and refuses what its flag does, with the same expected wording. An error names the variable as its source. settings reads the mirrors in one pass, and a variable set to the empty string counts as unset.

  • The mirror of a flag that takes a value is one token, trimmed.
  • The mirror of --tag or --exclude-tag is a comma-separated list, whose items are trimmed and whose empty items are dropped.
  • -f and -e repeat as well, but their mirrors are one token each, because a test name may hold a comma.
  • The mirror of a flag that takes no value is a boolean (Os.bool_of_string). True gives the flag and false is its absence. Any other word is refused.
  • The mirror of a flag whose value is optional reads both ways. A boolean is the bare flag or its absence, and any other word is the value, trimmed.

Seven flags have no mirror, and none must be given one. -l, --failed and -x serve a loop of runs by hand, which is a command line's, and a listing is not a run. -u and --corrected accept baselines, and a build action must never accept one because of a variable in its environment. -h and -V only print.

Parsed flags

Sourcetype parsed = {
  1. filter : string list;
    (*

    -f PATTERN, --filter PATTERN and the positional arguments, repeatable: the patterns in the order given.

    *)
  2. exclude : string list;
    (*

    -e PATTERN, --exclude PATTERN, repeatable: the patterns in the order given.

    *)
  3. tags : string list;
    (*

    --tag TAG, repeatable: the tags in the order given.

    *)
  4. exclude_tags : string list;
    (*

    --exclude-tag TAG, repeatable: the tags in the order given.

    *)
  5. shard : (int * int) option;
    (*

    --shard K/N, with 1 <= K <= N. K and N are plain decimal numerals, so a sign, 0x and _ are refused.

    *)
  6. failed_only : bool option;
    (*

    --failed.

    *)
  7. list_only : bool option;
    (*

    -l, --list. settings ignores it, and the caller lists the selection (see Run.list_selection).

    *)
  8. bail : bool option;
    (*

    -x, --fail-fast.

    *)
  9. stream : bool option;
    (*

    -s, --stream.

    *)
  10. update : bool option;
    (*

    -u, --update, for Baseline.mode.Update.

    *)
  11. corrected : bool option;
    (*

    --corrected, for Baseline.mode.Corrected.

    *)
  12. seed : int64 option;
    (*

    --seed TOKEN: an s1: token, read by Seed.of_string.

    *)
  13. timeout : float option;
    (*

    --timeout SECONDS: a finite and positive number.

    *)
  14. slow_threshold : float option;
    (*

    --slow-threshold SECONDS: a finite and non-negative number.

    *)
  15. prop_count : int option;
    (*

    --prop-count N: a positive integer.

    *)
  16. verbose : bool option;
    (*

    -v, --verbose.

    *)
  17. junit : string option;
    (*

    --junit PATH.

    *)
  18. color : Windtrap__.Os.color_mode option;
    (*

    --color MODE: always, never or auto, in any case.

    *)
  19. log_dir : string option;
    (*

    -o DIR, --output DIR.

    *)
  20. mutate : string list option;
    (*

    --mutate[=PREFIX,…]: Some [] for the bare flag, and else the comma-separated prefixes.

    *)
  21. arm : string option;
    (*

    --arm ID: the identifier as typed. It is not parsed here, so a malformed one is no error, and Windtrap_runtime.Mutate.id_of_string reports it.

    *)
  22. help : bool;
    (*

    -h, --help.

    *)
  23. version : bool;
    (*

    -V, --version.

    *)
}

The type for the flags of one command line, one field per flag, before the environment and the defaults. An absent flag is None, [] for a repeatable one, and false for help and version. A bool option field is None or Some true and never Some false. Run.config says what a run does with each.

Sourceval empty : parsed

empty is the record with every flag absent.

Errors

Sourcetype error =
  1. | Unknown_flag of string
    (*

    The flag is not in the table. The payload is the argument as typed, but for the =value of a long flag: --bogus=1 gives --bogus, and -f=x gives -f=x. An argument of two bytes or more that starts with - is read as a flag, so -1 and a bundled -xv are unknown flags.

    *)
  2. | Missing_value of string
    (*

    The flag takes a value and the command line ended. A flag takes the next argument whatever it looks like.

    *)
  3. | Invalid_value of {
    1. source : string;
    2. value : string;
    3. expected : string;
    }
    (*

    value was refused. source is the flag as typed, or the variable that carried value, and expected describes what is accepted. A flag that takes no value and is given one, as in --verbose=1, is refused this way, with expected = "no argument".

    *)
  4. | Incompatible_flags of string * string
    (*

    Both flags were given, and they contradict each other. The payload is ("-u", "--corrected") or ("--mutate", "--arm"), whatever spelling or mirror carried them.

    *)

The type for the errors of parse and settings.

Sourceval error_message : error -> string

error_message error is one sentence on error for a user, which names the flag or the variable concerned. It is not stable enough for a program to match.

An unknown long flag ends with the nearest long flag when one is near, as in ; did you mean '--junit'?, and a short flag gets no suggestion.

Parsing

Sourceval parse : string array -> (parsed, error) result

parse argv is the flags of argv, or the first error from the left. argv.(0) is not read, and an empty argv is Ok empty. It reads no environment and never raises.

  • A repeated flag keeps its last value, and -f, -e, --tag and --exclude-tag accumulate.
  • A long flag also takes its value as --flag=value. A short flag does not, and -f=x and -fx are unknown flags.
  • A flag whose value is optional takes it only as --flag=value. Bare, it never takes the next argument.
  • A bare argument is added to filter, as -f adds one. Every argument after -- is positional, which is how a pattern that starts with - is given.
  • Parsing stops at --help and at --version, so the flags after them are not checked. An error before them still wins.
  • -u with --corrected is Incompatible_flags. It is checked after the scan, so it also wins over a --help that follows the two.

Resolution

Sourceval settings : parsed -> (Windtrap__.Run.config, error) result

settings cli is the configuration that one invocation resolves to. Each field is cli's, else its mirror's, else that of Run.default_config.

  • tags and exclude_tags add up, the command line's first and then the mirror's. filter and exclude are the command line's patterns when it gives one, and else the mirror's.
  • A mirror whose flag the command line gave is not read, so a valid --timeout hides a malformed WINDTRAP_TIMEOUT. Any other mirror that its flag would refuse is Error (Invalid_value _) naming the variable, and is never ignored. The mirrors are read in the order of help, and the first error ends the resolution.
  • baseline is Baseline.mode.Update under update, else Baseline.mode.Corrected under corrected, else Baseline.mode.Check.
  • mutation is Run.mutation.Loop of mutate, Run.mutation.Armed of arm, or Run.mutation.No_mutation. Both at once is Error (Incompatible_flags _), whichever layer gave each, and it is checked after every mirror. A prefix that spells a boolean cannot go through the variable.
  • A relative path of --junit or -o is made absolute, against the working directory when the command line gives it and against Os.project_root when its mirror does. It is kept as given when that directory cannot be read.
  • github is Os.in_github_actions (), allow_focus is false and invocation is `Mirrors. list_only, help and version are ignored.

It never raises. It reads the environment and the working directory, and on every call it draws a seed from Seed.random, which the result carries when no layer gives one.

Sourceval color_mode : unit -> (Windtrap__.Os.color_mode, error) result

color_mode () is the colour mode that WINDTRAP_COLOR gives, read by the parser of --color, for a command whose one runner flag is --color (parse_color). It is Ok Os.Auto when the variable is unset or empty, and Error (Invalid_value _) naming the variable for a word that the flag would refuse.

Sourceval parse_color : string -> (Windtrap__.Os.color_mode, error) result

parse_color value is value read as the value of --color on the command line, and Error (Invalid_value _) naming --color for a word that the flag refuses.

Help

Sourceval usage : prog:string -> string

usage ~prog is usage: <prog> [OPTIONS] [PATTERN...], with the basename of prog.

Sourceval help : prog:string -> string

help ~prog is the help page. It gives each flag with its spellings, its mirror and its description, in the order of the table, then the settings that only a variable spells. It ends with a newline.

Every line fits 80 columns when the basename of prog leaves the first two within them.