Many programs have command line options that can be specified in either a long or short form.
The most common example would be --help and -h (which are automaticaly included with flag).
As the package currently exists, there is no real good way to define other flags that have this behavior.
This can be done using the Var variants of the functions. For example
var frobVal int
func init() {
flag.IntVar(&frobVal, "frob", 0, "set the frob value")
flag.IntVar(&frobVal, "f", 0, "set the frob value")
}
there are 2 problems with that. First, most of that code is the exact same. Second, using -h will result in 2 entries with the exact same text.
If there was a function like the one I'm proposing, the output would be more like:
-f, -frob set the frob value
OK, we can think about it. Do you have a suggested API?
I don't have any real ideas for function names, but the should probably be the same as current functions (with a normal and Var form) but with 2 name arguments (perhaps short and long?).
that's just my idea, and I'd be open to hearing any better ideas anyone has.
I think something like func Synonym(flag string, synonyms ...string) would suffice. That changes the example to:
var frobVal int
func init() {
flag.IntVar(&frobVal, "f", 0, "set the frob value")
flag.Synonym("f", "frob") // displayed in this order in usage message
}
See https://github.com/rsc/getopt for an example of what you can build on top of the flag package as-is.
I think something like
func Synonym(flag string, synonyms ...string)would suffice. That changes the example to:var frobVal int func init() { flag.IntVar(&frobVal, "f", 0, "set the frob value") flag.Synonym("f", "frob") // displayed in this order in usage message }
Yeah, this seem like it would be a better way to do this, as it wouldn't require doubling the amount of functions in the package.
Perhaps Alias would be a better name though? It's already a common term in relation to shell commands, and it's also shorter to type.
I think long and short flags can be added easily with backwards compatibility by extending the name argument of the flags. Currently, the name argument can be anything, but in practice it's just a word, since having a whitespace in the name is unusable.
Instead, by splitting the name using strings.Fields, multiple names for a single flag can be provided:
flag.IntVar(&frobVal, "frob f", 0, "set the frob value")
This way, you won't get a second entry in flag.PrintDefaults, and no new API surface will need to be introduced.
I do not think its worth it trying to squeeze it into the current function signature. I do not see any current restrictions on the name string in the flags package. Are we sure non-ASCII whitespace is currently not usable in Flag names?
@martisch
Setting up a flag with a whitespace in it currently produces the following help text:
-foo bar
usage (default true)
However, if you try to use what the help text displays ./prog -foo bar, you get the following error:
flag provided but not defined: -foo
Instead, one would have to invoke it as ./prog -foo\ bar. This is quite unusable, since the help text itself does not tell you this. I can also make an educated guess that no cli app with users has any flags that contain whitespaces.
I think long and short flags can be added easily with backwards compatibility by extending the name argument of the flags. Currently, the name argument can be anything, but in practice it's just a word, since having a whitespace in the name is unusable.
Instead, by splitting the name using strings.Fields, multiple names for a single flag can be provided:flag.IntVar(&frobVal, "frob f", 0, "set the frob value")This way, you won't get a second entry in flag.PrintDefaults, and no new API surface will need to be introduced.
While this likely wouldn't break anything in practice, it would technically be a breaking change, and the benefit of slightly less typing doesn't justify the cost.
Other problems include:
Also, the flag could be specified with -"foo bar" or -'foo bar', same with filename with whitespace.
This is a duplicate of #35761. Please see the discussion there about why this part of this is possible today and the other part is not possible at all.
@rsc what do you mean by "this part" and "the other part"?
@lolbinarycat
Judging by the linked issue, the "other part" could be reusing the "name" argument of the flag methods.
Sorry for the confusion, "this part" was supposed to be "part".
Based on the discussion above (in particular it being a duplicate of #35761 and half-impossible), this seems like a likely decline.
No change in consensus, so declined.
Most helpful comment
I think something like
func Synonym(flag string, synonyms ...string)would suffice. That changes the example to: