Home

Awesome

Cmdline

Build Status Build status codecov

Command line argument parser (C++14)

Quick start

The following example shows how to use the library to parse command line arguments from the argv array.

// Include the CmdLine library.
// It's header-only.
#include "Cmdline.h"

int main(int argc, char* argv[])
// or:
// int wmain(int argc, wchar_t* argv[])
{
    // Create a command line parser.
    cl::Cmdline cli("Example", "A short description");

    // The parser needs to know about the valid options (and the syntax which
    // might be used to specifiy the options on the command line).
    // Options can be created and attached to the parser using the Cmdline::Add
    // method.

    // This adds an option to enable (or disable) debug output.
    // The value of the option will be assigned to the variable `debug`.

    bool debug = false;

    cli.Add(
        // 1)
        //
        // The 1st parameter is the name of the option. Multiple option names
        // may be separated by `|`. So the `debug` option might be specified as
        // `-d` or `--debug`.
        //
        "d|debug",

        // 2)
        //
        // The 2nd parameter provides a short description of the option which
        // will be displayed in the automatically generated help message.
        //
        "Enable debug output",

        // 3)
        //
        // The 3rd parameter is a combination of flags, which specify ow and how
        // often the option might be specified on the command line and whether
        // the option takes an argument or not.
        //
        // The `Multiple` flag can be used to tell the parser that an option
        // may appear multiple times on the command line.
        // The default value for `Multiple` is `no`, i.e. the option may
        // appear at most once on the command line.
        //
        cl::Multiple::yes
        //
        // The `Arg` flag can be used to tell the parser whether the option
        // accepts an argument. The `optional` value means that an argument is
        // optional, i.e. both `--debug` and `--debug=on` or `--debug=false` are
        // valid.
        // The default value is `Arg::no`, i.e. an argument is not allowed.
        //
        | cl::Arg::optional,
        //
        // There are more options which can be used to customize the syntax for
        // options. These are described later.
        //

        // 4)
        //
        // The 4th parameter is the actual option parser which effectively takes
        // the string representation of the command line argument and is used to
        // convert the option (or the options' argument - if present) into the
        // target object.
        //
        // For now it should be sufficient to note that Var(T& target) is a
        // convenience function which converts the string as given on the
        // command line into an object of type `T` and assigns the result to the
        // given target variable.
        // More advanced usages of the parser will be described later.
        //
        cl::Var(debug)
    );

    // The next command adds an option which may be specified multiple times and
    // the argument of each occurence will be added to the `include_directories`
    // array defined below.

    std::vector<std::string> include_directories;
    // or:
    // std::vector<std::wstring> include_directories;

    cli.Add("I", "Include directories",

        // The `Arg::required` flag tells the parser that an "-I" must have an
        // argument specified. Either using the "-I=dir" syntax or as an
        // additional argument like "-I dir".
        cl::Multiple::yes | cl::Arg::required,

        // `Var` works with STL containers, too.
        cl::Var(include_directories)
        );

    // The `cli` object now knows everything it needs to know to parse the
    // command line argument array.

    // The Cmdline::Parse method takes a pair of iterators, parses the command
    // line arguments and calls the options' parser to convert the strings into
    // some objects of another type. Note that the Parse method does not know
    // anything about the program name which is stored in argv[0], so we skip
    // that.
    auto const result = cli.Parse(argv + 1, argv + argc);

    // The parser may generate warning and/or error messages. These messages
    // may be obtained with `Cmdline::diag()`. For convenience the `PrintDiag()`
    // method prints the diagnostic messages to `stderr`.
    cli.PrintDiag();

    if (!result) {
        // The result of `Cmdline::Parse` can be explicitly converted to `bool`
        // to indicate success or failure. If the options were specified with
        // an invalid syntax or a conversion error has occurred, the result will
        // be `false`.
        //
        // To provide the user with some information how to avoid these mistakes
        // the Cmdling objects provides a `FormatHelp` methods which returns a
        // string containing a description of all the options which the program
        // accepts.
        // Again, for convenience, the `PrintHelp` method prints this help
        // message to `stderr`. Here we need to tell the CmdLine library the
        // program name in order to print some nicer help message...
        cli.PrintHelp();
        return -1;
    }

    // The command line has been successfully parsed.
    // Now do something useful...

    return 0;
}

Option flags

As noted above, the flags argument (3rd) controls how the options must/may be specified on the command line. Here is a list of the options flags the library supports.

In the examples below, the descr parameter is used to indicate the type of the variable.

There are (currently) no restrictions on the combinations of flags. You may combine any flag with any other, but the syntax may become odd or ambiguous. So be careful.

TODO

Implement Cmdline::SyntaxCheck() to check for odd or ambiguous option combinations. Or perform this check (in debug-mode only) in Cmdline::Add()?

enum class Required

Controls whether an option must appear on the command line.

enum class Multiple

Determines whether an option may appear multiple times on the command line.

enum class Arg

Controls the number of arguments the option accepts.

enum class MayJoin

Controls whether the option may/must join its argument.

enum class MayGroup

May this option group with other options?

enum class Positional

Positional option?

enum class CommaSeparated

TODO

enum class StopParsing

TODO

Option parser

TODO

General

bool parse(ParseContext const& ctx); // 'const' is required here
ctx.name     // option name
ctx.arg      // option argument
ctx.index    // index in argv[]
ctx.cmdline  // for warning and/or error messages
auto parse = [](ParseContext const& ctx) {
    std::cout << "Index " << ctx.index << ":"
        << " --" << ctx.name << " " << ctx.arg << "\n";
    if (ctx.name == "b") {
        ctx.cmdline->EmitDiag(
            Diagnostic::warning, ctx.index, "option 'b' is deprecated");
    }
    return true;
};

cli.Add("a|b", "custom", Arg::optional | Multiple::yes, parse);

// "-a -b=eins -a=zwei" ==>
//      Index 0: --a
//      Index 1: --b eins
//      Index 2: --a zwei

and emits a warning:

warning: option 'b' is deprecated

Predefined

Assign

Append

Var

Map

Predicates / Filters / Transforms

bool predicate(ParseContext const&, auto /*[const]*/& value);

Command-line parser

TODO

Unicode support

TODO

Yes. UTF conversions built-in.

Tokenize

TODO

const auto vec = TokenizeWindows("-a -b -c")
// vec = {"-a", "-b", "-c"}
const auto vec = TokenizeUnix("-a -b -c");
// vec = {"-a", "-b", "-c"}

Subcommands

TODO

No, not really. Example.

Console colors

TODO

#define CL_ANSI_CONSOLE_COLORS 1 // Windows/Unix (if supported)
#define CL_WINDOWS_CONSOLE_COLORS 1 // Windows only