alecthomas / kingpin

CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

HintAction can break the argument order

OliverGoetz opened this issue · comments

go version go1.13.5 darwin/amd64
kingpn version v2.2.6

I came across a strange issue where the introduction of a HintAction broke the order of the arguments. I managed to come up with a small example, which you can find here:
https://github.com/OliverGoetz/kingpin-hintaction/blob/master/kingpin-hintaction.go

The gist of it is that under certain circumstances the HintAction implementation can break the order in which the arguments for a command are expected. This is also reflected in the help output as you can see here"

usage: kingpin-hintaction [<flags>] <command> [<args> ...]

demo how hintaction breaks arg order

Flags:
  -h, --help        Show context-sensitive help (also try --help-long and --help-man).
      --argset="x"  set of arguments to use
      --version     Show application version.

Commands:
  help [<command>...]
    Show help.

  correctorder <arg1> <arg2>
    Command with correct arg order

  brokenorder <barg2> <barg1>
    Command with broken arg order

For both commands the argument with number 1 should be first.

I don't understand this behaviour, but I cannot imagine that this is as intended.
It's also a mystery to me why the implementation of the HintAction should have any influence over this, as my understanding is that the HintAction methods are not even invoked when just a help message is printed out.

Ok, so I think I found a solution for this issue, and by now I think that this is not a coding error in kingpin, but rather an issue with understanding how go handles the var blocks.

I uploaded a fixed version of my example to a new branch: https://github.com/OliverGoetz/kingpin-hintaction/blob/solution/kingpin-hintaction.go

You can see that I extracted the actual calls to construct the kingpin commands into their own init functions and am now calling them from main rather than calling them inside the var declaration.
With this change the order of arguments is now retained correctly.

usage: kingpin-hintaction [<flags>] <command> [<args> ...]

demo how hintaction breaks arg order

Flags:
  -h, --help        Show context-sensitive help (also try --help-long and --help-man).
      --argset="x"  set of arguments to use
      --version     Show application version.

Commands:
  help [<command>...]
    Show help.

  correctorder <arg1> <arg2>
    Command with correct arg order

  fixedorder <barg1> <barg2>
    Command with fixed arg order

I think the reason for this behavior could be that go is parallelizing the execution of the var declarations/definitions, and that maybe the lookup/reflection for the function that is using non-local variable takes just a bit longer and therefore the declaration of the next argument overtakes it.
This is just a wild guess, but at the moment the only feasible explanation I can come up with.