diff --git a/category.go b/category.go index 99fe5b7495..3a8abb1e80 100644 --- a/category.go +++ b/category.go @@ -100,10 +100,24 @@ func newFlagCategories() FlagCategories { func newFlagCategoriesFromFlags(fs []Flag) FlagCategories { fc := newFlagCategories() + + var categorized bool + for _, fl := range fs { if cf, ok := fl.(CategorizableFlag); ok { - if cf.GetCategory() != "" { - fc.AddFlag(cf.GetCategory(), fl) + if cat := cf.GetCategory(); cat != "" { + fc.AddFlag(cat, fl) + categorized = true + } + } + } + + if categorized { + for _, fl := range fs { + if cf, ok := fl.(CategorizableFlag); ok { + if cf.GetCategory() == "" { + fc.AddFlag("", fl) + } } } } diff --git a/command_test.go b/command_test.go index a23672ee7b..0492467472 100644 --- a/command_test.go +++ b/command_test.go @@ -526,12 +526,15 @@ func TestCommand_VisibleFlagCategories(t *testing.T) { } vfc := cmd.VisibleFlagCategories() - require.NotEmpty(t, vfc) - assert.Equal(t, vfc[0].Name(), "cat1", "expected category name cat1") + require.Len(t, vfc, 2) - require.Len(t, vfc[0].Flags(), 1, "expected flag category to have just one flag") + assert.Equal(t, vfc[0].Name(), "", "expected category name to be empty") - fl := vfc[0].Flags()[0] + assert.Equal(t, vfc[1].Name(), "cat1", "expected category name cat1") + + require.Len(t, vfc[1].Flags(), 1, "expected flag category to have just one flag") + + fl := vfc[1].Flags()[0] assert.Equal(t, fl.Names(), []string{"intd", "altd1", "altd2"}) } diff --git a/help_test.go b/help_test.go index 141e978195..1026e5afa5 100644 --- a/help_test.go +++ b/help_test.go @@ -1482,3 +1482,62 @@ OPTIONS: output.String(), ) } + +func TestCategorizedHelp(t *testing.T) { + // Reset HelpPrinter after this test. + defer func(old helpPrinter) { + HelpPrinter = old + }(HelpPrinter) + + output := new(bytes.Buffer) + cmd := &Command{ + Name: "cli.test", + Writer: output, + Action: func(context.Context, *Command) error { return nil }, + Flags: []Flag{ + &StringFlag{ + Name: "strd", // no category set + }, + &IntFlag{ + Name: "intd", + Aliases: []string{"altd1", "altd2"}, + Category: "cat1", + }, + }, + } + + HelpPrinter = func(w io.Writer, templ string, data interface{}) { + funcMap := map[string]interface{}{ + "wrapAt": func() int { + return 30 + }, + } + + HelpPrinterCustom(w, templ, data, funcMap) + } + + r := require.New(t) + r.NoError(cmd.Run(buildTestContext(t), []string{"cli.test", "help"})) + + r.Equal(`NAME: + cli.test - A new cli + application + +USAGE: + cli.test [global options] [command [command options]] [arguments...] + +COMMANDS: + help, h Shows a list of + commands or help + for one command + +GLOBAL OPTIONS: + --help, -h show help (default: false) + --strd value + + cat1 + + --intd value, --altd1 value, --altd2 value (default: 0) + +`, output.String()) +}