www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - optparse module

reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

Me again :P

I found I needed something to dump a file as hex the other day, so
naturally the first thing I wrote was a command-line argument parser :P

Here's the preliminary version, and since I can't see anything similar
in either phobos or on dsource, I thought I'd post it up here to see if
anyone thinks I should try getting it online somewhere.

So comments, criticisms and suggestions all welcome.  The archive
contains the module itself, a module to fix the problem with std.boxer,
and a test program.  It builds just fine with either

$ build optparse_test

or

$ dmd optparse_test.d optparse.d dmdbug_std_boxer_assert.d

So let me know what you think.  And thanks for all the help with getting
this to work :)

	-- Daniel

-- 

v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D
a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP    http://hackerkey.com/
Apr 14 2006
next sibling parent reply John C <johnch_atms hotmail.com> writes:
Daniel Keep wrote:
 Me again :P
 
 I found I needed something to dump a file as hex the other day, so
 naturally the first thing I wrote was a command-line argument parser :P
 
 Here's the preliminary version, and since I can't see anything similar
 in either phobos or on dsource, I thought I'd post it up here to see if
 anyone thinks I should try getting it online somewhere.

I was looking for a command-line parser just yesterday. Searching the newsgroups, I found this: http://www.digitalmars.com/d/archives/digitalmars/D/announce/553.html It's called ... er ... optparse ... just like yours. I guess after the Python library?
 
 So comments, criticisms and suggestions all welcome.  The archive
 contains the module itself, a module to fix the problem with std.boxer,
 and a test program.  It builds just fine with either
 
 $ build optparse_test
 
 or
 
 $ dmd optparse_test.d optparse.d dmdbug_std_boxer_assert.d
 
 So let me know what you think.  And thanks for all the help with getting
 this to work :)
 
 	-- Daniel
 

I'll have to try it out. Looks promising. Is there support for "/"-style options as well as the GNU/POSIX syntax?
Apr 14 2006
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
John C wrote:
 Daniel Keep wrote:
 Me again :P

 I found I needed something to dump a file as hex the other day, so
 naturally the first thing I wrote was a command-line argument parser :P

 Here's the preliminary version, and since I can't see anything similar
 in either phobos or on dsource, I thought I'd post it up here to see if
 anyone thinks I should try getting it online somewhere.

I was looking for a command-line parser just yesterday. Searching the newsgroups, I found this: http://www.digitalmars.com/d/archives/digitalmars/D/announce/553.html

Man, I suck at finding things...
 It's called ... er ... optparse ... just like yours. I guess after the
 Python library?
 

Wow. It's... pretty damn close to mine :P
 So comments, criticisms and suggestions all welcome.  The archive
 contains the module itself, a module to fix the problem with std.boxer,
 and a test program.  It builds just fine with either

 $ build optparse_test

 or

 $ dmd optparse_test.d optparse.d dmdbug_std_boxer_assert.d

 So let me know what you think.  And thanks for all the help with getting
 this to work :)

     -- Daniel

I'll have to try it out. Looks promising. Is there support for "/"-style options as well as the GNU/POSIX syntax?

Not at the moment, no. Since it was based on Python's optparse, I went with its syntax, although I was thinking on how to support different option styles. I couldn't decide between having a compile-time switch, or being able to override bits and pieces at runtime, so I just put it off :P Besides, I still have to get short option concatenation working... -- Daniel -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 14 2006
prev sibling next sibling parent reply Frank Benoit <keinfarbton nospam.xyz> writes:
Or this one

http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d
Apr 14 2006
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Frank Benoit wrote:
 Or this one
 
 http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d

That one's pretty nice; much shorter than mine. But then, mine produces a hash of boxes of pre-formatted values. With that one, you have to write a new delegate for each option. Plus, it doesn't have the way, way cool OptionParser.showHelp() method ^_^. -- Daniel -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 14 2006
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Daniel Keep wrote:

 
 Frank Benoit wrote:
 Or this one
 
 http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d

