A C++14 compliant command line parser.
- Strongly typed command line options
- Letter-based or string-based options
- Enforcing requirement of specific options
- Allowed values for a specific option
- Default values for a specific option
- Subparsing, various parsers that depend on the value of a preceding option
Branch | Build Status |
---|---|
master | |
feature |
OS | Compiler |
---|---|
Linux | Clang 8.X |
Linux | Clang 7.X |
Linux | Clang 6.X |
Linux | GCC 8.X |
Linux | GCC 7.X |
Linux | GCC 6.X |
Linux | GCC 5.X |
#include "argparse/argparse.h"
argparse::Parser p("my name", "my cool program");
- Starting value is "yaml" if no values are provided
- Provided value must be either
cpp
,yaml
, orpy
- The option can be specified with
--type <value>
or-t <value>
- The help text is displayed in a table when
-h
,--help
is provided or on error - The required flag tells the parser to enforce any options to be present
const auto type = p.add(argparse::Config<std::string>{
.default_value = "yaml",
.allowed_values = {"cpp", "yaml", "py"},
.name = "type",
.help = "Type of the input file",
.required = true,
.letter = 't',
});
- The configuration applies the same as a non positional
- The positional arguments are expected in the order they are added
const auto first = p.add_leading_positional(argparse::Config<std::string>{ .name = "first" });
const auto second = p.add_leading_positional(argparse::Config<std::string>{ .name = "second" });
const auto third = p.add_leading_positional(argparse::Config<std::string>{ .name = "third" });
// Expected call
<PROGRAM_NAME> <first VALUE> <second VALUE> <third VALUE>
- The configuration applies the same as a non positional
- This option can have multiple values
- It will parse all the values after the
--name
or-letter
flag until the next flag
const auto values = p.add_multivalent(argparse::Config<std::string>{ .name = "values" });
// Expected call
<PROGRAM_NAME> --values value1 value2 value3
- After all options are registered, the command line arguments need to be parsed
- Any additional arguments provided after
--
will be stored in a vector returned byparse
const auto &remaining_arguments = p.parse(argc, argv);
- Every
add
function returns aConstPlaceHolder<T>
- Every
add_multivalent
function returns aConstPlaceHolder<std::vector<T>>
- This placeholder is a
std::shared_ptr<optional<T>>
- The
std::shared_ptr
wrapper is so that the value can be populated at parsing - The
optional
second wrapper is to signify whether there exists a value - This library uses
tl::optional
as the optional implementation since C++14 does not support it yet tl::optional
// Example option
const auto option = p.add(argparse::Config<std::string>{ ... });
// We can assume the pointer is valid
assert(option);
// First we can check if the value exists
if (option->has_value()) {
...
}
// Next we can get a const reference to the value
const auto &value = option->value();
// Or use it directly
if (option->value() == "some expected value") {
...
}
- On any failure, errors are printed in red of the cause
- The usage, description, and information about the options are printed
- Then the program will throw a
std::runtime_error
exception
This is the help text from the sample program:
Usage: Sample Program [mode] [path] [--verbose] [--h] [--id] [--help]
Description: Testing...
Options:
--------------------------------------------------------------------------------------------------------------
|Required|Positional| Name |Letter| Type |Default| Help | Allowed Values |
--------------------------------------------------------------------------------------------------------------
| | | id | |int64_t | | some identification number | 1234 , 9999 , 127127127 |
| | |verbose| |uint64_t| 5 | | |
| x | 2 | path | | bool | 0 | | |
| x | 1 | mode | | string | |Operation mode of this program| a , c , b |
| | | help | h | bool | 0 | Show help message | |
--------------------------------------------------------------------------------------------------------------
- Suppose we wanted a specific argument to determine what options to parse
- For example we want different options for 3 different modes
- We can create this by using a subparser, then adding the different options to the subparsers and not the parent parser
- The value that the subparser will switch on is treated like a leading positional argument
- It must be specified first, prior to other options
// Create subparsers
auto &subparsers = p.add_subparser("mode", {"read", "write", "append"});
// Split the subparsers into individual parsers
auto &read = subparsers["read"];
auto &write = subparsers["write"];
auto &append = subparsers["append"];
// Add options for each subparser
const auto read_only_option = read.add(argparse::Config<std::string>{ .name = "read_only_option" });
const auto write_only_option = write.add(argparse::Config<std::string>{ .name = "write_only_option" });
const auto append_only_option = append.add(argparse::Config<std::string>{ .name = "append_only_option" });
// Expected call
<PROGRAM_NAME> <MODE> <MODE OPTIONS>
./sample read --read_only_option option_value
./sample write --write_only_option option_value
./sample append --append_only_option option_value
The add functions take a structure Config<T>
. To simplify / prettify the syntax, designated initializers are used in the examples when calling these functions to save a line from declaring the Config<T>
variable. With clang
the type of the desginated initializers can be deduced and the verbosity of argparse::Config<T>
is not necessary. However g++
fails to deduce these contexts, and so all examples and code in this library explicitly specify the object type. If the user is using clang
then these can be happily ommitted.
Example clang
:
const auto option = p.add<std::string>({ ... });
All of the above examples use std::string
as the option type but all fundamental types are supported as well.
To read more about how the library works, you can start with argparse.h.