Home

Awesome

CI status

Fire for C++

Fire for C++ is a single header library that creates a command line interface from a function signature. Here's the whole program for adding two numbers with command line:

#include <iostream>
#include <fire-hpp/fire.hpp>

int fired_main(int x = fire::arg("-x"), int y = fire::arg("-y")) {
    std::cout << x + y << std::endl;
    return 0;
}

FIRE(fired_main)

That's all. Usage:

$ ./add -x=1 -y=2
3

As you likely expect,

What's covered?

Why yet another CLI library?!

With most libraries, creating a CLI roughly follows this pattern:

  1. define arguments
  2. call parse(argc, argv);
  3. check whether errors are detected by parse(), print them and return (optional)
  4. check for -h and --help, print the help message and return (optional)
  5. for each argument:
    1. get argument from the map and if necessary convert to the right type
    2. try/catch for errors in conversion and return (optional)

That's a non-trivial amount of boilerplate, especially for simple scripts. Because of that, programmers (and a lot of library examples) tend to skip the optional parts, however this incurs a significant usability cost. Also, many libraries don't help at all with the conversion step.

With fire-hpp, you only call FIRE(fired_main) and define arguments as function parameters. When fired_main() scope begins, all steps have already been completed.

Q. Quickstart

Q.1 Requirements

Q.2 Running examples

Steps to run examples:

Q.3 Usage with cmake

T. Tutorial

Let's go through each part of the following example.

int fired_main(int x = fire::arg("-x"), int y = fire::arg("-y")) { // Define and convert arguments
    std::cout << x + y << std::endl; // Use x and y, they're ints!
    return 0;
}

FIRE(fired_main) // call fired_main()

D. Documentation

<a id="fire"></a> D.1 FIRE(fired_main[, program_description]) and variants

Program description can be supplied as the second argument:

FIRE(fired_main, "Hello there")

D.2 <a id="fire_arg"></a> fire::arg(identifiers[, default_value]])

<a id="identifier"></a> D.2.1 Identifiers

Identifiers are used to find arguments from command line and provide a description. In general, it's a brace enclosed list of elements (braces can be omitted for a single element):


<a id="default"></a> D.2.2 Default value (optional)

Default value if no value is provided through command line. Can be either std::string, integral or floating-point type and fire::arg must be converted to that same type. This default is also displayed on the help page.

For an optional argument without a default, see fire::optional.

<a id="constraints"></a> D.2.3 Constraints

Constraints can be applied to arguments by calling fire:arg's constraint methods:

These methods

  1. check whether user supplied value fits the constraint and emit a proper error message if condition is not met
  2. append the constraint to argument's help message

<a id="conversions"></a> D.3 fire::arg conversions

To conveniently obtain arguments with the right type and automatically check the validity of input, fire::arg class defines several implicit conversions.

<a id="standard"></a> D.3.1 std::string, integral, or floating point

Converts the argument value on command line to the respective type. Displays an error if the conversion is impossible or default value has wrong type.

<a id="optional"></a> D.3.2 fire::optional

Used for optional arguments without a reasonable default value. This way the default value doesn't get printed in a help message. The underlying type can be std::string, integral or floating-point.

fire::optional is a tear-down version of std::optional, with compatible implementations for has_value(), value_or() and value().

For an optional argument with a sensible default value, see default value.

<a id="flag"></a> D.3.3 bool: flag argument

Boolean flags are true when they exist on command line and false when they don't. Multiple single-character flags can be packed on command line by prefixing with a single hyphen: -abc <=> -a -b -c

<a id="variadic"></a> D.3.4 std::vector<T>: variadic argument

A method for getting all positional arguments as a vector. The fire::arg object can be converted to std::vector<std::string>, std::vector<integral type> or std::vector<floating-point type>. Using variadic argument forbids extracting positional arguments with fire::arg(index).

In this case, identifier should be fire::variadic(). Description can be supplied in the usual way.

<a id="post_functions"></a> D.4 Post fired_main() functions

<a id=""></a> D.4.1.1 Print help or error message with fire formatting

<a id=""></a> D.4.1.2 Helper function for getting named argument names in assert messages:

std::string fire::helpful_name(const string &name) - return user called name of the specified argument (given by one name) if it exists, otherwise return empty string.

std::string fire::helpful_name(int pos) - return correctly formatted positional argument number

<a id="raw_args"></a> D.4.2 Accessing raw arguments

Some third party libraries require access to raw argc/argv. This is gained through fire::raw_args (of type fire::c_args), which has argc() and argv() methods for accessing the arguments.

Examples:

int argc = fire::raw_args.argc();
char ** argv = fire::raw_args.argv();
non_modifying_call(argc, argv);
fire::c_args raw_args_copy = fire::raw_args; 
int& argc = raw_args_copy.argc();
char ** argv = raw_args_copy.argv();
modifying_call(argc, argv);
// Once out of scope, raw_args_copy releases argv strings

You also need FIRE_ALLOW_UNUSED(...) if the third party library processes it's own arguments.

G. Guides

L. Links

Other libraries you might find useful: