Skip to content

Commit

Permalink
Improve handling of version flag
Browse files Browse the repository at this point in the history
* Only use/show builtin `--version` flag if args are versioned with a non-empty `Version()`
* If args define a `--version` flag, honor it and disable/hide the builtin version flag
* Only return `ErrVersion` when using the builtin version flag
  • Loading branch information
hhromic committed Jul 14, 2023
1 parent 463902e commit c73f38c
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 6 deletions.
17 changes: 14 additions & 3 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ type command struct {
parent *command
}

// ErrHelp indicates that -h or --help were provided
// ErrHelp indicates that the builtin -h or --help were provided
var ErrHelp = errors.New("help requested by user")

// ErrVersion indicates that --version was provided
// ErrVersion indicates that the builtin --version was provided
var ErrVersion = errors.New("version requested by user")

// for monkey patching in example code
Expand Down Expand Up @@ -591,6 +591,15 @@ func (p *Parser) process(args []string) error {
}
}

// determine if the current command has a version option spec
var hasVersionOption bool
for _, spec := range curCmd.specs {
if spec.long == "version" {
hasVersionOption = true
break
}
}

// process each string from the command line
var allpositional bool
var positionals []string
Expand Down Expand Up @@ -648,7 +657,9 @@ func (p *Parser) process(args []string) error {
case "-h", "--help":
return ErrHelp
case "--version":
return ErrVersion
if !hasVersionOption && p.version != "" {
return ErrVersion
}
}

// check for an equals sign, as in "--foo=bar"
Expand Down
48 changes: 46 additions & 2 deletions parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1380,11 +1380,55 @@ func TestReuseParser(t *testing.T) {
assert.Error(t, err)
}

func TestVersion(t *testing.T) {
func TestNoVersion(t *testing.T) {
var args struct{}
err := parse("--version", &args)

p, err := NewParser(Config{}, &args)
require.NoError(t, err)

err = p.Parse([]string{"--version"})
assert.Error(t, err)
assert.NotEqual(t, ErrVersion, err)
}

func TestBuiltinVersion(t *testing.T) {
var args struct{}

p, err := NewParser(Config{}, &args)
require.NoError(t, err)

p.version = "example 3.2.1"

err = p.Parse([]string{"--version"})
assert.Equal(t, ErrVersion, err)
}

func TestArgsVersion(t *testing.T) {
var args struct {
Version bool `arg:"--version"`
}

p, err := NewParser(Config{}, &args)
require.NoError(t, err)

err = p.Parse([]string{"--version"})
require.NoError(t, err)
require.Equal(t, args.Version, true)
}

func TestArgsAndBuiltinVersion(t *testing.T) {
var args struct {
Version bool `arg:"--version"`
}

p, err := NewParser(Config{}, &args)
require.NoError(t, err)

p.version = "example 3.2.1"

err = p.Parse([]string{"--version"})
require.NoError(t, err)
require.Equal(t, args.Version, true)
}

func TestMultipleTerminates(t *testing.T) {
Expand Down
9 changes: 8 additions & 1 deletion usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ func (p *Parser) WriteHelpForSubcommand(w io.Writer, subcommand ...string) error
// writeHelp writes the usage string for the given subcommand
func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
var positionals, longOptions, shortOptions, envOnlyOptions []*spec
var hasVersionOption bool
for _, spec := range cmd.specs {
switch {
case spec.positional:
Expand Down Expand Up @@ -243,6 +244,9 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
}
for _, spec := range longOptions {
p.printOption(w, spec)
if spec.long == "version" {
hasVersionOption = true
}
}
}

Expand All @@ -259,6 +263,9 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
fmt.Fprint(w, "\nGlobal options:\n")
for _, spec := range globals {
p.printOption(w, spec)
if spec.long == "version" {
hasVersionOption = true
}
}
}

Expand All @@ -269,7 +276,7 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
short: "h",
help: "display this help and exit",
})
if p.version != "" {
if !hasVersionOption && p.version != "" {
p.printOption(w, &spec{
cardinality: zero,
long: "version",
Expand Down

0 comments on commit c73f38c

Please sign in to comment.