digitalmars.D.announce - optparse.d -- good enough to be std.optparse?
- derick_eddington nospam.yashmoo.com May 30 2005
- derick_eddington nospam.yashmoo.com May 30 2005
- "Kris" <fu bar.com> May 30 2005
- derick_eddington nospam.yashmoo.com May 30 2005
- kris <fu bar.org> May 30 2005
- James Dunne <james.jdunne gmail.com> May 31 2005
- derick_eddington nospam.yashmoo.com Jun 01 2005
- "Andrew Fedoniouk" <news terrainformatica.com> May 31 2005
- derick_eddington nospam.yashmoo.com Jun 01 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 01 2005
I've made a command-line option helper similar to Python's optparse. It allows
you to specify what D-type you want the option as, short name, long name, help,
and more. It automatically creates a formatted help message and prints it on
errors. It checks that clients' usage of the module is proper; and it checks
that the command-line arguments meet what was specified. It has a compehensive
unittest that demonstrates more. The source is attached.
: /**
: * Example usage:
: */
: int main (char[][] args)
: {
: int verbosity;
: char[] outfile;
: char[][] files;
:
: // Constructor parameters are used in printing help.
: // -h / --help is always added by default
: // and uses program-name and usage.
: // --version (no short name) is added by
: // default if version is given.
: // program-name
: OptionParser op = new OptionParser(__FILE__[0..$-2],
: // usage version
: "[options] --files=f1,fN [outfile]", "0.2");
:
: // int, short and long, help, metavar,
: // no default, not mandatory
: op.addOption!(int)("v", "verbose",
: "Be more and more and more and more and more "
: "and more and more verbose.", "LEVEL");
: // comma-separated string list, short and long, help,
: // metavar, no default, mandatory
: op.addOption!(char[][])("fs", "files",
: "Files to process, and make this a really long help "
: "string as well to test aligning.", "FILE,FILE,...",
: null, true);
: // float, long-only, help, metavar, default, not mandatory
: op.addOption!(float)(null, "thing", "Do it with this.",
: "FLOAT", -4.297e21f);
: // no-value, short-only, with help, no metavar,
: // no default, not mandatory
: op.addOption!()("a", null, "Use alternate method.");
:
: // Parse command-line arguments, including args[0]
: // program-name (it's skipped).
: // args will be reset to the remaining non-option
: // command-line arguments in the order they appeared.
: Options options = op.parse(args);
:
: // Check if option was given on the command-line
: // by using (char[] in Options).
: // If the option has both short and long names,
: // either can be used.
: if ("verbose" in options)
: // If option was given and it has a value,
: // retrieve it by indexing Options with short
: // or long name (or only one if only one)
: // and do getValue!(T)
: verbosity = options["verbose"].getValue!(int);
:
: if (verbosity > 0)
: writefln("I'll say a little.");
: if (verbosity > 1)
: writefln("I'll say a lot more.");
:
: // args was reset by parse to the remaining
: // non-option command-line arguments
: if (args.length == 1)
: // use the first non-option argument
: outfile = args[0];
: else if (args.length > 1)
: // OptionError.errorExit("message") can be used to
: // print help and exit process;
: // useful when checking non-option arguments
: op.errorExit("more than one output file specified");
:
: // mandatory options can be assumed to be
: // there after successful parse
: assert ("files" in options);
: files = options["files"].getValue!(char[][]);
: if (files.length == 0)
: op.errorExit("need to specifiy at least one input file");
:
: if (verbosity > 0)
: {
: if ("thing" in options)
: writefln("my thing is: ",
: options["thing"].getValue!(float));
:
: // no-value options are simply tested for being in Options
: if ("a" in options)
: writefln("I would process files using alternate method:");
: else
: writefln("I would process files using normal method:");
: foreach (char[] f; files)
: writefln("\t",f);
: writefln("and output to ",
: outfile.length ? outfile : "<stdout>");
: }
:
: return 0;
: }
Example command-line output of above program:
---------------------------------------------------------------
$ ./example -h
usage: optparse [options] --files=f1,fN [outfile]
options:
-h, --help Show this help message and exit.
--version Show program's version number and exit.
-vLEVEL, --verbose=LEVEL
Be more and more and more and more and more and more
and more verbose.
-fsFILE,FILE,..., --files=FILE,FILE,...
Files to process, and make this a really long help
string as well to test aligning.
--thing=FLOAT Do it with this.
-a Use alternate method.
---------------------------------------------------------------
$ ./example -v2 --files=somefile,anotherfile,nextfile --thing -4.23e-6 -a
outputfile
I'll say a little.
I'll say a lot more.
my thing is: -4.23e-06
I would process files using alternate method:
somefile
anotherfile
nextfile
and output to outputfile
---------------------------------------------------------------
$ ./example --asdf
optparse: error: no such option: --asdf
[help]
---------------------------------------------------------------
$ ./example
optparse: error: -fs / --files option is mandatory
[help]
May 30 2005
In article <d7g5nd$3i3$1 digitaldaemon.com>, derick_eddington nospam.yashmoo.com says...Example command-line output of above program: --------------------------------------------------------------- $ ./example -h usage: optparse [options] --files=f1,fN [outfile] options: -h, --help Show this help message and exit. --version Show program's version number and exit. -vLEVEL, --verbose=LEVEL Be more and more and more and more and more and more and more verbose. -fsFILE,FILE,..., --files=FILE,FILE,... Files to process, and make this a really long help string as well to test aligning. --thing=FLOAT Do it with this. -a Use alternate method.
Arg, forgot to : these. The help print is nicely formatted...
May 30 2005
Very useful. I'd like to add this to Mango, if that would be OK? - Kris <derick_eddington nospam.yashmoo.com> wrote in message news:d7g5nd$3i3$1 digitaldaemon.com...I've made a command-line option helper similar to Python's optparse. It
you to specify what D-type you want the option as, short name, long name,
and more. It automatically creates a formatted help message and prints it
errors. It checks that clients' usage of the module is proper; and it
that the command-line arguments meet what was specified. It has a
unittest that demonstrates more. The source is attached. : /** : * Example usage: : */ : int main (char[][] args) : { : int verbosity; : char[] outfile; : char[][] files; : : // Constructor parameters are used in printing help. : // -h / --help is always added by default : // and uses program-name and usage. : // --version (no short name) is added by : // default if version is given. : // program-name : OptionParser op = new OptionParser(__FILE__[0..$-2], : // usage version : "[options] --files=f1,fN [outfile]", "0.2"); : : // int, short and long, help, metavar, : // no default, not mandatory : op.addOption!(int)("v", "verbose", : "Be more and more and more and more and more " : "and more and more verbose.", "LEVEL"); : // comma-separated string list, short and long, help, : // metavar, no default, mandatory : op.addOption!(char[][])("fs", "files", : "Files to process, and make this a really long help " : "string as well to test aligning.", "FILE,FILE,...", : null, true); : // float, long-only, help, metavar, default, not mandatory : op.addOption!(float)(null, "thing", "Do it with this.", : "FLOAT", -4.297e21f); : // no-value, short-only, with help, no metavar, : // no default, not mandatory : op.addOption!()("a", null, "Use alternate method."); : : // Parse command-line arguments, including args[0] : // program-name (it's skipped). : // args will be reset to the remaining non-option : // command-line arguments in the order they appeared. : Options options = op.parse(args); : : // Check if option was given on the command-line : // by using (char[] in Options). : // If the option has both short and long names, : // either can be used. : if ("verbose" in options) : // If option was given and it has a value, : // retrieve it by indexing Options with short : // or long name (or only one if only one) : // and do getValue!(T) : verbosity = options["verbose"].getValue!(int); : : if (verbosity > 0) : writefln("I'll say a little."); : if (verbosity > 1) : writefln("I'll say a lot more."); : : // args was reset by parse to the remaining : // non-option command-line arguments : if (args.length == 1) : // use the first non-option argument : outfile = args[0]; : else if (args.length > 1) : // OptionError.errorExit("message") can be used to : // print help and exit process; : // useful when checking non-option arguments : op.errorExit("more than one output file specified"); : : // mandatory options can be assumed to be : // there after successful parse : assert ("files" in options); : files = options["files"].getValue!(char[][]); : if (files.length == 0) : op.errorExit("need to specifiy at least one input file"); : : if (verbosity > 0) : { : if ("thing" in options) : writefln("my thing is: ", : options["thing"].getValue!(float)); : : // no-value options are simply tested for being in Options : if ("a" in options) : writefln("I would process files using alternate method:"); : else : writefln("I would process files using normal method:"); : foreach (char[] f; files) : writefln("\t",f); : writefln("and output to ", : outfile.length ? outfile : "<stdout>"); : } : : return 0; : } Example command-line output of above program: --------------------------------------------------------------- $ ./example -h usage: optparse [options] --files=f1,fN [outfile] options: -h, --help Show this help message and exit. --version Show program's version number and exit. -vLEVEL, --verbose=LEVEL Be more and more and more and more and more and more and more verbose. -fsFILE,FILE,..., --files=FILE,FILE,... Files to process, and make this a really long help string as well to test aligning. --thing=FLOAT Do it with this. -a Use alternate method. --------------------------------------------------------------- $ ./example -v2 --files=somefile,anotherfile,nextfile --thing -4.23e-6 -a outputfile I'll say a little. I'll say a lot more. my thing is: -4.23e-06 I would process files using alternate method: somefile anotherfile nextfile and output to outputfile --------------------------------------------------------------- $ ./example --asdf optparse: error: no such option: --asdf [help] --------------------------------------------------------------- $ ./example optparse: error: -fs / --files option is mandatory [help]
May 30 2005
Certainly. I'll keep you updated as I enhance and fix bugs. In article <d7g9q7$7b3$1 digitaldaemon.com>, Kris says...Very useful. I'd like to add this to Mango, if that would be OK? - Kris <derick_eddington nospam.yashmoo.com> wrote in message news:d7g5nd$3i3$1 digitaldaemon.com...I've made a command-line option helper similar to Python's optparse. It
you to specify what D-type you want the option as, short name, long name,
and more. It automatically creates a formatted help message and prints it
errors. It checks that clients' usage of the module is proper; and it
that the command-line arguments meet what was specified. It has a
unittest that demonstrates more. The source is attached.
May 30 2005
derick_eddington nospam.yashmoo.com wrote:Certainly. I'll keep you updated as I enhance and fix bugs.
Excellent ~ thx!
May 30 2005
In article <d7gqjo$nth$2 digitaldaemon.com>, kris says...derick_eddington nospam.yashmoo.com wrote:Certainly. I'll keep you updated as I enhance and fix bugs.
Who doesn't love to enhance bugs? =PExcellent ~ thx!
Regards, James Dunne
May 31 2005
I've updated optparse.d:
Option groups for help printout.
Example:
: optionParser = new OptionParser("myapp", "[option [value]]");
: optionParser.addOption!()("v", "verbose");
: optionParser.addOption!(float)("f", "foo", null, null, null, true);
: optionParser.addOption!(int)("x", "xeno", "does this and that", "THING");
: optionParser.addOption!(int[])("a", "apple", "make applesauce", null);
: optionParser.addOption!(long)("l", "long", "be longer", "LONG");
: optionParser.addOption!(double)("d", "double", null, "DOUBLE");
: optionParser.addOption!(uint[])("ui", "uint", null, "UINT,...");
: // make a group, options must have previously been added
: optionParser.makeGroup("number options", "f", "x", "a", "l", "d", "ui");
: optionParser.addOption!(char[])(null, "bar", "make it happen", "BLOB");
: optionParser.addOption!(char[][])("sb", "shabang", "blow up", "IT");
: // make a group, options must have previously been added
: optionParser.makeGroup("string options", "bar", "sb");
Will make help:
: usage: myapp [option [value]]
:
: options:
: -h, --help Show this help message and exit.
: --version Show program's version number and exit.
: -v, --verbose
:
: number options:
: -f, --foo
: -x THING, --xeno=THING
: does this and that
: -a, --apple make applesauce
: -l LONG, --long=LONG
: be longer
: -d DOUBLE, --double=DOUBLE
: -ui UINT,..., --uint=UINT,...
:
: string options:
: --bar=BLOB make it happen
: -sb IT, --shabang=IT
: blow up
Help string formatting separates short-name from METAVAR by a space for easier
reading.
Smarter use of templates to support more types.
Bug *un-enhanced* :) where "--option= --next-opt" would consume --next-opt as
--option's value instead of causing error because --option has no value.
A few more unittest cases.
Question for potential users of optparse.d:
Would you rather have anal checking of all usage of the module or reduce the
object-file size from 55k to 35k? I tried to use "version" but it's too buggy (I
just wanted version'd else-if...)
--Derick
Jun 01 2005
Cool, Derick!
What about using box values there?
Having them and use TypeList instead of
optionParser = new OptionParser(__FILE__[0..$-2], "[option [value]]",
"0.0");
optionParser.addOption!()("v","verbose");
optionParser.addOption!(float)("f","foo",null,null,null,true);
optionParser.addOption!(int)("x","xeno","does this and that","THING",123);
will allow to build such declarations in compile time - statically.
Just hypothesis....
Andrew.
<derick_eddington nospam.yashmoo.com> wrote in message
news:d7g5nd$3i3$1 digitaldaemon.com...
I've made a command-line option helper similar to Python's optparse. It
allows
you to specify what D-type you want the option as, short name, long name,
help,
and more. It automatically creates a formatted help message and prints it
on
errors. It checks that clients' usage of the module is proper; and it
checks
that the command-line arguments meet what was specified. It has a
compehensive
unittest that demonstrates more. The source is attached.
: /**
: * Example usage:
: */
: int main (char[][] args)
: {
: int verbosity;
: char[] outfile;
: char[][] files;
:
: // Constructor parameters are used in printing help.
: // -h / --help is always added by default
: // and uses program-name and usage.
: // --version (no short name) is added by
: // default if version is given.
: // program-name
: OptionParser op = new OptionParser(__FILE__[0..$-2],
: // usage version
: "[options] --files=f1,fN [outfile]", "0.2");
:
: // int, short and long, help, metavar,
: // no default, not mandatory
: op.addOption!(int)("v", "verbose",
: "Be more and more and more and more and more "
: "and more and more verbose.", "LEVEL");
: // comma-separated string list, short and long, help,
: // metavar, no default, mandatory
: op.addOption!(char[][])("fs", "files",
: "Files to process, and make this a really long help "
: "string as well to test aligning.", "FILE,FILE,...",
: null, true);
: // float, long-only, help, metavar, default, not mandatory
: op.addOption!(float)(null, "thing", "Do it with this.",
: "FLOAT", -4.297e21f);
: // no-value, short-only, with help, no metavar,
: // no default, not mandatory
: op.addOption!()("a", null, "Use alternate method.");
:
: // Parse command-line arguments, including args[0]
: // program-name (it's skipped).
: // args will be reset to the remaining non-option
: // command-line arguments in the order they appeared.
: Options options = op.parse(args);
:
: // Check if option was given on the command-line
: // by using (char[] in Options).
: // If the option has both short and long names,
: // either can be used.
: if ("verbose" in options)
: // If option was given and it has a value,
: // retrieve it by indexing Options with short
: // or long name (or only one if only one)
: // and do getValue!(T)
: verbosity = options["verbose"].getValue!(int);
:
: if (verbosity > 0)
: writefln("I'll say a little.");
: if (verbosity > 1)
: writefln("I'll say a lot more.");
:
: // args was reset by parse to the remaining
: // non-option command-line arguments
: if (args.length == 1)
: // use the first non-option argument
: outfile = args[0];
: else if (args.length > 1)
: // OptionError.errorExit("message") can be used to
: // print help and exit process;
: // useful when checking non-option arguments
: op.errorExit("more than one output file specified");
:
: // mandatory options can be assumed to be
: // there after successful parse
: assert ("files" in options);
: files = options["files"].getValue!(char[][]);
: if (files.length == 0)
: op.errorExit("need to specifiy at least one input file");
:
: if (verbosity > 0)
: {
: if ("thing" in options)
: writefln("my thing is: ",
: options["thing"].getValue!(float));
:
: // no-value options are simply tested for being in Options
: if ("a" in options)
: writefln("I would process files using alternate method:");
: else
: writefln("I would process files using normal method:");
: foreach (char[] f; files)
: writefln("\t",f);
: writefln("and output to ",
: outfile.length ? outfile : "<stdout>");
: }
:
: return 0;
: }
Example command-line output of above program:
---------------------------------------------------------------
$ ./example -h
usage: optparse [options] --files=f1,fN [outfile]
options:
-h, --help Show this help message and exit.
--version Show program's version number and exit.
-vLEVEL, --verbose=LEVEL
Be more and more and more and more and more and more
and more verbose.
-fsFILE,FILE,..., --files=FILE,FILE,...
Files to process, and make this a really long help
string as well to test aligning.
--thing=FLOAT Do it with this.
-a Use alternate method.
---------------------------------------------------------------
$ ./example -v2 --files=somefile,anotherfile,nextfile --thing -4.23e-6 -a
outputfile
I'll say a little.
I'll say a lot more.
my thing is: -4.23e-06
I would process files using alternate method:
somefile
anotherfile
nextfile
and output to outputfile
---------------------------------------------------------------
$ ./example --asdf
optparse: error: no such option: --asdf
[help]
---------------------------------------------------------------
$ ./example
optparse: error: -fs / --files option is mandatory
[help]
May 31 2005
If it could be setup statically at compile-time and have the same conciseness, flexibility, and ease of checking for options and retrieving their values, that would be awesome, but I don't follow what you mean about box values and TypeList. Could you elaborate? The only way to parameterize something at compile-time is with templates, right? But they can only take integral values, not char[] for option names or arbitrary types for default values. Statically-initialized structs could be used but then they still have to be given to an OptionParser and variables for them would also need to be declared. I don't think it can be done and retain the same degree of simpleness of use. In article <d7iifp$2jhh$1 digitaldaemon.com>, Andrew Fedoniouk says...Cool, Derick! What about using box values there? Having them and use TypeList instead of optionParser = new OptionParser(__FILE__[0..$-2], "[option [value]]", "0.0"); optionParser.addOption!()("v","verbose"); optionParser.addOption!(float)("f","foo",null,null,null,true); optionParser.addOption!(int)("x","xeno","does this and that","THING",123); will allow to build such declarations in compile time - statically. Just hypothesis.... Andrew.
Jun 01 2005
<derick_eddington nospam.yashmoo.com> wrote in message news:d7jvl1$1420$1 digitaldaemon.com...If it could be setup statically at compile-time and have the same conciseness, flexibility, and ease of checking for options and retrieving their values, that would be awesome, but I don't follow what you mean about box values and TypeList. Could you elaborate? The only way to parameterize something at compile-time is with templates, right? But they can only take integral values, not char[] for option names or arbitrary types for default values. Statically-initialized structs could be used but then they still have to be given to an OptionParser and variables for them would also need to be declared. I don't think it can be done and retain the same degree of simpleness of use.
Yep. You are right. I was thinking about simple implementation of something close to boost::spirit http://spirit.sourceforge.net/ but it seems like even simple implementation is an overkill for such task. Andrew.In article <d7iifp$2jhh$1 digitaldaemon.com>, Andrew Fedoniouk says...Cool, Derick! What about using box values there? Having them and use TypeList instead of optionParser = new OptionParser(__FILE__[0..$-2], "[option [value]]", "0.0"); optionParser.addOption!()("v","verbose"); optionParser.addOption!(float)("f","foo",null,null,null,true); optionParser.addOption!(int)("x","xeno","does this and that","THING",123); will allow to build such declarations in compile time - statically. Just hypothesis....
Andrew.
Jun 01 2005









derick_eddington nospam.yashmoo.com 