Skip to content
Golubchikov Mihail edited this page Feb 21, 2024 · 9 revisions

Argument Parser for C++

argparse — Parser for command-line options, arguments and sub-commands

This is the single-header C++ implementation of the python's argparse module for C++ projects.

The argparse module makes it easy to write user-friendly command-line interfaces. The program defines what arguments it requires, and argparse will figure out how to parse those out of argv. The argparse module also automatically generates help and usage messages and issues errors when users give the program invalid arguments.

Preparation

Download

Download the latest version GitHub releases of the argparse (argparse.hpp) and put it into the 'argparse' folder in one of your indlude directories (for ex., in the 'third_party' directory).

Official repositories:

cpp-argparse-dev PPA

cpp-argparse-dev AUR

cpp-argparse-dev MacPorts

.deb and .rpm packages will install argparse to the /usr/include folder (full path: /usr/include/argparse/argparse.hpp)

CMake support as a git submodule

You can add this library as a git submodule in third parties:

git submodule add https://github.com/rue-ryuzaki/argparse third_party/argparse

and in main CMakeLists.txt

add_subdirectory(third_party/argparse)
...
target_link_libraries(${PROJECT_NAME} argparse)

Include header

#include <argparse/argparse.hpp>

Example

#include <iostream>

#include <argparse/argparse.hpp>

int main(int argc, char const* const argv[])
{
    auto parser = argparse::ArgumentParser(argc, argv).prog("prog");
    parser.add_argument("-f", "--foo").help("FOO help").default_value("foo");
    parser.add_argument("-b", "--bar").help("BAR help").default_value("42").type<int>();

    auto const args = parser.parse_args();

    std::cout << "foo: " << args.get<std::string>("-f") << std::endl;
    std::cout << "bar: " << args.get<int>("--bar") << std::endl;

    return 0;
}

it can be run at the command line and provides useful help messages:

$ ./a.out -h
usage: prog [-h] [-f FOO] [-b BAR]

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO  FOO help
  -b BAR, --bar BAR  BAR help

When run with the appropriate arguments, it prints "foo" and "bar" from the command-line options:

$ ./a.out -f=myfoo -b 101
foo: myfoo
bar: 101

If invalid arguments are passed in, it will issue an error:

$ ./a.out -b a
foo: foo
terminate called after throwing an instance of 'argparse::TypeError'
  what():  TypeError: invalid int value: 'a'

Creating a parser

The first step in using the argparse is creating an ArgumentParser object:

...

int main(int argc, char const* const argv[])
{
    // by default ArgumentParser's 'prog' value is "untitled"

    // 'prog' and command line arguments will be used from argv
    auto parser = argparse::ArgumentParser(argc, argv);
    // 'prog' can be overrided:
    parser.prog("prog");

    // or with one line:
    auto parser = argparse::ArgumentParser(argc, argv).prog("prog");

    // or you can create ArgumentParser with custom 'prog', but without command line arguments.
    // this is useful when you need to parse arbitrary arguments as the program runs.
    // for ex. in tests or in the 'in-game console'.
    auto parser = argparse::ArgumentParser("prog");

    ...
}

The ArgumentParser object will hold all the information necessary to parse the command line arguments.

Adding arguments

Filling an ArgumentParser with information about program arguments is done by making calls to the add_argument() method. Generally, these calls tell the ArgumentParser how to take the strings on the command line and turn them into objects. This information is stored and used when parse_args() is called. For example:

...
parser.add_argument("-f", "--foo").help("FOO help").default_value("foo");
parser.add_argument("-b", "--bar").help("BAR help").default_value("42").type<int>();
// possible alternatives (for -f/--foo argument, the same is valid for the -b/--bar argument):
parser.add_argument({ "-f", "--foo" }).help("FOO help").default_value("foo");
parser.add_argument(argparse::Argument("-f", "--foo").help("FOO help").default_value("foo"));
parser.add_argument(argparse::Argument({ "-f", "--foo" }).help("FOO help").default_value("foo"));
...

Later, calling parse_args() will return an object with two attributes, "foo" ("-f" / "f" / "--foo" / "foo") and "bar" ("-b" / "b" / "--bar" / "bar").

Parsing arguments

ArgumentParser parses arguments through the parse_args() method. This will inspect the command line, convert each argument to the appropriate type and then invoke the appropriate action. In most cases, this means a simple Namespace object will be built up from attributes parsed out of the command line:

...
auto const args = parser.parse_args();
// or you can call parse_args with custom options:
auto const args = parser.parse_args("-f=myfoo -b 101");
// or
auto const args = parser.parse_args("-f myfoo -b=101");
// or
auto const args = parser.parse_args({ "-f=myfoo", "-b", "101" });

std::cout << "foo: " << args.get<std::string>("-f") << std::endl;
std::cout << "bar: " << args.get<int>("--bar") << std::endl;
// or
std::cout << "foo: " << args.get<std::string>("f") << std::endl;
std::cout << "bar: " << args.get<int>("bar") << std::endl;
// or
std::cout << "foo: " << args.get<std::string>("foo") << std::endl;
std::cout << "bar: " << args.get<int>("b") << std::endl;
// or
std::cout << "foo: " << args.get<std::string>("--foo") << std::endl;
std::cout << "bar: " << args.get<int>("-b") << std::endl;
...

parse_args() will typically be called with no arguments, and the ArgumentParser will automatically determine the command-line arguments from argv, if ArgumentParser was created as ArgumentParser(argc, argv).

ArgumentParser objects

Create a new ArgumentParser object. All parameters can be passed by calling the same setter function. Each parameter has its own more detailed description below, but in short they are:

Same as in python's argparse:

  • prog - The name of the program (default: argv[0] or "untitled")
  • usage - The string describing the program usage (default: generated from arguments added to parser)
  • description - Text to display before the argument help (default: "")
  • epilog - Text to display after the argument help (default: "")
  • parents - A list of ArgumentParser objects whose arguments should also be included
  • formatter_class - A class for customizing the help output
  • prefix_chars - The set of characters that prefix optional arguments (default: "-")
  • fromfile_prefix_chars - The set of characters that prefix files from which additional arguments should be read (default: "")
  • argument_default - The global default value for arguments (default: "")
  • conflict_handler - The strategy for resolving conflicting optionals (usually unnecessary)
  • add_help - Add a -h/--help option to the parser (default: true)
  • allow_abbrev - Allows long options to be abbreviated if the abbreviation is unambiguous. (default: true)
  • exit_on_error - Determines whether or not ArgumentParser exits with error info when an error occurs. (default: true)

Aditional parameters of current argparse:

  • have_env / get_env - Check if environment variable exists / get value (from envp[])
  • output_width - The width of usage and help output (default: auto-detected or 80, min 33)
  • handle - A handler to be called when the ArgumentParser starts or finishes parsing.

prog

By default, ArgumentParser objects use argv[0] (or use "untitled" name) to determine how to display the name of the program in help messages.

int main(int argc, char const* const argv[])
{
    auto parser1 = argparse::ArgumentParser(argc, argv);
    // prog will be argv[0]

    auto parser2 = argparse::ArgumentParser();
    // prog will be "untitled"
    ...
}

To change this default behavior, another value can be supplied calling the prog() setter function of ArgumentParser or pass value to ArgumentParser's constructor:

auto parser = argparse::ArgumentParser().prog("myprogram");
// equivalent to:
// auto parser = argparse::ArgumentParser("myprogram");
parser.print_help();
usage: myprogram [-h]

options:
  -h, --help  show this help message and exit

Note that the program name, whether determined from argv[0] or from the prog function, is available to help messages using the %(prog)s format specifier.

auto parser = argparse::ArgumentParser().prog("myprogram");
parser.add_argument("--foo").help("foo of the %(prog)s program");
parser.print_help();
usage: myprogram [-h] [--foo FOO]

options:
  -h, --help  show this help message and exit
  --foo FOO   foo of the myprogram program

usage

By default, ArgumentParser calculates the usage message from the arguments it contains:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("--foo").nargs("?").help("foo help");
parser.add_argument("bar").nargs("+").help("bar help");
parser.print_help();
usage: PROG [-h] [--foo [FOO]] bar [bar ...]

positional arguments:
  bar          bar help

options:
  -h, --help   show this help message and exit
  --foo [FOO]  foo help

