package bos

  1. Overview
  2. Docs

Quick and dirty program arguments parsing.

This is for quick hacks and scripts. If your program evolves to a tool for end users you should rather use Cmdliner to parse your command lines: it generates man pages and its parsing is more flexible and user friendly. The syntax of command lines parsed by this module is a subset of what Cmdliner is able to parse so migrating there should not be a problem for existing invocations of your program.

This module supports short and long options with option arguments either glued to the option or specified as the next program argument. It also supports the -- program argument to notify that subsequent arguments have to be treated as positional arguments. Parsing functions always respond to the -h, -help or --help flags by showing the program's usage and command line options documentation.

See the basics.

Warning. This module is not thread-safe.

Executable name

val exec : string

exec is the name of the executable. This is Sys.argv.(0) if Sys.argv is non-empty or Sys.executable_name otherwise.

Argument converters

Argument converters transform string arguments of the command line to OCaml values. Consult the predefined converters.

type 'a conv

The type for argument converters.

val conv : ?docv:string -> (string -> ('a, Rresult.R.msg) result) -> (Format.formatter -> 'a -> unit) -> 'a conv

conv ~docv parse print is an argument converter parsing values with parse and printing them with print. docv is a documentation meta-variable used in the documentation to stand for the argument value, defaults to "VALUE".

val conv_parser : 'a conv -> string -> ('a, Rresult.R.msg) result

conv_parser c is c's parser.

val conv_printer : 'a conv -> Format.formatter -> 'a -> unit

conv_printer c is c's printer.

val conv_docv : 'a conv -> string

conv_printer c is c's documentation meta-variable.

val parser_of_kind_of_string : kind:string -> (string -> 'a option) -> string -> ('a, Rresult.R.msg) result

parser_of_kind_of_string ~kind kind_of_string is an argument parser using the kind_of_string function for parsing and kind for errors (e.g. could be "an integer" for an int parser).

val some : ?none:string -> 'a conv -> 'a option conv

some none c is like the converter c but wraps its result in Some. This is used for command line arguments that default to None when absent. none is what should be printed by the printer for None (defaults to "").

Flag and option queries

Flag and option names. They are specified without dashes. A one character name defines a short option; "d" is -d. Longer names define long options "debug" is --debug.

Option argument specification. On the command line, option arguments are either specified as the next program argument or glued to the option. For short options gluing is done directly: -farchive.tar. For long options an "=" characters stands between the option and the value: --file=archive.tar.

Warning. These functions are effectful invoking them twice on the same option names will result in parse errors. All the following functions raise Invalid_argument if they are invoked after parsing.

val flag : ?doc:string -> ?env:string -> string list -> bool

flag ~doc ~env names is true if one of the flags in names is present on the command line at most once and false otherwise.

If there is no flag on the command line and env is specified and defined in the environment, its value is parsed with Env.bool and the resulting value is used. doc is a documentation string.

val flag_all : ?doc:string -> ?env:string -> string list -> int

flag_all is like flag but counts the number of occurences of the flag on the command line. If there is no flag on the command line and env is specified and defined in the environment, its value is parsed with Env.bool and converted to an integer.

val opt : ?docv:string -> ?doc:string -> ?env:string -> string list -> 'a conv -> absent:'a -> 'a

opt ~docv ~doc ~env names c ~absent is a value defined by the value of an optional argument that may appear at most once on the command line under one of the names specified by names.

The argument of the option is converted with c and absent is used if the option is absent from the command line. If there is no option on the command line and env is specified and defined in the environment, its value is parsed with parse and that value is used instead of absent.

doc is is a documentation string. docv a documentation meta-variable used in the documentation to stand for the option argument, if unspecified c's conv_docv is used. In doc occurences of the substring "$(docv)" in are replaced by the value of docv.

val opt_all : ?docv:string -> ?doc:string -> ?env:string -> string list -> 'a conv -> absent:'a list -> 'a list

opt_all is like opt but the optional argument can be repeated.

Parsing

Note. Before parsing make sure you have invoked all the queries.

Warning. All the following functions raise Invalid_argument if they are reinvoked after parsing.

val parse_opts : ?doc:string -> ?usage:string -> unit -> unit

parse_opts () can:

  • Return () if no command line error occured and -help or --help was not specified.
  • Never return and exit the program with 0 after having printed the help on stdout.
  • Never return and exit the program with 1 after having printed an error on stderr if a parsing error occured.

A parsing error occurs either if an option parser failed, if a non repeatable option was specified more than once, if there is an unknown option on the line, if there is a positional argument on the command line (use parse to parse them). usage is the command argument synopsis (default is automatically inferred). doc is a documentation string for the program.

val parse : ?doc:string -> ?usage:string -> pos:'a conv -> unit -> 'a list

parse ~pos is like parse_opts but returns and converts the positional arguments with pos rather than error on them. Note that any thing that comes after a -- argument on the command line is deemed to be a positional argument.

Predefined argument converters

val string : string conv

string converts a string argument. This never errors.

val path : Fpath.t conv

path converts a path argument using Fpath.of_string.

val bin : Cmd.t conv

bin is string mapped by Cmd.v.

val cmd : Cmd.t conv

cmd converts a non-empty command line with Cmd.of_string

val char : char conv

char converts a single character.

val bool : bool conv

bool converts a boolean with String.to_bool.

val int : int conv

int converts an integer with String.to_int.

val nativeint : nativeint conv

int converts a nativeint with String.to_nativeint.

val int32 : int32 conv

int32 converts an int32 with String.to_int32.

val int64 : int64 conv

int64 converts an int64 with String.to_int64.

val float : float conv

float converts an float with String.to_float.

val enum : (string * 'a) list -> 'a conv

enum l p converts values such that string names in l map to the corresponding value of type 'a.

Warning. The type 'a must be comparable with Stdlib.compare.

  • raises Invalid_argument

    if l is empty.

val list : ?sep:string -> 'a conv -> 'a list conv

list ~sep c converts a list of c. For parsing the argument is first String.cuts ~sep and the resulting string list is converted using c.

val array : ?sep:string -> 'a conv -> 'a array conv

array ~sep c is like list but returns an array instead.

val pair : ?sep:string -> 'a conv -> 'b conv -> ('a * 'b) conv

pair ~sep fst snd converts a pair of fst and snd. For parsing the argument is String.cut ~sep and the resulting strings are converted using fst and snd.

Basics

To parse a command line, first perform all the option queries and then invoke one of the parsing functions. Do not invoke any query after parsing has been done, this will raise Invalid_argument. This leads to the following program structure:

(* It is possible to define things at the toplevel as follows. But do not
   abuse this. The following flag, if unspecified on the command line, can
   also be specified with the DEBUG environment variable. *)
let debug = OS.Arg.(flag ["g"; "debug"] ~env:"DEBUG" ~doc:"debug mode.")
...

let main () =
  let depth =
    OS.Arg.(opt ["d"; "depth"] int ~absent:2 ~doc:"recurses $(docv) times.")
  in
  let pos_args = OS.Arg.(parse ~pos:string ()) in
  (* No command line error or help request occured, run the program. *)
  ...

let main () = main ()