Yarg is a one-header-only C++11 replacement for getopt()
that is object oriented and typed.
Support long options (example: --help
), short options (-h
), more short options in sequence (-hvl
), options without values (flags) or followed by a value, negative flags (--verbose
and --noverbose
bounded on the same flag), repeatable options (--name foo --name=bar --name "foo bar"
), special --
argument to stop the option recognition and automatic generation of usage/help message.
Every option is associated with a specific type (bool
for flags) and trying to assign a wrong type value (as in --level three
when "level" is defined of type int
) cause an error in the parsing phase.
For repeatable options it's possible to choose the type of container (std::set
, std::vector
, std::array
, etc.) where to store the values; so, by example, if it's important maintain the order expressed in the command line, std::vector
could be a good choice, otherwise std::set
(or std::multi_set
, if it's important maintain the multiplicity) could be good.
A minimal example can be the following (see examples/yarg-example-001.cpp
)
#include <iostream>
#include <yarg/yarg.h>
int main (int argc, char * argv[])
{
yarg::yarg y;
// Attention: l is a *reference*
auto & l = y.addOpt('l', "level", "set the level value", 3);
if ( y.parse(argc, argv) )
std::cout << "level is " << l << std::endl;
else
{
std::cerr << std::endl << y.getParserError() << std::endl;
y.usage();
}
return EXIT_SUCCESS;
}
Other examples in the examples/
directory.
#include <yarg/yarg.h>
yarg::yarg y;
// flag (option without value) declaration
bool & addFlag (char shortOption, std::string const & longOption,
std::string const & description = "", bool revert = false,
bool defaultValue = false);
// option (with value) declaration
template <typename T>
T & addOpt (char shortOption, std::string const & longOption,
std::string const & description = "",
T const & defaultValue = T());
// repeteable flag declaration (Cont is a container of bool)
template <typename Cont>
Cont & addFlagCont (char shortOption, std::string const & longOption,
std::string const & description = "",
bool revert = false, Cont const & defaultValue = Cont());
// repeteable option declaration (Cont is a container of values)
template <typename Cont>
Cont & addOptCont (char shortOptions, std::string const & longOptions,
std::string const & description = "",
Cont const & defaultValue = Cont());
These methods of yarg::yarg
return a reference to the internal variable with the default value that can be modified in following parsing phase if the corresponding option is encountered.
The single value method (addOpt()
) is intended to work with bool
, all standard integer types (both signed
and unsigned
versions of short int
, int
, long int
and long int int
), std::string
and should work with every type with input operator<<()
defined.
The multiple value containers versions (addFlagCont()
and addOptCont()
) are intended to work with std::vector
, std::array
, std::set
, std::multiset
, std::unordered_set
, std::unordered_multiset
, std::deque
, std::queue
, std::priority_queue
, std::forward_list
and std::stack
and should work with every container type for single values (so std::map
and similar double value containers are excluded) with a insert()
or push()
or push_back()
or push_front()
method.
Argument description:
- shortOption - a single char that set the short option; by example, pass
'h'
to activate the-h
recognition; to exclude the use of short option, pass0
(zero) - longOption - a string that set the long option, excluding the starting
--
; by example, pass"help"
to activate--help
recognition; to exclude the use of long option, pass""
(empty string); if revert istrue
(only for flags) this value activate a double long option (see revert) - description - a human understandable description of the option; an example: "show this help and exit"; used by
usage()
- revert - only for flags (
addFlag()
andaddFlagCont()
); iftrue
and if a not empty longOption (see) is set, activate another long option (pre posing "no") to intercept a negative value; by example, iftrue
and the long option is"verbose"
, set totrue
the flag (or add atrue
flag in the container, when repeatable) when (a)--verbose
argument is encountered and set tofalse
the same flag (o add afalse
flag in the container, when repeatable) when (a)--noverbose
argument is encountered - defaultValue - default value for the flag (or option) value (or container of values); can be used to set the template type (not in
addFlag()
, where is fixed tobool
), otherwise is necessary to explicit it (se "option declaration examples")
auto & v = y.addFlag ('h', "help", "show this helps and exit");
Return a reference to a bool
that is set to true
if the parsing phase encounter a -h
or a --help
argument; otherwise remain false
(the default value); observe that v
is a reference to auto
(that become a reference to a bool
) because must be bounded to the value, internal to the yarg::yarg y
instance, where the flag is stored.
auto & l = y.addOpt('l', "level", "set the level value", 3);
Return a reference to a int
that is set to the value of the -l
(or --level
) option; without a -l
or --level
, l
remain with the initial default value, 3
; observe that the type of l
is determined by the type of the default value (3
is an int
, in this example).
auto & l = y.addOpt<long>('l', "level", "set the level value");
Like in preceding example but the default value isn't expressed (so it's T()
, that is 0L
is this example); observe that, without the default value, you have to explicit (the <long>
part after addOpt
) the template type (the type of l
).
auto & flagsV = y.addFlagCont<std::vector<bool>>(0, "flag", "a repeteable boolean flag", true);
Return a reference to a std::vector
of bool
where are stored the values corresponding to a repeatable and reversible flags; so when a --flag
argument is encountered in the parsing phase, a true
is added (push_back(true)
) at the end of flagsV
; when a --noflag
is encountered in the parsing phase, a false
value is added at the end of flagsV
; observe that using a std::vector
the order of the --flags
/--noflags
arguments in the command line is preserved.
Cont & namesS = y.addOptCont<std::set<std::string>>('n', "--name", "set a name (repeteable)");
Return a reference to a std::set
of std::string
where are stored the values corresponding to a repeatable option; so when a -n <value>
, or --name <value>
, is encountered in the parsing phase, the string value is added (insert(value)
) in namesS
; observe that using a std::set
the order and the multiplicity of the values in the command line isn't preserved.
Given a main ()
declared as
int main (int argc, char * argv[])
instantiated a y
yarg::yarg
object and declared some flags, you can parse the command line arguments, extracting the options, simply with
y.parse(argc, argv)
The parse()
method return true
when the parsing phase conclude with success, return false
otherwise (in case of error).
In case of error, the method getParserError()
return a human readable std::string
with informations about the actual error.
So the parsing can be done as follows
if ( ! y.parse(argc, argv) )
throw std::runtime_error("yarg parsing error: " + y.getParserError());
After the parsing phase, you can get the name of the program (the classic argv[0]
argument) using the method getArgv0()
, that return a std::string
.
After the parsing phase (without errors) you can get the not options values arguments list using the method getNoOpts()
that return a std::deque
of std::string
.
Yarg permits the printing of a usage/help message automatically generated using, mainly, the description
argument of addFlag()
, addOpt()
, addFlagCont()
and addOptCont()
methods.
By example, in the executable obtained from the minimal example that you can see in "Minimale example" section, the call to usage()
print the following message
Usage: ./yarg-example-001 [options]
where options are
-l, --level = <value>
set the level value
The following is the corresponding interface
// set a short otional description for the arguments (imput parameters post
// options and flags) that is printed in head of the usage() message
void setUsageArgsDescr (std::string const & ad);
// set an optional initial description that is printed after the head of the
// usage() message and before the list of the options
void setUsageInitalDescr (std::string const & id);
// set an optional final description that is printed after the list of the
// options, at the end of the usage() message
void setUsageFinalDescr (std::string const & fd);
// set the width (number of columns) available for the usage() message; the
// default value is 79
void setUsageWidth (std::size_t uw);
// print the usage() message to the 'os' output stream (the default is
// std::cerr)
void usage (std::ostream & os = std::cerr) const
You can see a detailed use example in examples/yarg-example-003.cpp
.
Calling the executable obtained from the minimal example that you can see in "Minimale example" section (that intercept only a -l
/--level
integer option) with the following command line
./example --level 5 name1 "name 2" name3
the l
level value is set to 5
, the getArgv0()
method return ./example
and getNoOpts()
return a std::deque
containing three strings: name1
, name 2
and name3
.
Calling it with
./example -- --level 5 name1 "name 2" name3
the l
level value remain set to 3
(the default value) because the special --
argument stop the option recognition; so getNoOpts()
return a std::deque
containing five strings: --level
, 5
, name1
, name 2
and name3
.
Calling it with
./example --level five name1 "name 2" name3
the parsing phase fail and the parse()
method return false
because the five
value is incompatible with the --level
option that is defined of type int
.