The default message can be overridden with by calling the usage() setter function:

auto parser = argparse::ArgumentParser("PROG").usage("%(prog)s [options]");
parser.add_argument("--foo").nargs("?").help("foo help");
parser.add_argument("bar").nargs("+").help("bar help");
parser.print_help();
usage: PROG [options]

positional arguments:
  bar          bar help

options:
  -h, --help   show this help message and exit
  --foo [FOO]  foo help

The %(prog)s format specifier is available to fill in the program name in your usage messages.

description

This argument gives a brief description of what the program does and how it works. In help messages, the description is displayed between the command-line usage string and the help messages for the various arguments:

auto parser = argparse::ArgumentParser().description("A foo that bars");
parser.print_help();
usage: untitled [-h]

A foo that bars

options:
  -h, --help  show this help message and exit

By default, the description will be line-wrapped so that it fits within the given space. To change this behavior, see the formatter_class function.

epilog

Some programs like to display additional description of the program after the description of the arguments. Such text can be specified by calling the epilog() setter function:

auto parser = argparse::ArgumentParser()
        .description("A foo that bars")
        .epilog("And that's how you'd foo a bar");
parser.print_help();
usage: untitled [-h]

A foo that bars

options:
  -h, --help  show this help message and exit

And that's how you'd foo a bar

As with the description, the epilog text is by default line-wrapped, but this behavior can be adjusted with the formatter_class function.

parents

Sometimes, several parsers share a common set of arguments. Rather than repeating the definitions of these arguments, a single parser with all the shared arguments and passed to parents setter function to ArgumentParser can be used. The parents function takes a list of ArgumentParser objects, collects all the argument groups, subparsers, positional and optional actions from them, and adds these actions to the ArgumentParser object being constructed:

auto parent_parser = argparse::ArgumentParser().add_help(false);
parent_parser.add_argument("--parent");

auto foo_parser = argparse::ArgumentParser().parents(parent_parser);
foo_parser.add_argument("foo");
std::cout << foo_parser.parse_args({ "--parent", "2", "XXX" }) << std::endl;

auto bar_parser = argparse::ArgumentParser().parents(parent_parser);
bar_parser.add_argument("--bar");
std::cout << bar_parser.parse_args({ "--bar", "YYY" }) << std::endl;
Namespace(parent='2', foo='XXX')
Namespace(parent=None, bar='YYY')

Note that most parent parsers will specify add_help(false). Otherwise, the ArgumentParser will see two -h/--help options (one in the parent and one in the child) and raise an error.

Note: You must fully initialize the parsers before passing them via parents(). If you change the parent parsers after the child parser, those changes will not be reflected in the child.

formatter_class

ArgumentParser objects allow the help formatting to be customized by specifying an alternate formatting class. Currently, there are four such values:

  • RawDescriptionHelpFormatter
  • RawTextHelpFormatter
  • ArgumentDefaultsHelpFormatter
  • MetavarTypeHelpFormatter

RawDescriptionHelpFormatter and RawTextHelpFormatter give more control over how textual descriptions are displayed. By default, ArgumentParser objects line-wrap the description and epilog texts in command-line help messages:

auto parser = argparse::ArgumentParser("PROG")
        .description("this description\n"
            "was indented weird\n"
            "    but that is okay")
        .epilog("\n"
            "    likewise for this epilog whose whitespace will\n"
            "be cleaned up and whose words will be wrapped\n"
            "across a couple lines");
parser.print_help();
usage: PROG [-h]

this description was indented weird but that is okay

options:
  -h, --help  show this help message and exit

likewise for this epilog whose whitespace will be cleaned up and whose words will be wrapped across a couple lines

Passing RawDescriptionHelpFormatter to formatter_class() indicates that description and epilog are already correctly formatted and should not be line-wrapped:

auto parser = argparse::ArgumentParser("PROG")
        .formatter_class(argparse::RawDescriptionHelpFormatter)
        .description(""
            "Please do not mess up this text!\n"
            "--------------------------------\n"
            "    I have indented it\n"
            "    exactly the way\n"
            "    I want it");
parser.print_help();
usage: PROG [-h]

Please do not mess up this text!
--------------------------------
    I have indented it
    exactly the way
    I want it

options:
  -h, --help  show this help message and exit

RawTextHelpFormatter maintains whitespace for all sorts of help text, including argument descriptions.

ArgumentDefaultsHelpFormatter automatically adds information about default values to each of the argument help messages:

auto parser = argparse::ArgumentParser("PROG")
        .formatter_class(argparse::ArgumentDefaultsHelpFormatter);
parser.add_argument("--foo").type<int>().default_value<int>(42).help("FOO!");
parser.add_argument("bar").nargs("*").default_value("1 2 3").help("BAR!");
parser.print_help();
usage: PROG [-h] [--foo FOO] [bar ...]

positional arguments:
  bar         BAR! (default: 1 2 3)

options:
  -h, --help  show this help message and exit
  --foo FOO   FOO! (default: 42)

MetavarTypeHelpFormatter uses the name of the type argument for each argument as the display name for its values (rather than using the dest as the regular formatter does):

auto parser = argparse::ArgumentParser("PROG")
        .formatter_class(argparse::MetavarTypeHelpFormatter);
parser.add_argument("--foo").type<int>();
parser.add_argument("bar").type<float>();
parser.print_help();
usage: PROG [-h] [--foo int] float

positional arguments:
  float

options:
  -h, --help  show this help message and exit
  --foo int

Note: You can use multiply types of formatting classes.

since v1.6.6: By default, RawDescriptionHelpFormatter and RawTextHelpFormatter replaces tab with 4 spaces expand. You can change amount of expanding spaces by defining ARGPARSE_TAB_SIZE value before #include <argparse/argparse.hpp> or add -DARGPARSE_TAB_SIZE=N to compile options.

since v1.8.0: By default, RawDescriptionHelpFormatter and RawTextHelpFormatter replaces tab with 4 spaces expand. You can change amount of expanding spaces by setting tab size value parser.formatter_class()._tab_size(N).

prefix_chars

Most command-line options will use - as the prefix, e.g. -f/--foo. Parsers that need to support different or additional prefix characters, e.g. for options like +f or /foo, may specify them using the prefix_chars setter function of the ArgumentParser:

auto parser = argparse::ArgumentParser("PROG").prefix_chars("-+");
parser.add_argument("+f");
parser.add_argument("++bar");
std::cout << parser.parse_args("+f X ++bar Y") << std::endl;
Namespace(f='X', bar='Y')

The prefix_chars argument defaults to "-". Supplying a set of characters that does not include - will cause -f/--foo options to be disallowed.

fromfile_prefix_chars

Sometimes, for example when dealing with a particularly long argument lists, it may make sense to keep the list of arguments in a file rather than typing it out at the command line. If the fromfile_prefix_chars setter function called of the ArgumentParser, then arguments that start with any of the specified characters will be treated as files, and will be replaced by the arguments they contain. For example:

$ cat args.txt
-f
bar
auto parser = argparse::ArgumentParser().fromfile_prefix_chars("@");
parser.add_argument("-f");
std::cout << parser.parse_args({ "-f", "foo", "@args.txt" }) << std::endl;
Namespace(f='bar')

Arguments read from a file must by default be one per line (but see also convert_arg_line_to_args()) and are treated as if they were in the same place as the original file referencing argument on the command line. So in the example above, the expression { "-f", "foo", "@args.txt" } is considered equivalent to the expression { "-f", "foo", "-f", "bar" }.

The fromfile_prefix_chars argument defaults to "", meaning that arguments will never be treated as file references.

argument_default

Generally, argument defaults are specified either by passing a default to add_argument() or by calling the set_defaults() methods with a specific set of name-value pairs. Sometimes however, it may be useful to specify a single parser-wide default for arguments. This can be accomplished by calling the argument_default() setter function of ArgumentParser. For example, to globally suppress attribute creation on parse_args() calls, we supply argument_default(argparse::SUPPRESS):

auto parser = argparse::ArgumentParser().argument_default(argparse::SUPPRESS);
parser.add_argument("--foo");
parser.add_argument("bar").nargs("?");

std::cout << parser.parse_args({ "--foo", "1", "BAR" }) << std::endl;
std::cout << parser.parse_args({ }) << std::endl;
Namespace(foo='1', bar='BAR')
Namespace()

