[Mono-dev] Program Option Parsing Library

Jay Logue jay-MonoDev at toaster.com
Thu Jan 10 13:43:06 EST 2008


You asked for thoughts, so here I go...   Overall I like it.  The use of 
lambda delegates is great.  As in perl, it helps keep the code succinct, 
and allows the snippets of option handling code to sit right next to the 
option definition.  A big plus in my book.

Where I think you may have OD'ed on the crack (:-) is in the use of an 
enumerator and ToArray() to parse the arguments.  Its a cleaver 
implementation, and I think you should keep it as an internal 
mechanism.  But from a user perspective it makes the code non-obvious.  
Most people would expect a method called Parse() on an object called 
Options to actually parse the options.  And seeing a call to ToArray() 
where you don't actually use the result (which will be typical for 
commands that don't use extra arguments) is very mysterious.

A better approach, I think, would be have a Parse() method that parses 
the argument list and returns the extra arguments via an out parameter.  
I like using an out parameter because it signals that Parse() is doing 
more than just producing an array.  Taking this approach, I would rename 
your existing Parse() method to something like GetArgumentParser() and 
make it private.  Then I would have the new Parse() method call 
GetArgumentParser() as part of its implementation.

Another thing I think is really important is better error handling for 
typed options.  If the call to TypeConverter.ConvertFromString() fails, 
the exception thrown needs to identify the name of the option that 
failed as well as its value.  I would create a specific exception class 
to convey this (with the original exception inside) so that the case can 
be caught and handled separately in the user's code.

Finally, it looks like this code doesn't handle the case of option 
values separated by whitespace--e.g. "--foo 42".  I think a lot of 
people will miss this feature.

I hope this was helpful.

-- Jay


Jonathan Pryor wrote:
> I've been doing a lot of work on monodocer, and (for some unknown
> reason) decided that the warning about the deprecation of
> Mono.GetOptions was annoying so I thought I'd come up with a
> replacement.
>
> This replacement is NOT currently intended to be stable, nor to be
> bundled with Mono itself for public use.
>
> It is also extremely crack-addled, which is why I'm liking it so much,
> and why I thought I'd share it with you.
>
> Crack-addled?  How else would you describe this cunning combination of
> collection initializers and lambda delegates?
>
>         bool help = false;
>         int verbose = 0;
>         string source = null;
>         
>         var p = new Options () {
>                 { "h|?|help",  v => help = v != null },
>                 { "v|verbose", v => { ++verbose; } },
>                 { "source=",   v => source = v },
>         };
>         p.Parse (new string[]{"--help", "-v", "-v", "-source=foo"})
>                 .ToArray ();
>         
> After p.Parse().ToArray(), help=true, verbose=2, and source="foo".
>
> It is inspired by Perl's Getopt::Long library, except that all option
> processing is done via delegates (i.e. Perl `sub's) and not via by-ref
> variables (as Perl also supports).
>
> No reflection is used unless you use TypeConverter to implicitly convert
> strings to random managed types:
>
>         int n = 0;
>         var p = new Options () {
>                 { "n=", (int v) => n = v }
>         };
>
> Options currently supports:
>
>       * Parameters of the form: -flag, --flag, /flag, -flag=value,
>         --flag=value, /flag=value, -flag:value,
>         --flag:value, /flag:value, -flag value, --flag value, /flag
>         value.
>       * "boolean" parameters of the form: -flag, --flag, and /flag.
>         Boolean parameters can have a `+' or `-' appended to explicitly
>         enable or disable the flag (in the same fashion as mcs -debug+).
>         For boolean callbacks, the provided value is non-null for
>         enabled, and null for disabled.
>       * "value" parameters with a required value (append `=' to the
>         option name) or an optional value (append `:' to the option
>         name). The option value can either be in the current option
>         (--opt=value) or in the following parameter (--opt value). The
>         actual value is provided as the parameter to the callback
>         delegate, unless it's (1) optional and (2) missing, in which
>         case null is passed.
>       * "bundled" parameters which must start with a single `-' and
>         consists of only single characters. In this manner, -abc would
>         be a shorthand for -a -b -c.
>       * Option processing is disabled when -- is encountered.
>
> Furthermore, it does not treat '-' options differently from '--' or '/'
> options, aside from the aforementioned bundling support.
>
> Regardless, at ~270 LOC for the associated classes (not including
> comments or tests), I think it's a reasonably concise and useful library
> for command-line option processing.
>
> See also: 
>     http://www.jprl.com/Blog/archive/development/mono/2008/Jan-07.html
>
> Thoughts?
>
> - Jon
>
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20080110/b527369a/attachment.html 


More information about the Mono-devel-list mailing list