test that short-only options are printed first in the help message

This commit is contained in:
Alex Flint 2021-01-31 19:15:49 -08:00
parent 438a91dba1
commit 788c166025
2 changed files with 39 additions and 16 deletions

View File

@ -117,9 +117,6 @@ func (p *Parser) writeUsageForCommand(w io.Writer, cmd *command) {
}
func printTwoCols(w io.Writer, left, help string, defaultVal string, envVal string) {
if left == "" {
return
}
lhs := " " + left
fmt.Fprint(w, lhs)
if help != "" {
@ -162,12 +159,15 @@ func (p *Parser) WriteHelp(w io.Writer) {
// writeHelp writes the usage string for the given subcommand
func (p *Parser) writeHelpForCommand(w io.Writer, cmd *command) {
var positionals, options []*spec
var positionals, longOptions, shortOptions []*spec
for _, spec := range cmd.specs {
if spec.positional {
switch {
case spec.positional:
positionals = append(positionals, spec)
} else {
options = append(options, spec)
case spec.long != "":
longOptions = append(longOptions, spec)
case spec.short != "":
shortOptions = append(shortOptions, spec)
}
}
@ -184,10 +184,13 @@ func (p *Parser) writeHelpForCommand(w io.Writer, cmd *command) {
}
}
// write the list of options
if len(options) > 0 || cmd.parent == nil {
// write the list of options with the short-only ones first to match the usage string
if len(shortOptions)+len(longOptions) > 0 || cmd.parent == nil {
fmt.Fprint(w, "\nOptions:\n")
for _, spec := range options {
for _, spec := range shortOptions {
p.printOption(w, spec)
}
for _, spec := range longOptions {
p.printOption(w, spec)
}
}
@ -233,15 +236,16 @@ func (p *Parser) writeHelpForCommand(w io.Writer, cmd *command) {
}
func (p *Parser) printOption(w io.Writer, spec *spec) {
text := make([]string, 0, 2)
ways := make([]string, 0, 2)
if spec.long != "" {
text = append(text, synopsis(spec, "--"+spec.long))
ways = append(ways, synopsis(spec, "--"+spec.long))
}
if spec.short != "" {
text = append(text, synopsis(spec, "-"+spec.short))
ways = append(ways, synopsis(spec, "-"+spec.short))
}
if len(ways) > 0 {
printTwoCols(w, strings.Join(ways, ", "), spec.help, spec.defaultVal, spec.env)
}
left := strings.Join(text, ", ")
printTwoCols(w, left, spec.help, spec.defaultVal, spec.env)
}
func synopsis(spec *spec, form string) string {

View File

@ -310,7 +310,7 @@ Global options:
assert.Equal(t, expectedHelp, help.String())
}
func TestUsageWithOptionalLongNames(t *testing.T) {
func TestUsageWithoutLongNames(t *testing.T) {
expectedHelp := `Usage: example [-a PLACEHOLDER] -b SHORTONLY2
Options:
@ -329,6 +329,25 @@ Options:
assert.Equal(t, expectedHelp, help.String())
}
func TestUsageWithShortFirst(t *testing.T) {
expectedHelp := `Usage: example [-c CAT] [--dog DOG]
Options:
-c CAT
--dog DOG
--help, -h display this help and exit
`
var args struct {
Dog string
Cat string `arg:"-c,--"`
}
p, err := NewParser(Config{Program: "example"}, &args)
assert.NoError(t, err)
var help bytes.Buffer
p.WriteHelp(&help)
assert.Equal(t, expectedHelp, help.String())
}
func TestUsageWithEnvOptions(t *testing.T) {
expectedHelp := `Usage: example [-s SHORT]