Skip to content

Commit d4c0af2

Browse files
committed
refactor: apply existing opt/arg help msg patterns to subcommands
1 parent bb61d71 commit d4c0af2

2 files changed

Lines changed: 91 additions & 18 deletions

File tree

help.go

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cli
22

33
import (
4-
"fmt"
54
"slices"
65
"strings"
76
"unicode"
@@ -103,7 +102,7 @@ func DefaultShortHelp(c *CommandInfo) string {
103102
if o.EnvVar != "" {
104103
desc += " [$" + o.EnvVar + "]"
105104
}
106-
rightPadding := strings.Repeat(" ", (optNameColWidth-len(optLeftPaddedNames[i]))+3)
105+
rightPadding := strings.Repeat(" ", optNameColWidth-len(optLeftPaddedNames[i])+3)
107106
paddedNameAndVal := " " + optLeftPaddedNames[i] + rightPadding
108107
u.WriteString(paddedNameAndVal)
109108
u.WriteString(wrapBlurb(desc, len(paddedNameAndVal), helpMsgTextWidth))
@@ -158,7 +157,20 @@ func DefaultShortHelp(c *CommandInfo) string {
158157
}
159158

160159
if len(c.Subcmds) > 0 {
161-
helpWriteSubcmds(&u, c)
160+
var maxCmdNameLen int
161+
for i := range c.Subcmds {
162+
if n := len(c.Subcmds[i].Name); n > maxCmdNameLen {
163+
maxCmdNameLen = n
164+
}
165+
}
166+
167+
u.WriteString("\ncommands:\n")
168+
for i := range c.Subcmds {
169+
rightPadding := strings.Repeat(" ", maxCmdNameLen-len(c.Subcmds[i].Name)+3)
170+
paddedNameCol := " " + c.Subcmds[i].Name + rightPadding
171+
u.WriteString(paddedNameCol)
172+
u.WriteString(wrapBlurb(c.Subcmds[i].HelpBlurb, len(paddedNameCol), helpMsgTextWidth) + "\n")
173+
}
162174
}
163175

164176
return u.String()
@@ -273,7 +285,37 @@ func DefaultFullHelp(c *CommandInfo) string {
273285
}
274286

275287
if len(c.Subcmds) > 0 {
276-
helpWriteSubcmds(&u, c)
288+
var maxCmdNameLen int
289+
var maxCmdBlurbLen int
290+
for i := range c.Subcmds {
291+
if n := len(c.Subcmds[i].Name); n > maxCmdNameLen {
292+
maxCmdNameLen = n
293+
}
294+
if n := len(c.Subcmds[i].HelpBlurb); n > maxCmdBlurbLen {
295+
maxCmdBlurbLen = n
296+
}
297+
}
298+
299+
doNonCondensed := maxCmdNameLen > helpShortMsgMaxFirstColLen ||
300+
maxCmdBlurbLen > (helpMsgTextWidth-maxCmdNameLen-6)
301+
302+
u.WriteString("\ncommands:\n")
303+
for i := range c.Subcmds {
304+
if doNonCondensed {
305+
u.WriteString(" ")
306+
u.WriteString(c.Subcmds[i].Name)
307+
u.WriteString("\n ")
308+
u.WriteString(wrapBlurb(c.Subcmds[i].HelpBlurb, 6, helpMsgTextWidth))
309+
u.WriteByte('\n')
310+
if i < len(c.Subcmds)-1 {
311+
u.WriteByte('\n')
312+
}
313+
} else {
314+
rightPadding := strings.Repeat(" ", maxCmdNameLen-len(c.Subcmds[i].Name)+3)
315+
paddedNameCol := " " + c.Subcmds[i].Name + rightPadding
316+
u.WriteString(paddedNameCol + c.Subcmds[i].HelpBlurb + "\n")
317+
}
318+
}
277319
}
278320

279321
return u.String()
@@ -346,20 +388,6 @@ func helpWriteUsageLines(u *strings.Builder, c *CommandInfo) {
346388
}
347389
}
348390

349-
func helpWriteSubcmds(u *strings.Builder, c *CommandInfo) {
350-
var maxCmdNameLen int
351-
for i := range c.Subcmds {
352-
if n := len(c.Subcmds[i].Name); n > maxCmdNameLen {
353-
maxCmdNameLen = n
354-
}
355-
}
356-
357-
u.WriteString("\ncommands:\n")
358-
for i := range c.Subcmds {
359-
fmt.Fprintf(u, " %-*s %s\n", maxCmdNameLen, c.Subcmds[i].Name, c.Subcmds[i].HelpBlurb)
360-
}
361-
}
362-
363391
func wrapBlurb(v string, indentLen, lineLen int) string {
364392
s := wrapText(v, indentLen, lineLen)
365393
return s[indentLen:]

help_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,47 @@ arguments:
133133
[enim-ad-minim]
134134
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
135135
consequat.
136+
`,
137+
},
138+
{
139+
Case: ttCase(),
140+
cmdInfo: New().
141+
Help("test example").
142+
Subcmd(NewCmd("lorem").
143+
Help("ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")).
144+
Subcmd(NewCmd("enim-ad-minim").
145+
Help("veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")),
146+
expectedShort: `cli.test - test example
147+
148+
usage:
149+
cli.test [options] <command>
150+
151+
options:
152+
-h, --help Show this help message and exit.
153+
154+
commands:
155+
lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
156+
tempor incididunt ut labore et dolore magna aliqua.
157+
enim-ad-minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
158+
commodo consequat.
159+
`,
160+
expectedFull: `cli.test - test example
161+
162+
usage:
163+
cli.test [options] <command>
164+
165+
options:
166+
-h, --help
167+
Show this help message and exit.
168+
169+
commands:
170+
lorem
171+
ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
172+
ut labore et dolore magna aliqua.
173+
174+
enim-ad-minim
175+
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
176+
consequat.
136177
`,
137178
},
138179
} {
@@ -141,11 +182,15 @@ arguments:
141182
tt.cmdInfo.prepareAndValidate()
142183

143184
gotShort := DefaultShortHelp(&tt.cmdInfo)
185+
// fmt.Println(gotShort)
186+
// continue
144187
if gotShort != tt.expectedShort {
145188
t.Errorf("%s:short helps don't match\nexpected:\n%s\ngot:\n%s", tt.Case, tt.expectedShort, gotShort)
146189
}
147190

148191
gotFull := DefaultFullHelp(&tt.cmdInfo)
192+
// fmt.Println(gotFull)
193+
// continue
149194
if gotFull != tt.expectedFull {
150195
t.Errorf("%s: full helps don't match\nexpected:\n%s\ngot:\n%s", tt.Case, tt.expectedFull, gotFull)
151196
}

0 commit comments

Comments
 (0)