Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members

s11n::argv_parser Class Reference

argv_parser is an object for parsing command line options. More...

#include <argv_parser.h>

Inheritance diagram for s11n::argv_parser:

s11n::property_store List of all members.

Public Member Functions

 argv_parser (int argc, char *argv[], int startAt=0)
 Creates a new parser using the given arguments array and arg count.
virtual void set_help (const std::string &key, const std::string &text)
 get/set_help() text for a given key.
virtual const std::string getHelp (const std::string &key) const
 Returns the help text associated with key.
virtual bool is_set (const std::string &key) const
 Re-implemented to check keys -FOO and --FOO if key FOO is not found.
virtual std::string get_string (const std::string &key, const std::string &defaultVal=std::string()) const
 get_string() is overridden to add a special case to all get() calls made via the property_store API: if a get() function is called with a key which does not start with a dash (-) character and they key cannot be found in our list then -key and --key will be tried.
virtual int args (int argc, char *argv[], int startAt, const char *argpre="-")
 Makes a half-hearted attempt to parse out any args (begining with "-").
virtual int args (std::string args, std::string separators=" ")
 Similar to parse( int.
virtual const std::string dump_help (bool showcurrentvals=true) const
 Creates a "usage"-like string for this object containing all keys for which set_help() has been called.
virtual bool is_help_set ()
 Returns true if -help --help, -? or --? is set.

Static Public Member Functions

static argv_parserargs (int argc, char *argv[])
 args( int, char * ) should be called once from your main() if you want clients to be able to use args() to get at them.
static argv_parserargs ()
 Returns the object containing the arguments supplied to args(int,char**).

Detailed Description

argv_parser is an object for parsing command line options.

It exists in the s11n source tree only to ease development of test apps, and should not be considered to be part of the core library.

Use it like this:

include <iostream>
include "argv_parser.h"

define VERBOSE if( opts.get( "verbose", false ) ) cerr

int main( int argc, char **argv )
{
	argv_parser & opts = argv_parser::args( argc, argv );
        opts.set( "dosomething", ! opts.get_bool( "donothing", false ) );
        if( ! opts.get( "dosomething", true ) ) { exit( 0 )); }
        int myint = opts.get( "width", 20 );
        double myangle = opts.get( "angle", 0.0 );

        VERBOSE << "This is a verbose message." << endl;
        return opts.get( "errorcode", 0 );
}
(that code's just off the top of my head - it may not compile as-is.)

Note that client code outside of main can then get access to the args via the static function args():

argv_parser & opts = argv_parser::args();
           

See the property_store object's API for a full list of accessor functions.

Supported command-line formats:

-foo bar [that is, -foo == "bar"]
is the same as:
[--foo bar] [-foo=bar] [--foo=bar]

-foo -bar false [-foo == true, -bar == false]
-foo -bar=false [same]
--double-dashed "some string value"
--double-dashed="some string value" [same as previous line]
           

Whether you use single or double dashes is irrelevant, but you must call get() with the same key as was actually passed on the command-line, like so:

int width = opts.getInt( "-width", opts.getInt( "--width", 42 ) ); will check for -width first, then --width, defaulting to 42.

Alternately, if you use this form: opts.get_string( "foo" ); // WITHOUT a dash the following options are searched:

  1. foo
  2. -foo
  3. --foo

so the above call may actually result in getting the value from -foo or --foo. This is a potential logic problem if your application uses two semantically-different, like-named arguments like -force and --force. In this case a call to get( "force" ) would find -force and not --force. Use get( "-force" ) or get("--force") to avoid this ambiguity. The dashed versions of an argument are only sought after if get() is called without a dash before the key.

These sample dash-searching rules apply to is_set().

A note to Qt users: call args() on this object before calling QApplication a(argc, argv ), or QApplication will steal any argument called -name (and possibly others), removing it from argv. i.e., if you do not call args() on this object first, QApplication may steal arguments so you'll never see them. Been there, done that.

Known Bugs and/or gotchyas:

Negative numbers:

--boolflag -123=something
           

will be parsed as:

[--boolflag == true] [-123=something]
           

Search the .cpp file for 'negative' and you'll find where this bug lives. Since numeric arguments are so rare this is not such a big deal, i think. i can think of only a few real-world examples which use args like -1: ssh, [GNU] xargs, head, tail, lpr, ... okay, maybe they aren't so uncommon :/

Along those same lines:

--bool -234 --foobar
           
will be parsed as:
[--bool == -234] [--foobar == true]
           

Which i consider to be correct for most cases. If you want to set --bool to a negative number use: --bool=-123 If you want to force a boolean value in this case:

--bool=true -234 546
           

parses as:

--bool=true
-234=456
           

i hate the inconsistency this adds, though. :/

Definition at line 139 of file argv_parser.h.


Member Function Documentation

virtual int s11n::argv_parser::args std::string  args,
std::string  separators = " "
[virtual]
 

Similar to parse( int.

.. ) except that this one reads a whole line of options, parses that into an array, then passes it to parse(...). Note that this _may_ (but should not, ideally) behave slightly differently from arguments passed to the other form, which typically come in as command-line args (parsed by your shell). This functions uses a stdstring_tokenizer to do it's parsing, so any differences in behaviour should be resolved there. i am not aware of any differences.

virtual int s11n::argv_parser::args int  argc,
char *  argv[],
int  startAt,
const char *  argpre = "-"
[virtual]
 

Makes a half-hearted attempt to parse out any args (begining with "-").

Any args without values passed after them are assigned the value true. Sample valid command lines:

 foo --a --b foo --c bar --f
   (--a and --f == true, --b == "foo" and --c == "bar")
 foo --a eat --b this --c "you lazy bum"
   (--a==eat, --b==this, --c=="you lazy bum")
 foo --a=b --c d
   (--a == b, --c == d)
                   

These are identical for purposes of get( "c" ):

 [... -c=-1.0 ...] [... -c -1.0 ...] [... --c 1.0 ...] [... --c=1.0 ...]
                   

To get the values, call the property_store API functions like:

    int foo = parser.getInt( "--i" ); // getInt("i") now works for -i or --i :)
    bool bar = parser.get_bool( "--b" ); // or get_bool( "b") for -b or --b
                   
'startat' says which element in argv[] to start with.

If argpre = 0 then it uses the default argument prefix (defaults to "-"). If it is >0 then that is used as a char * prefix for all arguments.

This function also stores all processed values in a way familiar to bash and perl users: $0 = the first argument, $1 = the second arg etc. Thus given:

     ./foo --arg1 val1 --arg2=foo
                   
We have:
  myargs["$1"] == "--arg1"
  myargs["$3"] == "--arg2=foo" (it is arguably useful to split these, but then usage would be
                                inconsistent with bash/perl. However, as it is now it is inconsistent
                                with the results of "--arg2 foo" :/)
                   
Note that the values are added to this object (or overwrite existing entries), and the list is not cleared by this function.

virtual const std::string s11n::argv_parser::dump_help bool  showcurrentvals = true  )  const [virtual]
 

