Elm  1.0
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Command Line Options

Classes

class  elm::option::ActionOption
 
class  elm::option::BoolOption
 
class  elm::option::EnumOption< T >
 
class  elm::option::IntOption
 
class  elm::option::ListOption< T >
 
class  elm::option::OptionException
 
class  elm::option::Manager
 
class  elm::option::Option
 
class  elm::option::StandardOption
 
class  elm::option::StringList
 
class  elm::option::StringOption
 
class  elm::option::SwitchOption
 
class  elm::option::ValueOption< T >
 

Detailed Description

#include <elm/options.h>

ELM provides several classes to manage efficiently and easily command line options. There are currently two ways to use these classes, the old approach that will become quickly deprecated (please no more use it) and the new one.

The New Generation Approach (third generation)

To perform the parsing of command line arguments, ELM provides two basic classes. elm::option::Manager represents the command as a base of documentation and as a list of options items. The manager is initialized as in the following example:

#include <elm/options.h>
...
option::Manager manager = Make("my command", Version(1, 0, 0))
.description("This is my command !")
.license("GPL V")
.author("me <me@here.there>");

According to your needs, as many configurations as needed can be passed to the Make() object while maintaining type checking. Refer to elm::option::Manager::Make class documentation for the list of available configurations.

The options works in the same way:

option::SwitchOption opt1 = Make(manager).cmd("-o").cmd("--com").help("option 1");

As many ".cmd()" method calls can be added and other configurations can be passed using the same syntax. Refer to the documentations of the different option classes to get details about the configuration items (elm::option::Option::Make, elm::option::SwitchOption::Make, ...).

Using both configuration system for the manager and the option, a command is usually defined as in the following example:

class MyCommand: public option::Manager {
public:
MyCommand(void): option::Manager(Make("my-command", Version(1, 0, 0))
.description("This is my command !")
.license("GPL V")
.author("me <me@here.there>")),
opt(Make(*this).cmd("-o").cmd("--com").help("option 1")),
val(Make(*this).cmd("-v").cmd("--val").help("my value")) { }
...
private:
option::SwitchOption opt;
option::ValueOption val;
};

At this point, the options may be used as normal values in the program as below:

if(opt)
doSomething(val);

Free arguments, not processed by an option item, are usually handled by overriding the method

class MyCommand: public option::Manager {
public:
...
protected:
virtual void process(String arg) {
if(!my_arg)
my_arg = arg;
else
throw OptionException("only one argument supported !");
}
...
private:
string my_arg;
};

The example above supports only one argument. If not defined, the argument arg is copied to the field my_arg. If it is already defined, an OptionException is raised. In this case, the passed message will be displayed and the syntax of the command will automatically be displayed to the user then.

To use such a command, the main parameters, argc and argv, must be passed to the parse() method:

int main(int argc, char *argv[]) {
MyCommand cmd;
return cmd.parse(argc, argv);
}

This new approach allows to combine several benefits:

The Second Generation Approach

The goal of the new approach is to remove as much developer disturbance as possible. The full option configuration is based on variable arguments formed as list of tags possibly followed by an argument. This let configure the option and the option manager in a more natural way.

Let's go with a little example:

#include <elm/options.h>
using namespace elm::option;
class MyManager: public Manager {
public:
MyManager(void): Manager(
option::program, "my_program",
option::version, new Version(1, 2),
option::copyright, "GPL (c) 2007 IRIT - UPS",
option::end)
{ };
virtual void process(string arg) {
cout << "add argument " << arg << io::endl;
}
} manager;
BoolOption ok(manager,
option::cmd, "-c",
option::cmd, "--ok",
option::help, "is ok ?",
StringOption arg(manager,
option::cmd, "-s",
option::cmd, "--string",
option::help, "set string",
option::arg_desc, "a simple string",

This approach add a lot of flexibility because (1) all arguments do not need to be passed to the constructor (only the used ones) and (2) as many commands ('-' short name or '–' long name) as needed may be added to an option. As an example, look at the BoolOption below:

BoolOption verbose(manager,
option::long_cmd, "verbose",

The only requirement is that the configuration list passed to the manager or to an option is terminated by and option::end. This system of tags and arguments may also be used with the Manager class that centralizes the list of options of an application.

The supported tags includes:

In parenthesis, the first part design the application of the tag: to the manager or to the options. The second value give the type of the argument value of the option (if any).

In this new approach, you will need a small set of options classes:

elm::option::ValueOption<T> and elm::option::ListOption<T> are provided for usual types (as support from the elm::io::Input class) but may be customized for other types by overring some templates functions as below:

template <> inline T ValueOption<T>::get(VarArg& args) { return args.next<T>(); }
template <> inline T read<string>(string arg) { process arg to set the value }
The manager

The manager is the main entry to handle options. It provides the list of options but also information about the program. To provides this kind of data, one has to create a class inheriting fropm Manager and to initialize some fields in the constructor.

Then, non-options string may be handled by overloading the Manager::process() method. Each time one of this argument is found, this method will be called with the string as parameter. For example, in the command below, the Manager::process() method will be called twice: once with "file.txt" as argument and once with "mydir/" as argument.

$ cp file.txt mydir/
Option Usage

All options inherits from the Option class. Each one provides a constructor taking the actual manager as parameter. The following parameters may include (take a look at each class documentation for more details):

There are many class that allows parsing and retrieving options values as BoolOption, IntOption, StringOption or EnumOption. The option value may be accessed as a usual variable as in the example below:

if(ok)
cout << "string argument is " << arg << io::endl;

The ActionOption class is a bit more complex because it allows associating an action with an option. To achieve this, the user has to derive a class from ActionOption and to overload the ActionOption::perform() method to implement the specific behaviour.