F# getopt to parse the command line

Many programs (especially console applications) need to parse the command line, and find which options the user want to set. As far as I know, .NET doesn't provide any function for this, but there several third-party libraries to do it. In F#, there are some functions for this in the Powerpack.

Many programs (especially console applications) need to parse the command line, and find which options the user want to set. As far as I know, .NET doesn't provide any function for this, but there several third-party libraries to do it. In F#, there are some functions for this in the Powerpack. However, I was not able to find any example or explanation to use, except an old blog post by Robert Pickering in 2005! I am sure other people will need it some day, so here is an example! If you are familiar with OCaml, it is almost the same as the Arg module.

First, we need to define the list of options. An option is defined by a tuple: the argument name (string), a type (ArgType), and the description (string). The type tells if the option requires an argument and defines a callback function. It is one of the following:

  • ArgType.Unit(f): the option has no argument, the callback f has type: unit -> unit
  • ArgType.Set(b): the option has no argument, b (bool ref) is set to true.
  • ArgType.Clear(b): the option has no argument, b (bool ref) is set to false.
  • ArgType.String(f): the option has a string argument, the callback f has type: string -> unit
  • ArgType.Int(f): the option has an int argument, the callback f has type: int -> unit
  • ArgType.Float(f): the option has a float argument, the callback f has type: float -> unit
  • ArgType.Rest(f): stop parsing the command line, call the function f (string -> unit) on each remaining argument.

The convention is to use the Rest type for the "--" argument. The nice thing is that the -h option is automatically added by the library, and the usage is generated.

open Microsoft.FSharp.Text


  let compile s = printfn "Compiling %s..." s

  let outputName = ref "a.out"
  let verbose = ref false
  let warningLevel = ref 0
  let specs =
    ["-o", ArgType.String (fun s -> outputName := s), "Name of the output"
     "-v", ArgType.Set verbose, "Display additional information"
     "--warn", ArgType.Int (fun i -> warningLevel := i), "Set warning level"
     "--", ArgType.Rest compile, "Stop parsing command line"
    ] |> List.map (fun (sh, ty, desc) -> ArgInfo(sh, ty, desc))

  let () =
    ArgParser.Parse(specs, compile)

Here it is! Don't forget to compile with the Powerpack to get these functions. It is very easy to use it, but the module is a bit limited (e.g, it doesn't make any difference between short and long options). Hopefully, it will be improved later!