That one's pretty nice; much shorter than mine. But then, mine produces a hash of boxes of pre-formatted values. With that one, you have to write a new delegate for each option.

Hmm, I'm not totally sure I understand what you mean, could you provide an example?
 
 Plus, it doesn't have the way, way cool OptionParser.showHelp() method
 ^_^.

Does it print the arguments handled by optparse, like a default help sortof? ArgParser is only meant to be a low level arg/opt parser. I also think it should be easy to extend, both internally, and on top of it.
Apr 14 2006
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Lars Ivar Igesund wrote:
 Daniel Keep wrote:
 
 Frank Benoit wrote:
 Or this one

 http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d

But then, mine produces a hash of boxes of pre-formatted values. With that one, you have to write a new delegate for each option.

Hmm, I'm not totally sure I understand what you mean, could you provide an example?

Well, from what I can see of ArgParser, it parses the arguments, and calls delegates that you bind to specific argument prefixes. So I assume you do the processing on the arguments in the delegates. With optparse, you use prefab objects (or make your own) whose job is to tell the parser what names to bind to, and to handle parsing arguments (much like ArgParser). The difference is that the parsed value is then stored in a hash of Box'es. So if you had this object: # Object debugLevel = new NumericOption!(int)( # "d", // "short" name # "debuglevel", // "long" name # "DebugLevel") // key to store parsed value under Then once you've parsed your command line, you can access the final value like this: # unbox!(int)(optionParser["DebugLevel"]); ArgParser does roughly the same thing--optparse just automates a few of the steps a little.
 Plus, it doesn't have the way, way cool OptionParser.showHelp() method
 ^_^.

Does it print the arguments handled by optparse, like a default help sortof?

Yeah. For every option that you add, it will print its long and short names (whichever exist), its argument name (if it has one), and a help string. I would also sort them alphabetically, except array.sort doesn't seem to work if "array" is an array of objects :P
 ArgParser is only meant to be a low level arg/opt parser. I also think it
 should be easy to extend, both internally, and on top of it.
 

Fair enough. I wrote optparse basically to handle the 90% of cases I could think of. The other 10% should be mostly possible :P -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 14 2006
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Daniel Keep wrote:
 
 Lars Ivar Igesund wrote:
 
Daniel Keep wrote:


Frank Benoit wrote:

Or this one

http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d

That one's pretty nice; much shorter than mine. But then, mine produces a hash of boxes of pre-formatted values. With that one, you have to write a new delegate for each option.

Hmm, I'm not totally sure I understand what you mean, could you provide an example?

Well, from what I can see of ArgParser, it parses the arguments, and calls delegates that you bind to specific argument prefixes. So I assume you do the processing on the arguments in the delegates.

Well, yes... but come on, you can't tell me this isn't sexy: # bool verbose = false ; # char[] datafile = args[0] ~ ".db" ; # char[] logfile = args[0] ~ ".log" ; # # with (new ArgParser( # delegate uint (char[] value, uint ordinal) { # if (ordinal > 0) # throw new Exception("Invalid argument: " ~ value); # datafile = value; # return value.length; # } # )) { # bind("-", "v", delegate void () { verbose = true; }); # # bind("-", "l", delegate uint (char[] value) { # logfile = value; # return value.length; # }); # # parse(args[1 .. $]); # } Okay, so it isn't exactly super sexy... but it does give me an idea for new D proposal... using aliases of delegate types as anonymous delegate declerations! Aka.. given: # alias int delegate (int dA, int dB) BinaryOpDlg; One should be able to do: # someclass.registerOp("+", BinaryOpDlg { return dA + dB; }); Rather than the current: # someclass.registerOp("+", delegate int (int dA, int dB) { return dA + dB; });
 With optparse, you use prefab objects (or make your own) whose job is to
 tell the parser what names to bind to, and to handle parsing arguments
 (much like ArgParser).  The difference is that the parsed value is then
 stored in a hash of Box'es.  So if you had this object:
 
 # Object debugLevel = new NumericOption!(int)(
 #     "d", // "short" name
 #     "debuglevel", // "long" name
 #     "DebugLevel") // key to store parsed value under
 
 Then once you've parsed your command line, you can access the final
 value like this:
 
 # unbox!(int)(optionParser["DebugLevel"]);
 

