-
Notifications
You must be signed in to change notification settings - Fork 481
Design discussion: how to handle --help option #600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Also relevant, from #596 - if AutoHelp is false, UnknownOptionError("help") should be returned when
|
While writing tests for this, I discovered that CommandLine has some fundamental differences from how |
@rmunn |
I've read the origin of AutoHelp and AutoVersion, and also the discussion of why help output goes to stderr by default instead of stdout. (Which is a mistake, and CLP version 3 should swtich to stdout by default). BTW, in your comment about why version and help are directed to stderr, you say there are no drawbacks. I'll intersperse my answer below to explain why there are drawbacks after all.
Yes, there are drawbacks, as I'll explain below.
If the user is redirecting output when they call
The fact that stderr is unbuffered is not an advantage when it comes to handling the BTW, you can't actually count on stderr always being unbuffered. http://www.cplusplus.com/reference/cstdio/stderr/ says "stderr is is never fully buffered on startup. It is library-dependent whether the stream is line buffered or not buffered by default (see setvbuf)." (Emphasis mine).
The
This is correct; either one defaults to the terminal, so that by itself is no reason to pick one over the other.
This breaks the GNU Coding Standards (here and here), and as someone else mentioned, it can break some build infrastructure that naïvely assumes that anything printed to stderr is an error. Printing the help text when
This at least mitigates CLP's mistake in putting help text on stderr, because library users can fix the mistake without waiting for CLP version 3.
Because it breaks the GNU Coding Standards as well as most Unix users' expectations, the default should be changed in the next major version number (where breaking changes are acceptable). |
The design principle behind CommandLineParser is to mimic the behavior of the standard GNU
getopt
library, but the handling of the standard--help
option is failing to mimicgetopt
correctly.How it currently works
Currently, the
--help
option is really only recognized if it's the first option passed, e.g.:progname --help
causes the parser to return a HelpRequestedError, which if AutoHelp=true (the default) will print the help text.progname help
causes the parser to return a HelpVerbRequestedError, which if AutoHelp=true will print the help text.progname foo --help
is handled differently depending on whetherfoo
is a verb:foo
is a verb, then the help for that verb is constructed and returned.foo
is NOT a verb, thenprogname foo --help
causes the parser to return an UnknownOptionError("help"), which if AutoHelp=true will print the help text, and NOT print "ERROR(S): Option 'help' is unknown." This is because UnknownOptionError("help") is explicitly filtered out of the "meaningful errors" list, and only "meaningful errors" are displayed to the user.progname foo bar --help
, whenfoo
is a verb, actually does the same asprogname foo --help
whenfoo
is not a verb: it returns an UnknownOptionError("help") which is then filtered out of the output.How it should work
The GNU Coding Standards docs on how to handle
--help
are short:This doesn't resolve some of the ambiguous situations. But by experimenting with standard GNU utilities and how they handle the
--help
option, some clear patterns emerge:progname --help
should print help outputprogname --help foo
should ignore the argument "foo" and print help output.progname arg1 arg2 --help
should ignorearg1
andarg2
and print help output. Whetherarg1
andarg2
were valid options or not should be completely ignored, and the help output should not contain any errors even ifarg1
andarg2
were invalid.progname --input-file --help
, where--input-file
is an option that expects a string parameter, is a bit of a gotcha. This should NOT print help output; rather,--input-file
should receive the string--help
as its parameter. (You can confirm this by running multiple GNU commands on Linux, such asls --help
vsls --quoting-style --help
, and so on). More about this later.progname verb --help
should display the help text for the specific verb in question if verbs are being used, otherwiseverb
should be ignored.progname verb arg1 arg2 --help
should also display the help text for the specific verb in question, and not return any errors about arg1 and arg2.The GNU standards do not specify whether
-h
should be taken as a short form for the long--help
option. Here the behavior differs between Linux programs: some programs allow-h
as a short form for--help
, while others use-h
as a short form for a different command (e.g.,ls -h
is short forls --human-readable
). The way CommandLineParser should handle this is to have a AutoHelpShortName flag (a bool), defaulting to *false. If it is true, then the-h
option will be taken as a shortname for--help
. AutoHelpShortName should not be a string or a char; it is not recommended to change the shortname of the auto-help parameter from-h
to something else, so if you want to do that you'll need to set AutoHelp=false and implement your own help option.About that
--input-file --help
scenarioThe naïve approach, of scanning the incoming arguments to look for a
--help
option, will fail in this scenario. What needs to happen instead is that all arguments need to be parsed, and then all options (but NOT values) need to be scanned for the--help
option, and/or the-h
option if AutoHelpShortName is true. If the--help
option is found, then all other errors are ignored (as per the GNU docs) and the help text is printed out. (The only time errors should be printed out is if--help
is not present).What about
--version
?The GNU docs for
--version
are similar to--help
:They go on to explain in more detail how to format the version information, but that's not really relevant for this issue. What's important here is that
--version
should be treated just like--help
: it should handle--version
appearing in any position in the options (except as a value to some other option), and should not return any other errors if--version
is found. Also, there should be flag named AutoVersionShortName, defaulting to false, which will use the shortname-V
(capital V) if it is true. (Lowercase-v
is usually reserved for--verbose
; the de facto standard in Linux utilities is that if--version
has a shortname, it's capital-V
).PR forthcoming
I plan to write a PR to handle
--help
and--version
correctly, as opposed to the slightly-wrong way that CommandLineParser currently handles it. Expect that PR in the next few weeks.The text was updated successfully, but these errors were encountered: