ArgParser

Synopsis

#include <ts/ArgParser.h>

Description

ArgParser is a powerful and easy-to-use command line Parsing library for ATS. The program defines what it requires by adding commands and options. Then ArgParser will figure out the related information from the command line. All parsed arguments and function will be put in a key-value pairs structure Arguments available for users to use.

Usage

The usage of the ArgParser is straightforward. An ArgParser instance is created. Commands and options are then added to this instance, along with details including ENV variable, arguments expected, etc. The method parse(argv) is called, passing the argv from the command line (main function arguments). An object containing the parsed command line information will be returned.

Create a parser

The first step to use ArgParser is to create a parser. The parser can be created simply by calling:

ts::ArgParser parser;

or initialize with the following arguments: name, help description, environment variable, argument number expected, function

ts::ArgParser parser("name", "description", "ENV_VAR", 0, &function);

To add the usage for the help message of this program:

parser.add_global_usage("traffic_blabla [--SWITCH]");

Add commands and options

We can perform all kinds of operations on the parser which is the ArgParser or command which is a Command.

To add commands to the program or current command:

ts::ArgParser &command1 = parser.add_command("command1", "description");
command1.add_command("command2", "description");
command1.add_command("command3", "description", "ENV_VAR", 0);
command1.add_command("command4", "description", "ENV_VAR", 0, &function, "lookup_key");

This function call returns the new Command instance added.

Note

The 0 here is the number of arguments we expected. It can be also set to MORE_THAN_ZERO_ARG_N or MORE_THAN_ONE_ARG_N to specify that this command expects all the arguments come later (more than zero or more than one).

To add options to the parser or current command:

parser.add_option("--switch", "-s", "switch description");
command1.add_option("--switch", "-s", "switch description", "", 0);
command1.add_option("--switch", "-s", "switch description", "ENV_VAR", 1, "default", "lookup_key");

This function call returns the new Option instance. (0 is also number of arguments expected)

We can also use the following chained way to add subcommand or option:

command.add_command("init", "description").add_command("subinit", "description");
command.add_command("remove", "description").add_option("-i", "--initoption");

which is equivalent to

ts::ArgParser::Command &init_command = command.add_command("init", "description");
ts::ArgParser::Command &remove_command = command.add_command("remove", "description");
init_command.add_command("subinit", "description");
remove_command.add_option("-i", "--initoption");

In this case, subinit is the subcommand of init and –initoption is a switch of command remove.

Parsing Arguments

ArgParser parses arguments through the parse(argv) method. This will inspect the command line and walk through it. A Arguments object will be built up from attributes parsed out of the command line holding key-value pairs all the parsed data and the function.

Arguments args = parser.parse(argv);

Invoke functions

To invoke the function associated with certain commands, we can perform this by simply calling invoke() from the Arguments object returned from the parsing. The function can be a lambda.

args.invoke();

Help and Version messages

  • Help message will be outputted when a wrong usage of the program is detected or –help option found.

  • Version message is defined unified in ArgParser::version_message().

Classes

class ArgParser
Option &add_option(std::string const &long_option, std::string const &short_option, std::string const &description, std::string const &envvar = "", unsigned arg_num = 0, std::string const &default_value = "", std::string const &key = "")

Add an option to current command with long name, short name, help description, environment variable, arguments expected, default value and lookup key. If no lookup key is provided, the long name will be used as lookup key without the prefix, for instance, for a long option --debug you should use debug as as lookup key. Return The Option object itself.

Command &add_command(std::string const &cmd_name, std::string const &cmd_description, std::function<void()> const &f = nullptr, std::string const &key = "")

Add a command with only name and description, function to invoke and lookup key. Return the new Command object.

Command &add_command(std::string const &cmd_name, std::string const &cmd_description, std::string const &cmd_envvar, unsigned cmd_arg_num, std::function<void()> const &f = nullptr, std::string const &key = "")

Add a command with name, description, environment variable, number of arguments expected, function to invoke and lookup key. The function can be passed by reference or be a lambda. It returns the new Command object.

void parse(const char **argv)

Parse the command line by calling parser.parse(argv). Return the new Arguments instance.

void help_message() const

Output usage to the console.

void version_message() const

Output version string to the console.

void add_global_usage(std::string const &usage)

Add a global_usage for help_message(). Example: traffic_blabla [–SWITCH [ARG]].

void set_default_command(std::string const &cmd)

Set a default command to the parser. This method should be called after the adding of the commands.

Command &require_commands()

Make the parser require commands. If no command is found, output help message. Return The Command instance for chained calls.

void set_error(std::string e)

Set the user customized error message for the parser.

std::string get_error() const

Return the error message of the parser.

class Option

Option is a data struct containing information about an option.

struct Option {
   std::string long_option;   // long option: --arg
   std::string short_option;  // short option: -a
   std::string description;   // help description
   std::string envvar;        // stored ENV variable
   unsigned arg_num;          // number of argument expected
   std::string default_value; // default value of option
   std::string key;           // look-up key
};
class Command

Command is a nested structure of command for ArgParser. The add_option(), add_command() and require_command() are the same with those in ArgParser. When add_command() is called under certain command, it will be added as a subcommand for the current command. For Example, command1.add_command("command2", "description") will make command2 a subcommand of command1. require_commands() is also available within Command.

void add_example_usage(std::string const &usage)

Add an example usage for the command to output in help_message. For Example: command.add_example_usage("traffic_blabla init --path=/path/to/file").

Command &set_default()

set the current command as default

class Arguments

Arguments holds the parsed arguments and function to invoke. It basically contains a function to invoke and a private map holding key-value pairs. The key is the command or option name string and the value is the Parsed data object which contains the environment variable and arguments that belong to this certain command or option.

std::string get(std::string const &name)

Return the ArgumentData object related to the name.

std::string set_env(std::string const &key, std::string const &value)

Set the environment variable given key.

void append(std::string const &key, ArgumentData const &value)

Append key-value pairs to the map in Arguments.

void append_arg(std::string const &key, std::string const &value)

Append value to the data of key.

void show_all_configuration() const

Show all the called commands, options, and associated arguments.

void invoke()

Invoke the function associated with the parsed command.

void has_action() const

return true if there is any function to invoke.

class ArgumentData

ArgumentData is a struct containing the parsed Environment variable and command line arguments. There are methods to get the data out of it.

Note: More methods can be added later to get specific types from the arguments.

operator bool() const noexcept

bool for checking if certain command or option is called.

std::string const &operator[](int x) const

Index accessing operator.

std::string const &env() const noexcept

Return the environment variable associated with the argument.

std::vector<std::string>::const_iterator begin() const noexcept

Begin iterator for iterating the arguments data.

std::vector<std::string>::const_iterator end() const noexcept

End iterator for iterating the arguments data.

std::string const &at(unsigned index) const

Index accessing method.

std::string const &value() const noexcept

Return the first element of the arguments data.

size_t size() const noexcept

Return the size of the arguments vector

size_t empty() const noexcept

Return true if the arguments vector and env variable are both empty.

Example

ArgParser

Below is a short example of using the ArgParser. We add some options and some commands to it using different ways. This program will have such functionality:

  • --switch, -s as a global switch.

  • Command func will call function() and this command takes 2 argument.

  • Command func2 will call function2(int num).

  • Command init has subcommand subinit and option --path which take 1 argument.

  • Command remove has option --path which takes 1 argument and has HOME as the environment variable.

#include "ts/ArgParser.h"

void function() {
    ...
}

void function2(int num) {
    ...
}

int main (int, const char **argv) {
    ts::ArgParser parser;
    parser.add_global_usage("traffic_blabla [some stuff]");

    parser.add_option("--switch", "-s", "top level switch");
    parser.add_command("func", "some function", "ENV_VAR", 2, &function);
    parser.add_command("func2", "some function2", [&]() { return function2(100); });

    auto &init_command = parser.add_command("init", "initialize");
    init_command.add_option("--path", "-p", "specify the path", "", 1);
    init_command.add_command("subinit", "sub initialize");

    parser.add_command("remove", "remove things").add_option("--path", "-p", "specify the path", "HOME", 1);

    ts::Arguments parsed_data = parser.parse(argv);
    parsed_data.invoke();
    ...
}

Arguments

To get the values from the arguments data, please refer to the methods in Arguments and ArgumentData