The command line parser allows you to easyly managed command line arguments of your programs.
The following features are available :
- multiple names for a flag (i.e --a-very-long-name, -shortname, --unotherone, etc)
- required flags that force the user to provide a value.
- vector of values as input of a flag
- automatic help flag generation.
First let's look at the anatomy of a flag.
It's a simple structure with the following required fields :
- cpp_tools::cl_parser::str_vec flags : a vector of strings with the different versions of the flag
- std::string description : the description of the flag that will appear in the help
- using type = float : the type of the flag
- type def = 1.0 : the default value of the flag (optional)
To use the library, two files are required cpp_tools/cl_parser/tcli.hpp and cpp_tools/cl_parser/help_descriptor.hpp
Now, let's have a look a a first example :
#include <cpp_tools/cl_parser/cl_parser.hpp>
struct n_count
{
// here, you specify several flags by providing an initializer list of strings
// to the flags variable.
cpp_tools::cl_parser::str_vec flags = {"--n-count", "-n"};
// then, you specify the description of the flag/s
std::string description = "An integer to catch.";
// register the type of the flag/s
using type = int;
// put the def variable to the default value of the flag (optional)
type def = 1;
};
// another example with some flaoting point type
struct delta
{
cpp_tools::cl_parser::str_vec flags = {"--delta", "-d"};
std::string description = "Delta to apply.";
using type = double;
type def = 0.1;
};Now let's add a required flag that will throw an exception if not provided
\\ you need to inherit from required_tag to register your flag as required.
struct input_file : cpp_tools::cl_parser::required_tag
{
cpp_tools::cl_parser::str_vec flags = {"--input-file", "-fin"};
std::string description = "Input filename.";
using type = std::string;
};After defining all of our flags, we create our parser:
auto main(int argc, char* argv[]) -> int
{
// Parameter handling, register all your flags and add the help flag for automated help.
auto parser = cpp_tools::cl_parser::make_parser( cpp_tools::cl_parser::help{}
, n_count{}
, delta{}
, input_file{});
// then, we ask the parser to parse argc and argv
parser.parse(argc, argv);
...
}Note that we added the cpp_tools::cl_parser::help{} flag to automatically generate the help command line arguments.
And finally we access the flag value by the get method as follows.
const auto n_count = parser.get<n_count>();
const auto file = parser.get<input_file>();The parameter description is aa class that exposes the following public interface.
typeargument typeflag(std::string) a vector of sting that contains the list of the optiondescription(std::string) (optional), argument default valuedef(optional) argument default valueflagenum -required(optional) the argument must be specified once -stackable(optional) the argument may be specified several time and the value are stacked -hidden(optional) the argument must be hidden in help message -flaggedbool typed parameter which value defaults tofalse.input_hint(std::string) the type of the parametertag-stackable_tag-required_tagif the parameter is mandatory.
We consider that the inputFile parameter is required to run the program. If the
struct inputFile {
using type = std::string; /*!< The type */
enum { required };
std::vector<std::string> flags = {"--input-file", "-fin", };
std::string description = "Input filename.";
std::string input_hint = "std::string";
};Another way is to inherit the required_tag
struct inputFile : cpp_tools::cl_parser::required_tag
{
cpp_tools::cl_parser::str_vec flags = {"--input-file", "-fin"};
std::string description = "Input filename.";
using type = std::string;
};
```
```bash
my_program --input-file results.csvIf --input-file is not in the command line an error occurs.
struct quiet {
using type = bool;
enum { flagged };
std::vector<std::string> flags = {"--quiet", "-q"};
std::string description = "No verbose node.";
};
```bash
my_program1 --quiet//
struct OutputFile {
using type = std::string;
cpp_tools::cl_parser::str_vec flags = {"--output-file", "-of"};
std::string description = "The output file name";
std::string input_hint = "std::string";
type def = "output.txt" ;
};if --output-file is specified with a name file we select this name and if teh option is not set then the name for teh OutputFile descriptor is the default value output.txt
my_program2 --output-file results.csvor
my_program2 --output-file results.csvNow we want to pass a set of values of the same type as an argument like the dimension of an array, point, ... Below, the structure center corresponds to a point of type double.
struct centre
{
cpp_tools::cl_parser::str_vec flags = {"--centre", "-c"}; /
std::string description = "the center of the final distribution";
std::string input_hint = "value,value,value";
using type = std::vector<double>;
};my_program --centre 0.0,1.0,2.0 - the
getmethod gets the value(s) for a given parameter.
const auto file = parser.get<input_file>();existsmethod checks whether option was specified in CLI
if (parser.exists<output_file>()) {
const auto output = parser.get<output_file>();
}