Skip to content

MickaelBlet/Args

Repository files navigation

Args

Parse and store options from argc and argv.
Inspired by the Python library argparse.
Header-only library available at single_include/blet/args.h.
Documentations available at documentations.

Quick Start

#include <iostream>

#include "blet/args.h"

enum eLogLevel {
    EMERG_LEVEL = 0,
    ALERT_LEVEL,
    CRITICAL_LEVEL,
    ERROR_LEVEL,
    WARNING_LEVEL,
    NOTICE_LEVEL,
    INFO_LEVEL,
    DEBUG_LEVEL
};

void argToLogLevel(eLogLevel& logLevel, bool /*isExists*/, const std::string& argument) {
    if (argument == "EMERG" || argument == "0") {
        logLevel = EMERG_LEVEL;
    }
    else if (argument == "ALERT" || argument == "1") {
        logLevel = ALERT_LEVEL;
    }
    else if (argument == "CRITICAL" || argument == "2") {
        logLevel = CRITICAL_LEVEL;
    }
    else if (argument == "ERROR" || argument == "3") {
        logLevel = ERROR_LEVEL;
    }
    else if (argument == "WARNING" || argument == "4") {
        logLevel = WARNING_LEVEL;
    }
    else if (argument == "NOTICE" || argument == "5") {
        logLevel = NOTICE_LEVEL;
    }
    else if (argument == "INFO" || argument == "6") {
        logLevel = INFO_LEVEL;
    }
    else if (argument == "DEBUG" || argument == "7") {
        logLevel = DEBUG_LEVEL;
    }
}

int main(int argc, char* argv[]) {
    eLogLevel logLevel = INFO_LEVEL;

    blet::Args args;
    // set message printed at version action option
    args.setVersion("Version: 0.0.0");
    // add required positional ARGUMENT
    args.addArgument("ARGUMENT").help("help of positional argument").required();
    // add version option (-v, --version)
    args.addArgument("-v").flag("--version").help("print version").action(args.VERSION);
    // add multiargument option (-o, --option)
    args.addArgument(args.vector("-o", "--option")).help("help of option").nargs(2).metavar("OPT1 OPT2");
    // add choise option (-l, --log-level) with "dest" function
    args.addArgument("--log-level")
        .flag("-l")
        .help("help of log-level")
        .metavar("LEVEL")
        .valid(new blet::Args::ValidChoise(args.vector("0", "1", "2", "3", "4", "5", "6", "7", "EMERG", "ALERT",
                                                       "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG")))
        .defaults("INFO")
        .dest(logLevel, &argToLogLevel); // fill logLevel using argToLogLevel

    try {
        args.setStrict()           // except with additional argument
            .setAlternative()      // accept simple '-' with a long flag
            .setHelpException()    // except when help flag is called
            .setVersionException() // except when version flag is called
            .parseArguments(argc, argv); // add help option automatically
    }
    catch (const blet::Args::VersionException& e) {
        std::cout << e.what() << std::endl;
        return 0;
    }
    catch (const blet::Args::HelpException& e) {
        std::cout << e.what() << std::endl;
        return 0;
    }
    catch (const blet::Args::ParseArgumentException& e) {
        std::cerr << args.getBinaryName() << ": " << e.what();
        std::cerr << " -- '" << e.argument() << "'" << std::endl;
        return 1;
    }

    std::cout << "ARGUMENT: " << args["ARGUMENT"] << '\n';
    // check if option exists
    if (args["--option"]) {
        std::cout << "--option: " << args["--option"][0] << ", " << args["--option"][1] << '\n';
    }
    std::cout << "--log-level: ";
    switch (logLevel) {
        case EMERG_LEVEL:
            std::cout << "EMERG";
            break;
        case ALERT_LEVEL:
            std::cout << "ALERT";
            break;
        case CRITICAL_LEVEL:
            std::cout << "CRITICAL";
            break;
        case ERROR_LEVEL:
            std::cout << "ERROR";
            break;
        case WARNING_LEVEL:
            std::cout << "WARNING";
            break;
        case NOTICE_LEVEL:
            std::cout << "NOTICE";
            break;
        case INFO_LEVEL:
            std::cout << "INFO";
            break;
        case DEBUG_LEVEL:
            std::cout << "DEBUG";
            break;
    }
    std::cout << std::endl;

    return 0;
}
$ ./a.out --version
Version: 0.0.0
$ ./a.out -h
usage: a.out [-h] [-l LEVEL] [-o OPT1 OPT2] [-v] -- ARGUMENT

