[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