Creates a "usage"-like string for this object containing all keys for which set_help() has been called.

If showcurrentvals is true then the current values are also added to th string, otherwise they are left out.

Note that the order of the dumped help text/keys is alphabetic (because that's how the container object stores them).

TODO: maintain the order of args, using the order from set_help().

Sample:

in main() do:
argv_parser & args = argv_parser::args( argc, argv );
if( args.is_hel_set() )
{ // triggers on --help, -help, -? or --?
	cerr << args.dump_help();
        exit( 0 ); // some apps exit with a non-zero for help, some don't.
}
                   

virtual std::string s11n::argv_parser::get_string const std::string &  key,
const std::string &  defaultVal = std::string()
const [virtual]
 

get_string() is overridden to add a special case to all get() calls made via the property_store API: if a get() function is called with a key which does not start with a dash (-) character and they key cannot be found in our list then -key and --key will be tried.

This means that, assuming the above sample code is in place, the following would work:

~/ > myapp --foo=17.34
...
double d = opts.getDouble( "foo", 0.0 ); // d == 17.34

As will this:

opts.set( "--mykey", "myvalue" );
...
cerr << "mykey="<< opts.get_string( "mykey" ) << endl;

Note, however, that command-line arguments passed without a leading dash are not treated as arguments, and will not be inside this object if the command-line arguments are passed in via args(). Additionally, it is important to note that if key is passed in with a leading "-" then the additional "dash checking" is NOT done. That is, if you call:

opts.get_string( "-d", 0.0 );

then ONLY the entry -d will match, and not --d.

Reimplemented from s11n::property_store.


The documentation for this class was generated from the following file:
Generated on Thu Jun 16 16:18:12 2005 for s11n by  doxygen 1.4.3-20050530