conflict_handler

ArgumentParser objects do not allow two actions with the same option string. By default, ArgumentParser objects raise an exception if an attempt is made to create an argument with an option string that is already in use:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-f", "--foo").help("old foo help");
parser.add_argument("--foo").help("new foo help");
terminate called after throwing an instance of 'argparse::ArgumentError'
  what():  argparse::ArgumentError: argument --foo: conflicting option string: --foo

Sometimes (e.g. when using parents) it may be useful to simply override any older arguments with the same option string. To get this behavior, the value "resolve" can be supplied to the conflict_handler of ArgumentParser:

auto parser = argparse::ArgumentParser("PROG").conflict_handler("resolve");
parser.add_argument("-f", "--foo").help("old foo help");
parser.add_argument("--foo").help("new foo help");
parser.print_help();
usage: PROG [-h] [-f FOO] [--foo FOO]

options:
  -h, --help  show this help message and exit
  -f FOO      old foo help
  --foo FOO   new foo help

Note that ArgumentParser objects only remove an action if all of its option strings are overridden. So, in the example above, the old -f/--foo action is retained as the -f action, because only the --foo option string was overridden.

add_help

By default, ArgumentParser objects add an option which simply displays the parser’s help message. For example, consider a file named main.cpp containing the following code:

#include <argparse/argparse.hpp>

int main(int argc, char const* const argv[])
{
    auto parser = argparse::ArgumentParser(argc, argv);
    parser.add_argument("--foo").help("foo help");
    auto args = parser.parse_args();
    return 0;
}

If -h or --help is supplied at the command line, the ArgumentParser help will be printed:

$ g++ main.cpp
$ ./a.out --help
usage: a.out [-h] [--foo FOO]

options:
  -h, --help  show this help message and exit
  --foo FOO   foo help

Occasionally, it may be useful to disable the addition of this help option. This can be achieved by passing false to the add_help() setter function to ArgumentParser:

auto parser = argparse::ArgumentParser("PROG").add_help(false);
parser.add_argument("--foo").help("foo help");
parser.print_help();
usage: PROG [--foo FOO]

options:
  --foo FOO  foo help

The help option is typically -h/--help. The exception to this is if the prefix_chars is specified and does not include -, in which case -h and --help are not valid options. In this case, the first character in prefix_chars is used to prefix the help options:

auto parser = argparse::ArgumentParser("PROG").prefix_chars("+/");
parser.print_help();
usage: PROG [+h]

options:
  +h, ++help  show this help message and exit

allow_abbrev

Normally, when you pass an argument list to the parse_args() method of an ArgumentParser, it recognizes abbreviations of long options.

This feature can be disabled by setting allow_abbrev to false:

auto parser = argparse::ArgumentParser("PROG").allow_abbrev(false);
parser.add_argument("--foobar").action("store_true");
parser.add_argument("--foonley").action("store_false");
parser.parse_args("--foon");
usage: PROG [-h] [--foobar] [--foonley]
PROG: error: unrecognized arguments: --foon

exit_on_error

Normally, when you pass an invalid argument list to the parse_args() method of an ArgumentParser, it will exit with error info.

If the user would like to catch errors manually, the feature can be enabled by setting exit_on_error() to false:

auto parser = argparse::ArgumentParser().exit_on_error(false);
parser.add_argument();
try {
    parser.parse_args("");
} catch (...) {
    std::cout << "Catching an error" << std::endl;
}
Catching an error

environment variables

ArgumentParser can hold environment variables (from envp[]) and have have_env and get_env functions to work with them

#include <iostream>

#include <argparse/argparse.hpp>

int main(int argc, char const* const argv[], char const* const envp[])
{
    auto parser = argparse::ArgumentParser(argc, argv, envp);
    if (parser.have_env("FOO")) {
        std::cout << parser.get_env("FOO") << std::endl;
    }
    return 0;
}

output_width

By default, usage and argument help messages are aligned to the terminal width (if possible otherwise to width 80). This behavior can be changed by setting a specific value to output_width setter function (note than the minimum value is 33).

Note: If you don't want to use terminal size auto-detection feature (for example to avoid using platform specific header files, namely <Windows.h> on OS Windows), define ARGPARSE_DISABLE_TERMINAL_SIZE_DETECTION before #include <argparse/argparse.hpp> or add -DARGPARSE_DISABLE_TERMINAL_SIZE_DETECTION to compile options.

handle

  • ArgumentParser::handle(std::function<void(std::string const&)> func)

Called when the parser is executed and passed the name (for subparsers) or prog (for main parser) of the ArgumentParser.

#include <iostream>

#include <argparse/argparse.hpp>

int main(int argc, char const* const argv[])
{
    auto parser = argparse::ArgumentParser(argc, argv)
            .handle([] (std::string const& value)
    {
        std::cout << "Main parser handle: " << value << std::endl;
    });
    parser.add_argument("--foo").action("store_true").help("foo help");
    
    auto& subparsers = parser.add_subparsers().help("sub-command help");
    
    auto& parser_a = subparsers.add_parser("a").help("a help")
            .handle([] (std::string const&) { std::cout << "Parser A handle" << std::endl; });
    parser_a.add_argument("bar").help("bar help");
    
    auto& parser_b = subparsers.add_parser("b").help("b help")
            .handle([] (std::string const& value) 
    { 
        std::cout << "Parser B handle " << value << std::endl; 
    });
    parser_b.add_argument("--baz").choices("XYZ").help("baz help");
    
    parser.parse_args();

    return 0;
}
  • ArgumentParser::handle(std::function<void(argparse::Namespace const&)> func)

Called when the parser is executed and passed the namespace of the parser.

#include <iostream>

#include <argparse/argparse.hpp>

int main(int argc, char const* const argv[])
{
    auto parser = argparse::ArgumentParser(argc, argv)
            .handle([] (argparse::Namespace const& args)
    {
        std::cout << "foo: " << args.get<bool>("foo") << std::endl;
    });
    parser.add_argument("--foo").action("store_true").help("foo help");
    
    auto& subparsers = parser.add_subparsers().help("sub-command help");
    
    auto& parser_a = subparsers.add_parser("a").help("a help");
    parser_a.add_argument("bar").help("bar help");
    parser_a.handle([] (argparse::Namespace const& args)
    {
        std::cout << "bar: " << args.get<uint32_t>("bar") << std::endl;
    });
    
    auto& parser_b = subparsers.add_parser("b").help("b help");
    parser_b.add_argument("--baz").choices("XYZ").help("baz help");
    parser_b.handle([] (argparse::Namespace const& args)
    {
        std::cout << "baz: " << args.get<std::string>("baz") << std::endl;
    });
    
    parser.parse_args();

    return 0;
}

The add_argument() method

Define how a single command-line argument should be parsed. Each parameter has its own more detailed description below, but in short they are:

Same as in python's argparse:

  • name or flags - Either a name or a list of option strings, e.g. foo, foo= or -f, --foo.
  • action - The basic type of action to be taken when this argument is encountered at the command line.
  • nargs - The number of command-line arguments that should be consumed.
  • const_value - A constant value required by some action and nargs selections.
  • default_value - The value produced if the argument is absent from the command line and if it is absent from the namespace object.
  • type - The type to which the command-line argument should be converted.
  • choices - A container of the allowable values for the argument.
  • required - Whether or not the command-line option may be omitted (optionals only).
  • help - A brief description of what the argument does.
  • metavar - A name for the argument in usage messages.
  • dest - The name of the attribute to be added to the object returned by parse_args().

Aditional parameters of current argparse:

  • implicit_value - The implicit value of the argument, if the argument is present and if it is not read any value from command line.
  • handle - A handler to be called when the argument is present.

The following sections describe how each of these are used.

name or flags

The add_argument() method must know whether an optional argument, like -f or --foo, or a operand argument (since v1.8.0), like an environment value baz=BAZ, or a positional argument, like a list of filenames, is expected. The arguments passed to add_argument() must therefore be either a series of flags, or a simple argument name.

For example, an optional argument could be created like:

parser.add_argument("-f", "--foo");

while a operand argument could be created like (by default required = true):

parser.add_argument("baz=").required(false);

while a positional argument could be created like:

parser.add_argument("bar");

Operand argument restrictions:

  • argument can have only one flag
  • actions "store" and "language" is allowed
  • nargs is not allowed
  • const_value is not allowed
  • metavar with single value is allowed

