-
Notifications
You must be signed in to change notification settings - Fork 12
Argument Parser
Joshua Z. Zhang edited this page Oct 5, 2016
·
7 revisions
--long
--long=argument
--long argument
-a
-ab
-abc argument # only c take the argument
-a -b -c --long
- Long option start with '--', any length
- Short option start with '-', support single character only
The font on Ubuntu is not my taste, but whatever, just show you the animation first:
// test.cpp
#include "zupply.hpp"
zz::cfg::argParser parser;
// note that short key is a char, long key is a std::string
parser.add_opt_help('h', "help"); // use -h or --help
parser.add_opt_version('v', "version", "0.1"); // use -v or --version
bool flag;
parser.add_opt_flag('f', "flag", "this is a flag option", &flag);
// If you specify "-f" or "--flag" in arguments, the bool flag will be set to true, otherwise flag == false.
int i;
parser.add_opt_value('i', "integer", i, -1, "set integer value of i", "INT").require(); // require this option
double d;
parser.add_opt_value('d', "double", d, 0.0, "set double value of d", "DOUBLE");
// vector is also supported
std::vector<double> vd;
// let the option take at most 4 arguments and store them in vd
parser.add_opt_value(-1, "vector", vd, std::vector<double>(), "load a vector").set_max(4);
// use -1 to ignore short key, use "" to ignore long key
parser.parse(argc, argv); //done
// now you can use flag, i, d, vd variables.
- If you specified the destination like i/d/vd, they are automatically set after parse, you are good to go. (This is the recommended way, it requires you to set default value and do the right things for you)
- A second option is to retrieve by key, either short key or long key:
// get count of option
std::cout << parser.count("longkey") << std::endl;
// get the value
std::cout << parser["filename"].str() << std::endl;
std::cout << parser['a'].load<bool>() << std::endl;
- Another way to do it is to store the option after adding it, this is useful when you adding a placeholder option with no keys assgined:
auto& option1 = parser.add_opt(-1, "").set_help("filename, placeholder");
...
// after parse
// get count
std::cout << option1.get_count() << std::endl;
// get value
std::cout << option1.get_value() << std::endl;
...
Compile and test
>>test -i 100 -d 0.1 --vector 0.1 1.2
# After parse, i = 100, d = 0.1, vd = { 0.1, 1.2 }
>>test
# will generate error, because '-i' or '--integer' is required!
>>test --vector=0.1 1.2 2.3 3.4 4.5 5.6
# vd = { 0.1, 1.2, 2.3, 3.4 } because max size set to 4
std::cout << parser.get_help() << std::endl;
// if you have specified the option for help like: parser.add_opt_help('h', "help"); // use -h or --help
// then you can trigger it by calling -h/--help in arguments
Usage: test.exe [-hf] -i=<INT> [-d <DOUBLE>] [--vector <DVEC> {<DVEC>}...]
<file> <file> [--custom]
This is a demo argument parser
Required options:
-i, --integer=INT set integer value of i(default: -1)
<file> input filename(default: input_filename)
Optional options:
-h, --help print this help and exit
-f, --flag this is a flag option
-d, --double=DOUBLE set double value of d(default: 0)
--vector=DVEC load a vector(default: 0.1 0.2 )
<file> output filename(default: output_filename)
--custom custom option, print msg
if (parser.count_error() > 0) std::cout << parser.get_error() << std::endl;
cfg::ArgParser parser;
// add option for help
parser.add_opt_help('h', "help");
// add version info
parser.add_opt_version('v', "version", "0.1");
struct MyOption
{
bool flag;
int i;
double d;
};
struct MyOption op;
// add a flag option, when set, the target will be set to true, otherwise false
parser.add_opt_flag('f', "flag", "this is a flag option", &op.flag);
// add an option to set integer i, also set to required
parser.add_opt_value('i', "integer", op.i, -1, "set integer value of i", "INT").require();
// add an option to set double d
parser.add_opt_value('d', "double", op.d, 0.0, "set double value of d", "DOUBLE");
// we could also load arguments into vector
std::vector<double> vd;
// no short argument, maximum 4 arguments
parser.add_opt_value(-1, "vector", vd, std::vector<double>(), "load a vector").set_max(4);
// argparser support custom option with lambda function
parser.add_opt("custom").set_help("custom option").call([](){std::cout << "hey, called my custom stuff" << std::endl; });
// now parse the arguments
parser.parse(argc, argv);
// check errors
if (parser.count_error() > 0)
{
std::cout << parser.get_error() << std::endl;
// print help
std::cout << parser.get_help() << std::endl;
// continue or exit()??
exit(-1);
}
// op.d, op.flag, op.i, vd stores the arguments
std::cout << "flag: " << op.flag << std::endl;
std::cout << "i: " << op.i << std::endl;
std::cout << "d: " << op.d << std::endl;
std::cout << "vector: " << std::endl;
for (auto i = vd.begin(); i != vd.end(); ++i)
{
std::cout << *i << std::endl;
}
With add_opt_flag() and add_opt_value() you can handle most situations. However, it provide more advance features with the following public member functions:
function | description |
---|---|
ArgOption & set_help (std::string helpInfo) | Set help info for this option. |
ArgOption & require (bool require=true) | Set this option to required or not. After parsing arguments, if this set to required but not found, ArgParser will generate an error information. |
ArgOption & set_once (bool onlyOnce=true) | Set this option to allow option be called only once. This is set to disable accidentally set a variable multiply times. |
ArgOption & set_type (std::string type) | Set option variable type. Optional. Let user know what type this option take, INT, FLOAT, STRING... |
ArgOption & set_min (int minCount) | Set minimum number of argument this option take. |
ArgOption & set_max (int maxCount) | Set maximum number of argument this option take. |
ArgOption & call (std::function< void()> todo) | Set callback function when this option is triggered. |
ArgOption & call (std::function< void()> todo, std::function< void()> otherwise) | Set callback functions. Both TODO function and Default function required. If ArgParser detect this option, the TODO function will be called. Otherwise, the default callback function will be executed. |
These functions can be chained:
// Tip: use -1 for short option if you don't want to specify it.
parser.add_opt(-1, "long").set_help("what you want to tell about the opt)
.set_type("INT").set_min(2).set_max(4)
.call([](){std::cout << "found!";}, [](){std::cout << "not found!";})
.require();