This actually is a nifty idea. It looks like OptParse and ArgParser are parallels fitting subtly different niches. ArgParser is better it seems for flag and label args, while OptParser seems possibly better suited to data args.
Plus, it doesn't have the way, way cool OptionParser.showHelp() method
^_^.

Does it print the arguments handled by optparse, like a default help sortof?

Yeah. For every option that you add, it will print its long and short names (whichever exist), its argument name (if it has one), and a help string. I would also sort them alphabetically, except array.sort doesn't seem to work if "array" is an array of objects :P

It does work, but only if the class of those objects has implemented opCmp and opEquals. # class Foo { # int value; # # int opCmp (Object other) { # if (auto x = cast(Foo) other) return this.opCmp(x); # throw new Exception("Cannot compare classes Foo and " ~ other.classinfo.name); # } # # int opCmp (Foo other) { # return value < other.value # ? -1 # : value == other.value # ? 0 # : 1 # ; # } # # int opEquals (Object other) { # if (auto x = cast(Foo) other) return this.opEquals(x); # throw new Exception("Cannot compare classes Foo and " ~ other.classinfo.name); # } # # int opEquals (Foo other) { # return value == other.value; # } # }
 
ArgParser is only meant to be a low level arg/opt parser. I also think it
should be easy to extend, both internally, and on top of it.

Fair enough. I wrote optparse basically to handle the 90% of cases I could think of. The other 10% should be mostly possible :P

It occurs to me that OptParse could possibly be written as an extension to ArgParser. Like a scaffold-style child class. Scary idea, but almost worth attempting. -- Chris Nicholson-Sauls
Apr 15 2006
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Chris Nicholson-Sauls wrote:
 
 Daniel Keep wrote:
 Lars Ivar Igesund wrote:

 Daniel Keep wrote:


 Frank Benoit wrote:

 Or this one

 http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d

That one's pretty nice; much shorter than mine. But then, mine produces a hash of boxes of pre-formatted values. With that one, you have to write a new delegate for each option.

Hmm, I'm not totally sure I understand what you mean, could you provide an example?

Well, from what I can see of ArgParser, it parses the arguments, and calls delegates that you bind to specific argument prefixes. So I assume you do the processing on the arguments in the delegates.

Well, yes... but come on, you can't tell me this isn't sexy: # bool verbose = false ; # char[] datafile = args[0] ~ ".db" ; # char[] logfile = args[0] ~ ".log" ; # # with (new ArgParser( # delegate uint (char[] value, uint ordinal) { # if (ordinal > 0) # throw new Exception("Invalid argument: " ~ value); # datafile = value; # return value.length; # } # )) { # bind("-", "v", delegate void () { verbose = true; }); # # bind("-", "l", delegate uint (char[] value) { # logfile = value; # return value.length; # }); # # parse(args[1 .. $]); # }

That *is* very nice... I think the thing ArgParser has over optparse is that since it calls delegates, you can do funky things like maybe alter the processing of further arguments when you encounter special switches. You could do it with optparse, but it wouldn't be as... neat :P
 Okay, so it isn't exactly super sexy... but it does give me an idea for
 new D proposal... using aliases of delegate types as anonymous delegate
 declerations!  Aka.. given:
 
 # alias int delegate (int dA, int dB) BinaryOpDlg;
 
 One should be able to do:
 
 # someclass.registerOp("+", BinaryOpDlg { return dA + dB; });
 
 Rather than the current:
 
 # someclass.registerOp("+", delegate int (int dA, int dB) { return dA +
 dB; });

