diff --git a/command.go b/command.go index 75d8b7ec33..590de63ea9 100644 --- a/command.go +++ b/command.go @@ -868,6 +868,19 @@ func (cmd *Command) appendFlag(fl Flag) { } } +// VisiblePersistentFlags returns a slice of [PersistentFlag] with Persistent=true and Hidden=false. +func (cmd *Command) VisiblePersistentFlags() []Flag { + var flags []Flag + for _, fl := range cmd.Root().Flags { + pfl, ok := fl.(PersistentFlag) + if !ok || !pfl.IsPersistent() { + continue + } + flags = append(flags, fl) + } + return visibleFlags(flags) +} + func (cmd *Command) appendCommand(aCmd *Command) { if !hasCommand(cmd.Commands, aCmd) { aCmd.parent = cmd diff --git a/godoc-current.txt b/godoc-current.txt index 80d41e856d..68a439fdf1 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -45,7 +45,9 @@ DESCRIPTION: OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .VisiblePersistentFlags}} + +GLOBAL OPTIONS:{{template "visiblePersistentFlagTemplate" .}}{{end}} ` CommandHelpTemplate is the text template for the command help topic. cli.go uses text/template to render templates. You can render custom help text by @@ -516,6 +518,10 @@ func (cmd *Command) VisibleFlagCategories() []VisibleFlagCategory func (cmd *Command) VisibleFlags() []Flag VisibleFlags returns a slice of the Flags with Hidden=false +func (cmd *Command) VisiblePersistentFlags() []Flag + VisiblePersistentFlags returns a slice of PersistentFlag with + Persistent=true and Hidden=false. + type CommandCategories interface { // AddCommand adds a command to a category, creating a new category if necessary. AddCommand(category string, command *Command) diff --git a/help.go b/help.go index 1d2938cfac..f4fc09ee6c 100644 --- a/help.go +++ b/help.go @@ -410,6 +410,10 @@ func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs handleTemplateError(err) } + if _, err := t.New("visiblePersistentFlagTemplate").Parse(visiblePersistentFlagTemplate); err != nil { + handleTemplateError(err) + } + if _, err := t.New("visibleGlobalFlagCategoryTemplate").Parse(strings.Replace(visibleFlagCategoryTemplate, "OPTIONS", "GLOBAL OPTIONS", -1)); err != nil { handleTemplateError(err) } diff --git a/help_test.go b/help_test.go index 91e8e65d5f..dd0228b0e2 100644 --- a/help_test.go +++ b/help_test.go @@ -687,6 +687,51 @@ UsageText`, "expected output to include usage text") } +func TestShowSubcommandHelp_GlobalOptions(t *testing.T) { + cmd := &Command{ + Flags: []Flag{ + &StringFlag{ + Name: "foo", + Persistent: true, + }, + }, + Commands: []*Command{ + { + Name: "frobbly", + Flags: []Flag{ + &StringFlag{ + Name: "bar", + }, + }, + Action: func(context.Context, *Command) error { + return nil + }, + }, + }, + } + + output := &bytes.Buffer{} + cmd.Writer = output + + _ = cmd.Run(buildTestContext(t), []string{"foo", "frobbly", "--help"}) + + expected := `NAME: + foo frobbly + +USAGE: + foo frobbly [command [command options]] + +OPTIONS: + --bar value + --help, -h show help + +GLOBAL OPTIONS: + --foo value +` + + assert.Contains(t, output.String(), expected, "expected output to include global options") +} + func TestShowSubcommandHelp_SubcommandUsageText(t *testing.T) { cmd := &Command{ Commands: []*Command{ diff --git a/template.go b/template.go index 8f8d96244d..d809dd780a 100644 --- a/template.go +++ b/template.go @@ -28,6 +28,9 @@ var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}} var visibleFlagTemplate = `{{range $i, $e := .VisibleFlags}} {{wrap $e.String 6}}{{end}}` +var visiblePersistentFlagTemplate = `{{range $i, $e := .VisiblePersistentFlags}} + {{wrap $e.String 6}}{{end}}` + var versionTemplate = `{{if .Version}}{{if not .HideVersion}} VERSION: @@ -80,7 +83,9 @@ DESCRIPTION: OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .VisiblePersistentFlags}} + +GLOBAL OPTIONS:{{template "visiblePersistentFlagTemplate" .}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. diff --git a/testdata/godoc-v3.x.txt b/testdata/godoc-v3.x.txt index 80d41e856d..68a439fdf1 100644 --- a/testdata/godoc-v3.x.txt +++ b/testdata/godoc-v3.x.txt @@ -45,7 +45,9 @@ DESCRIPTION: OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .VisiblePersistentFlags}} + +GLOBAL OPTIONS:{{template "visiblePersistentFlagTemplate" .}}{{end}} ` CommandHelpTemplate is the text template for the command help topic. cli.go uses text/template to render templates. You can render custom help text by @@ -516,6 +518,10 @@ func (cmd *Command) VisibleFlagCategories() []VisibleFlagCategory func (cmd *Command) VisibleFlags() []Flag VisibleFlags returns a slice of the Flags with Hidden=false +func (cmd *Command) VisiblePersistentFlags() []Flag + VisiblePersistentFlags returns a slice of PersistentFlag with + Persistent=true and Hidden=false. + type CommandCategories interface { // AddCommand adds a command to a category, creating a new category if necessary. AddCommand(category string, command *Command)