Skip to content
Joshua Z. Zhang edited this page Oct 5, 2016 · 7 revisions

What argument options?

    --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

How does it look?

The font on Ubuntu is not my taste, but whatever, just show you the animation first:

Animation

Start with an argument parser

// test.cpp
#include "zupply.hpp"
zz::cfg::argParser parser;

Add option for help information

// note that short key is a char, long key is a std::string
parser.add_opt_help('h', "help"); // use -h or --help

Add version info

parser.add_opt_version('v', "version", "0.1"); // use -v or --version

Add a bool flag

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.

Add simple value option

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

Parse arguments

parser.parse(argc, argv);  //done
// now you can use flag, i, d, vd variables.

Retrieve the options

  • 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;
...

Try input some arguments

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

Print help information:

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

Get error in parsing process

if (parser.count_error() > 0) std::cout << parser.get_error() << std::endl;

Full example with error handler

	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;
	}

Advanced control over options

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();