Oh now I LIKE that ^_^. Makes passing around delegates much easier on the eyes. I just wonder if that would be context free...
 
 With optparse, you use prefab objects (or make your own) whose job is to
 tell the parser what names to bind to, and to handle parsing arguments
 (much like ArgParser).  The difference is that the parsed value is then
 stored in a hash of Box'es.  So if you had this object:

 # Object debugLevel = new NumericOption!(int)(
 #     "d", // "short" name
 #     "debuglevel", // "long" name
 #     "DebugLevel") // key to store parsed value under

 Then once you've parsed your command line, you can access the final
 value like this:

 # unbox!(int)(optionParser["DebugLevel"]);

This actually is a nifty idea. It looks like OptParse and ArgParser are parallels fitting subtly different niches. ArgParser is better it seems for flag and label args, while OptParser seems possibly better suited to data args.

Well, you can do flags easily as well: # Object showHelp = new FlagTrueOption("?", "help", "ShowHelp"); # ... # if( unbox!(bool)(optionParser["ShowHelp"]) ) # { # optionParser.showHelp(); # }
 Plus, it doesn't have the way, way cool OptionParser.showHelp() method
 ^_^.

Does it print the arguments handled by optparse, like a default help sortof?

Yeah. For every option that you add, it will print its long and short names (whichever exist), its argument name (if it has one), and a help string. I would also sort them alphabetically, except array.sort doesn't seem to work if "array" is an array of objects :P

It does work, but only if the class of those objects has implemented opCmp and opEquals. # class Foo { # int value; # # int opCmp (Object other) { # if (auto x = cast(Foo) other) return this.opCmp(x); # throw new Exception("Cannot compare classes Foo and " ~ other.classinfo.name); # } # # int opCmp (Foo other) { # return value < other.value # ? -1 # : value == other.value # ? 0 # : 1 # ; # } # # int opEquals (Object other) { # if (auto x = cast(Foo) other) return this.opEquals(x); # throw new Exception("Cannot compare classes Foo and " ~ other.classinfo.name); # } # # int opEquals (Foo other) { # return value == other.value; # } # }

Oh AND opEquals! Damnit, I thought having opCmp would be enough... obviously not :P Thanks for that.
 ArgParser is only meant to be a low level arg/opt parser. I also
 think it
 should be easy to extend, both internally, and on top of it.

Fair enough. I wrote optparse basically to handle the 90% of cases I could think of. The other 10% should be mostly possible :P

It occurs to me that OptParse could possibly be written as an extension to ArgParser. Like a scaffold-style child class. Scary idea, but almost worth attempting. -- Chris Nicholson-Sauls

Yeah, that WOULD be scary. Funnily enough, I reckon you could do the opposite: implement ArgParser's interface on top of OptParse... just make an Option object that takes a delegate in the constructor, and calls it when it gets found :P Hmm... better stop now... we're getting into chicken-and-the-egg territory here :P -- Daniel -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 15 2006
prev sibling parent reply jcc7 <jcc7_member pathlink.com> writes:
In article <e1ocf1$2iej$1 digitaldaemon.com>, Daniel Keep says...
This is a multi-part message in MIME format.
--------------090201060608040605000801
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

Me again :P

I found I needed something to dump a file as hex the other day, so
naturally the first thing I wrote was a command-line argument parser :P

Here's the preliminary version, and since I can't see anything similar
in either phobos or on dsource, I thought I'd post it up here to see if
anyone thinks I should try getting it online somewhere.

Something like really needs to be added to Phobos since it's such a popular idea. I created a wiki page to list the existing modules (including this newest one): http://www.prowiki.org/wiki4d/wiki.cgi?Phobos/PosixGetOpt jcc7
Apr 14 2006
next sibling parent Frank Benoit <keinfarbton nospam.xyz> writes:
In Java I loved to use JCmdLine
http://jcmdline.sourceforge.net/

