Home

Awesome

Docopt.fs is a F# port of docopt

let ``Docopt.fs`` = docopt |> ``F#`` in


Isn't it awesome how CommandLineParser and PowerArgs generate help messages based on your code?!

Hell no! You know what's awesome? It's when the option parser is generated based on the beautiful help message that you write yourself! This way you don't need to write this stupid repeatable parser-code, and instead can write only the help message—the way you want it.

Docopt.fs helps you create most beautiful command-line interfaces easily:

open Docopt

let doc = """
Naval Fate.

Usage:
  naval_fate.exe ship new <name>...
  naval_fate.exe ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.exe ship shoot <x> <y>
  naval_fate.exe mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.exe (-h | --help)
  naval_fate.exe --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.
"""

[<EntryPoint>]
let main argv =
  let docopt = new Docopt(doc)
  try
    let dict = docopt.Parse(argv)
    printfn "Success:\n%A" dict
    0
  with ArgvException(message) ->
    printfn "Error: %s" message
    -42

Beat that! The option parser is generated based on the docstring above that is passed to the Docopt.Parse method. Docopt.Parse parses the usage pattern (doc in this example) and option descriptions (lines starting with dash -) and ensures that the program invocation matches the usage pattern. It parses options, arguments and commands based on that. The basic idea is that a good help message has all necessary information in it to make a parser.

Differences from reference python implementation

Compiling

TODO

Installation

TODO

Testing

After compiling, you can run the TestCases.exe binary in bin/Tests/TestCases.exe. If no window appears, it’s all good!

API

Docopt.fsi

type Docopt.HelpCallback = string -> bool

A simple callback function used by the Docopt.Docopt described below.

new Docopt.Docopt : doc      : string
                  * ?argv    : string array
                  * ?help    : HelpCallback
                  * ?version : obj
                  -> Docopt

The main constructor takes 1 required and 3 optional arguments:

This constructor can throw an exception of type UsageException defined as:

exception UsageException of string

if there is a syntax error in the usage patterns. The message carried by the exception describes precisely the error.

member Docopt.Parse : ?argv : string array 
                    * ?args : Arguments.Dictionary 
                    -> Arguments.Dictionary 

The parse method parses the argument vector and stores the results in a Docopt.Arguments.Dictionary instance. It takes 2 optional arguments:

The return value is a Docopt.Arguments.Dictionary with options, arguments and commands as keys, spelled exactly like in your help message. Informations that were described but not matched will not be in the dictionary (options with [default:...] arguments will still be registered); however accessing them will yield Docopt.Result.None instead of throwing an exception. For instance, if you invoke the top example as:

naval_fate.exe ship Guardian move 100 150 --speed=15

the returned dictionary will be:

Docopt.Arguments.Dictionary [("ship", Flag);
                             ("<name>", Argument "Guardian");
                             ("move", Flag);
                             ("<x>", Argument "100");
                             ("<y>", Argument "150");
                             ("--speed", Argument "15")]

This function can throw an exception of type ArgvException defined as:

exception ArgvException of string

if argv does not satisfy the AST created at construction. The message carried by the exception describes what the error is.

member Docopt.Usage : string

This property contains all the usage parts fused into one string for convenience. Might be slow, as each use calls System.String.Join.

member Docopt.UsageParser : UsageParser

This property allows you to get the UsageParser generated from doc.

Help message format

Help message consists of 2 parts:

Their format is described below; other text is ignored.

Usage patterns syntax

This list describes each lexeme in the usage pattern grammar, and exposes the lexeme’s syntax using standard EBNF extended with range ("a"..."z") syntax at the end.
Usage pattern is a substring of doc that starts with usage: (case insensitive) and ends with a visibly empty line. Minimum example:

"""Usage: my_program.exe

"""

The first word after usage: is interpreted as your program’s name. You can specify your program's name several times to signify several exclusive patterns:

"""Usage: my_program.exe FILE
          my_program.exe COUNT FILE

"""

Each pattern can consist of the following elements:

This gives us the following BNF describing a full usage pattern:

whitespace   = " " | ? tabulation ? ;
newline      = ? newline or eof ? ;
pattern_base = argument
             | option
             | brackets
             | parens
             | pipe
             | ellipsis
             | options
             | single_hyphen
             | double_hyphen
             | command
             ;
pattern      = pattern_base , whitespace ;
program_name = command ;
usage_part   = ? case-insensitive "usage:" ? ;
usage_line   = [ usage_part ] , program_name , { pattern } ;
usage        = { usage_line , newline } ;
grammar      = usage .

If your pattern allows to match argument-less option (a flag) several times:

"""
Usage: my_program.exe [-v | -vv | -vvv]
"""

then number of occurrences of the option will be counted. I.e. args.["-v"] will be Flags(2) if program was invoked as my_program.exe -vv. Same works for commands.

If your usage patterns allows to match same-named option with argument or positional argument several times, the matched arguments will be collected into a list:

"""
Usage: my_program.py <file> <file> --path=<path>...
"""

I.e. invoked with my_program.exe file1 file2 --path=./here --path=./there the returned dictionary will be:

Docopt.Arguments.Dictionary [("<file>", Arguments ["file1";"file2"]);
                             ("--path", Arguments ["./here";"./there"])]

Option descriptions format

Option descriptions consist of a list of options that you put below your usage patterns.

It is necessary to list option descriptions in order to specify:

The rules are as follows:



Changelog

The first stable release will be v1.0. Until then, use with caution as things might change drastically.

Notes

Pull requests welcome!
If you see a typo, or something wrong in the documentation, feel free to submit one too!

What’s next