optparse module

Daniel Keep daniel.keep.lists at gmail.com
Sat Apr 15 03:39:06 PDT 2006



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/



More information about the Digitalmars-d mailing list