From 69753e839fb34a09d787167b4ff8a882e17466c8 Mon Sep 17 00:00:00 2001 From: Kevin Cui Date: Tue, 9 Jul 2024 16:35:54 +0800 Subject: [PATCH 1/3] feat(command): show global options in command help If there are persistent flags, they should also be displayed in the command. Signed-off-by: Kevin Cui --- command.go | 12 ++++++++++++ godoc-current.txt | 6 +++++- help.go | 4 ++++ help_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ template.go | 7 ++++++- 5 files changed, 72 insertions(+), 2 deletions(-) diff --git a/command.go b/command.go index 75d8b7ec33..efbcfeed20 100644 --- a/command.go +++ b/command.go @@ -868,6 +868,18 @@ func (cmd *Command) appendFlag(fl Flag) { } } +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..51d5c8e4b9 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,8 @@ 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 + 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. From 3b1ad974fa6fbb20cbac4600e2135555b911e047 Mon Sep 17 00:00:00 2001 From: Kevin Cui Date: Tue, 9 Jul 2024 20:35:35 +0800 Subject: [PATCH 2/3] refactor: add comment for VisiblePersistentFlags Co-authored-by: Eng Zer Jun --- command.go | 1 + 1 file changed, 1 insertion(+) diff --git a/command.go b/command.go index efbcfeed20..590de63ea9 100644 --- a/command.go +++ b/command.go @@ -868,6 +868,7 @@ 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 { From eba3ce625aff203d906b977a6fadf1f40b6ebc70 Mon Sep 17 00:00:00 2001 From: Kevin Cui Date: Tue, 9 Jul 2024 20:37:47 +0800 Subject: [PATCH 3/3] docs: update docs Signed-off-by: Kevin Cui --- godoc-current.txt | 2 ++ testdata/godoc-v3.x.txt | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/godoc-current.txt b/godoc-current.txt index 51d5c8e4b9..68a439fdf1 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -519,6 +519,8 @@ 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. 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)