Recovering options to getopt after a GetOptException is raised

Andrew Pennebaker andrew.pennebaker at gmail.com
Sat Dec 8 19:58:16 UTC 2018


On Wednesday, 7 October 2015 at 17:15:17 UTC, Charles McAnany 
wrote:
> Friends,
>
> I'm a bit puzzled by the behavior of this code:
>
> import std.getopt;
> import std.stdio;
>
> void main(string[] args){
>     string val;
>     GetoptResult opts;
>     try{
>         opts = getopt(args, std.getopt.config.required, "val", 
> "value you need to specify", &val);
>     }catch(GetOptException e){
>         writeln("You idiot. You had to give these options:");
>         writeln(opts.options);
>     }
> }
>
> Expected result:
> :) programName --without --correct --argument
>    You idiot. You had to give these options:
>    --val value you need to specify
>
> Actual result:
> :) programName --without --correct --argument
>    You idiot. You had to give these options:
>    []
>
> It seems that the exception is thrown as soon as a missing 
> option is encountered. It would be nice if getopt would 
> populate GetoptResult.options before it threw the exception, 
> because it would make the above code work smoothly. 
> Alternatively, GetOptException could get a field containing the 
> documentation that was provided in the call to getopt:
>
> catch(GetOptException e){
>     writefln("You idiot. You didn't provide the required %s 
> argument (%s)", e.optionName, e.optionDocumentation);
> }
>
> If there is a way to handle this cleanly, I'd appreciate it. As 
> it is, std.getopt.config.required seems like it's not very 
> useful because it emits a rather unhelpful error message 
> (containing only the name of the missing option) and I can't 
> see a way to print a more useful message without checking all 
> the options in my own code.
>
> Cheers,
> Charles.

Yup, I just came across the same problem. D's getopt() is silly. 
GetoptException could have included a field representing the 
option specification, for use with defaultGetoptPrinter(); Or 
getopt() could have printed the -h usage and exit()'ed; Or 
std.getopt could have separated option specification construction 
vs. validation into distinct function calls, so that the spec 
could be bound to a variable for later use in printing the help 
message when a parse error might occur.

But D's getopt doesn't do any of these things! Not the most 
helpful. If D at least had splats like Ruby, then we could copy 
the inputs that would go into the getopt() call to an array, and 
reuse that spec, with a ["-h"] array of user arguments, to 
actually print out a help message.

Or, programmers can manually re-type the getopt() spec, yuck!

Or, I can imagine adding a loop around the try/catch, so that a 
failure sets a "fail" boolean and changes the user arguments to 
["-h"].

For me, I have to gauge how much time I want to spend cleaning up 
the stack trace-style usage message on invalid user input, 
against more productive use of my time.

By the way, the getopt() documentation seems to suggest that when 
users supply "-h|--help", that a usage banner is automatically 
printed. But in fact, the programmer must manually check the 
.helpWanted field on the result and manually run 
defaultGetoptPrinter(). Lame!


More information about the Digitalmars-d mailing list