getopt
getopt copied to clipboard
Flags don't parse after encountering positional parameter
Based on what I've read in the documentation I would expect the following to work, but I might have misconfigured something. Essentially I would like to support syntax like what git
exposes, ala git status --short
command.
Here's some sample code:
connection := ""
migrations := ""
getopt.FlagLong(&connection, "connection", 'c', "SQL connection string")
getopt.FlagLong(&migrations, "migrations", 'm', "Migrations directory")
getopt.Parse()
config := MigConfig{
Connection: connection,
Migrations: migrations,
}
args := getopt.Args()
fmt.Println("CONFIG")
fmt.Println(config)
fmt.Println("ARGS")
fmt.Println(args)
return config, nil
Next, I'm invoking the program in two ways:
$ app status --connection="foo"
CONFIG
{ }
ARGS
[status --connection=foo]
$ app --connection="foo" status
CONFIG
{foo }
ARGS
[status]
The second invocation works as expected, pulling the flag data out and providing the remaining non-flag arguments via .Args()
. However the first invocation, in the style of the git
command, wasn't able to parse the flags. Have I configured this wrong or is this expected behavior?
There's nothing misconfigured. That's just how this library has been written to work. There's precedent for it; it's how the corresponding GNU function works when the POSIXLY_CORRECT
environment variable is set.
It can be useful when the argument list allows subcommands. Arguments to the "main" program aren't necessarily valid for the subcommand. You mention git
as inspiration for your use case. The "main" git
command accepts -c
to specify config options that apply for the current command. But git commit
interprets -c
to specify a commit ID to populate the commit message from. If we were implementing git
using this library, we'd want parsing to stop when it reached the first non-option so we could do subcommand-specific parsing.
I wonder how much effort it would take to make this library support both the POSIX and default GNU behaviors.