positional arguments:
  ARGUMENT              help of positional argument (required)

optional arguments:
  -h, --help            show this help message and exit
  -l, --log-level LEVEL
                        help of log-level (default: INFO)
  -o, --option OPT1 OPT2
                        help of option
  -v, --version         print version
$ ./a.out
./a.out: argument is required -- 'ARGUMENT'
$ ./a.out 42 -log-level Foo
./a.out: "Foo" is not a valid choise ("0", "1", "2", "3", "4", "5", "6", "7", "EMERG", "ALERT", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG") -- '-l'
$ ./a.out 42
ARGUMENT: 42
--log-level: INFO
$ ./a.out 42 --log-level=DEBUG --option Foo
./a.out: bad number of argument -- 'option'
$ ./a.out 42 -l7 -o Foo Bar
ARGUMENT: 42
--option: Foo, Bar
--log-level: DEBUG

Build

# Static Release
mkdir build; pushd build; cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 .. && make -j && make install; popd
# Dynamic Release
mkdir build; pushd build; cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 .. && make -j && make install; popd

# Static Release C++98
mkdir build; pushd build; cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=98 -DBUILD_SHARED_LIBS=0 .. && make -j && make install; popd
# Dynamic Release C++98
mkdir build; pushd build; cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=98 -DBUILD_SHARED_LIBS=1 .. && make -j && make install; popd

# Install with custom directory
mkdir build; pushd build; cmake -DCMAKE_INSTALL_PREFIX="YOUR_INSTALL_PATH" .. && make -j && make install; popd

# Example
mkdir build; pushd build; cmake -DBUILD_EXAMPLE=1 .. && make -j; popd

# Single Include + Test
mkdir build; pushd build; cmake -DBUILD_SINGLE_INCLUDE=1 -DBUILD_TESTING=1 .. && make -j; popd

# Tests + Coverage
mkdir build; pushd build; cmake -DBUILD_SHARED_LIBS=0 -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=1 -DBUILD_COVERAGE=1 -DCMAKE_CXX_STANDARD=11 .. && make -j && make test -j; popd

Option format

Short format

"-b"          # [b] == true
"-s" "Simple" # [s] == Simple
"-sSimple"    # [s] == Simple
"-s=Simple"   # [s] == Simple
"-bsSimple"   # [b] == true and [s] == Simple
"-bs=Simple"  # [b] == true and [s] == Simple

Long format

"--boolean"         # [boolean] == true
"--simple" "Simple" # [simple] == Simple
"--simple=Simple"   # [simple] == Simple
"-simple" "Simple"  # (alternative) [simple] == Simple
"-simple=Simple"    # (alternative) [simple] == Simple

Methods

addArgument

Define how a single command-line argument should be parsed.

std::vector<double> doublesFromArg;
blet::Args args;
args.addArgument({"-E", "--example"}) // Either a name or a list of option strings, e.g. foo or -f, --foo
    .flag("--new-example")            // Add option strings e.g. -f, --foo
    .action(args.INFINITE)            // The basic type of action to be taken when this argument is encountered at the command line
    .help("help message")             // A brief description of what the argument does
    .required(true)                   // Whether or not the command-line option may be omitted (optionals only)
    .metavar("ARGUMENT")              // A name for the argument in usage messages
    .nargs(1)                         // The number of command-line arguments that should be consumed
    .defaults({"0"})                  // A list of default string argument values
    .valid(new blet::Args::ValidMinMax(0, 100)) // Validate class from IValid interface
    .dest(doublesFromArg);            // Fill argument in destination

Definitions

Method Description
action The basic type of action to be taken when this argument is encountered at the command line.
defaults A list of default string argument values.
dest Fill argument in destination.
flag Add option strings e.g. -f, --foo
help A brief description of what the argument does.
metavar A name for the argument in usage messages.
nargs The number of command-line arguments that should be consumed.
required Whether or not the command-line option may be omitted (optionals only).
valid Validate argument from IValid interface.

parseArguments

Convert argument strings to objects and assign them as attributes of the args map.
Previous calls to addArgument determine exactly what objects are created and how they are assigned.

void parseArguments(int argc, char* argv[]);

Parse Options

blet::Args& setStrict(); // Activate exception if not all arguments are used; otherwise, you can take additional arguments with getAdditionalArguments method
blet::Args& setAlternative(); // Activate parsing to accept long option with only one '-' character
blet::Args& setHelpException(); // Throw a HelpException when help action is present in arguments; otherwise, exit(0) after outputting usage to stdout
blet::Args& setVersionException(); // Throw a VersionException when version action is present in arguments; otherwise, exit(0) after outputting version to stdout

Vector

Vector is an object that can be initialized with an initializer list, single string, or for C++98 with the vector static method.

blet::Args args;
args.addArgument("--simple");
args.addArgument({"-s", "--simple"});
args.addArgument("-s").flag("--simple");
args.addArgument(args.vector("-s", "--simple"));     // C++98
args.addArgument((const char*[]){"-s", "--simple"}); // C++98

Documentations

Args Basic Methods

Method Description
addArgument Define how a single command-line argument should be parsed.
parseArguments Convert argument strings to objects and assign them as attributes of the args map.
Previous calls to addArgument determine exactly what objects are created and how they are assigned.
If called without help action, define '-h' and '--help' if not used.

Custom Usage

Method Description
getDescription Get the description message.
getEpilog Get the epilog message.
getUsage Get the usage message.
setDescription Set the description in usage message.
setEpilog Set the epilog in usage message.
setUsage Set the usage message.
setUsageWidth Set the Usage Widths.

Args Methods

Method Description
argumentExists Check if argument exist.
clear Clear and reset with defaults values.
getAdditionalArguments Get the vector of additional argument.
getArgument Get the argument object.
getBinaryName Get the binary name.
getVersion Get the version message.
isAlternative Get the status of alternative.
isHelpException Get the status of helpException.
isStrict Get the status of strict.
isVersionException Get the status of versionException.
removeArguments Remove previously arguments.
setAlternative Activate parsing to accept long option with only one '-' character.
setBinaryName Set the binary name.
setHelpException Throw a HelpException when help action is present in arguments; otherwise, exit(0) after outputting usage to stdout.
setStrict Activate exception if not all arguments are used; otherwise, you can take additional arguments with getAdditionalArguments method.
setVersion Set the version message.
setVersionException Throw a VersionException when version action is present in arguments; otherwise, exit(0) after outputting version to stdout.
updateArgument Get the ref. of argument from name or flag.

Args::Argument Construct Methods

Method Description
action Add a action when this argument is encountered at the command line.
defaults Define the defaults string values.
dest Define a reference of object for insert the value after parseArguments method.
flag Add flag in argument object.
help Set the help description massge for this argument.
metavar A name for the argument in usage messages.
nargs The number of command-line arguments that should be consumed by this object.
required Whether or not the command-line argument may be omitted.
valid You can check format of argument with IValid interface.

Args::Argument::Action Types

Enum Description
APPEND This stores a list, and appends each argument value to the list.
It is useful to allow an option to be specified multiple times.
EXTEND This stores a list, and extends each argument value to the list.
HELP This case used for create the help flag.
INFINITE This stores a list.
NONE This just stores the argument’s value. This is the default action.
STORE_FALSE This case used for storing the values false respectively.
STORE_TRUE This case used for storing the values true respectively.
VERSION This case used for define the version flag.

Args::Argument Access Methods

Method Description
count After parseArguments method check if number of this argument in argv.
getAction Get action option.
getDefault Get the default value of argument.
getDefaults Get the default(s) value(s) of this argument.
getHelp Get help option.
getMetavar Get metavar option.
getNameOrFlags Get the name or flag(s) of this argument.
getNargs Get nargs option.
getNumber Get Number if isNumber.
getString Get the string format of this argument.
isExists After parseArguments method check if this argument is present in argv.
isNumber Check if this argument is a number ("1234aaa" is true with 1234 like number).
isRequired Get required option.
operator bool() Check if argument object isExists.
operator std::string() Call getString method.
operator std::vector<std::string>() If the argument object contains a lot of one argument, you can get a std::vector of std::string.
operator std::vector<std::vector<std::string> >() If the argument object contains a lot of one argument with number of argument (nargs) bigger than one, you can get a std::vector of std::vector of std::string.
operator T() Call the getNumber method with your custom type.

Examples

For more examples, see docs/examples.md.