September 01, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 9/1/13 2:07 AM, Jacob Carlborg wrote:
> On 2013-09-01 04:29, Jonathan M Davis wrote:
>
>> std.getopt is definitely lacking some nice-to-have features (like
>> automatically
>> generating --help from the options), but for the most part, I don't
>> think that
>> it can be improved much without seriously complicating it. I think
>> that it's
>> about at the limit of what can be done and still have it be simple,
>> and it
>> works really well for the most part, so if we haven't hit the sweet spot,
>> we're at least close. I've toyed with trying to figure out how to
>> improve it,
>> but I think that doing so cleanly would be very hard.
>
> I don't know if you're referring to the API or the implementation. But
> if you're referring to the API I think something like this could be made
> to work:
>
> string outputFile;
> getopt(args, "output", &outputFile).min(2).max(4).restrict("a", "b",
> "c", "d");
What would this line do?
Andrei
|
September 01, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 2013-09-01 16:28, Andrei Alexandrescu wrote: >> string outputFile; >> getopt(args, "output", &outputFile).min(2).max(4).restrict("a", "b", >> "c", "d"); > > What would this line do? The "output" argument expects at least two values and at most four. The values can be "a", "b", "c" or "d". -- /Jacob Carlborg |
September 01, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Sunday, 1 September 2013 at 17:20:56 UTC, Jacob Carlborg wrote:
> On 2013-09-01 16:28, Andrei Alexandrescu wrote:
>
>>> string outputFile;
>>> getopt(args, "output", &outputFile).min(2).max(4).restrict("a", "b",
>>> "c", "d");
>>
>> What would this line do?
>
> The "output" argument expects at least two values and at most four. The values can be "a", "b", "c" or "d".
Conceptionally questionable. The job of an argument parser is to
parse arguments, to possibly do some comfort magic (like
generating arg help) and to return info about the arguments in a
sensible manner.
It is *not* to do things that are not general but rather the
programms job.
And it is based on well established standards like having args in
either short form '-' (or '/' on windoze) plus one letter or in
long form '--' plus optionname and letting options have optional
arguments as in '-o outfile'.
Unless we want to arbitrarily (and therefore often uselessly)
pick out one of the many multi option argument notations like "-x
a:b=3:c=8859-15" it is - and should be - the task of the programm.
phobos job shouldn't be to provide comfort and magic for any and
every no matter how abstruse situation but to offer concise,
clear, well defined and real world mechanisms.
Considering that a standard lib is rather close to (and by many
considered part of) the language, there are, as in language
design, many trade offs to be decided upon, generality and
reliability weighing in much higher than "it can do everything
including the kitchen sink and a colour picker".
|
September 01, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ramon | On 2013-09-01 20:10, Ramon wrote: > Considering that a standard lib is rather close to (and by many > considered part of) the language, there are, as in language > design, many trade offs to be decided upon, generality and > reliability weighing in much higher than "it can do everything > including the kitchen sink and a colour picker". That's why I don't use it since it doesn't fit my needs. Why should I reimplement something that is already available for me? -- /Jacob Carlborg |
September 02, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
On Sat, Aug 31, 2013 at 07:29:42PM -0700, Jonathan M Davis wrote: > On Saturday, August 31, 2013 19:18:11 Andrei Alexandrescu wrote: > > I remember sitting next to Kirk McDonald at the D conference in 2007 as he was showing me Python's argparse. I personally found pretty much any example we could think of more verbose and uglier than std.getopt. > > std.getopt is definitely lacking some nice-to-have features (like automatically generating --help from the options), but for the most part, I don't think that it can be improved much without seriously complicating it. I think that it's about at the limit of what can be done and still have it be simple, and it works really well for the most part, so if we haven't hit the sweet spot, we're at least close. I've toyed with trying to figure out how to improve it, but I think that doing so cleanly would be very hard. I've had several people complain to me about std.getopt not understanding / supporting "standard" command-line syntax. Like '-c5' vs. '-c 5'. I've also experienced some quirks in how it handles option parsing, such as being unable to distinguish between '-w' and '--water' where both are distinct options (the use case is that multiple options begin with 'w', but one is more common than the others so '-w' is desirable as a shorthand, but currently std.getopt support for this is sketchy and unreliable). I'm not sure how to address this issue, though; I assume some of the design decisions stemmed from Windows vs. Posix compatibility, which may make supporting this kind of syntax tricky to support. > The main thing that I'd really like to see changed is the exception types that it throws, because I'd very much like to be able to have code which can give specific information about how the flags were incorrectly used and whatnot, and ConvException (which is usually what you get) doesn't cut it for that. You'd need getopt-specific exceptions for that. But we can fix that without changing the API. It's just that doing so would likely break code which was catching ConvException explicitly, so if we do that, we might be forced to introduce getOpt to replace getopt or something like that. But even if we did that, the basic design wouldn't change, just what it's throwing on failure. [...] Ideally, getopt should catch ConvExceptions (and whatever other exceptions that get thrown when a conversion fails, e.g., from a user-supplied delegate) and rethrow it with a better message. For example, "unable to convert 'abc' to int in option '-a'" instead of "std.exception.convException: illegal digit" or something similarly obscure, which is completely unhelpful to the end user. T -- Meat: euphemism for dead animal. -- Flora |
September 02, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
On Sunday, September 01, 2013 22:32:34 H. S. Teoh wrote: > On Sat, Aug 31, 2013 at 07:29:42PM -0700, Jonathan M Davis wrote: > > On Saturday, August 31, 2013 19:18:11 Andrei Alexandrescu wrote: > > > I remember sitting next to Kirk McDonald at the D conference in 2007 as he was showing me Python's argparse. I personally found pretty much any example we could think of more verbose and uglier than std.getopt. > > > > std.getopt is definitely lacking some nice-to-have features (like automatically generating --help from the options), but for the most part, I don't think that it can be improved much without seriously complicating it. I think that it's about at the limit of what can be done and still have it be simple, and it works really well for the most part, so if we haven't hit the sweet spot, we're at least close. I've toyed with trying to figure out how to improve it, but I think that doing so cleanly would be very hard. > > I've had several people complain to me about std.getopt not understanding / supporting "standard" command-line syntax. Like '-c5' vs. '-c 5'. I've also experienced some quirks in how it handles option parsing, such as being unable to distinguish between '-w' and '--water' where both are distinct options (the use case is that multiple options begin with 'w', but one is more common than the others so '-w' is desirable as a shorthand, but currently std.getopt support for this is sketchy and unreliable). > > I'm not sure how to address this issue, though; I assume some of the design decisions stemmed from Windows vs. Posix compatibility, which may make supporting this kind of syntax tricky to support. Some of its defaults are definitely wrong (e.g. bundling should be the default so that -water is identical to -w -a -t -e -r), but those are minor design flaws that could be fixed quite easily without really changing the API (though fixing some of them would change behavior enough that it would change the behavior of current code in a silent manner that might tick off some developers). If we were to have to create a new function to fix any of getopt's problems (e.g. the exception types that it throws), then I would want to fix some of getopt's defaults. If we had a nice list of getopt's quirks that should arguably be fixed, then we can look at creating a getOpt function with the improved behavior, but I think that that's very different from actually coming up with a new API, which is what would be required for some of the changes that some people want (like automatically generating --help), and that's what I think would be quite difficult to do cleanly. What we have is very close to ideal IMHO. It just needs a few tweaks. > > The main thing that I'd really like to see changed is the exception types that it throws, because I'd very much like to be able to have code which can give specific information about how the flags were incorrectly used and whatnot, and ConvException (which is usually what you get) doesn't cut it for that. You'd need getopt-specific exceptions for that. But we can fix that without changing the API. It's just that doing so would likely break code which was catching ConvException explicitly, so if we do that, we might be forced to introduce getOpt to replace getopt or something like that. But even if we did that, the basic design wouldn't change, just what it's throwing on failure. > > [...] > > Ideally, getopt should catch ConvExceptions (and whatever other exceptions that get thrown when a conversion fails, e.g., from a user-supplied delegate) and rethrow it with a better message. For example, "unable to convert 'abc' to int in option '-a'" instead of "std.exception.convException: illegal digit" or something similarly obscure, which is completely unhelpful to the end user. The message really isn't enough. I need to be able to programatically deal with the the error, meaning that I have to know things like exactly which flag failed. I may or may not have any interest in what the ConvException said. Having a nicer message for a GetOptException would be nice, but that would just be a bonus as far as I'm concerned. - Jonathan M Davis |
September 02, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 2013-09-02 07:58, Jonathan M Davis wrote: > If we had a nice list of getopt's quirks that should arguably be fixed, then we > can look at creating a getOpt function with the improved behavior, but I think > that that's very different from actually coming up with a new API, which is > what would be required for some of the changes that some people want (like > automatically generating --help), and that's what I think would be quite > difficult to do cleanly. What we have is very close to ideal IMHO. It just needs > a few tweaks. I don't see why the API needs to be changed to support automatically generating help messages. Extended yes, but not changed. This is a simple idea: uint timeout; getopt(args, "timeout|t", &timeout).help("Set the timeout"); This interface assumes you can call "getopt" multiple times and call "getopt" once per flag. Alternatively pass in some form of options struct or similar: struct Options { string help; } auto options = Options("Set the timeout"); uint timeout; getopt(args, "timeout|t", &timeout, options); -- /Jacob Carlborg |
September 02, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 9/2/13, Jacob Carlborg <doob@me.com> wrote:
> This is a simple idea:
>
> uint timeout;
> getopt(args, "timeout|t", &timeout).help("Set the timeout");
W.r.t. help strings, I would prefer if we could instead use:
getopt(args,
"timeout|t", &timeout, "Set the timeout",
"other", &other, // note: no comment!
"flag|f", &flag, "Set the flag")
I think we could make getopt support this. For example:
["foo", &foo] => name, field
["foo", &foo, "foo text"] => name, field, #3 is a comment
["foo", &foo, "foo text", "bar", &bar] => #3 is a commen
["foo", &foo, "foo text", &bar] => #3 is a new name
Essentially all getopt has to do is slice up the arguments into groups, where an address and the string before it begin a new group.
@Andrei: What do you think?
|
September 02, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
On Mon, Sep 02, 2013 at 04:16:30PM +0200, Andrej Mitrovic wrote: > On 9/2/13, Jacob Carlborg <doob@me.com> wrote: > > This is a simple idea: > > > > uint timeout; > > getopt(args, "timeout|t", &timeout).help("Set the timeout"); I don't like having to call getopt multiple times. This is D, we have delegates, we should only need to traverse args once and do whatever it is we need to do. > W.r.t. help strings, I would prefer if we could instead use: > > getopt(args, > "timeout|t", &timeout, "Set the timeout", > "other", &other, // note: no comment! > "flag|f", &flag, "Set the flag") > > I think we could make getopt support this. For example: > > ["foo", &foo] => name, field > ["foo", &foo, "foo text"] => name, field, #3 is a comment > ["foo", &foo, "foo text", "bar", &bar] => #3 is a commen > ["foo", &foo, "foo text", &bar] => #3 is a new name > > Essentially all getopt has to do is slice up the arguments into groups, where an address and the string before it begin a new group. [...] I like this idea. I like keeping the option definition, address, and help text all in one place. When a parse error occurs, getopt can display the help text for that particular option automatically. T -- Democracy: The triumph of popularity over principle. -- C.Bond |
September 02, 2013 Re: obsolete D libraries/modules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 9/1/13 10:20 AM, Jacob Carlborg wrote:
> On 2013-09-01 16:28, Andrei Alexandrescu wrote:
>
>>> string outputFile;
>>> getopt(args, "output", &outputFile).min(2).max(4).restrict("a", "b",
>>> "c", "d");
>>
>> What would this line do?
>
> The "output" argument expects at least two values and at most four. The
> values can be "a", "b", "c" or "d".
So output should probably be a string[].
We're looking at:
enforce(output.length >= 2 && output.length <= 4.
"Incorrect number of outputs passed");
enforce(["a", "b", "c", "d"].any(output),
"Invalid value for output");
This is a one-time work per program. Granted, error messages could be nicer so that's a couple more lines. The gain from integrating such checks would be small.
Andrei
|
Copyright © 1999-2021 by the D Language Foundation