Parsing command-line options with optparse begins with defining the options the program can accept. This starts with creating an instance of the OptionParser class, whose constructor is defined like this:
OptionParser(char[] desc="")
The desc parameter should be a short description of your program. It is used by the built-in help features, described later. OptionParser has a number of methods, the most important of which is addOption. The addOption method has a large number of overloads, representing the large number of kinds of options that optparse supports. Before going over these overloads, it is necessary to go over some of optparse's concepts.
First, this documentation makes the distinction between an option and an argument. An option is a literal string supplied by client code, such as "-f" or "--file". An argument is supplied by the end-user on the command-line. Some options accept arguments. If the user supplies "myapp --file=somefile.txt" to your program, then "--file" is an option, and "somefile.txt" is an argument to it. Arguments not associated with any particular option are called leftover arguments.
Options of the form "-f" are called short options. They start with a dash and are followed by any single non-dash character. Options of the form "--file" are called long options. They start with two dashes and may be of any length, and contain any characters, so long as they don't start with a third dash.
Every option has an action associated with it. The actions supported by optparse are:
The meaning of these actions will be discussed later. (Users of Python's optparse will probably find them familiar.) Certain actions accept arguments, and others do not. If an option's action accepts an argument, then that option also has a type. Types are represented by the ArgType enumerated type. Currently, the only types supported by optparse are ArgType.String and ArgType.Integer, which represent the D types char[] and int, respectively.
Options also have a name, which is used in a number of contexts. The name defaults to the first long option specified, without the dashes. If no long options are specified, it uses the first short option. An option's name is mainly used when retrieving its results, after parsing the arguments. Occasionally, it is useful to give multiple options the same name. Examples of this are given later.
For completeness' sake, here are all of the overloads of addOption:
As I describe each action, I will also list the relevant addOption overloads to that action. Not all of these apply to all of the actions.
A very simple use of optparse looks like this:
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption("-o", "--option"); auto options = parser.parse(args); }
Once the command-line has been parsed, the results are stored in an instance of the Options class. How you retrieve the results depends on the action.
Actions in optparse are represented by the Action enumerated type. Each of the following is a member of this enum.
This is the default action. An option with the Store action accepts an argument, and stores it. If the option is specified multiple times, then the last one is the one captured.
Retrieving the results of Store differs based on the option's type. Store's default type is String.
To retrieve a string argument, simply index the Options object with the option's name:
char[] filename = options["file"];
To retrieve an integer argument, pass the option's name to the value method of Options:
int num = options.value("number");
If the option was not provided on the command line, and no default was supplied with def, opIndex will return the empty string, and value will return 0.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption("-f", "--file"); parser.addOption(["-n", "--number"], ArgType.Integer); auto options = parser.parse(args); writefln("file: %s", options["file"]); writefln("number: %s", options.value("number")); }
This produces the following on the command-line:
$ myapp --file foo.txt -n28 file: foo.txt number: 28 $ myapp file: number: 0
Append behaves much like Store. Instead of simply storing its arguments, however, it appends them to a list.
Also as with Store, Append's default type is String. If the type of the option is string, pass its name to the list method of Options:
char[][] imports = options.list("import");
If the type is Integer, use the valueList method:
int[] values = options.valueList("value");
If the option is not provided on the command line, and no default was provided with def, these will both return an empty array.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption(["-I", "--import"], Action.Append); parser.addOption(["-V", "--value"], Action.Append, ArgType.Integer); auto options = parser.parse(args); writefln("imports: %s", options.list("import")); writefln("values: %s", options.valueList("value")); }
This produces the following on the command-line:
$ myapp -Isome/path -Ianother/path -V20 --value=30 imports: [some/path,another/path] values: [20,30] $ myapp imports: [] values: []
When an option with the StoreConst action is found, it stores some constant value provided by the client code. This is one way to implement a simple flag.
It is worth pointing out that you can have two different StoreConst options with the same name, but different constant values. This is one way of implementing a pair of "--enable" and "--disable" flags. (Even better would be using the SetTrue and SetFalse actions.)
Accessing the results of a StoreConst option is exactly like accessing those of a Store action with a String type. (Using opIndex.) If the option was specified, the constant value will be returned. If it wasn't, and no default was provided with def, it will return an empty string.
At this time, only strings are supported as constant values.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption(["--enable"], "flag", Action.StoreConst, "on"); parser.addOption(["--disable"], "flag", Action.StoreConst, "off"); auto options = parser.parse(args); writefln("flag: %s", options["flag"]); }
This produces the following on the command-line:
$ myapp --enable flag: on $ myapp --disable flag: off $ myapp flag:
Similar to StoreConst, this will append the supplied constant to a list whenever the option is found on the command-line.
Accessing the results of AppendConst works just like accessing those of an Append action with the String type, using the list method.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption(["--blue"], "color", Action.AppendConst, "blue"); parser.addOption(["--green"], "color", Action.AppendConst, "green"); auto options = parser.parse(args); writefln("colors: %s", options.list("color")); }
This produces the following on the command-line:
$ myapp --blue --green --blue colors: [blue,green,blue] $ myapp colors: []
Flag options may be implemented with these actions. The SetTrue action will set a flag to true, and SetFalse will set it to false.
The flag is retrieved using the flag method of the Options class.
bool flag = options.flag("flag");
If the flag was not specified, and no default was provided with def, it defaults to false.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption(["--enable"], "flag", Action.SetTrue); parser.addOption(["--disable"], "flag", Action.SetFalse); auto options = parser.parse(args); writefln("flag: %s", options.flag("flag")); }
This produces the following on the command-line:
$ myapp --enable flag: true $ myapp --enable --disable flag: false $ myapp flag: false
The Count action simply counts the number of times the option occurs on the command-line.
The count may be retrieved from the count method of Options.
int c = options.count("verbosity");
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption(["-v", "--verbose"], "verbosity", Action.Count); auto options = parser.parse(args); writefln("verbosity: %s", options.count("verbosity")); }
This produces the following on the command-line:
$ myapp -vvv verbosity: 3 $ myapp -v --verbose verbosity: 2 $ myapp verbosity: 0
Sometimes, the above actions aren't enough. To extend optparse, users may provide a callback as an option's action. A callback option may accept an argument. Whether it accepts an argument is determined by the type of the callback.
Important note: A callback is called as soon as it is encountered in the argument list. This means that optparse may still exit with an error if it finds malformed or invalid options on the command line, after the callback is run. For this reason, users should not place actual program logic inside of callbacks, and should only use them to store option data for later use.
The results of a callback option are not stored anywhere by optparse. It is assumed the user will keep any information about the callback themselves.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption(["--callback"], { writefln("Callback encountered!"); }); auto options = parser.parse(args); writefln("Done."); }
This produces the following on the command-line:
$ myapp --callback Callback encountered! Done. $ myapp Done.
If client code wants to handle the parsing process at a lower level, optparse provides these advanced callbacks.
The first four arguments to these callbacks have the following types and meanings:
The fifth argument to the callback, if it exists, controls the type of the argument to the option.
As with regular callbacks, optparse does not store the results of advanced callbacks.
void main(char[][] args) { auto parser = new OptionParser(); parser.addOption( ["--adv-callback"], (Options o, inout char[][] a, inout int i, char[] name) { // Skip the next argument, whatever it is. ++i; } ); parser.addOption(["-c"], Action.Count); auto options = parser.parse(args); writefln("count: %s", options.count("c")); }
This produces the following on the command-line:
$ myapp -c --adv-callback -cc count: 1
The Help action prints out a listing of the options in the parser.
The listing begins with a header like the following:
Usage: myapp [options] args... A short description of myapp. Options:
This header is customizable in two ways:
Additionally, the name of the application is derived directly from the first element of the args array.
Options are printed in the following form. Given these options:
parser.addOption("-f", "--file").help("The file to operate on.") parser.addOption(["--enable"], Action.SetTrue).help("Enables the option.")
Help produces the following:
-f, --file=FILE The file to operate on. --enable Enables the option.
The help method of the Option class provides the description used in the listing. Notice also the "=FILE" in the first option above. This indicates that the option accepts an argument. If you wanted to have this say "=FILENAME" instead, you would instead define the --file option as:
parser.addOption("-f", "--file").help("The file to operate on.").argName("filename");
The argName method of Option class defines this string, which otherwise defaults to the option's name. Note that it always converts the argument's name to all-caps.
Help terminates the program when found.
Bringing it all together, we get this:
void main(char[][] args) { auto parser = new OptionParser("Testing the Help action."); parser.argdesc = "[options]"; parser.addOption("-f", "--file").help("Defines the file to use.").argName("filename"); parser.addOption(["-n", "--number"], ArgType.Integer).help("Specifies the number."); parser.addOption(["--blue"], "color", Action.AppendConst, "blue").help("Adds the color blue."); parser.addOption(["--green"], "color", Action.AppendConst, "green").help("Adds the color green."); parser.addOption(["--help"], Action.Help).help("Displays this help message."); auto options = parser.parse(args); writefln("Done."); }
This produces the following on the command-line:
$ myapp --help Usage: myapp [options] Testing the Help action. Options: -f, --file=FILENAME Defines the file to use. -n, --number=NUMBER Specifies the number. --blue Adds the color blue. --green Adds the color green. --help Displays this help message. $ myapp Done.
class OptionError : Exception;
This exception is thrown by OptionParser when client code attempts to set up a malformed option.
enum Action { Store, StoreConst, Append, AppendConst, Count, SetTrue, SetFalse, Callback, CallbackFancy, Help }
enum ArgType { None, String, Integer }
The following delegate types define all the possible callback types used by optparse:
alias void delegate(Options, inout char[][], inout int, char[], char[]) OptionCallbackFancyArg;
alias void delegate(Options, inout char[][], inout int, char[], int) OptionCallbackFancyInt;
alias void delegate(Options, inout char[][], inout int, char[]) OptionCallbackFancy;
alias void delegate(char[]) OptionCallbackArg;
alias void delegate(int) OptionCallbackInt;
alias void delegate() OptionCallback;
Refer to the rest of this document for the meanings of parse and addOption.
class OptionParser { Option[] options; char[] argdesc; this(char[] desc=""); void setErrorCallback(void delegate(char[]) dg); void error(char[] err); void helpText(); Options parse(char[][] args); void leftoverCallback(OptionCallbackArg dg); Option addOption(Option option); Option addOption(char[][] options ...); Option addOption(char[][] options, char[] name); Option addOption(char[][] options, Action action); Option addOption(char[][] options, ArgType type); Option addOption(char[][] options, Action action, ArgType type); Option addOption(char[][] options, char[] name, Action action); Option addOption(char[][] options, char[] name, Action action, ArgType type); Option addOption(char[][] options, Action action, char[] const_value); Option addOption(char[][] options, char[] name, char[] const_value); Option addOption(char[][] options, char[] name, Action action, char[] const_value); Option addOption(char[][] options, OptionCallback dg); Option addOption(char[][] options, OptionCallbackArg dg); Option addOption(char[][] options, OptionCallbackInt dg); Option addOption(char[][] options, OptionCallbackFancy dg); Option addOption(char[][] options, OptionCallbackFancyArg dg); Option addOption(char[][] options, OptionCallbackFancyInt dg); Option addOption(char[][] options, char[] name, OptionCallbackFancy dg); Option addOption(char[][] options, char[] name, OptionCallbackFancyArg dg); Option addOption(char[][] options, char[] name, OptionCallbackFancyInt dg); }
Usage: myapp [options] args...The "[options] args..." part of this message is contained in argdesc, and may be overidden by client code. (The "myapp" part of the message is automatically derived from the first element of the args array.)
Each option defined by the client code is represented by an instance of this class. Client code does not typically interact with or instantiate this class directly, although the help and argName methods are needed when using the Help action.
class Option { Option help(char[] helpstr); Option argName(char[] argname); bool hasArg(); char[] toString(); }
parser.addOption("--someopt").help("Does something.");
When a command-line gets parsed by optparse, parse returns an instance of this class. All of the parsing results are stored here.
class Options { char[] opIndex(char[] name); int value(char[] name); char[][] list(char[] name); int[] valueList(char[] name); int count(char[] name); bool flag(char[] name); char[][] args; }