Perhaps someone wants to port it :D
Or someone knows how to use the j2d or language machine or something
like that.
Apr 14 2006
prev sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Yup.  Definitely need to learn to look better :P

In all honesty, I never liked getopt.  Too fiddly for my tastes.  I
suppose in the end, the good thing about all these different
implementations is that when Walter chooses one (you ARE going to put
one in the standard library, right?), he'll have a wide selection to
make his choice from.

And when he picks one, we can all bitch endlessly about it here ^_^

Ah well.  I think I'll go work on short form now... must... dethrone...
other... implementations...

	-- Daniel

jcc7 wrote:
 In article <e1ocf1$2iej$1 digitaldaemon.com>, Daniel Keep says...
 This is a multi-part message in MIME format.
 --------------090201060608040605000801
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 7bit

 Me again :P

 I found I needed something to dump a file as hex the other day, so
 naturally the first thing I wrote was a command-line argument parser :P

 Here's the preliminary version, and since I can't see anything similar
 in either phobos or on dsource, I thought I'd post it up here to see if
 anyone thinks I should try getting it online somewhere.

Something like really needs to be added to Phobos since it's such a popular idea. I created a wiki page to list the existing modules (including this newest one): http://www.prowiki.org/wiki4d/wiki.cgi?Phobos/PosixGetOpt jcc7

-- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 14 2006
next sibling parent jcc7 <jcc7_member pathlink.com> writes:
In article <e1op4c$2ueu$1 digitaldaemon.com>, Daniel Keep says...
Yup.  Definitely need to learn to look better :P

Well, I remembered where the one I found was, so it wasn't a fair fight.
In all honesty, I never liked getopt.  Too fiddly for my tastes.  I
suppose in the end, the good thing about all these different
implementations is that when Walter chooses one (you ARE going to put
one in the standard library, right?), he'll have a wide selection to
make his choice from.

That's right.
And when he picks one, we can all bitch endlessly about it here ^_^

Maybe he'll be generous and let us have two (yeah, right). jcc7
Apr 14 2006
prev sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <e1op4c$2ueu$1 digitaldaemon.com>, Daniel Keep says...
Yup.  Definitely need to learn to look better :P

In all honesty, I never liked getopt.  Too fiddly for my tastes.  I
suppose in the end, the good thing about all these different
implementations is that when Walter chooses one (you ARE going to put
one in the standard library, right?), he'll have a wide selection to
make his choice from.

And when he picks one, we can all bitch endlessly about it here ^_^

Ah well.  I think I'll go work on short form now... must... dethrone...
other... implementations...

	-- Daniel

Well, while we're on the topic, how about ArgParser for a twist: http://svn.dsource.org/projects/ddl/trunk/utils/ArgParser.d Example of it in action: http://svn.dsource.org/projects/ddl/trunk/utils/ddlinfo.d
jcc7 wrote:
 In article <e1ocf1$2iej$1 digitaldaemon.com>, Daniel Keep says...
 This is a multi-part message in MIME format.
 --------------090201060608040605000801
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 7bit

 Me again :P

 I found I needed something to dump a file as hex the other day, so
 naturally the first thing I wrote was a command-line argument parser :P

 Here's the preliminary version, and since I can't see anything similar
 in either phobos or on dsource, I thought I'd post it up here to see if
 anyone thinks I should try getting it online somewhere.

Something like really needs to be added to Phobos since it's such a popular idea. I created a wiki page to list the existing modules (including this newest one): http://www.prowiki.org/wiki4d/wiki.cgi?Phobos/PosixGetOpt jcc7

-- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/

- EricAnderton at yahoo
Apr 14 2006
parent pragma <pragma_member pathlink.com> writes:
I missed the message ealier in the thread when this was already mentioned.
Please disregard my previous post.

- Eric
Apr 14 2006