The Lean Mean C++ Option Parser
Classes | Typedefs | Enumerations | Functions
option Namespace Reference

Detailed Description

The namespace of The Lean Mean C++ Option Parser.

Classes

struct  Arg
 Functions for checking the validity of option arguments. More...
 
struct  Descriptor
 Describes an option, its help text (usage) and how it should be parsed. More...
 
class  Option
 A parsed option from the command line together with its argument if it has one. More...
 
class  Parser
 Checks argument vectors for validity and parses them into data structures that are easier to work with. More...
 
struct  Stats
 Determines the minimum lengths of the buffer and options arrays used for Parser. More...
 

Typedefs

typedef ArgStatus(* CheckArg) (const Option &option, bool msg)
 Signature of functions that check if an argument is valid for a certain type of option. More...
 

Enumerations

Functions

template<typename OStream >
void printUsage (OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
 Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping. More...
 

Typedef Documentation

typedef ArgStatus(* CheckArg) (const Option &option, bool msg)

Signature of functions that check if an argument is valid for a certain type of option.

Every Option has such a function assigned in its Descriptor.

Descriptor usage[] = { {UNKNOWN, 0, "", "", Arg::None, ""}, ... };

A CheckArg function has the following signature:

ArgStatus CheckArg(const Option& option, bool msg);

It is used to check if a potential argument would be acceptable for the option. It will even be called if there is no argument. In that case option.arg will be NULL.

If msg is true and the function determines that an argument is not acceptable and that this is a fatal error, it should output a message to the user before returning ARG_ILLEGAL. If msg is false the function should remain silent (or you will get duplicate messages).

See ArgStatus for the meaning of the return values.

While you can provide your own functions, often the following pre-defined checks (which never return ARG_ILLEGAL) will suffice:

  • Arg::None For options that don't take an argument: Returns ARG_NONE.
  • Arg::Optional Returns ARG_OK if the argument is attached and ARG_IGNORE otherwise.

Definition at line 288 of file optionparser.h.

Enumeration Type Documentation

enum ArgStatus

Possible results when checking if an argument is valid for a certain option.

In the case that no argument is provided for an option that takes an optional argument, return codes ARG_OK and ARG_IGNORE are equivalent.

Enumerator
ARG_NONE 

The option does not take an argument.

ARG_OK 

The argument is acceptable for the option.

ARG_IGNORE 

The argument is not acceptable but that's non-fatal because the option's argument is optional.

ARG_ILLEGAL 

The argument is not acceptable and that's fatal.

Definition at line 248 of file optionparser.h.

Function Documentation

void option::printUsage ( OStream &  prn,
const Descriptor  usage[],
int  width = 80,
int  last_column_min_percent = 50,
int  last_column_own_line_max_percent = 75 
)

Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping.

printUsage() takes the help texts of a Descriptor[] array and formats them into a usage message, wrapping lines to achieve the desired output width.

Table formatting:

Aside from plain strings which are simply line-wrapped, the usage may contain tables. Tables are used to align elements in the output.

// Without a table. The explanatory texts are not aligned.
-c, --create |Creates something.
-k, --kill |Destroys something.
// With table formatting. The explanatory texts are aligned.
-c, --create |Creates something.
-k, --kill |Destroys something.

Table formatting removes the need to pad help texts manually with spaces to achieve alignment. To create a table, simply insert \t (tab) characters to separate the cells within a row.

const option::Descriptor usage[] = {
{..., "-c, --create \tCreates something." },
{..., "-k, --kill \tDestroys something." }, ...

Note that you must include the minimum amount of space desired between cells yourself. Table formatting will insert further spaces as needed to achieve alignment.

You can insert line breaks within cells by using \v (vertical tab).

const option::Descriptor usage[] = {
{..., "-c,\v--create \tCreates\vsomething." },
{..., "-k,\v--kill \tDestroys\vsomething." }, ...
// results in
-c, Creates
--create something.
-k, Destroys
--kill something.

You can mix lines that do not use \t or \v with those that do. The plain lines will not mess up the table layout. Alignment of the table columns will be maintained even across these interjections.

const option::Descriptor usage[] = {
{..., "-c, --create \tCreates something." },
{..., "----------------------------------" },
{..., "-k, --kill \tDestroys something." }, ...
// results in
-c, --create Creates something.
----------------------------------
-k, --kill Destroys something.

You can have multiple tables within the same usage whose columns are aligned independently. Simply insert a dummy Descriptor with help==0.

const option::Descriptor usage[] = {
{..., "Long options:" },
{..., "--very-long-option \tDoes something long." },
{..., "--ultra-super-mega-long-option \tTakes forever to complete." },
{..., 0 }, // ---------- table break -----------
{..., "Short options:" },
{..., "-s \tShort." },
{..., "-q \tQuick." }, ...
// results in
Long options:
--very-long-option Does something long.
--ultra-super-mega-long-option Takes forever to complete.
Short options:
-s Short.
-q Quick.
// Without the table break it would be
Long options:
--very-long-option Does something long.
--ultra-super-mega-long-option Takes forever to complete.
Short options:
-s Short.
-q Quick.

Output methods:

Because TheLeanMeanC++Option parser is freestanding, you have to provide the means for output in the first argument(s) to printUsage(). Because printUsage() is implemented as a set of template functions, you have great flexibility in your choice of output method. The following example demonstrates typical uses. Anything that's similar enough will work.

#include <unistd.h> // write()
#include <iostream> // cout
#include <sstream> // ostringstream
#include <cstdio> // fwrite()
using namespace std;
void my_write(const char* str, int size) {
fwrite(str, size, 1, stdout);
}
struct MyWriter {
void write(const char* buf, size_t size) const {
fwrite(str, size, 1, stdout);
}
};
struct MyWriteFunctor {
void operator()(const char* buf, size_t size) {
fwrite(str, size, 1, stdout);
}
};
...
printUsage(my_write, usage); // custom write function
printUsage(MyWriter(), usage); // temporary of a custom class
MyWriter writer;
printUsage(writer, usage); // custom class object
MyWriteFunctor wfunctor;
printUsage(&wfunctor, usage); // custom functor
printUsage(write, 1, usage); // write() to file descriptor 1
printUsage(cout, usage); // an ostream&
printUsage(fwrite, stdout, usage); // fwrite() to stdout
ostringstream sstr;
printUsage(sstr, usage); // an ostringstream&
Notes:
  • the write() method of a class that is to be passed as a temporary as MyWriter() is in the example, must be a const method, because temporary objects are passed as const reference. This only applies to temporary objects that are created and destroyed in the same statement. If you create an object like writer in the example, this restriction does not apply.
  • a functor like MyWriteFunctor in the example must be passed as a pointer. This differs from the way functors are passed to e.g. the STL algorithms.
  • All printUsage() templates are tiny wrappers around a shared non-template implementation. So there's no penalty for using different versions in the same program.
  • printUsage() always interprets Descriptor::help as UTF-8 and always produces UTF-8-encoded output. If your system uses a different charset, you must do your own conversion. You may also need to change the font of the console to see non-ASCII characters properly. This is particularly true for Windows.
  • Security warning: Do not insert untrusted strings (such as user-supplied arguments) into the usage. printUsage() has no protection against malicious UTF-8 sequences.
Parameters
prnThe output method to use. See the examples above.
usagethe Descriptor[] array whose help texts will be formatted.
widththe maximum number of characters per output line. Note that this number is in actual characters, not bytes. printUsage() supports UTF-8 in help and will count multi-byte UTF-8 sequences properly. Asian wide characters are counted as 2 characters.
last_column_min_percent(0-100) The minimum percentage of width that should be available for the last column (which typically contains the textual explanation of an option). If less space is available, the last column will be printed on its own line, indented according to last_column_own_line_max_percent.
last_column_own_line_max_percent(0-100) If the last column is printed on its own line due to less than last_column_min_percent of the width being available, then only last_column_own_line_max_percent of the extra line(s) will be used for the last column's text. This ensures an indentation. See example below.
// width=20, last_column_min_percent=50 (i.e. last col. min. width=10)
--3456789 1234567890
1234567890
// width=20, last_column_min_percent=75 (i.e. last col. min. width=15)
// last_column_own_line_max_percent=75
--3456789
123456789012345
67890
// width=20, last_column_min_percent=75 (i.e. last col. min. width=15)
// last_column_own_line_max_percent=33 (i.e. max. 5)
--3456789
12345
67890
12345
67890

Definition at line 2788 of file optionparser.h.