Parsing command line arguments in C++ with Clara

In a previous post, I wrote about the C++ unit-testing framework Catch2. Catch uses another library, called Clara, for parsing command line arguments. Clara is an open-source, single-header, simple, composable and easy to use parser written by the author of Catch2. In this post, I will show how you can use Clara in C++ to parse command line arguments.

Clara is available on Github at https://github.com/catchorg/Clara. Although there is not much documentation at the moment, the library is easy to use. The following sample shows an example of using Clara. We’ll drill down on it in a moment.

We can split this program into several parts:

  • Declaration of variables to hold values of command line arguments.
  • Creation of a parser by combining individual parsers clara::Opt, clara::Arg, and clara::Help.
  • Parsing the command line with parse().
  • Interpreting the result and doing something based on the argument value. In this example, if the arguments were correctly parsed they are just printed to the console.

clara::Opt and clara::Arg are individiual parsers that are very similar execept for one important difference: the first specify an argument tied to an option (such as -v normal or --ignore) and the later to arguments that are not tied to an option (and therefore mising the square bracket names). Options are specified with - or -- but on Windows / is also accepted. clara::Help is yet another parser that always binds to a boolean variable setting it to true if any of the standard help options, -h, --help and -?, are found.

To understand the Opt parser’s parts let’s take the following example:

There are three main parts in this construction:

  • (threshold, "threshold") specifies a variable (threshold) that will receive the value of the command line argument tied to the option and a hint ("threshold") for the value.
  • ["-t"] indicates one or more names for the option (for multiple names just chain them like ["-t"]["-threshold"]).
  • ("Threshold for analysis inclusion") indicates a description of the option.

The syntax for Arg and Help is very similar, except that the square bracket names are missing. The description part is optional for all parser types.

If you want to validate the input values for an option or argument, for instance to restrict a numeric value to a certain range, you can specify a lambda instead of the variable. This is shown in the previous example with the parsing of the depth option.

Should the parsing be successful, you must return ParserResult::ok(ParseResultType::Matched). Otherwise, you can return an error, such as ParserResult::runtimeError("Depth must be between 1 and 10").

In the example above, verbosity is variable of type verbosity_level, which is a scoped enum. You can only bind to enums if have overwritten operator >> for them. Therefore, for my example to work, I have also implemented the following:

Parsing the actual command line options is done with a call to parse() and passing the arguments through an Args object. The result of the call is a clara::detail::InternalParseResult object. There are various ways to check its value. The explicit operator bool returns true if the type of the result is Ok (the other options being LogicError and RuntimeError).

You can actually print the parser description to an output stream using the writeToStream() method. This is how the result looks for the example shown above:

Let’s look at some parsing examples for the program above:

  • no arguments provided
  • only one argument provided (i.e. source)
  • both arguments provided (source and dest)
  • additionally option -t provided
  • additionally option -i or --ignore provided
  • additionally option -d provided with valid numerical value in accepted range
  • additionally option -d provided with invalid numerical value outside the accepted range
  • additionally option -v provided with valid numerical value
  • additionally option -v provided with valid textual value
  • additionally option -v provided with invalid numerical value
  • additionally option -v provided with invalid textual value

Leave a Reply