When parse_args() is called, optional arguments will be identified by the - prefix, operand arguments will be identified by the = suffix, and the remaining arguments will be assumed to be positional:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-f", "--foo");
parser.add_argument("baz=").required(false);
parser.add_argument("bar");

std::cout << parser.parse_args({ "BAR" }) << std::endl;
std::cout << parser.parse_args({ "BAR", "baz=BAZ" }) << std::endl;
std::cout << parser.parse_args({ "BAR", "--foo", "FOO" }) << std::endl;
std::cout << parser.parse_args({ "--foo", "FOO" }) << std::endl;
Namespace(foo=None, baz=None, bar='BAR')
Namespace(foo=None, baz='BAZ', bar='BAR')
Namespace(foo='FOO', baz=None, bar='BAR')
usage: PROG [-h] [-f FOO] [baz=BAZ] bar
PROG: error: the following arguments are required: bar

action

ArgumentParser objects associate command-line arguments with actions. These actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by parse_args(). The action setter function specifies how the command-line arguments should be handled. The supplied actions are:

  • "store" - This just stores the argument’s value. This is the default action. For example:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo");
std::cout << parser.parse_args("--foo 1") << std::endl;
Namespace(foo='1')
  • "store_const" - This stores the value specified by the const_value setter function; note that the const_value argument defaults to "". The "store_const" action is most commonly used with optional arguments that specify some sort of flag. For example:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action("store_const").const_value(42);
std::cout << parser.parse_args("--foo") << std::endl;
Namespace(foo='42')
  • "store_true" and "store_false" - These are special cases of "store_const" used for storing the values true and false respectively. In addition, they create default values of false and true respectively. For example:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action("store_true");
parser.add_argument("--bar").action("store_false");
parser.add_argument("--baz").action("store_false");
std::cout << parser.parse_args("--foo --bar") << std::endl;
Namespace(foo=true, bar=false, baz=true)
  • "append" - This stores a list, and appends each argument value to the list. This is useful to allow an option to be specified multiple times. Example usage:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action("append");
std::cout << parser.parse_args("--foo 1 --foo 2") << std::endl;
Namespace(foo=['1', '2'])
  • "append_const" - This stores a list, and appends the value specified by the const_value argument to the list; note that the const_value argument defaults to "". The "append_const" action is typically useful when multiple arguments need to store constants to the same list. For example:
auto parser = argparse::ArgumentParser();
parser.add_argument("--str").action("append_const").const_value("str");
parser.add_argument("--int").action("append_const").const_value("int");
std::cout << parser.parse_args("--str --int") << std::endl;
Namespace(str=['str'], int=['int'])
  • "extend" - This stores a list, and extends each argument value to the list. Example usage:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action("extend").nargs("+");
std::cout << parser.parse_args({ "--foo", "f1", "--foo", "f2", "f3", "f4" }) << std::endl;
Namespace(foo=['f1', 'f2', 'f3', 'f4'])
  • "count" - This counts the number of times a keyword argument occurs. For example, this is useful for increasing verbosity levels:
auto parser = argparse::ArgumentParser();
parser.add_argument("--verbose", "-v").action("count");
std::cout << parser.parse_args({ "-vvv" }) << std::endl;
Namespace(verbose=3)
  • "help" - This prints a complete help message for all the options in the current parser and then exits. By default a help action is automatically added to the parser. See ArgumentParser for details of how the output is created.
  • "version" - This expects to set a version argument in the add_argument() call, and prints version information and exits when invoked:
auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("--version").action("version").version("%(prog)s 2.0");
std::cout << parser.parse_args({ "--version" }) << std::endl;
PROG 2.0
  • "language" (since v1.7.1) - This stores language value, which is used for help printing. Also, help messages can be specified for each language.
#include <argparse/argparse.hpp>

int main(int argc, char const* const argv[])
{
    auto parser = argparse::ArgumentParser(argc, argv)
            .prog("prog")
            .add_help(false)
            .description("description")
            .description("la description", "fr")
            .description("beschreibung", "de")
            .description("popis", "cz")
            .optionals_title("arguments facultatifs", "fr")
            .optionals_title("optionale argumente", "de")
            .optionals_title("volitelné argumenty", "cz")
            .epilog("epilog")
            .epilog("épilogue", "fr")
            .epilog("epilog", "de")
            .epilog("epilog", "cz");
    parser.add_argument("-h", "--help")
            .action(argparse::help)
            .help("show this help message and exit")
            .help("afficher ce message d'aide et quitter", "fr")
            .help("diese hilfemeldung anzeigen und beenden", "de")
            .help("zobrazit tuto nápovědu a odejít", "cz");
    parser.add_argument("-l", "--lang")
            .action(argparse::language)
            .choices({ "fr", "de", "cz" })
            .help("set language")
            .help("définir la langue", "fr")
            .help("sprache einstellen", "de")
            .help("nastavit jazyk", "cz");
    parser.add_argument("--foo")
            .help("foo help")
            .help("foo aider", "fr")
            .help("foo hilfe", "de")
            .help("foo pomoc", "cz");

    parser.parse_args();

    return 0;
}
// default usage
./a.out -h
usage: prog [-h] [-l {fr,de,cz}] [--foo FOO]

description

options:
  -h, --help            show this help message and exit
  -l {fr,de,cz}, --lang {fr,de,cz}
                        set language
  --foo FOO             foo help

epilog

// -l fr
./a.out -l fr -h
usage: prog [-h] [-l {fr,de,cz}] [--foo FOO]

la description

arguments facultatifs:
  -h, --help            afficher ce message d'aide et quitter
  -l {fr,de,cz}, --lang {fr,de,cz}
                        définir la langue
  --foo FOO             foo aider

épilogue

// -l de
./a.out -l de -h
usage: prog [-h] [-l {fr,de,cz}] [--foo FOO]

beschreibung

optionale argumente:
  -h, --help            diese hilfemeldung anzeigen und beenden
  -l {fr,de,cz}, --lang {fr,de,cz}
                        sprache einstellen
  --foo FOO             foo hilfe

epilog

// -l cz
./a.out -l cz -h
usage: prog [-h] [-l {fr,de,cz}] [--foo FOO]

popis

volitelné argumenty:
  -h, --help            zobrazit tuto nápovědu a odejít
  -l {fr,de,cz}, --lang {fr,de,cz}
                        nastavit jazyk
  --foo FOO             foo pomoc

epilog
  • argparse::BooleanOptionalAction - The BooleanOptionalAction is available in argparse and adds support for boolean actions such as --foo and --no-foo:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action(argparse::BooleanOptionalAction);
std::cout << parser.parse_args({ "--no-foo" }) << std::endl;
Namespace(foo=false)

nargs

ArgumentParser objects usually associate a single command-line argument with a single action to be taken. The nargs keyword argument associates a different number of command-line arguments with a single action. The supported values are:

  • N (an integer). N arguments from the command line will be gathered together into a list. For example:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").nargs(2);
parser.add_argument("bar").nargs(1);
std::cout << parser.parse_args("c --foo a b") << std::endl;
Namespace(foo=['a', 'b'], bar=['c'])

Note that nargs=1 produces a list of one item. This is different from the default, in which the item is produced by itself.

  • "?" (or zero_or_one() or optional()). One argument will be consumed from the command line if possible, and produced as a single item. If no command-line argument is present, the value from default_value will be produced. Note that for optional arguments, there is an additional case - the option string is present but not followed by a command-line argument. In this case the value from const_value will be produced. Some examples to illustrate this:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").nargs("?").const_value("c").default_value("d");
parser.add_argument("bar").nargs("?").default_value("d");
std::cout << parser.parse_args({ "XX", "--foo", "YY" }) << std::endl;
std::cout << parser.parse_args({ "XX", "--foo" }) << std::endl;
std::cout << parser.parse_args({ }) << std::endl;
Namespace(foo='YY', bar='XX')
Namespace(foo='c', bar='XX')
Namespace(foo='d', bar='d')
  • "*" (or zero_or_more()). All command-line arguments present are gathered into a list. Note that it generally doesn’t make much sense to have more than one positional argument with nargs("*"), but multiple optional arguments with nargs("*") is possible. For example:
auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").nargs("*");
parser.add_argument("--bar").nargs("*");
parser.add_argument("baz").nargs("*");
std::cout << parser.parse_args("a b --foo x y --bar 1 2") << std::endl;
Namespace(foo=['x', 'y'], bar=['1', '2'], baz=['a', 'b'])
  • "+" (or one_or_more()). Just like "*", all command-line args present are gathered into a list. Additionally, an error message will be generated if there wasn’t at least one command-line argument present. For example:
auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("foo").nargs("+");
std::cout << parser.parse_args("a b") << std::endl;
std::cout << parser.parse_args("") << std::endl;
Namespace(foo=['a', 'b'])
usage: PROG [-h] foo [foo ...]
PROG: error: the following arguments are required: foo
  • argparse::REMAINDER (or remainder()). All the remaining command-line arguments are gathered into a list. This is commonly useful for command line utilities that dispatch to other command line utilities:
auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("--foo");
parser.add_argument("command");
parser.add_argument("args").remainder();
std::cout << parser.parse_args("--foo B cmd --arg1 XX ZZ") << std::endl;
Namespace(foo='B', command='cmd', args=['--arg1', 'XX', 'ZZ'])

If the nargs argument is not provided, the number of arguments consumed is determined by the action. Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.

const_value

The const_value argument of add_argument() is used to hold constant values that are not read from the command line but are required for the various ArgumentParser actions. The two most common uses of it are:

  • When add_argument() is called with action("store_const") or action("append_const"). These actions add the const_value to one of the attributes of the object returned by parse_args(). See the action description for examples. If const_value is not provided to add_argument(), it will receive a default value of "".
  • When add_argument() is called with option strings (like -f or --foo) and nargs("?"). This creates an optional argument that can be followed by zero or one command-line arguments. When parsing the command line, if the option string is encountered with no command-line argument following it, the value of const_value will be assumed to be "" instead. See the nargs description for examples.

default_value

All optional arguments and some positional arguments may be omitted at the command line. The default_value argument of add_argument(), whose value defaults to "", specifies what value should be used if the command-line argument is not present. For optional arguments, the default_value is used when the option string was not present at the command line:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").default_value(42);
std::cout << parser.parse_args({ "--foo", "2" }) << std::endl;
std::cout << parser.parse_args({ }) << std::endl;
Namespace(foo='2')
Namespace(foo='42')

If the target namespace already has an attribute set, the action default will not over write it:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").default_value(42);
auto const args = parser.parse_args({ "--foo", "101" });
std::cout << args << std::endl;
std::cout << parser.parse_args({ }, args) << std::endl;
Namespace(foo='101')
Namespace(foo='101')

For positional arguments with nargs equal to "?" or "*", the default_value is used when no command-line argument was present:

auto parser = argparse::ArgumentParser();
parser.add_argument("foo").nargs("?").default_value(42);
std::cout << parser.parse_args({ "a" }) << std::endl;
std::cout << parser.parse_args({ }) << std::endl;
Namespace(foo='a')
Namespace(foo='42')

Providing default_value(argparse::SUPPRESS) causes no attribute to be added if the command-line argument was not present:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").default_value(argparse::SUPPRESS);
std::cout << parser.parse_args({ }) << std::endl;
std::cout << parser.parse_args({ "--foo", "1" }) << std::endl;
Namespace()
Namespace(foo='1')

type

The parser reads command-line arguments in as simple strings. The type function for add_argument() allows any necessary type-checking at Namespace::get call. Type-checking is based on basic type comparison (note: basic type for std::string is std::string):

Argument::type Basic type Namespace::get
bool bool bool, stl_container< bool >
int int int, stl_container< int >
float float float, stl_container< float >
double double double, stl_container< double >
std::string std::string std::string, stl_container< std::string >
std::pair< T, U > std::pair< T, U > std::pair< T, U >, stl_map< T, U >, stl_container< std::pair< T, U > >
std::tuple< ... > std::tuple< ... > std::tuple< ... >, stl_container< std::tuple< ... > >
stl_container< T > T T, stl_container< T >
stl_map< T, U > std::pair< T, U > std::pair< T, U >, stl_map< T, U >, stl_container< std::pair< T, U > >

Note: when type(std::string) are called, type value don't used for type-checking, but used by MetavarTypeHelpFormatter.

Note: when default_value, const_value or implicit_value are called with non-string value, type value auto-detected.

auto parser = argparse::ArgumentParser();
parser.add_argument("foo").type<std::vector<int> >(); // basic type -> int
parser.add_argument("bar").type<std::string>(); // basic type -> std::string

auto const args = parser.parse_args("42 foobar");
auto foo = args.get<int>("foo"); // OK. basic type -> int = int
auto str = args.get<std::string>("foo"); // ERROR. basic type -> std::string != int
auto bar = args.get<std::vector<std::string> >("bar"); // OK. basic type -> std::string

The bool type is not recommended as a type converter. All it does is convert empty strings to false and non-empty strings to true. This is usually not what is desired.

For type checkers that simply check against a fixed set of values, consider using the choices function instead.

choices

Some command-line arguments should be selected from a restricted set of values. These can be handled by passing a container object to the choices setter function to add_argument(). When the command line is parsed, argument values will be checked, and an error message will be displayed if the argument was not one of the acceptable values:

auto parser = argparse::ArgumentParser();
parser.add_argument("move").choices({ "rock", "paper", "scissors" });

std::cout << parser.parse_args({ "rock" }) << std::endl;
std::cout << parser.parse_args({ "fire" }) << std::endl;
Namespace(move='rock')
usage: untitled [-h] {rock,paper,scissors}
untitled: error: argument move: invalid choice: 'fire' (choose from 'rock', 'paper', 'scissors')

Note: Passing a std::string to choices as choices("ABC") is equivalent to passing a container of characters: choices({ "A", "B", "C" }).

Formatted choices overrides the default metavar which is normally derived from dest. This is usually what you want because the user never sees the dest parameter. If this display isn’t desirable (perhaps because there are many choices), just specify an explicit metavar.

required

In general, the argparse module assumes that flags like -f and --bar indicate optional arguments, which can always be omitted at the command line. To make an option required, true can be specified for the required setter function to add_argument():

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").required(true);

std::cout << parser.parse_args({ "--foo", "BAR" }) << std::endl;
std::cout << parser.parse_args({ }) << std::endl;
Namespace(foo='BAR')
usage: untitled [-h] --foo FOO
untitled: error: the following arguments are required: --foo

As the example shows, if an option is marked as required, parse_args() will report an error if that option is not present at the command line.

Note: Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.

help

The help value is a string containing a brief description of the argument. When a user requests help (usually by using -h or --help at the command line), these help descriptions will be displayed with each argument:

auto parser = argparse::ArgumentParser("frobble");
parser.add_argument("--foo").action("store_true").help("foo the bars before frobbling");
parser.add_argument("bar").nargs("+").help("one of the bars to be frobbled");
parser.parse_args({ "-h" });
usage: frobble [-h] [--foo] bar [bar ...]

positional arguments:
  bar         one of the bars to be frobbled

options:
  -h, --help  show this help message and exit
  --foo       foo the bars before frobbling

The help strings can include various format specifiers to avoid repetition of things like the program name or the argument default. The available specifiers include the program name, %(prog)s and argument default, %(default)s:

auto parser = argparse::ArgumentParser("frobble");
parser.add_argument("bar").nargs("?").default_value(42)
        .help("the bar to %(prog)s (default: %(default)s)");
parser.print_help();
usage: frobble [-h] [bar]

positional arguments:
  bar         the bar to frobble (default: 42)

options:
  -h, --help  show this help message and exit

argparse supports silencing the help entry for certain options, by setting the help value to argparse::SUPPRESS:

auto parser = argparse::ArgumentParser("frobble");
parser.add_argument("--foo").help(argparse::SUPPRESS);
parser.print_help();
usage: frobble [-h]

options:
  -h, --help  show this help message and exit

metavar

When ArgumentParser generates help messages, it needs some way to refer to each expected argument. By default, ArgumentParser objects use the dest value as the "name" of each object. By default, for positional argument actions, the dest value is used directly, and for optional argument actions, the dest value is uppercased. So, a single positional argument with dest("bar") will be referred to as bar. A single optional argument --foo that should be followed by a single command-line argument will be referred to as FOO. An example:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo");
parser.add_argument("bar");
std::cout << parser.parse_args("X --foo Y") << std::endl;
parser.print_help();
Namespace(foo='Y', bar='X')
usage: untitled [-h] [--foo FOO] bar

