Skip to content

Customizing programs

The following sections explain the various attributes of Program and how to set them via the provided member functions.

In code, however, they are not member variables of Program (that's why I called them attributes instead). They are actually member variables of the ProgramMetadata class, held in the metadata member variable of Program.

This detail deserves a longer explanation somewhere else, so to keep things short here, it suffices to say that it serves the purpose of having a common data structure between Program and ProgramView. ProgramView is like a std::string_view, but for Program, and all program data is accessible through it, including its arguments and commands.

name

The first and most basic information of Program is name. It is the only attribute that the user is required to provide. Thus, it is specified in the constructor:

constexpr auto wget = Program("wget");

It is used, for example, when printing the automatic help text, and as identifier when adding a program as command of another program.

Output of the snippet above1:

wget

Usage:
    wget [--help]

Options & Flags:
    -h, --help    Display this information

title

The title is like the headline of the program. It is optional, but is also given in the constructor, as the second argument:

constexpr auto wget = Program("wget", "a non-interactive network retriever");

There is currently no special use for it, so it is only informational.

Output of the snippet above:

wget - a non-interactive network retriever

Usage:
    wget [--help]

Options & Flags:
    -h, --help    Display this information

version

version is... well, the program version. It is specified via the version member function and can be any string.

constexpr auto wget =
    Program("wget", "a non-interactive network retriever")
      .version("1.20.3");

In the automatic help, it is printed right next to the program name in the title line, so it is best to keep it within a maximum of ~16 characters.

Output of the snippet above:

wget 1.20.3 - a non-interactive network retriever

Usage:
    wget [--help]

Options & Flags:
    -h, --help    Display this information

introduction

introduction is what goes between the program name and its list of arguments. So, for example, it can be used as an actual introduction to the program and what it does, or some message about its usage. It is specified via the intro member function.

It has a special purpose, though. The introduction is used as the description for commands in the automatic help text of their parent program. In that case, an actual introduction is recommended. So an introduction like the one in the example below is OK if the program is the root program. It's also best to keep it short (2 or 3 lines maximum).

constexpr auto wget =
    Program("wget", "a non-interactive network retriever")
      .version("1.20.3")
      .intro("Mandatory arguments to long options are mandatory for short options too.");

Output of the snippet above:

wget 1.20.3 - a non-interactive network retriever

Mandatory arguments to long options are mandatory for short options too.

Usage:
    wget [--help]

Options & Flags:
    -h, --help    Display this information

details

details is a piece of text that goes after the list of arguments. It can be used, for example, to add some details that weren't relevant before, like website, documentation, or contact information. It is specified via the details member function.

constexpr auto wget =
    Program("wget", "a non-interactive network retriever")
      .version("1.20.3")
      .intro("Mandatory arguments to long options are mandatory for short options too.")
      .details("Email bug reports, questions, discussions to <bug-wget@gnu.org>"
               " and/or open issues at https://savannah.gnu.org/bugs/?func=additem&group=wget.");

Note that C++ allows strings to be break into separate pieces for better code formatting, but that does not affect the output of the automatic help. Don't make it too long, though, as that will move the argument list up in the help text.

Output of the snippet above:

wget 1.20.3 - a non-interactive network retriever

Mandatory arguments to long options are mandatory for short options too.

Usage:
    wget [--help]

Options & Flags:
    -h, --help    Display this information

Email bug reports, questions, discussions to <bug-wget@gnu.org> and/or open issues at
https://savannah.gnu.org/bugs/?func=additem&group=wget.

msg_width

The msg_width is what determines the maximum width of the messages that opzioni will output related to the program. For example, it is used when printing the automatic help and when using the built-in error handling actions. The default is 100 and it can be changed via the msg_width member function.

constexpr auto wget =
    Program("wget", "a non-interactive network retriever")
      .version("1.20.3")
      .intro("Mandatory arguments to long options are mandatory for short options too.")
      .details("Email bug reports, questions, discussions to <bug-wget@gnu.org>"
               " and/or open issues at https://savannah.gnu.org/bugs/?func=additem&group=wget.")
      .msg_width(64);

Output of the snippet above:

wget 1.20.3 - a non-interactive network retriever

Mandatory arguments to long options are mandatory for short
options too.

Usage:
    wget [--help]

Options & Flags:
    -h, --help    Display this information

Email bug reports, questions, discussions to <bug-wget@gnu.org>
and/or open issues at
https://savannah.gnu.org/bugs/?func=additem&group=wget.

It is a best-effort, though, so don't make it too narrow. If the maximum width is not enough for long words (like the URL above), they will be printed in a dedicated line anyway (try this last snippet with a maximum width of 32).

error_handler

error_handler determines how the program behaves when a user error occurs. This doesn't affect the automatic help text.

The default is to print the error message and the usage of the program. Changing it is done via the on_error member function. For example, to only print the error message:

constexpr auto wget =
    Program("wget", "a non-interactive network retriever")
      .version("1.20.3")
      .intro("Mandatory arguments to long options are mandatory for short options too.")
      .details("Email bug reports, questions, discussions to <bug-wget@gnu.org>"
               " and/or open issues at https://savannah.gnu.org/bugs/?func=additem&group=wget.")
      .msg_width(64)
      .on_error(print_error);

This also deserves a longer documentation, but until that's available, here is a brief explanation:

The argument to on_error must be of the ErrorHandler type, which is actually a using declaration for the following function pointer:

using ErrorHandler = int (*)(ProgramView const, UserError const &);

ProgramView was introduced earlier.

UserError is the base class of the exceptions that are thrown when a user error occurs (user as in user of the command-line program). All opzioni exceptions inherit from std::exception, so the error message can be obtained via their what member function.

Currently, the built-in error handlers are:

  • print_error: print the error message only.
  • print_error_and_usage: print the error message and the program usage (the default).
  • rethrow: rethrow the exception.

Just a detail about rethrow: note that, given the signature of ErrorHandler, the information of the actual class of the exception that was thrown is lost. In order to preserve their type information (and also be able to granularly catch exceptions, if that's desired), use the parse free function instead of Program's call operator when parsing the command-line. Just add a try and as many catches as desired to the following snippet:

auto const map = parse(wget, {argv, argc});

argc and argv are "flipped" and within {} because that's constructing a std::span.

Calling parse instead of Program::operator() avoids the built-in try... catch (which invokes error_handler). This means that "unsetting" or clearing error_handler isn't needed. In fact, on_error(nullptr) or on_error(NULL) doesn't compile. error_handler is a required attribute of Program.


  1. snippet output generated by adding the automatic help to the example. 

Back to top