Skip to content

Commit 369d5c8

Browse files
committed
refactor: fix awkward option data in some short help messages
1 parent 71d7a26 commit 369d5c8

2 files changed

Lines changed: 89 additions & 22 deletions

File tree

help.go

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,24 @@ func DefaultShortHelp(c *CommandInfo) string {
6464
return strings.Compare(nameToCmpA, nameToCmpB)
6565
})
6666

67-
var nonCondensedOpts bool
68-
for i := range c.Opts {
69-
if l := len(c.Opts[i].optUsgNameAndArg()); l >= helpShortMsgMaxFirstColLen {
70-
nonCondensedOpts = true
71-
break
67+
// First we need to determine the length of the longest left padded 'name(s) + value
68+
// name' for the options (meaing which `-s, --long <arg>` is the longest when spacing
69+
// is added for any absent short names). This will determine if we ouptut 'condensed'
70+
// option data or not, and (if we do condensed) what the right padding should be for
71+
// the option name columns that are shorter than the longest one.
72+
optLeftPaddedNames := make([]string, len(opts))
73+
optNameColWidth := 0
74+
for i := range opts {
75+
optLeftPaddedNames[i] = opts[i].leftPaddedNames()
76+
if l := len(optLeftPaddedNames[i]); l > optNameColWidth {
77+
optNameColWidth = l
7278
}
7379
}
7480

75-
if nonCondensedOpts {
81+
// If the name column width would be longer than the (arbitrary) max width, then we'll
82+
// output 'non-condensed' lines of option data so it won't all look awkwardly crammed
83+
// off to the right.
84+
if optNameColWidth > helpShortMsgMaxFirstColLen {
7685
for _, o := range opts {
7786
desc := o.HelpBlurb
7887
if o.IsRequired {
@@ -106,14 +115,7 @@ func DefaultShortHelp(c *CommandInfo) string {
106115
u.WriteByte('\n')
107116
}
108117
} else {
109-
var optNameColWidth int
110-
for i := range c.Opts {
111-
if l := len(c.Opts[i].optUsgNameAndArg()); l > optNameColWidth && l <= helpShortMsgMaxFirstColLen {
112-
optNameColWidth = l
113-
}
114-
}
115-
for _, o := range opts {
116-
paddedNameAndArg := fmt.Sprintf(" %-*s", optNameColWidth, o.optUsgNameAndArg())
118+
for i, o := range opts {
117119
desc := o.HelpBlurb
118120
if o.IsRequired {
119121
desc += " (required)"
@@ -124,13 +126,8 @@ func DefaultShortHelp(c *CommandInfo) string {
124126
if o.EnvVar != "" {
125127
desc += " [$" + o.EnvVar + "]"
126128
}
127-
content := paddedNameAndArg
128-
if len(paddedNameAndArg) > helpShortMsgMaxFirstColLen {
129-
content += "\n" + strings.Repeat(" ", optNameColWidth+5)
130-
} else {
131-
content += " "
132-
}
133-
content += wrapBlurb(desc, len(paddedNameAndArg)+3, helpMsgTextWidth)
129+
content := fmt.Sprintf(" %-*s ", optNameColWidth, optLeftPaddedNames[i])
130+
content += wrapBlurb(desc, len(content), helpMsgTextWidth)
134131
u.WriteString(content)
135132
u.WriteByte('\n')
136133
}
@@ -346,7 +343,7 @@ func DefaultFullHelp(c *CommandInfo) string {
346343
return u.String()
347344
}
348345

349-
func (o *InputInfo) optUsgNameAndArg() string {
346+
func (o *InputInfo) leftPaddedNames() string {
350347
var s string
351348
if o.NameShort != "" {
352349
s += "-" + o.NameShort

help_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package cli
2+
3+
import "testing"
4+
5+
func TestDefaultHelps(t *testing.T) {
6+
for _, tt := range []struct {
7+
Case string
8+
cmdInfo CommandInfo
9+
expectedShort string
10+
expectedFull string
11+
}{
12+
{
13+
Case: ttCase(),
14+
cmdInfo: New().
15+
Opt(NewOpt("lorem").
16+
Short('l').
17+
Required().
18+
Help("ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")).
19+
Opt(NewOpt("enim-ad-minim").
20+
Required().
21+
Help("veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")),
22+
expectedShort: `cli.test -
23+
24+
usage:
25+
cli.test [options]
26+
27+
options:
28+
--enim-ad-minim <arg>
29+
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
30+
consequat. (required)
31+
-h, --help
32+
Show this help message and exit.
33+
-l, --lorem <arg>
34+
ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
35+
ut labore et dolore magna aliqua. (required)
36+
`,
37+
expectedFull: `cli.test -
38+
39+
usage:
40+
cli.test [options]
41+
42+
options:
43+
--enim-ad-minim <arg> (required)
44+
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
45+
consequat.
46+
47+
-h, --help
48+
Show this help message and exit.
49+
50+
-l, --lorem <arg> (required)
51+
ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
52+
ut labore et dolore magna aliqua.
53+
`,
54+
},
55+
} {
56+
// Due to the current design, we have to call this in order to get the default
57+
// help option inserted in (if necessary).
58+
tt.cmdInfo.prepareAndValidate()
59+
60+
gotShort := DefaultShortHelp(&tt.cmdInfo)
61+
if gotShort != tt.expectedShort {
62+
t.Errorf("%s:short helps don't match\nexpected:\n%s\ngot:\n%s", tt.Case, tt.expectedShort, gotShort)
63+
}
64+
65+
gotFull := DefaultFullHelp(&tt.cmdInfo)
66+
if gotFull != tt.expectedFull {
67+
t.Errorf("%s: full helps don't match\nexpected:\n%s\ngot:\n%s", tt.Case, tt.expectedFull, gotFull)
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)