positional arguments:
  bar

options:
  -h, --help  show this help message and exit
  --foo FOO

An alternative name can be specified with metavar:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").metavar("YYY");
parser.add_argument("bar").metavar("XXX");
std::cout << parser.parse_args("X --foo Y") << std::endl;
parser.print_help();
Namespace(foo='Y', bar='X')
usage: untitled [-h] [--foo YYY] XXX

positional arguments:
  XXX

options:
  -h, --help  show this help message and exit
  --foo YYY

Note that metavar only changes the displayed name - the name of the attribute on the parse_args() object is still determined by the dest value.

Different values of nargs may cause the metavar to be used multiple times. Providing a tuple to metavar specifies a different display for each of the arguments:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-x").nargs(2);
parser.add_argument("--foo").nargs(2).metavar({ "bar", "baz" });
parser.print_help();
usage: PROG [-h] [-x X X] [--foo bar baz]

options:
  -h, --help     show this help message and exit
  -x X X
  --foo bar baz

dest

Most ArgumentParser actions add some value as an attribute of the object returned by parse_args(). The name of this attribute is determined by the dest argument of add_argument(). For positional argument actions, dest is normally supplied as the first argument to add_argument():

auto parser = argparse::ArgumentParser();
parser.add_argument("bar");
std::cout << parser.parse_args("XXX") << std::endl;
Namespace(bar='XXX')

For optional argument actions, the value of dest is normally inferred from the option strings. ArgumentParser generates the value of dest by taking the first long option string and stripping away the initial -- string. If no long option strings were supplied, dest will be derived from the first short option string by stripping the initial - character. The examples below illustrate this behavior:

auto parser = argparse::ArgumentParser();
parser.add_argument("-f", "--foo-bar", "--foo");
parser.add_argument("-x", "-yy");
std::cout << parser.parse_args("-f 1 -x 2") << std::endl;
std::cout << parser.parse_args("--foo 1 -yy 2") << std::endl;
Namespace(foo-bar='1', x='2')
Namespace(foo-bar='1', x='2')

dest allows a custom attribute name to be provided:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").dest("bar");
std::cout << parser.parse_args("--foo XXX") << std::endl;
Namespace(bar='XXX')

implicit_value

This is an alternative for the const_value for optional arguments (const_value works only for nargs("?"), implicit_value works with nargs("?") and nargs("*"))

handle

  • Argument::handle(std::function<void(std::string const&)> func) Called when the argument is present and passed the value of the argument. Preferably for value-dependent arguments (Action: "store", "store_const", "append", "append_const" or "extend")

For value-independent arguments gets const_value (Action: "store_true", "store_false", argparse::BooleanOptionalAction) or empty string (Action: "count")

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action("store_true")
        .handle([] (std::string const& value)
{ std::cout << "Handle value '" << value << "'" << std::endl; });
parser.add_argument("--bar").action("store_false")
        .handle([] (std::string const& value)
{ std::cout << "Handle value '" << value << "'" << std::endl; });
parser.add_argument("--baz").action("count")
        .handle([] (std::string const& value)
{ std::cout << "Handle value '" << value << "'" << std::endl; });
parser.parse_args("--foo --bar --baz");
Handle value '1'
Handle value ''
Handle value ''

Note: Empty strings converts to false and non-empty strings converts to true.

format specifiers

Supported Argument format specifiers:

  • %(choices)s
  • %(const)s
  • %(default)s
  • %(dest)s
  • %(help)s
  • %(metavar)s
  • %(nargs)s
  • %(option_strings)s
  • %(required)s
  • %(type)s

The parse_args() method

ArgumentParser::parse_args(args, namespace)

Convert argument strings to objects and assign them as attributes of the namespace. Return the populated namespace.

Previous calls to add_argument() determine exactly what objects are created and how they are assigned. See the documentation for add_argument() for details.

  • args - List of strings to parse (can be a string, in which case it is split into a list of strings by whitespaces). The default is taken from argv.
  • namespace - An object to take the attributes. The default is a new empty Namespace object.

Option value syntax

The parse_args() method supports several ways of specifying the value of an option (if it takes one). In the simplest case, the option and its value are passed as two separate arguments:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-x");
parser.add_argument("--foo");
std::cout << parser.parse_args({ "-x", "X" }) << std::endl;
std::cout << parser.parse_args({ "--foo", "FOO" }) << std::endl;
Namespace(x='X', foo=None)
Namespace(x=None, foo='FOO')

For long options (options with names longer than a single character), the option and value can also be passed as a single command-line argument, using = to separate them:

std::cout << parser.parse_args({ "--foo=FOO" }) << std::endl;
Namespace(x=None, foo='FOO')

For short options (options only one character long), the option and its value can be concatenated:

std::cout << parser.parse_args({ "-x=X" }) << std::endl;
Namespace(x='X', foo=None)

Several short options can be joined together, using only a single - prefix, as long as only the last option (or none of them) requires a value:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-x").action("store_true");
parser.add_argument("-y").action("store_true");
parser.add_argument("-z");
std::cout << parser.parse_args({ "-xyzZ" }) << std::endl;
Namespace(x=true, y=true, z='Z')

Invalid arguments

While parsing the command line, parse_args() checks for a variety of errors, including ambiguous options, invalid types, invalid options, wrong number of positional arguments, etc. When it encounters such an error, it exits and prints the error along with a usage message:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("--foo").type<int>();
parser.add_argument("bar").nargs("?");
// invalid type
parser.parse_args({ "--foo", "spam" }).get<int>("foo");
// invalid option
parser.parse_args({ "--bar" });
// wrong number of arguments
parser.parse_args({ "spam", "badger" });
terminate called after throwing an instance of 'argparse::TypeError'
  what():  TypeError: invalid int value: 'spam'
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: unrecognized arguments: --bar
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: unrecognized arguments: badger

Argument containing -

The parse_args() method attempts to give errors whenever the user has clearly made a mistake, but some situations are inherently ambiguous. For example, the command-line argument -1 could either be an attempt to specify an option or an attempt to provide a positional argument. The parse_args() method is cautious here: positional arguments may only begin with - if they look like negative numbers and there are no options in the parser that look like negative numbers:

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-x");
parser.add_argument("foo").nargs("?");
// no negative number options, so -1 is a positional argument
std::cout << parser.parse_args({ "-x", "-1" }) << std::endl;
// no negative number options, so -1 and -5 are positional arguments
std::cout << parser.parse_args({ "-x", "-1", "-5" }) << std::endl;
Namespace(foo=None, x='-1')
Namespace(foo='-5', x='-1')
auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-1").dest("one");
parser.add_argument("foo").nargs("?");
// negative number options present, so -1 is an option
std::cout << parser.parse_args({ "-1", "X" }) << std::endl;
// negative number options present, so -2 is an option
std::cout << parser.parse_args({ "-2" }) << std::endl;
// negative number options present, so both -1s are options
std::cout << parser.parse_args({ "-1", "-1" }) << std::endl;
Namespace(one='X', foo=None)
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: unrecognized arguments: -2
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: argument -1: expected one argument

If you have positional arguments that must begin with - and don’t look like negative numbers, you can insert the pseudo-argument "--" which tells parse_args() that everything after that is a positional argument:

std::cout << parser.parse_args({ "--", "-f" }) << std::endl;
Namespace(one=None, foo='-f')

Argument abbreviations (prefix matching)

The parse_args() method by default allows long options to be abbreviated to a prefix, if the abbreviation is unambiguous (the prefix matches a unique option):

auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("-bacon");
parser.add_argument("-badger");
std::cout << parser.parse_args("-bac MMM") << std::endl;
std::cout << parser.parse_args("-bad WOOD") << std::endl;
std::cout << parser.parse_args("-ba BA") << std::endl;
Namespace(bacon='MMM', badger=None)
Namespace(bacon=None, badger='WOOD')
usage: PROG [-h] [-bacon BACON] [-badger BADGER]
PROG: error: ambiguous option: '-ba' could match -bacon, -badger

An error is produced for arguments that could produce more than one options. This feature can be disabled by setting allow_abbrev to false.

The Namespace object

class argparse::Namespace

