Skip to content

Commit

Permalink
Merge pull request #1506 from dearchap/issue_1505
Browse files Browse the repository at this point in the history
Fix:(issue_1505) Fix flag alignment in help
  • Loading branch information
dearchap committed Oct 6, 2022
2 parents 8f469ab + 86809ce commit 2a4809f
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 107 deletions.
2 changes: 1 addition & 1 deletion app_test.go
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions command.go
Expand Up @@ -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 {
Expand Down
27 changes: 27 additions & 0 deletions command_test.go
Expand Up @@ -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})
}
57 changes: 22 additions & 35 deletions godoc-current.txt
Expand Up @@ -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}}
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -585,6 +569,9 @@ 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) VisibleCommands() []*Command
VisibleCommands returns a slice of the Commands with Hidden=false

func (c *Command) VisibleFlagCategories() []VisibleFlagCategory
VisibleFlagCategories returns a slice containing all the visible flag
categories with the flags they contain
Expand Down
17 changes: 16 additions & 1 deletion help.go
Expand Up @@ -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 == "" {
Expand Down Expand Up @@ -358,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 {
Expand Down
76 changes: 76 additions & 0 deletions help_test.go
Expand Up @@ -1443,3 +1443,79 @@ OPTIONS:
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 {
t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s",
output.String(), expected)
}
}

0 comments on commit 2a4809f

Please sign in to comment.