The option parsing library consists of a set of classes derived from util::Option
which describe the types of the options the program accepts, for example a string, a float, an array of floats, etc.
There are two option readers, one constructing a list of options from the command line, the util::CommandLineReader
, and one constructing a list of options from a file, the util::ConfigFileReader
. Both are derived from the generic util::OptionReader
. They can also be used in combination, i.e. reading options from a file and allowing the user to override values via the command line. The example code below should make things clear.
When using the option parsing library, the first thing to do is to tell it what options a program accepts. This is done by adding Option
objects to an instance of OptionParser
. Each option will have a data type, and will hold a long option name (used on the command line with --long-option [value], an optional short option form (e.g. -l), a default value, and, optionally, a pointer to the data type where the option will store its value (a pointer to, e.g., a global variable, or a member of a struct.
Next, a program would tell the OptionParser
to parse the options it was given on the command line or in the config file. The OptionParser
uses an OptionReader
to do the actual reading. The values can then be probed using OptionParser::getOption()
.
Any arguments passed on the command line without a preceding '-' or '--' *AFTER* the last option are considered "file name arguments" and can be retrieved from the CommandLineReader
using CommandLineReader::fileArguments()
.
The command line syntax is as follows: --long-name or -s, arguments separated by a space from the option, array arguments separated by commas without space. Bool flags toggle their default value.
program --find-things --this-number 2.0 --array 1,2,3 -v 5.0 -s hello file1 file2 file3
In a config file, the syntax is long-option-name = value. '#' is the comment character. Value syntax the same as for the command line.
find-things = TRUE # true|false|TRUE|FALSE for bool options this-number = 2.0 # a float option array = 1,2,3 # an integer array value = 5.0 # another float, -v is short form, in the file we give the long name string = hello # -s was the short form
This config file can then be used together with the command line like this:
program --config-file program.conf --find-things --array 5,6,7 file1 file2 file3
So that the program will find --find-things
to be FALSE and array to be 5,6,7 (both overridden on the command line) and the remaining options as given in the config file.
The OptionParser::printUsage()
method generates properly formatted and annotated usage information:
-h, --help <FLAG> [FALSE] Print usage information. -e, --expr <STRING> [] The expression to evaluate. Mandatory. Function and variable names are case insensitive. The file operands are assigned to the variables in the expression in order. -o, --outfile <STRING> [test.fits] Output filename. ...
To make everything clear, here is an example using just the command line.
// globals bool help; string outfile; int size[3]; CommandLineReader comline(argc, argv); // read from command line OptionParser flags(&comline); // type --name default description -short ptr to value (optional) flags.addOption(new BoolOption("help", "FALSE", "Print usage information.", 'h', &help) ); flags.addOption(new StringOption("outfile", "test.fits", "Output filename.", 'o', &outfile) ); flags.addOption(new IntArrayOption("size", "0,0,0", "Size array", 's', 3, &size[0]) ); flags.parseOptions(); list<string> files = comline.fileArguments(); // get the filenames
Finally, here is a more complex example using first a config file and then allowing options to be overridden by the command line.
// globals bool help; string outfile; int size[3]; string cf = ""; // config file name should be the first command line argument: if( argc >= 3 && (!strcmp(argv[1],"--config-file") || !strcmp(argv[1],"-c")) ) cf = argv[2]; try { ConfigFileReader cfgfile( cf ); OptionParser flags( &cfgfile ); // here we use the ConfigFileReader // type --name default description -short ptr to value (optional) flags.addOption(new BoolOption("help", "FALSE", "Print usage information.", 'h', &help) ); flags.addOption(new StringOption("outfile", "test.fits", "Output filename.", 'o', &outfile) ); flags.addOption(new IntArrayOption("size", "0,0,0", "Size array", 's', 3, &size[0]) ); // read the config file flags.parseOptions(); // then try again from the command line CommandLineReader comline(argc, argv); // read from command line flags.changeReader( &comline ); flags.parseOptions(); } catch (exception& e) { flags.printUsage(cerr); throw; } // finally, retrieve the file arguments list<string> files = comline.fileArguments(); // get the filenames
ostream & operator<< | ( | ostream & | os, | |
Option & | op | |||
) | [related, inherited] |
Pretty-print the option to os.
ostream & operator<< | ( | ostream & | os, | |
const OptionParser & | op | |||
) | [friend, inherited] |
Write ltl::FVector to ascii stream. Compatible with opertor>>
.
Write options to op. Will pretty-print the options, their default values, and their given values to the stream:
expr | e | | help | h | FALSE | FALSE outfile | o | test.fits | test.fits propagate-errors | p | FALSE | FALSE size | s | 0,0,0 | 0,0,0 verbose | v | FALSE | FALSE