Simple class used by default by parse_args() to create an object holding attributes and return it. To get attributes use get<T>(name) (returns T type value) or try_get<T>(name) (returns std::optional type value, for C++17 and later) functions. To check if value exists before get calling, use exists(name) function.

Note: exists(name) is true if any value was holded, otherwise it returns false and get<T> returns default value T() (if argument with name exists in Namespace) or throws an error (if Namespace don't have arguments with name); try_get<T> returns non std::nullopt value if any value was holded (exists = true), otherwise it returns std::nullopt (exists = false).

auto parser = argparse::ArgumentParser(argc, argv);
parser.add_argument("--foo").action("store_true").help("foo help");

auto& subparsers = parser.add_subparsers().dest("sub").help("sub-command help");

auto& parser_a = subparsers.add_parser("a").help("a help");
parser_a.add_argument("bar").help("bar help");

auto& parser_b = subparsers.add_parser("b").help("b help");
parser_b.add_argument("--baz").choices("XYZ").help("baz help");

auto const args = parser.parse_args();

std::cout << "foo: " << args.get<bool>("foo") << std::endl;
std::cout << "foo: " << args.to_string("foo") << std::endl;
if (args.exists("sub")) {
    std::cout << "sub: " << args.get<std::string>("sub") << std::endl;
}
if (args.exists("bar")) {
    std::cout << "bar: " << args.get<uint32_t>("bar") << std::endl;
}
if (args.exists("baz")) {
    std::cout << "baz: " << args.get<std::string>("baz") << std::endl;
}

Supported types:

  • base types (bool, integral types, floating point types, std::string)
  • byte types (char, signed/unsigned char, int8_t, uint8_t, std::byte (since C++17), char8_t (since C++20))
  • containers (std::array (since C++11), std::deque, std::forward_list (since C++11), std::list, std::multiset, std::priority_queue, std::queue, std::set, std::stack, std::vector, std::unordered_multiset (since C++11), std::unordered_set (since C++11))
  • containers with std::pair/std::tuple (since C++11)
  • 2 dimensional containers
  • mapped types (std::map, std::multimap, std::unordered_map (since C++11), std::unordered_multimap (since C++11))
  • std::pair
  • std::tuple (since C++11)
  • custom types

Example how to use custom type:

#include <iostream>

#include <argparse/argparse.hpp>

struct Coord
{
    Coord()
        : x(),
          y(),
          z()
    { }

    explicit Coord(int x, int y, int z)
        : x(x),
          y(y),
          z(z)
    { }

    inline void print() const
    {
        std::cout << "x=" << x << ";y=" << y << ";z=" << z << std::endl;
    }

    int x;
    int y;
    int z;
};

inline std::istream& operator >>(std::istream& is, Coord& c)
{
    is >> c.x >> c.y >> c.z;
    return is;
}

inline std::ostream& operator <<(std::ostream& os, Coord const& c)
{
    os << c.x << " " << c.y << " " << c.z;
    return os;
}

int main(int argc, char const* const argv[])
{
    auto parser = argparse::ArgumentParser();
    // it's recommended to pass each custom type value in quotes: 'value1 value2 ...'
    parser.add_argument("--coord").help("coord help");
    parser.add_argument("--const_coord").action("store_const").default_value(Coord(0, 0, 0))
            .const_value(Coord(1, 1, 1)).help("const coord help");

    auto const args = parser.parse_args("--coord='1 2 3'");

    auto c = args.get<Coord>("coord");
    c.print();
    auto c2 = args.get<Coord>("const_coord");
    c2.print();

    return 0;
}

Other utilities

Sub-commands

ArgumentParser::add_subparsers()

Many programs split up their functionality into a number of sub-commands, for example, the svn program can invoke sub-commands like svn checkout, svn update, and svn commit. Splitting up functionality this way can be a particularly good idea when a program performs several different functions which require different kinds of command-line arguments. ArgumentParser supports the creation of such sub-commands with the add_subparsers() method. The add_subparsers() method is normally called with no arguments and returns a special action object. This object has a single method, add_parser(), which takes a command name and returns an ArgumentParser object that can be modified as usual.

Description of supported parameters:

  • title - title for the sub-parser group in help output; by default "subcommands" if description is provided, otherwise uses title for positional arguments
  • description - description for the sub-parser group in help output, by default ""
  • prog - usage information that will be displayed with sub-command help, by default the name of the program and any positional arguments before the subparser argument
  • dest - name of the attribute under which sub-command name will be stored; by default "" and no value is stored
  • required - Whether or not a subcommand must be provided, by default false
  • help - help for sub-parser group in help output, by default ""
  • metavar - string presenting available sub-commands in help; by default it is "" and presents sub-commands in form {cmd1, cmd2, ..}

Some example usage:

// create the top-level parser
auto parser = argparse::ArgumentParser("PROG");
parser.add_argument("--foo").action("store_true").help("foo help");
auto& subparsers = parser.add_subparsers().help("sub-command help");
// create the parser for the "a" command
auto& parser_a = subparsers.add_parser("a").help("a help");
parser_a.add_argument("bar").help("bar help");
// create the parser for the "b" command
auto& parser_b = subparsers.add_parser("b").help("b help");
parser_b.add_argument("--baz").choices("XYZ").help("baz help");
// parse some argument lists
std::cout << parser.parse_args({ "a", "12" }) << std::endl;
std::cout << parser.parse_args({ "--foo", "b", "--baz", "Z" }) << std::endl;
Namespace(foo=false, bar='12')
Namespace(foo=true, baz='Z')

Note that the object returned by parse_args() will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the a command is specified, only the foo and bar attributes are present, and when the b command is specified, only the foo and baz attributes are present.

Similarly, when a help message is requested from a subparser, only the help for that particular parser will be printed. The help message will not include parent parser or sibling parser messages. (A help message for each subparser command, however, can be given by supplying to the help setter function to add_parser() as above.)

parser.parse_args({ "--help" });
usage: PROG [-h] [--foo] {a,b} ...

positional arguments:
  {a,b}       sub-command help
    a         a help
    b         b help

options:
  -h, --help  show this help message and exit
  --foo       foo help
parser.parse_args({ "a", "--help" });
usage: PROG a [-h] bar

positional arguments:
  bar         bar help

options:
  -h, --help  show this help message and exit
parser.parse_args({ "b", "--help" });
usage: PROG b [-h] [--baz {X,Y,Z}]

options:
  -h, --help     show this help message and exit
  --baz {X,Y,Z}  baz help

The add_subparsers() method also supports title and description arguments. When either is present, the subparser’s commands will appear in their own group in the help output. For example:

auto parser = argparse::ArgumentParser();
auto& subparsers = parser.add_subparsers("subcommands", "valid subcommands")
        .help("additional help");
subparsers.add_parser("foo");
subparsers.add_parser("bar");
parser.parse_args({ "-h" });
usage: untitled [-h] {foo,bar} ...

options:
  -h, --help  show this help message and exit

subcommands:
  valid subcommands

  {foo,bar}   additional help

Furthermore, add_parser supports an additional aliases argument, which allows multiple strings to refer to the same subparser. This example, like svn, aliases co as a shorthand for checkout:

auto parser = argparse::ArgumentParser();
auto& subparsers = parser.add_subparsers();
auto& checkout = subparsers.add_parser("checkout").aliases({ "co" });
checkout.add_argument("foo");
std::cout << parser.parse_args({ "co", "bar" }) << std::endl;
Namespace(foo='bar')

If it is necessary to check the name of the subparser that was invoked, the dest setter function to the add_subparsers() call will work:

auto parser = argparse::ArgumentParser();
auto& subparsers = parser.add_subparsers().dest("subparser_name");
auto& subparsers1 = subparsers.add_parser("1");
subparsers1.add_argument("-x");
auto& subparsers2 = subparsers.add_parser("2");
subparsers2.add_argument("y");
std::cout << parser.parse_args({ "2", "frobble" }) << std::endl;
Namespace(subparser_name='2', y='frobble')

Argument groups

ArgumentParser::add_argument_group(title = "", description = "")

By default, ArgumentParser groups command-line arguments into "positional arguments" and "options" when displaying help messages. When there is a better conceptual grouping of arguments than this default one, appropriate groups can be created using the add_argument_group() method:

auto parser = argparse::ArgumentParser("PROG").add_help(false);
auto& group = parser.add_argument_group("group");
group.add_argument("--foo").help("foo help");
group.add_argument("bar").help("bar help");
parser.print_help();
usage: PROG [--foo FOO] bar

group:
  --foo FOO  foo help
  bar        bar help

The add_argument_group() method returns an argument group object which has an add_argument() method just like a regular ArgumentParser. When an argument is added to the group, the parser treats it just like a normal argument, but displays the argument in a separate group for help messages. The add_argument_group() method accepts title and description arguments which can be used to customize this display:

auto parser = argparse::ArgumentParser("PROG").add_help(false);
auto& group1 = parser.add_argument_group("group1", "group1 description");
group1.add_argument("foo").help("foo help");
auto& group2 = parser.add_argument_group("group2", "group2 description");
group2.add_argument("--bar").help("bar help");
parser.print_help();
usage: PROG [--bar BAR] foo

group1:
  group1 description

  foo        foo help

group2:
  group2 description

  --bar BAR  bar help

Note that any arguments not in your user-defined groups will end up back in the usual "positional arguments" and "options" sections.

Mutual exclusion

ArgumentParser::add_mutually_exclusive_group(required = false)

Create a mutually exclusive group. argparse will make sure that only one of the arguments in the mutually exclusive group was present on the command line:

auto parser = argparse::ArgumentParser("PROG");
auto& group = parser.add_mutually_exclusive_group();
group.add_argument("--foo").action("store_true");
group.add_argument("--bar").action("store_false");
std::cout << parser.parse_args({ "--foo" }) << std::endl;
std::cout << parser.parse_args({ "--bar" }) << std::endl;
std::cout << parser.parse_args({ "--foo", "--bar" }) << std::endl;
Namespace(foo=true, bar=true)
Namespace(foo=false, bar=false)
usage: PROG [-h] [--foo | --bar]
PROG: error: argument --bar: not allowed with argument --foo

The add_mutually_exclusive_group() method also accepts a required argument, to indicate that at least one of the mutually exclusive arguments is required:

auto parser = argparse::ArgumentParser("PROG");
auto& group = parser.add_mutually_exclusive_group(true);
group.add_argument("--foo").action("store_true");
group.add_argument("--bar").action("store_false");
usage: PROG [-h] (--foo | --bar)
PROG: error: one of the arguments --foo --bar is required

Note that currently mutually exclusive argument groups do not support the title and description arguments of add_argument_group().

Parser defaults

ArgumentParser.set_defaults(pairs)

Most of the time, the attributes of the object returned by parse_args() will be fully determined by inspecting the command-line arguments and the argument actions. set_defaults() allows some additional attributes that are determined without any inspection of the command line to be added:

auto parser = argparse::ArgumentParser();
parser.add_argument("foo");
parser.set_defaults({ { "bar", "42" }, { "baz", "badger" } });
std::cout << parser.parse_args({ "736" }) << std::endl;
Namespace(foo='736', bar='42', baz='badger')

Note that parser-level defaults always override argument-level defaults:

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").default_value("bar");
parser.set_defaults({ { "foo", "spam" } });
std::cout << parser.parse_args({ }) << std::endl;
Namespace(foo='spam')

ArgumentParser.get_default(dest)

Get the default value for a namespace attribute, as set by either add_argument() or by set_defaults():

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").default_value("badger");
std::cout << parser.get_default("foo") << std::endl;
badger

Printing help

In most typical applications, parse_args() will take care of formatting and printing any usage or error messages. However, several formatting methods are available:

ArgumentParser::print_usage(os = std::cout)

Print a brief description of how the ArgumentParser should be invoked on the command line.

ArgumentParser::print_help(os = std::cout)

Print a help message, including the program usage and information about the arguments registered with the ArgumentParser.

There are also variants of these methods that simply return a string instead of printing it:

ArgumentParser::format_usage()

Return a string containing a brief description of how the ArgumentParser should be invoked on the command line.

ArgumentParser::format_help()

Return a string containing a help message, including the program usage and information about the arguments registered with the ArgumentParser.

Partial parsing

ArgumentParser::parse_known_args(args, namespace)

Sometimes a script may only parse a few of the command-line arguments, passing the remaining arguments on to another script or program. In these cases, the parse_known_args() method can be useful. It works much like parse_args() except that it does not produce an error when extra arguments are present. Instead, it returns a two item tuple containing the populated namespace and the list of remaining argument strings.

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo").action("store_true");
parser.add_argument("bar");
std::cout << parser.parse_known_args({ "--foo", "--badger", "BAR", "spam" }) << std::endl;
(Namespace(foo=true, bar='BAR'), ['--badger', 'spam'])

Warning: Prefix matching rules apply to parse_known_args(). The parser may consume an option even if it’s just a prefix of one of its known options, instead of leaving it in the remaining arguments list.

Customizing file parsing

ArgumentParser::convert_arg_line_to_args(arg_line)

Arguments that are read from a file (see the fromfile_prefix_chars function of the ArgumentParser) are read one argument per line. convert_arg_line_to_args() can be overridden for fancier reading.

This method takes a single argument arg_line which is a string read from the argument file. It returns a list of arguments parsed from this string. The method is called once per line read from the argument file, in order.

A useful override of this method is one that treats each space-separated word as an argument. The following example demonstrates how to do this:

class MyArgumentParser : public argparse::ArgumentParser
{
public:
    using argparse::ArgumentParser::ArgumentParser;

    inline std::vector<std::string>
    convert_arg_line_to_args(std::string const& arg_line) const override
    {
        char delim = ' ';
        std::vector<std::string> result;
        std::string value;
        for (auto c : arg_line) {
            if (c == delim) {
                if (!value.empty()) {
                    result.push_back(value);
                    value.clear();
                }
            } else {
                value += c;
            }
        }
        if (!value.empty()) {
            result.push_back(value);
            value.clear();
        }
        return result;
    }
};
...
// create custom parser
MyArgumentParser parser(argc, argv);
// next, edit parser's parameters / add arguments
parser.description("this program uses custom ArgumentParser");
parser.add_argument("-f", "--foo").help("foo help");

Exiting methods

ArgumentParser::exit(status = 0, message = "")

This method terminates the program, exiting with the specified status and, if given, it prints a message before that. The user can override this method to handle these steps differently:

class ErrorCatchingArgumentParser : public argparse::ArgumentParser
{
public:
    using argparse::ArgumentParser::ArgumentParser;

    void exit(int status, std::string const& message) const override
    {
        if (status) {
            throw std::logic_error("Exiting because of an error: " + message);
        }
        argparse::ArgumentParser::exit(status);
    }
};
...
// create custom parser
ErrorCatchingArgumentParser parser(argc, argv);
// next, edit parser's parameters / add arguments
parser.description("this program uses custom ArgumentParser");
parser.add_argument("-f", "--foo").help("foo help");

ArgumentParser::error(message)

This method prints a usage message including the message to the standard error and terminates the program with a status code of 2.

Intermixed parsing

ArgumentParser::parse_intermixed_args(args, namespace)

ArgumentParser::parse_known_intermixed_args(args, namespace)

A number of Unix commands allow the user to intermix optional arguments with positional arguments. The parse_intermixed_args() and parse_known_intermixed_args() methods support this parsing style.

These parsers do not support all the argparse features, and will raise exceptions if unsupported features are used. In particular, subparsers, argparse::REMAINDER, and mutually exclusive groups that include both optionals and positionals are not supported.

The following example shows the difference between parse_known_args() and parse_intermixed_args(): the former returns { "2", "3" } as unparsed arguments, while the latter collects all the positionals into rest.

auto parser = argparse::ArgumentParser();
parser.add_argument("--foo");
parser.add_argument("cmd");
parser.add_argument("rest").nargs("*");
std::cout << parser.parse_known_args("doit 1 --foo bar 2 3") << std::endl;
std::cout << parser.parse_intermixed_args("doit 1 --foo bar 2 3") << std::endl;
(Namespace(foo='bar', cmd='doit', rest=['1']), ['2', '3'])
Namespace(foo='bar', cmd='doit', rest=['1', '2', '3'])

parse_known_intermixed_args() returns a two item tuple containing the populated namespace and the list of remaining argument strings. parse_intermixed_args() raises an error if there are any remaining unparsed argument strings.