Skip to content

Commit de83493

Browse files
authored
Merge pull request #1499 from dearchap/issue_557
Fix help results inconsistency
2 parents a81e201 + d639533 commit de83493

File tree

7 files changed

+94
-41
lines changed

7 files changed

+94
-41
lines changed

app_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,13 @@ func ExampleApp_Run_commandHelp() {
177177
// greet describeit - use it to see a description
178178
//
179179
// USAGE:
180-
// greet describeit [arguments...]
180+
// greet describeit [command options] [arguments...]
181181
//
182182
// DESCRIPTION:
183183
// This is how we describe describeit the function
184+
//
185+
// OPTIONS:
186+
// --help, -h show help (default: false)
184187
}
185188

186189
func ExampleApp_Run_noAction() {

command.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ func (c *Command) Run(ctx *Context) (err error) {
170170
}
171171

172172
if c.Action == nil {
173-
c.Action = helpSubcommand.Action
173+
c.Action = helpCommand.Action
174174
}
175175

176176
cCtx.Command = c
@@ -284,7 +284,7 @@ func (c *Command) startApp(ctx *Context) error {
284284
if c.Action != nil {
285285
app.Action = c.Action
286286
} else {
287-
app.Action = helpSubcommand.Action
287+
app.Action = helpCommand.Action
288288
}
289289
app.OnUsageError = c.OnUsageError
290290

@@ -298,7 +298,12 @@ func (c *Command) startApp(ctx *Context) error {
298298
// VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain
299299
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory {
300300
if c.flagCategories == nil {
301-
return []VisibleFlagCategory{}
301+
c.flagCategories = newFlagCategories()
302+
for _, fl := range c.Flags {
303+
if cf, ok := fl.(CategorizableFlag); ok {
304+
c.flagCategories.AddFlag(cf.GetCategory(), cf)
305+
}
306+
}
302307
}
303308
return c.flagCategories.VisibleCategories()
304309
}

godoc-current.txt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,10 @@ DESCRIPTION:
8282

8383
OPTIONS:{{range .VisibleFlagCategories}}
8484
{{if .Name}}{{.Name}}
85-
{{end}}{{range .Flags}}{{.}}
86-
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
85+
{{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}}
8786

8887
OPTIONS:
89-
{{range .VisibleFlags}}{{.}}
90-
{{end}}{{end}}{{end}}
88+
{{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}}
9189
`
9290
CommandHelpTemplate is the text template for the command help topic. cli.go
9391
uses text/template to render templates. You can render custom help text by
@@ -161,8 +159,7 @@ COMMANDS:{{range .VisibleCategories}}{{if .Name}}
161159
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
162160

163161
OPTIONS:
164-
{{range .VisibleFlags}}{{.}}
165-
{{end}}{{end}}
162+
{{range .VisibleFlags}}{{.}}{{end}}{{end}}
166163
`
167164
SubcommandHelpTemplate is the text template for the subcommand help topic.
168165
cli.go uses text/template to render templates. You can render custom help
@@ -568,6 +565,7 @@ type Command struct {
568565
// cli.go uses text/template to render templates. You can
569566
// render custom help text by setting this variable.
570567
CustomHelpTemplate string
568+
571569
// Has unexported fields.
572570
}
573571
Command is a subcommand for a cli.App.
@@ -586,6 +584,13 @@ func (c *Command) Run(ctx *Context) (err error)
586584
Run invokes the command given the context, parses ctx.Args() to generate
587585
command-specific flags
588586

587+
func (c *Command) VisibleCategories() []CommandCategory
588+
VisibleCategories returns a slice of categories and commands that are
589+
Hidden=false
590+
591+
func (c *Command) VisibleCommands() []*Command
592+
VisibleCommands returns a slice of the Commands with Hidden=false
593+
589594
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory
590595
VisibleFlagCategories returns a slice containing all the visible flag
591596
categories with the flags they contain

help.go

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,59 @@ const (
1515
helpAlias = "h"
1616
)
1717

18-
var helpCommand = &Command{
18+
// this instance is to avoid recursion in the ShowCommandHelp which can
19+
// add a help command again
20+
var helpCommandDontUse = &Command{
1921
Name: helpName,
2022
Aliases: []string{helpAlias},
2123
Usage: "Shows a list of commands or help for one command",
2224
ArgsUsage: "[command]",
23-
Action: func(cCtx *Context) error {
24-
args := cCtx.Args()
25-
if args.Present() {
26-
return ShowCommandHelp(cCtx, args.First())
27-
}
28-
29-
_ = ShowAppHelp(cCtx)
30-
return nil
31-
},
3225
}
3326

34-
var helpSubcommand = &Command{
27+
var helpCommand = &Command{
3528
Name: helpName,
3629
Aliases: []string{helpAlias},
3730
Usage: "Shows a list of commands or help for one command",
3831
ArgsUsage: "[command]",
3932
Action: func(cCtx *Context) error {
4033
args := cCtx.Args()
41-
if args.Present() {
42-
return ShowCommandHelp(cCtx, args.First())
34+
argsPresent := args.First() != ""
35+
firstArg := args.First()
36+
37+
// This action can be triggered by a "default" action of a command
38+
// or via cmd.Run when cmd == helpCmd. So we have following possibilities
39+
//
40+
// 1 $ app
41+
// 2 $ app help
42+
// 3 $ app foo
43+
// 4 $ app help foo
44+
// 5 $ app foo help
45+
46+
// Case 4. when executing a help command set the context to parent
47+
// to allow resolution of subsequent args. This will transform
48+
// $ app help foo
49+
// to
50+
// $ app foo
51+
// which will then be handled as case 3
52+
if cCtx.Command.Name == helpName || cCtx.Command.Name == helpAlias {
53+
cCtx = cCtx.parentContext
4354
}
4455

56+
// Case 4. $ app hello foo
57+
// foo is the command for which help needs to be shown
58+
if argsPresent {
59+
return ShowCommandHelp(cCtx, firstArg)
60+
}
61+
62+
// Case 1 & 2
63+
// Special case when running help on main app itself as opposed to indivdual
64+
// commands/subcommands
65+
if cCtx.parentContext.App == nil {
66+
_ = ShowAppHelp(cCtx)
67+
return nil
68+
}
69+
70+
// Case 3, 5
4571
return ShowSubcommandHelp(cCtx)
4672
},
4773
}
@@ -212,9 +238,19 @@ func ShowCommandHelp(ctx *Context, command string) error {
212238

213239
for _, c := range ctx.App.Commands {
214240
if c.HasName(command) {
241+
if !ctx.App.HideHelpCommand && !c.HasName(helpName) && len(c.Subcommands) != 0 {
242+
c.Subcommands = append(c.Subcommands, helpCommandDontUse)
243+
}
244+
if !ctx.App.HideHelp && HelpFlag != nil {
245+
c.appendFlag(HelpFlag)
246+
}
215247
templ := c.CustomHelpTemplate
216248
if templ == "" {
217-
templ = CommandHelpTemplate
249+
if len(c.Subcommands) == 0 {
250+
templ = CommandHelpTemplate
251+
} else {
252+
templ = SubcommandHelpTemplate
253+
}
218254
}
219255

220256
HelpPrinter(ctx.App.Writer, templ, c)

help_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
186186

187187
c := NewContext(app, set, nil)
188188

189-
err := helpSubcommand.Action(c)
189+
err := helpCommand.Action(c)
190190

191191
if err == nil {
192192
t.Fatalf("expected error from helpCommand.Action(), but got nil")
@@ -248,7 +248,7 @@ func TestShowCommandHelp_HelpPrinter(t *testing.T) {
248248
fmt.Fprint(w, "yo")
249249
},
250250
command: "",
251-
wantTemplate: SubcommandHelpTemplate,
251+
wantTemplate: AppHelpTemplate,
252252
wantOutput: "yo",
253253
},
254254
{
@@ -333,7 +333,7 @@ func TestShowCommandHelp_HelpPrinterCustom(t *testing.T) {
333333
fmt.Fprint(w, "yo")
334334
},
335335
command: "",
336-
wantTemplate: SubcommandHelpTemplate,
336+
wantTemplate: AppHelpTemplate,
337337
wantOutput: "yo",
338338
},
339339
{
@@ -1357,10 +1357,13 @@ DESCRIPTION:
13571357
and a description long
13581358
enough to wrap in this test
13591359
case
1360+
1361+
OPTIONS:
1362+
--help, -h show help (default: false)
13601363
`
13611364

13621365
if output.String() != expected {
1363-
t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s",
1366+
t.Errorf("Unexpected wrapping, got:\n%s\nexpected:\n%s",
13641367
output.String(), expected)
13651368
}
13661369
}
@@ -1426,7 +1429,6 @@ USAGE:
14261429
14271430
OPTIONS:
14281431
--help, -h show help (default: false)
1429-
14301432
`
14311433

14321434
if output.String() != expected {

template.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,10 @@ DESCRIPTION:
5454
5555
OPTIONS:{{range .VisibleFlagCategories}}
5656
{{if .Name}}{{.Name}}
57-
{{end}}{{range .Flags}}{{.}}
58-
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
57+
{{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}}
5958
6059
OPTIONS:
61-
{{range .VisibleFlags}}{{.}}
62-
{{end}}{{end}}{{end}}
60+
{{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}}
6361
`
6462

6563
// SubcommandHelpTemplate is the text template for the subcommand help topic.
@@ -80,8 +78,7 @@ COMMANDS:{{range .VisibleCategories}}{{if .Name}}
8078
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
8179
8280
OPTIONS:
83-
{{range .VisibleFlags}}{{.}}
84-
{{end}}{{end}}
81+
{{range .VisibleFlags}}{{.}}{{end}}{{end}}
8582
`
8683

8784
var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }}

testdata/godoc-v2.x.txt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,10 @@ DESCRIPTION:
8282

8383
OPTIONS:{{range .VisibleFlagCategories}}
8484
{{if .Name}}{{.Name}}
85-
{{end}}{{range .Flags}}{{.}}
86-
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
85+
{{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}}
8786

8887
OPTIONS:
89-
{{range .VisibleFlags}}{{.}}
90-
{{end}}{{end}}{{end}}
88+
{{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}}
9189
`
9290
CommandHelpTemplate is the text template for the command help topic. cli.go
9391
uses text/template to render templates. You can render custom help text by
@@ -161,8 +159,7 @@ COMMANDS:{{range .VisibleCategories}}{{if .Name}}
161159
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
162160

163161
OPTIONS:
164-
{{range .VisibleFlags}}{{.}}
165-
{{end}}{{end}}
162+
{{range .VisibleFlags}}{{.}}{{end}}{{end}}
166163
`
167164
SubcommandHelpTemplate is the text template for the subcommand help topic.
168165
cli.go uses text/template to render templates. You can render custom help
@@ -568,6 +565,7 @@ type Command struct {
568565
// cli.go uses text/template to render templates. You can
569566
// render custom help text by setting this variable.
570567
CustomHelpTemplate string
568+
571569
// Has unexported fields.
572570
}
573571
Command is a subcommand for a cli.App.
@@ -586,6 +584,13 @@ func (c *Command) Run(ctx *Context) (err error)
586584
Run invokes the command given the context, parses ctx.Args() to generate
587585
command-specific flags
588586

587+
func (c *Command) VisibleCategories() []CommandCategory
588+
VisibleCategories returns a slice of categories and commands that are
589+
Hidden=false
590+
591+
func (c *Command) VisibleCommands() []*Command
592+
VisibleCommands returns a slice of the Commands with Hidden=false
593+
589594
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory
590595
VisibleFlagCategories returns a slice containing all the visible flag
591596
categories with the flags they contain

0 commit comments

Comments
 (0)