API¶
Argo’s API consists of a number of related classes in the following namespaces:
argo
: general objectsargo::action
: action specific functionalityargo::handler
: argument handlersargo::program
: program informationargo::nargs
: cardinality behavior
The core functionality resides in the argo::core
namespace and is not intended for direct usage by client code, with a minor exception for some of the methods of the core::Context
object.
Note
A good source of API examples is to look at the unit-tests for the library.
Arguments¶
-
class Arguments¶
Arguments is the toplevel parser of arguments. It is configured step-by-step by iteratively adding handlers to it.
Public Functions
-
inline Arguments()¶
Default constructor.
-
inline explicit Arguments(const Configuration &config)¶
Constructs the parser with the given configuration.
-
inline const Configuration &configuration() const¶
Returns the configuration.
-
inline bool add(const core::handler::IHandler &handler)¶
Adds the given handler to the parser. Returns a boolean indicating success.
-
inline bool merge(const Arguments &other, bool replace = true)¶
Merges the given parser by adding all its handlers. If a handler conflicts, the handler of the other parser is used when
replace = true
or skipped whenreplace = false
.
-
inline Result parse(const std::vector<std::string> &arguments, const bool skip_first_argument = false)¶
Parses the given arguments. By default, the first argument is not skipped. Useful for unit-testing or when the arguments are not directly read from
argv
.
-
template<typename CharArrayType>
inline Result parse(unsigned int argc, CharArrayType argv, const bool skip_first_argument = true)¶ Parses the given C-style arguments. By default, the first argument is skipped. Useful to directly pass the arguments of
main
where the first argument is the application’s executable name.
-
inline bool print_usage(std::ostream &os) const¶
Prints the usage section to the given output stream.
-
inline bool print_help(std::ostream &os) const¶
Prints the help section to the given output stream.
-
inline bool print_version(std::ostream &os) const¶
Prints the version section to the given output stream.
-
inline Arguments()¶
Configuration¶
-
struct Configuration¶
Configuration is a structure containing parser behavior and program information.
-
struct Parser¶
Public Members
-
bool help = true¶
Addition of the
--help
flag.
-
bool version = true¶
Addition of the
--version
flag.
-
bool responsefile = true¶
Addition of the default response file handler.
-
bool dash_names = true¶
Named arguments on the command line have underscores turned to dashes.
-
bool implicit_values = true¶
When false, values must explicitly be set, e.g.
--option a --option b
, instead of--option a b
-
bool argument_values = false¶
When true, values can be of the form
--value
or-v
-
bool empty_values = false¶
When true, values can be empty.
-
bool help = true¶
-
struct Parser¶
Program¶
The argo::program
namespace contains objects holding program specific information. This is mostly useful for displaying help and output error messages.
-
struct program::Info¶
Aggregate of program-related information.
-
struct program::Description¶
Holds program descriptions: goal and intended usage.
Public Members
-
std::string brief¶
Short description: a one-liner describing the program’s goal.
-
std::string extended¶
Long description which may span multiple lines.
-
std::string usage¶
Describes the program’s usage, i.e. its argument invocation. When empty, the output formatters are responsible for generating this information based on the available handlers. However, when the string is not empty, output formatters should use this instead.
-
std::string brief¶
-
struct program::Name¶
Holds the program’s different name aliases.
Handlers¶
Handlers are delegate parsers: the toplevel Arguments
parser searches for handlers that ‘recognize’ the current argument. If found, the parsing is delegated to that handler allowing it to process any required values before yielding back control.
Handlers have certain properties:
- Cardinality: controlled by the
nargs
methods, it determines the number of values a handler expects: nargs(n)
: fixed number of n valuesnargs("?")
: zero or one valuenargs("*")
: zero or more valuesnargs("+")
: one or more values
- Cardinality: controlled by the
Help: controlled by the
help
method, it is a description of the handled argument, usually used by formatters in the help outputRequired/Optional: controlled by the
required/optional
methods, they indicate whether the argument is required, i.e. must be present in the processed arguments. By default, all handlers are optional.Actionable: controlled by the
action
method, it is a list of attached Actions that are invoked on the processed values
Options¶
Options are named arguments that expect values, depending on the cardinality. By default, a single value is expected.
Examples of invocations for which options are suitable are:
--bar 1
--foo 1 2 3
--foo 1 --foo 2
--foo=1,2
--foo=1,2 --foo 3
The handler::Option
class implements the required behavior.
-
class handler::Option : public core::handler::IHandler, public core::handler::property::Named, public core::handler::property::Help<Option>, public core::handler::property::Required<Option>, public core::handler::property::Cardinality<Option>, public core::handler::property::Actionable<Option>¶
Handler that processes arguments with values.
Public Functions
-
inline explicit Option(const std::string &first, const std::string &second)¶
Constructs an option with a longhand and shorthand. They may be provided in any order. This constructor is useful if no direct variable binding can be done. Using this constructor implies adding a custom action later in order to create a valid Option.
-
inline explicit Option(const std::string &name)¶
Constructs an option with a longhand or shorthand. This constructor is useful if no direct variable binding can be done. Using this constructor implies adding a custom action later in order to create a valid Option.
-
inline explicit Option(const char *first, const char *second)¶
Constructs an option with a longhand and shorthand. They may be provided in any order. This constructor is useful if no direct variable binding can be done. Using this constructor implies adding a custom action later in order to create a valid Option.
-
inline explicit Option(const char *name)¶
Constructs an option with a longhand or shorthand.
-
template<typename Variable, typename = typename std::enable_if<!std::is_const<Variable>::value>::type>
inline explicit Option(const std::string &first, const std::string &second, Variable &variable)¶ Constructs an option with a longhand and shorthand. They may be provided in any order. Any values will be stored in the given variable.
-
template<typename Variable, typename = typename std::enable_if<!std::is_const<Variable>::value>::type>
inline explicit Option(const std::string &name, Variable &variable)¶ Constructs an option with a longhand or shorthand. Any values will be stored in the given variable.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual core::handler::Ptr clone() const override¶
Returns a cloned version of the handler.
-
inline virtual bool parse(core::Context &context) override¶
Takes over the parsing process in the current context. Returns a boolean indicating success.
-
inline virtual bool is_satisfied(core::Context &context) const override¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline bool has_longhand() const¶
Indicates if a longhand is set.
-
inline std::string longhand() const¶
Returns the longhand. Note that the longhand must be set.
-
inline bool has_shorthand() const¶
Indicates if a shorthand is set.
-
inline std::string shorthand() const¶
Returns the shorthand. Note that the shorthand must be set.
-
inline std::string help() const¶
Returns the help description.
-
inline Option &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Option &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline Option &optional(const Condition &condition =
[]() { return false;}
)¶ Marks the handler as optional and returns it.
-
inline Option &nargs(const std::string &type)¶
Sets the expected number of arguments and returns the handler.
-
inline Option &nargs(const unsigned nr)¶
Sets the expected fixed number of arguments and returns the handler.
-
inline std::string nargs_type() const¶
Returns the cardinality description.
-
inline std::string nargs_symbol() const¶
Returns the cardinality symbol.
-
inline explicit Option(const std::string &first, const std::string &second)¶
Note that named arguments such as options always have dashed names. That is to say: adding an option --foo_bar
, will silently be replaced by --foo-bar
.
Toggles¶
Toggles are named arguments that expect at most one value. This value must be ‘truthy’: something that can be interpreted as either true or false. The following table indicates which values (case insensitive) are considered true or false.
Value |
Interpretation |
---|---|
|
true |
|
true |
|
true |
|
true |
|
false |
|
false |
|
false |
|
false |
Any other value results in an error. Note that this intepretation is not limited to toggles and holds for any type conversion to a bool.
A useful feature for toggles is that they automagically support negations. For example, adding a toggle --debug
mapped to bool debug = false
would not only set debug=true when --debug true
is parsed, but would also set it to true if --no-debug false
is parsed.
Consider the following toy example:
struct {
bool debug = default_value;
} options;
Arguments args;
args.add(handler::Toggle{"--debug", options.debug});
const auto result = args.parse(raw_args);
std::cout << std::boolalpha << options.debug << std::endl;
This would result in the following input/output table:
Command line |
|
Output |
---|---|---|
–debug |
true |
true |
–debug true |
true |
true |
–debug false |
true |
false |
–no-debug |
true |
false |
–no-debug true |
true |
false |
–no-debug false |
true |
true |
–debug |
false |
true |
–debug true |
false |
true |
–debug false |
false |
false |
–no-debug |
false |
false |
–no-debug true |
false |
false |
–no-debug false |
false |
true |
The handler::Toggle
class implements the required behavior.
-
class handler::Toggle : public core::handler::IHandler, public core::handler::property::Named, public core::handler::property::Help<Toggle>, public core::handler::property::Required<Toggle>, public core::handler::property::Actionable<Toggle>¶
A handler that processes toggles: arguments that toggle boolean values.
Public Functions
-
inline explicit Toggle(const std::string &first, const std::string &second, const std::function<bool(core::Context&, const bool)> &setter)¶
Constructs a toggle with a longhand and shorthand. They may be provided in any order. The passed setter function will be called with the truthy value when the handler is triggered. This version of the setter function can alter the parsing process.
-
inline explicit Toggle(const std::string &first, const std::string &second, const std::function<void(const bool)> &setter)¶
Constructs a toggle with a longhand and shorthand. They may be provided in any order. The passed setter function will be called with the truthy value when the handler is triggered. This version of the setter function cannot alter the parsing process.
-
inline explicit Toggle(const std::string &first, const std::string &second, const std::function<bool(core::Context&, const bool)> &setter, const std::function<bool()> &getter)¶
Constructs a toggle with a longhand and shorthand. They may be provided in any order. The passed setter function will be called with the truthy value when the handler is triggered. This version of the setter function can alter the parsing process. The passed getter is useful for formatters to display helpful output.
-
inline explicit Toggle(const std::string &first, const std::string &second, bool &variable)¶
Constructs a toggle with a longhand and shorthand. They may be provided in any order. The passed variable will be toggled when the handler is triggered.
-
inline explicit Toggle(const std::string &name, const std::function<bool(core::Context&, const bool)> &setter)¶
Constructs a toggle with a longhand or shorthand. The passed setter function will be called with the truthy value when the handler is triggered. This version of the setter function cal alter the parsing process.
-
inline explicit Toggle(const std::string &name, const std::function<void(const bool)> &setter)¶
Constructs a toggle with a longhand or shorthand. The passed setter function will be called with the truthy value when the handler is triggered. This version of the setter function cannot alter the parsing process.
-
inline explicit Toggle(const std::string &name, const std::function<bool(core::Context&, const bool)> &setter, const std::function<bool()> &getter)¶
Constructs a toggle with a longhand or shorthand. The passed setter function will be called with the truthy value when the handler is triggered. This version of the setter function cannot alter the parsing process. The passed getter is useful for formatters to display helpful output.
-
inline explicit Toggle(const std::string &name, bool &variable)¶
Constructs a toggle with a longhand or shorthand. The passed variable will be toggled when the handler is triggered.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline Toggle &with_negation(const std::string &longhand)¶
Sets the negation longhand. For example, constructing a “–debug” toggle will automatically respond to a “–no-debug” argument. If the latter name is to be different, it can be set using this method.
-
inline std::string negation_longhand() const¶
Returns the negation longhand.
-
inline bool has_default_value() const¶
Indicates if the default value is available.
-
inline bool default_value() const¶
Returns the default value. This assumes
has_default_value()
returns true.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual core::handler::Ptr clone() const override¶
Returns a cloned version of the handler.
-
inline virtual bool parse(core::Context &context) override¶
Takes over the parsing process in the current context. Returns a boolean indicating success.
-
inline virtual bool is_satisfied(core::Context &context) const override¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline bool has_longhand() const¶
Indicates if a longhand is set.
-
inline std::string longhand() const¶
Returns the longhand. Note that the longhand must be set.
-
inline bool has_shorthand() const¶
Indicates if a shorthand is set.
-
inline std::string shorthand() const¶
Returns the shorthand. Note that the shorthand must be set.
-
inline std::string help() const¶
Returns the help description.
-
inline Toggle &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Toggle &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline explicit Toggle(const std::string &first, const std::string &second, const std::function<bool(core::Context&, const bool)> &setter)¶
Flags¶
Flags are named arguments that do not expect any value. They serve as triggers, nothing more.
Examples of invocations for which flags are suitable are:
--foo
The handler::Flag
class implements the required behavior.
-
class handler::Flag : public core::handler::IHandler, public core::handler::property::Named, public core::handler::property::Help<Flag>, public core::handler::property::Required<Flag>, public core::handler::property::Actionable<Flag>¶
A handler that processes flags: shorthand or longhand arguments without values.
Public Functions
-
inline explicit Flag(const std::string &first, const std::string &second)¶
Constructs a flag with a longhand and shorthand. They may be provided in any order.
-
inline explicit Flag(const std::string &name)¶
Constructs an option with a longhand or shorthand.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual core::handler::Ptr clone() const override¶
Returns a cloned version of the handler.
-
inline virtual bool parse(core::Context &context) override¶
Takes over the parsing process in the current context. Returns a boolean indicating success.
-
inline virtual bool is_satisfied(core::Context &context) const override¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline bool has_longhand() const¶
Indicates if a longhand is set.
-
inline std::string longhand() const¶
Returns the longhand. Note that the longhand must be set.
-
inline bool has_shorthand() const¶
Indicates if a shorthand is set.
-
inline std::string shorthand() const¶
Returns the shorthand. Note that the shorthand must be set.
-
inline std::string help() const¶
Returns the help description.
-
inline Flag &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Flag &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline explicit Flag(const std::string &first, const std::string &second)¶
Positional arguments¶
Positional arguments are unnamed arguments which are actually references to values passed in the command line, like a list of input or output files. Argo first looks for options, custom handlers, and then positional arguments. Care needs to be taken with positional arguments. For example, it generally doesn’t make much sense to have more than one positional argument with nargs = "*"
. This is in contrast with options, where it could make sense to multiple optional arguments with nargs="*"
.
Examples of invocations for which positional arguments are suitable are:
a.cpp.obj b.cpp.obj c.a
The handler::Positional
class implements the required behavior.
-
class handler::Positional : public core::handler::IHandler, public core::handler::property::Help<Positional>, public core::handler::property::Required<Positional>, public core::handler::property::Cardinality<Positional>, public core::handler::property::Actionable<Positional>¶
A handler that processes positional arguments: unnamed arguments that signal values.
Public Functions
-
inline explicit Positional(const std::string &name)¶
Constructs the positional handler with the given name. Note that the name may not be a shorthand or longhand. It is merely used in the generation of help output and error messages.
-
template<typename Variable>
inline explicit Positional(const std::string &name, Variable &variable)¶ Constructs the positional handler with the given name. Note that the name may not be a shorthand or longhand. It is merely used in the generation of help output and error messages. Any values are stored in the given variable.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual core::handler::Ptr clone() const override¶
Returns a cloned version of the handler.
-
inline virtual bool parse(core::Context &context) override¶
Takes over the parsing process in the current context. Returns a boolean indicating success.
-
inline virtual bool is_satisfied(core::Context &context) const override¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline std::string help() const¶
Returns the help description.
-
inline Positional &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Positional &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline Positional &optional(const Condition &condition =
[]() { return false;}
)¶ Marks the handler as optional and returns it.
-
inline Positional &nargs(const std::string &type)¶
Sets the expected number of arguments and returns the handler.
-
inline Positional &nargs(const unsigned nr)¶
Sets the expected fixed number of arguments and returns the handler.
-
inline std::string nargs_type() const¶
Returns the cardinality description.
-
inline std::string nargs_symbol() const¶
Returns the cardinality symbol.
-
inline Positional &action(const action::IAction &action)¶
Adds an action to the handler and returns it.
-
inline Positional &require(const action::IAction &requirement)¶
Adds a requirement to the handler and returns it. Note that this is syntactic sugar since it has the same effect as calling
action
.
-
inline explicit Positional(const std::string &name)¶
Interface¶
Custom handlers can be implemented by subclassing the handler::Interface
class. For example, the default response file handler class handler::ResponseFile
is actually does this.
-
class handler::Interface : public core::handler::IHandler, public core::handler::property::Help<Interface>¶
A handler that can serve as a base class for custom handlers.
Subclassed by handler::ResponseFile
Public Functions
-
virtual std::string help() const = 0¶
Returns the help description.
-
virtual bool is_valid() const = 0¶
Indicates if the handler is correctly configured.
-
virtual std::string name() const = 0¶
Returns the handler’s name.
-
virtual std::string type() const = 0¶
Returns the handler’s type description.
-
virtual Ptr clone() const = 0¶
Returns a cloned version of the handler.
-
virtual bool parse(Context &context) = 0¶
Takes over the parsing process in the current context. Returns a boolean indicating success.
-
virtual bool is_satisfied(Context &context) const = 0¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
virtual std::string help() const = 0¶
Response files¶
Response files are files containing command line arguments. See ResponseFile. The required behavior is implemented by the handler::ResponseFile
class.
-
class handler::ResponseFile : public handler::Interface¶
A handler that processes response files.
Public Functions
-
inline explicit ResponseFile(const std::string &identifier =
"@")¶ Constructs the response file handler with the given identifier. By default, the commonly used
@
character is chosen. As such, invocations such as./app @/path/to/response/file.rsp
are processed by this handler. Note that the path to the response file must immediately follow the identifier string. In the case of the@character
there is therefore no white space between the@
the response file.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline virtual std::string help() const override¶
Returns the help description.
-
inline explicit ResponseFile(const std::string &identifier =
Groups¶
Groups are collection of handlers with limited properties:
a
name
, mostly useful for formattersand an
optional
/required
marker
Note that the latter can override the optional
/required
behavior of
individual handlers in the group. This behavior depends on the group type.
There are three built-in group types:
Custom groups¶
The handler::group
hierarchy can be extended. It suffices to subclass the handler::group::Interface
and implement the clone
and is_satisfied
methods. In fact, all built-in group types differ only in the implementation of these methods where - obviously - the latter method determines the group behavior.
-
class handler::group::Interface : public core::handler::IHandler, public core::handler::property::Help<Interface>, public core::handler::property::Required<Interface>¶
Subclassed by handler::group::Exclusive, handler::group::Inclusive, handler::group::Simple
Public Functions
-
inline explicit Interface(const std::string &name, const std::string &type)¶
Constructs the group with the given name and type description.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
virtual Ptr clone() const = 0¶
Returns a cloned version of the handler.
-
virtual bool is_satisfied(Context &context) const = 0¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline std::string help() const¶
Returns the help description.
-
inline Interface &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Interface &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline explicit Interface(const std::string &name, const std::string &type)¶
Simple groups¶
All handlers in a simple group must be satisfied, i.e. their properties such as expected number of arguments, required, etc. must be met. Additionally, optional simple groups do not require any of the handlers to have been triggered. On the other hand, required simple groups must have at least one handler that triggered during the parsing process.
For practical examples, check out the unit-tests.
-
class handler::group::Simple : public handler::group::Interface¶
Group that holds a simple collection of handlers.
Public Functions
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline std::string help() const¶
Returns the help description.
-
inline Interface &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Interface &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline virtual bool is_valid() const override¶
Inclusive groups¶
The presence of handlers in an inclusive group is forced depending on whether any handler within the group triggered. In other words, if one handler is triggered then all other handlers must be triggered as well. Additionally, optional inclusive groups do not require any of the handlers to have been triggered (even those marked as required) whereas required inclusive groups enforce the presence of all handlers. Put simply: a required inclusive groups is equivalent to a simple group (be it optional or required) where all handlers of the simple group are required.
For practical examples, check out the unit-tests.
-
class handler::group::Inclusive : public handler::group::Interface¶
Group in which the presence of any one option/group within it, forces the presence of the others.
Public Functions
-
inline virtual core::handler::Ptr clone() const override¶
Returns a cloned version of the handler.
-
inline virtual bool is_satisfied(core::Context &context) const override¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline std::string help() const¶
Returns the help description.
-
inline Interface &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Interface &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline virtual core::handler::Ptr clone() const override¶
Exclusive groups¶
Similarly to inclusive groups, the presence of handlers in an exclusive group is forced depending on whether any handler within the group triggered. In other words, if one handler is triggered then none ofthe other handlers must be triggered as well. Additionally, optional exclusive groups do not require a single handler to have been triggered (even those marked as required).
For practical examples, check out the unit-tests.
-
class handler::group::Exclusive : public handler::group::Interface¶
Group in which the presence of any one option/group within it, forces the exclusion of the others.
Public Functions
-
inline virtual core::handler::Ptr clone() const override¶
Returns a cloned version of the handler.
-
inline virtual bool is_satisfied(core::Context &context) const override¶
Indicates if the handler is satisfied were the parsing to stop at this point.
-
inline virtual bool is_valid() const override¶
Indicates if the handler is correctly configured.
-
inline virtual std::string name() const override¶
Returns the handler’s name.
-
inline virtual bool accept(core::handler::visitor::IConstVisitor &visitor) const override¶
Accepts a constant visitor. Returns a boolean indicating success.
-
inline virtual bool accept(core::handler::visitor::IMutatingVisitor &visitor) override¶
Accepts a mutating visitor. Returns a boolean indicating success.
-
inline virtual std::string type() const override¶
Returns the handler’s type description.
-
inline std::string help() const¶
Returns the help description.
-
inline Interface &help(const std::string description)¶
Sets the help description and returns the handler.
-
inline bool is_required() const¶
Indicates if the handler is required.
-
inline Interface &required(const Condition &condition =
[]() { return true;}
)¶ Marks the handler as required and returns it.
-
inline bool is_optional() const¶
Indicates if the handler is optional. This is the default state.
-
inline virtual core::handler::Ptr clone() const override¶
Note
It is left up to the user to make sure that handlers contained in exclusive groups play well. For instance, placing more than one required handler in an exclusive group will most likely not be the sought after behavior.
Actions¶
Actions are callbacks attached to handlers. They are a central part of Argo’s architecture: when a handler consumes a value, all attached handlers are invoked with the value. They can then do any required computation or modify the parsing process using the core::Context
class. For instance, they can generate errors or abort the parsing.
The most useful action is the action::run()
action with all its overloads:
-
template<typename Type = std::string>
Run<Type> action::run(const typename Run<Type>::function_type &fnc)¶ Creates an action that accepts a callback with prototype
bool(const Type)
. By default,Type = std::string
.
-
template<typename Type = std::string>
Run<Type> action::run(const typename Run<Type>::function_with_context_type &fnc)¶ This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Warning
doxygenfunction: Unable to resolve function “action::run” with arguments (const std::function<boolcore::Context&>&) in doxygen xml output for project “Argo” from directory: ../doxyxml/. Potential matches:
- Run<std::string> run(const std::function<bool(core::Context&)> &fnc)
- Run<std::string> run(const std::function<void()> &fnc)
- template<typename Type = std::string> Run<Type> run(const typename Run<Type>::function_type &fnc)
- template<typename Type = std::string> Run<Type> run(const typename Run<Type>::function_with_context_type &fnc)
Warning
doxygenfunction: Unable to resolve function “action::run” with arguments (const std::function<void>&) in doxygen xml output for project “Argo” from directory: ../doxyxml/. Potential matches:
- Run<std::string> run(const std::function<bool(core::Context&)> &fnc)
- Run<std::string> run(const std::function<void()> &fnc)
- template<typename Type = std::string> Run<Type> run(const typename Run<Type>::function_type &fnc)
- template<typename Type = std::string> Run<Type> run(const typename Run<Type>::function_with_context_type &fnc)
All action::run()
actions are free functions that return an action::Run
which implements action::Interface
:
-
template<typename Type>
class Run : public action::Interface<Type>¶ Action that performs all required conversions and then invokes the associated callback function.
When designing complex actions, it might be necessary to subclass action::Interface
. However, this is very unlikely and it will usually be sufficient to create a callback and pass it to action::Run
. In fact, this is how the other built-in action action::store()
(with all the overloads) is implemented:
-
template<typename Type, typename ConstType>
Run<Type> action::store(Type &variable, ConstType const_value)¶ Stores the
const_value
in the given variable when the associated handler triggers.ConstType
must be copy-assignable toType
.
-
template<typename Type>
Run<Type> action::store(Type &variable)¶ Stores the parsed value in the given variable.
-
template<typename Type>
Run<Type> action::store(std::list<Type> &variable)¶ Appends the parsed values in-order to the given list.
-
template<typename Type>
Run<Type> action::store(std::set<Type> &variable)¶ Inserts the parsed values in the given set.
-
template<typename Type>
Run<Type> action::store(std::vector<Type> &variable)¶ Appends the parsed values in-order to the given vector.
Warning
Client-code must take care not to pass in lambda expressions which hold references to variables that are out-of-scope at the time of execution of the lambda expressions. The latter happens during the parsing.
Requirements¶
Requirements reflect restrictions that apply to the parsed values. A collection of built-in requirements is available in the require
namespace:
-
template<typename Collection, typename Type = typename core::traits::conversion<typename std::remove_cv<typename Collection::value_type>::type>::result_type>
action::Run<Type> require::any_of(const Collection &values)¶ Verifies that the parsed value is any of the given values.
-
template<typename Collection, typename Type = typename core::traits::conversion<typename std::remove_cv<typename Collection::value_type>::type>::result_type>
action::Run<Type> require::none_of(const Collection &values)¶ Verifies that the parsed value is none of the given values.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::greater_than(Type cutoff)¶ Verifies that the parsed value is greater than the given value.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::greater_than_or_equal(Type cutoff)¶ Verifies that the parsed value is greater than or equal to the given value.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::lesser_than(Type cutoff)¶ Verifies that the parsed value is lesser than the given value.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::lesser_than_or_equal(Type cutoff)¶ Verifies that the parsed value is lesser than or equal to the given value.
There are also range-based requirements in the require::range
namespace:
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::range::closed_closed(Type first, Type last)¶ Verifies that the parsed value lies within the range
[first, last]
.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::range::closed_open(Type first, Type last)¶ Verifies that the parsed value lies within the range
[first, last[
.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::range::open_closed(Type first, Type last)¶ Verifies that the parsed value lies within the range
]first, last]
.
-
template<typename Type, typename = typename std::is_arithmetic<Type>::type>
action::Run<Type> require::range::open_open(Type first, Type last)¶ Verifies that the parsed value lies within the range
]first, last[
.
You can of course pass your own requirements as an action. In fact, requirements are syntactic sugar since calling require
has the same effect as calling action
: requirements are of type action::IAction
.
Type conversions¶
By its very nature, all command line arguments enter the application as strings. Argo takes care of all required conversions from std::string
to the requested type. This type can often be deduced automatically, for instance when handlers are constructed with binding to some target variable in which to store the values. However, when attaching actions, the value must be explicitly stated. As previously mentioned, the action::Run
class invokes the associated callbacks with the converted values. Most relevant built-in types are supported:
(unsigned) short
(unsigned) int
(unsigned) long
(unsigned) long long
float
double
bool
Enumeration types providing a
Nr_
member as final item. This is purely a convenience utility and usage is subject to client code discretion
Note that this list implies support for all std::(u)int_<n>_t
types as the latter are not part of the C++ language but defined in terms of the types listed above which are often referred to as the fundamental types.
Automatic conversions can be extended by specializing the core::traits::conversion
structure. For example, the following built-in specialization provides the conversion to double precision floating point values:
template <>
struct conversion<double>
{
using result_type = double;
static constexpr const char *description = "a double";
static optional<double> run(std::string value)
{
REPLACE_METRIC_SYMBOLS;
double dvalue;
if (!convert(dvalue, value)) return nullopt;
return dvalue;
}
};
Finally, std::optional<T> (since C++17) is optionally supported (pun intended). To enable support, define ARGO_ENABLE_STD_OPTIONAL
prior to including the library:
#define ARGO_ENABLE_STD_OPTIONAL 1
#include <argo/Argo.hpp>
or in your build system, e.g. -DARGO_ENABLE_STD_OPTIONAL=1
Scientific notation and metric prefixes¶
Some syntactic sugar is available for conversions of numbers: scientific notation such as 2e3
and metric prefixes are recognized. For the latter, the following table indicates the supported symbols:
Prefix |
Symbol |
Power of 10 |
---|---|---|
deka |
|
1e1 |
hecto |
|
1e2 |
kilo |
|
1e3 |
mega |
|
1e6 |
giga |
|
1e9 |
tera |
|
1e12 |
peta |
|
1e15 |
exa |
|
1e18 |
Result¶
The result of the parsing process is not much more than a status code and an optional error message. This is in contrast to other frameworks where the result is often a variant type object in which all arguments are collected. In Argo’s design, this offers very few advantages and causes more issues in the ‘success path’ (sometimes referred to as the hot path) of the code than anything else. In Argo, actions are triggered during the parsing process allowing for more type safety and a more flexible approach in the success path. Consequently, the result of the parsing is limited and given by a small aggregate.
-
struct Result¶
Aggregate holding the end result of the parsing process.
Public Members
-
ReturnCode status = ReturnCode::SuccessAndContinue¶
Return code status.
-
std::string message¶
Empty unless ReturnCode::Error, in which case it contains a descriptive error message which is intended for the end user.
-
std::vector<std::string> arguments¶
The normalized and expanded arguments that were processed. This includes normalizing invocations such as
--foo 1 --foo=2,3
to--foo 1 2 3
and expanding all response files.
-
ReturnCode status = ReturnCode::SuccessAndContinue¶
ReturnCode¶
There are three possible outcome states for the parsing process, represented by the ReturnCode
enum class.
-
enum ReturnCode¶
Enumeration class that holds the three end states of the parsing process.
Values:
-
enumerator Error¶
Indicates an error occurred during parsing. The intent is to signal the application to handle the error and exit.
-
enumerator SuccessAndAbort¶
Indicates parsing was successful. The intent is to signal the application that although no error occurred, it should still abort. Usually used by flags like
--help
.
-
enumerator SuccessAndContinue¶
Indicates parsing was successful. The intent is to signal the application that it may proceed with normal execution.
-
enumerator Error¶
Formatter¶
The format of all generated output is provided by a formatter object which implements the formatter::Interface
. Formatters can be set using Arguments::set_formatter()
.
Interface¶
-
class formatter::Interface¶
Interface serving as a base class for concrete formatters.
Subclassed by formatter::Default
Public Functions
-
inline virtual void set_width(unsigned width)¶
Sets the output width. Note that a width of 0 corresponds to full width, i.e. the entire width of the terminal console.
-
inline virtual unsigned width() const¶
Returns the output width.
-
virtual std::string format_error(const core::Context &context, const std::string &message) const = 0¶
Returns the formatted error message.
-
virtual std::string format_usage(const core::Context &context) const = 0¶
Returns the formatted usage section.
-
inline virtual void set_width(unsigned width)¶
Default¶
The default formatter provides clear, helpful and beautiful output. It also supports colors via ANSI escape codes. It can in itself serve as a base class for custom formatters.
-
class formatter::Default : public formatter::Interface¶
Default formatter.
Public Functions
-
inline virtual unsigned width() const override¶
Returns the output width.
-
inline virtual std::string format_error(const core::Context &context, const std::string &message) const override¶
Returns the formatted error message.
-
inline virtual std::string format_usage(const core::Context &context) const override¶
Returns the formatted usage section.
-
inline virtual std::string format_help(const core::Context &context) const override¶
Returns the formatted help section.
-
inline virtual std::string format_version(const core::Context &context) const override¶
Returns the formatted version section.
-
inline virtual void set_width(unsigned width)¶
Sets the output width. Note that a width of 0 corresponds to full width, i.e. the entire width of the terminal console.
-
inline virtual unsigned width() const override¶
ResponseFile¶
As an alternative to placing all the options on the command line, some applications accept special files called response files: plain text files that list command line arguments. This may be useful due to limitations of your build environment or as a convenience for your build process. Arguments in a response file are interpreted as if they were present at that place in the invocation. Each argument in a response file must begin and end on the same line. You cannot use the backslash character to concatenate lines. Comments are supported by prefixing lines with the // characters, similar to C/C++ comments.
An example of an invocation with a response file could look like:
$ ./app --foo @options.rsp
where options.rsp
might look like:
//This is a response file listing some command line arguments
--bar
--foobar 1 2 3
//--barfoo
--barbar foofoo
In the above example, the invocation would be equivalent to:
$ ./app --foo --bar --foobar 1 2 3 --barbar foofoo
On Windows, response files can be a necessary way of circumventing the limitations of the CreateProcessA API function, which limits the command line string to 32,768 characters.
Argo has built-in support for response files via the handler::ResponseFile
argument handler. If a custom response file handler is required, the ResponseFile
parser class can be used for the implementation:
-
class ResponseFile¶
Response file parser.
Public Functions
-
inline bool parse(const std::string &filename)¶
Parses the given reponse file and returns a boolean indicating success.
-
inline std::string filename() const¶
Returns the filename of the last parsed response file.
-
inline int argc() const¶
Returns the number of parsed arguments.
-
inline std::vector<std::string> argv() const¶
Returns the parsed arguments.
-
inline bool parse(const std::string &filename)¶
Note that one or more response files may be provided in an invocation and that these may be combined with other command line arguments. Furthermore, response file parsing is enabled by default in the Configuration
.
Core Functionality¶
This section limits itself to the core functionality that is likely to be used by client code, i.e. low threshold usage. More intrusive development will require consulting the actual code.
The primary class with which interaction is likely is the core::Context
, a class which holds the parsing context: the active parser, its configuration, the current argument to be processed, etc.
-
class core::Context¶
Class that allows access and modification of the parsing state.
Public Functions
-
inline Error error()¶
Returns an Error object for usage within the caller’s scope. The result’s status will be set to
ReturnCode::Error
.
-
inline void abort()¶
Signals the parsing to process to abort. The result’s status will be set to
ReturnCode::SuccessAndAbort
.
-
inline void switch_parser(Arguments &parser)¶
Switches to another parser which will continue the processing using the current context.
-
inline bool is_current_parser(const Arguments &parser)¶
Indicates if the given parser is the parser processing the current context.
-
inline const Configuration &config() const¶
Returns the configuration of the active parser.
-
inline Error error()¶
Another widely used class is the core::Error
class, which is a helper utility class for generating error messages.
-
class core::Error¶
Class that sets the current result’s status to
ReturnCode::Error
and assigns the given message.
For example, the following code attaches an action to handler to validate some input. If the input doesn’t satisfy some criterium, it ends the parsing process with an error message:
handler.action(action::run<unsigned int>([](core::Context &context, unsigned int value) {
if (value % 2 == 0)
{
context.error() << "Value must be even (not " << value << ")";
return false;
}
else return true;
}));