From 2ee25484767bd563966c237cb5f74eb13d31874b Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 29 Sep 2022 20:49:22 -0400 Subject: [PATCH 1/8] Fix:(issue_1505) Fix flag alignment in help --- template.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/template.go b/template.go index 9e13604f35..53a76b74cf 100644 --- a/template.go +++ b/template.go @@ -56,8 +56,8 @@ OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}} +OPTIONS:{{range .VisibleFlags}} + {{.}}{{end}}{{end}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. @@ -70,15 +70,24 @@ USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}} + {{wrap .Description 3}}{{end}}{{if .VisibleCommands}} COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}} +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}}{{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} + +OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} + {{wrap $option.String 6}}{{end}}{{end}}{{end}} ` var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} From 2da6e685553ebc07aad40c14a3f1b1ead317bcfe Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 29 Sep 2022 21:06:07 -0400 Subject: [PATCH 2/8] Fix command help subcommand --- command.go | 11 +++++++++++ template.go | 11 ++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/command.go b/command.go index d24b61e239..e66985e71f 100644 --- a/command.go +++ b/command.go @@ -295,6 +295,17 @@ func (c *Command) startApp(ctx *Context) error { return app.RunAsSubcommand(ctx) } +// VisibleCommands returns a slice of the Commands with Hidden=false +func (c *Command) VisibleCommands() []*Command { + var ret []*Command + for _, command := range c.Subcommands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} + // VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain func (c *Command) VisibleFlagCategories() []VisibleFlagCategory { if c.flagCategories == nil { diff --git a/template.go b/template.go index 53a76b74cf..bb9cbc42b8 100644 --- a/template.go +++ b/template.go @@ -72,16 +72,9 @@ USAGE: DESCRIPTION: {{wrap .Description 3}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{if .VisibleFlagCategories}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} - OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}}{{end}}{{range .Flags}}{{.}} {{end}}{{end}}{{else}}{{if .VisibleFlags}} From 6504da449b46d7af9c37346e58e9673054d4f33c Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 30 Sep 2022 08:23:18 -0400 Subject: [PATCH 3/8] Add test case --- app_test.go | 2 +- help.go | 6 +++- help_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ template.go | 8 +++--- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/app_test.go b/app_test.go index f7ecd135fc..d3fa3dfdad 100644 --- a/app_test.go +++ b/app_test.go @@ -177,7 +177,7 @@ func ExampleApp_Run_commandHelp() { // greet describeit - use it to see a description // // USAGE: - // greet describeit [command options] [arguments...] + // greet describeit [arguments...] // // DESCRIPTION: // This is how we describe describeit the function diff --git a/help.go b/help.go index 6929a226ab..45e6f2b3cd 100644 --- a/help.go +++ b/help.go @@ -242,7 +242,11 @@ func ShowCommandHelp(ctx *Context, command string) error { c.Subcommands = append(c.Subcommands, helpCommandDontUse) } if !ctx.App.HideHelp && HelpFlag != nil { - c.appendFlag(HelpFlag) + if c.flagCategories == nil { + c.flagCategories = newFlagCategoriesFromFlags([]Flag{HelpFlag}) + } else { + c.flagCategories.AddFlag("", HelpFlag) + } } templ := c.CustomHelpTemplate if templ == "" { diff --git a/help_test.go b/help_test.go index d7cdfa2d8f..6b1e8c6b4e 100644 --- a/help_test.go +++ b/help_test.go @@ -1367,6 +1367,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) + ` if output.String() != expected { @@ -1436,6 +1437,84 @@ USAGE: OPTIONS: --help, -h show help (default: false) + +` + + if output.String() != expected { + t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", + output.String(), expected) + } +} + +func TestWrappedHelpSubcommand(t *testing.T) { + + // Reset HelpPrinter after this test. + defer func(old helpPrinter) { + HelpPrinter = old + }(HelpPrinter) + + output := new(bytes.Buffer) + app := &App{ + Name: "cli.test", + Writer: output, + Commands: []*Command{ + { + Name: "bar", + Aliases: []string{"a"}, + Usage: "add a task to the list", + UsageText: "this is an even longer way of describing adding a task to the list", + Description: "and a description long enough to wrap in this test case", + Action: func(c *Context) error { + return nil + }, + Subcommands: []*Command{ + { + Name: "grok", + Usage: "remove an existing template", + UsageText: "longer usage text goes here, la la la, hopefully this is long enough to wrap even more", + Action: func(c *Context) error { + return nil + }, + Flags: []Flag{ + &StringFlag{ + Name: "test-f", + Usage: "my test usage", + }, + }, + }, + }, + }, + }, + } + + HelpPrinter = func(w io.Writer, templ string, data interface{}) { + funcMap := map[string]interface{}{ + "wrapAt": func() int { + return 30 + }, + } + + HelpPrinterCustom(w, templ, data, funcMap) + } + + _ = app.Run([]string{"foo", "bar", "help", "grok"}) + + expected := `NAME: + cli.test bar grok - remove + an + existing + template + +USAGE: + longer usage text goes + here, la la la, hopefully + this is long enough to wrap + even more + +OPTIONS: + --help, -h show help (default: false) + --test-f value my test usage + ` if output.String() != expected { diff --git a/template.go b/template.go index bb9cbc42b8..d67931bba0 100644 --- a/template.go +++ b/template.go @@ -54,10 +54,10 @@ DESCRIPTION: OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} - -OPTIONS:{{range .VisibleFlags}} - {{.}}{{end}}{{end}}{{end}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} + {{wrap $option.String 6}}{{end}}{{end}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. From 8f6acfe15d2c4ff62094c6cf15613607729599e2 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 30 Sep 2022 12:12:41 -0400 Subject: [PATCH 4/8] Componentize template --- help.go | 11 +++++++ help_test.go | 9 ++---- template.go | 81 ++++++++++++++++++++++++++++------------------------ 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/help.go b/help.go index 45e6f2b3cd..d78444a0c6 100644 --- a/help.go +++ b/help.go @@ -362,6 +362,17 @@ func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + t.New("helpNameTemplate").Parse(helpNameTemplate) + t.New("usageTemplate").Parse(usageTemplate) + t.New("descriptionTemplate").Parse(descriptionTemplate) + t.New("visibleCommandTemplate").Parse(visibleCommandTemplate) + t.New("copyrightTemplate").Parse(copyrightTemplate) + t.New("versionTemplate").Parse(versionTemplate) + t.New("visibleFlagCategoryTemplate").Parse(visibleFlagCategoryTemplate) + t.New("visibleFlagTemplate").Parse(visibleFlagTemplate) + t.New("visibleGlobalFlagCategoryTemplate").Parse(strings.Replace(visibleFlagCategoryTemplate, "OPTIONS", "GLOBAL OPTIONS", -1)) + t.New("authorsTemplate").Parse(authorsTemplate) + t.New("visibleCommandCategoryTemplate").Parse(visibleCommandCategoryTemplate) err := t.Execute(w, data) if err != nil { diff --git a/help_test.go b/help_test.go index 6b1e8c6b4e..de8e2f0cd9 100644 --- a/help_test.go +++ b/help_test.go @@ -1367,8 +1367,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) - -` + ` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected:\n%s", @@ -1437,8 +1436,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) - -` + ` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", @@ -1514,8 +1512,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) --test-f value my test usage - -` + ` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", diff --git a/template.go b/template.go index d67931bba0..dfdd434cce 100644 --- a/template.go +++ b/template.go @@ -1,10 +1,36 @@ package cli +var helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}` +var usageTemplate = `{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}` +var descriptionTemplate = `{{wrap .Description 3}}` +var authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}` +var visibleCommandTemplate = `{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}` +var visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}` +var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}` + +var visibleFlagTemplate = `{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} + {{wrap $option.String 6}}{{end}}` + +var versionTemplate = `{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}` + +var copyrightTemplate = `{{wrap .Copyright 3}}` + // AppHelpTemplate is the text template for the Default help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var AppHelpTemplate = `NAME: - {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} @@ -13,75 +39,56 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}}{{if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -GLOBAL OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{wrap .Copyright 3}}{{end}} + {{template "copyrightTemplate" .}}{{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 setting this variable. var CommandHelpTemplate = `NAME: - {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} -OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} - {{wrap $option.String 6}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` // SubcommandHelpTemplate is the text template for the subcommand help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleCommands}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}}{{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} - {{wrap $option.String 6}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} From 0b2aca7ccc3d689b941e73179c7cafd37fe1f77d Mon Sep 17 00:00:00 2001 From: dearchap Date: Wed, 5 Oct 2022 08:35:11 -0400 Subject: [PATCH 5/8] Update template.go Co-authored-by: Anatoli Babenia --- template.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/template.go b/template.go index dfdd434cce..f48e5099f3 100644 --- a/template.go +++ b/template.go @@ -39,7 +39,8 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{template "descriptionTemplate" .}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} From 05db729d667f9f6339010c34709ebdfe2f3176df Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 10:00:37 -0400 Subject: [PATCH 6/8] Do make v2approve --- godoc-current.txt | 93 +++++++++++++++++++++++------------------ testdata/godoc-v2.x.txt | 93 +++++++++++++++++++++++------------------ 2 files changed, 106 insertions(+), 80 deletions(-) diff --git a/godoc-current.txt b/godoc-current.txt index 3d5cb9a298..73e3419efa 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -32,7 +32,7 @@ var ( SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate ) var AppHelpTemplate = `NAME: - {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} @@ -41,52 +41,39 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -GLOBAL OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{wrap .Copyright 3}}{{end}} + {{template "copyrightTemplate" .}}{{end}} ` AppHelpTemplate is the text template for the Default help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagTemplate" .}}{{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 setting this variable. @@ -145,22 +132,19 @@ var OsExiter = os.Exit os.Exit. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` SubcommandHelpTemplate is the text template for the subcommand help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. @@ -458,6 +442,8 @@ type BoolFlag struct { EnvVars []string Count *int + + Action func(*Context, bool) error } BoolFlag is a flag with type bool @@ -565,7 +551,6 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string - // Has unexported fields. } Command is a subcommand for a cli.App. @@ -584,10 +569,6 @@ func (c *Command) Run(ctx *Context) (err error) Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) VisibleCategories() []CommandCategory - VisibleCategories returns a slice of categories and commands that are - Hidden=false - func (c *Command) VisibleCommands() []*Command VisibleCommands returns a slice of the Commands with Hidden=false @@ -776,6 +757,8 @@ type DurationFlag struct { Aliases []string EnvVars []string + + Action func(*Context, time.Duration) error } DurationFlag is a flag with type time.Duration @@ -952,6 +935,8 @@ type Float64Flag struct { Aliases []string EnvVars []string + + Action func(*Context, float64) error } Float64Flag is a flag with type float64 @@ -1038,6 +1023,8 @@ type Float64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []float64) error } Float64SliceFlag is a flag with type *Float64Slice @@ -1115,6 +1102,8 @@ type GenericFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, interface{}) error } GenericFlag is a flag with type Generic @@ -1181,6 +1170,8 @@ type Int64Flag struct { EnvVars []string Base int + + Action func(*Context, int64) error } Int64Flag is a flag with type int64 @@ -1267,6 +1258,8 @@ type Int64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int64) error } Int64SliceFlag is a flag with type *Int64Slice @@ -1338,6 +1331,8 @@ type IntFlag struct { EnvVars []string Base int + + Action func(*Context, int) error } IntFlag is a flag with type int @@ -1428,6 +1423,8 @@ type IntSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int) error } IntSliceFlag is a flag with type *IntSlice @@ -1533,6 +1530,8 @@ type PathFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, Path) error } PathFlag is a flag with type Path @@ -1673,6 +1672,8 @@ type StringFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, string) error } StringFlag is a flag with type string @@ -1761,6 +1762,8 @@ type StringSliceFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, []string) error } StringSliceFlag is a flag with type *StringSlice @@ -1867,6 +1870,8 @@ type TimestampFlag struct { Layout string Timezone *time.Location + + Action func(*Context, *time.Time) error } TimestampFlag is a flag with type *Timestamp @@ -1932,6 +1937,8 @@ type Uint64Flag struct { EnvVars []string Base int + + Action func(*Context, uint64) error } Uint64Flag is a flag with type uint64 @@ -2018,6 +2025,8 @@ type Uint64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint64) error } Uint64SliceFlag is a flag with type *Uint64Slice @@ -2080,6 +2089,8 @@ type UintFlag struct { EnvVars []string Base int + + Action func(*Context, uint) error } UintFlag is a flag with type uint @@ -2170,6 +2181,8 @@ type UintSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint) error } UintSliceFlag is a flag with type *UintSlice diff --git a/testdata/godoc-v2.x.txt b/testdata/godoc-v2.x.txt index 3d5cb9a298..73e3419efa 100644 --- a/testdata/godoc-v2.x.txt +++ b/testdata/godoc-v2.x.txt @@ -32,7 +32,7 @@ var ( SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate ) var AppHelpTemplate = `NAME: - {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} @@ -41,52 +41,39 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -GLOBAL OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{wrap .Copyright 3}}{{end}} + {{template "copyrightTemplate" .}}{{end}} ` AppHelpTemplate is the text template for the Default help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagTemplate" .}}{{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 setting this variable. @@ -145,22 +132,19 @@ var OsExiter = os.Exit os.Exit. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` SubcommandHelpTemplate is the text template for the subcommand help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. @@ -458,6 +442,8 @@ type BoolFlag struct { EnvVars []string Count *int + + Action func(*Context, bool) error } BoolFlag is a flag with type bool @@ -565,7 +551,6 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string - // Has unexported fields. } Command is a subcommand for a cli.App. @@ -584,10 +569,6 @@ func (c *Command) Run(ctx *Context) (err error) Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) VisibleCategories() []CommandCategory - VisibleCategories returns a slice of categories and commands that are - Hidden=false - func (c *Command) VisibleCommands() []*Command VisibleCommands returns a slice of the Commands with Hidden=false @@ -776,6 +757,8 @@ type DurationFlag struct { Aliases []string EnvVars []string + + Action func(*Context, time.Duration) error } DurationFlag is a flag with type time.Duration @@ -952,6 +935,8 @@ type Float64Flag struct { Aliases []string EnvVars []string + + Action func(*Context, float64) error } Float64Flag is a flag with type float64 @@ -1038,6 +1023,8 @@ type Float64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []float64) error } Float64SliceFlag is a flag with type *Float64Slice @@ -1115,6 +1102,8 @@ type GenericFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, interface{}) error } GenericFlag is a flag with type Generic @@ -1181,6 +1170,8 @@ type Int64Flag struct { EnvVars []string Base int + + Action func(*Context, int64) error } Int64Flag is a flag with type int64 @@ -1267,6 +1258,8 @@ type Int64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int64) error } Int64SliceFlag is a flag with type *Int64Slice @@ -1338,6 +1331,8 @@ type IntFlag struct { EnvVars []string Base int + + Action func(*Context, int) error } IntFlag is a flag with type int @@ -1428,6 +1423,8 @@ type IntSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int) error } IntSliceFlag is a flag with type *IntSlice @@ -1533,6 +1530,8 @@ type PathFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, Path) error } PathFlag is a flag with type Path @@ -1673,6 +1672,8 @@ type StringFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, string) error } StringFlag is a flag with type string @@ -1761,6 +1762,8 @@ type StringSliceFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, []string) error } StringSliceFlag is a flag with type *StringSlice @@ -1867,6 +1870,8 @@ type TimestampFlag struct { Layout string Timezone *time.Location + + Action func(*Context, *time.Time) error } TimestampFlag is a flag with type *Timestamp @@ -1932,6 +1937,8 @@ type Uint64Flag struct { EnvVars []string Base int + + Action func(*Context, uint64) error } Uint64Flag is a flag with type uint64 @@ -2018,6 +2025,8 @@ type Uint64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint64) error } Uint64SliceFlag is a flag with type *Uint64Slice @@ -2080,6 +2089,8 @@ type UintFlag struct { EnvVars []string Base int + + Action func(*Context, uint) error } UintFlag is a flag with type uint @@ -2170,6 +2181,8 @@ type UintSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint) error } UintSliceFlag is a flag with type *UintSlice From d5a1252ef3d30a4ed4e2c9424a5322df44c713a0 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 13:52:05 -0400 Subject: [PATCH 7/8] Add test coverage for Command.VisibleCommands() --- command_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/command_test.go b/command_test.go index 9dfd46f476..a953e943cd 100644 --- a/command_test.go +++ b/command_test.go @@ -422,3 +422,30 @@ func TestCommand_CanAddVFlagOnCommands(t *testing.T) { err := app.Run([]string{"foo", "bar"}) expect(t, err, nil) } + +func TestCommand_VisibleSubcCommands(t *testing.T) { + + subc1 := &Command{ + Name: "subc1", + Usage: "subc1 command1", + } + subc3 := &Command{ + Name: "subc3", + Usage: "subc3 command2", + } + c := &Command{ + Name: "bar", + Usage: "this is for testing", + Subcommands: []*Command{ + subc1, + { + Name: "subc2", + Usage: "subc2 command2", + Hidden: true, + }, + subc3, + }, + } + + expect(t, c.VisibleCommands(), []*Command{subc1, subc3}) +} From 194ed2bb9b5e6ed113b30a51165291fd8e1ad8d5 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 14:40:59 -0400 Subject: [PATCH 8/8] Remove extra 3 spaces in last line --- help_test.go | 6 +++--- template.go | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/help_test.go b/help_test.go index de8e2f0cd9..37410a5449 100644 --- a/help_test.go +++ b/help_test.go @@ -1367,7 +1367,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) - ` +` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected:\n%s", @@ -1436,7 +1436,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) - ` +` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", @@ -1512,7 +1512,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) --test-f value my test usage - ` +` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", diff --git a/template.go b/template.go index f48e5099f3..1133b8907c 100644 --- a/template.go +++ b/template.go @@ -13,8 +13,10 @@ var visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}` var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}` + + {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}} +{{else}}{{$e}} + {{end}}{{end}}{{end}}` var visibleFlagTemplate = `{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} {{wrap $option.String 6}}{{end}}`