dlangBugzillaToGithub / migration_test

0 stars 0 forks source link

[std.getopt] defaultGetoptPrinter can't be used if an exception fires #1009

Open dlangBugzillaToGithub opened 8 years ago

dlangBugzillaToGithub commented 8 years ago

kevin reported this on 2016-10-08T07:29:26Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=16604

CC List

Description

If an exception is thrown by getopt, the GetoptResults.options array is never returned. If it isn't returned, then I can't use the defaultGetoptPrinter function. This makes it impossible to call defaultGetoptPrinter in the event that a program's user ever makes a mistake.

The GetoptResults.options array is static regardless of what options are passed to the arguments of the program. It should always be built before any exceptions fire.

The only way around this is to have an exception show a generic "you made a mistake calling the program, call 'program --help' to see usage", or to call getopt with an empty args string and no required parameters to build a second options array first. Both are klunky.
dlangBugzillaToGithub commented 7 years ago

edi33416 commented on 2017-01-10T22:07:24Z

There is a more elegant solution.
You can use the passThrough config directive.

From the docs:
"Passing unrecognized options through:
If an application needs to do its own processing of whichever arguments getopt did not understand, it can pass the std.getopt.config.passThrough directive to getopt.

An unrecognized option such as "--baz" will be found untouched in args after getopt returns."

So, you could do something like this:

        auto helpInformation = getopt(
                args,
                std.getopt.config.passThrough,
                /* Your options here */);

        if (helpInformation.helpWanted || (args.length > 1))
        {
            defaultGetoptPrinter("Some information about the program.",
                    helpInformation.options);
        }

Any mistaken/nonexistent option will be in args, starting with index 1 (at args[0] you will have the name of your program)
dlangBugzillaToGithub commented 4 years ago

witold.baryluk+d commented on 2020-05-11T04:00:13Z

Yeah, I did find the exception throwing a bit problematic, and after some time of scratching, used similar trick to what Eduard proposed here.

But the fact that getopt is a function the immediately operates on the args, and doesn't provide introspection or compostability is a problem.

I think a Python argparse has a bit more interesting design, not because of it OOP-ness, but because it can have sub-parsers, you can compose them compose them easily, i.e. if you have multiple libraries that can be tweaked by some program flags, it is essentially impossible to use getopt. You can grab the unprocessed args, but then there is no easy way to forward it to other consumers implicitly really.

I grow a lot with Google flags ( https://github.com/gflags/gflags ) and golang flags (https://golang.org/pkg/flag/) when I did work at Google, and in fact I like them a lot. Similar solutions exist for Java.

If there is a way to do this things easily with getopt, I think documentation should be updated to show how to do it.