From 254c38ea72e18e58f2ba8a4e25c7c553f19161e6 Mon Sep 17 00:00:00 2001 From: dearchap Date: Tue, 30 Aug 2022 17:56:37 -0400 Subject: [PATCH] Fix:(issue_1293) Wrap usage text for commands (#1460) * Fix:(issue_1293) Wrap usage text for commands * Change way to calculate offset * Make test case more robust * Remove add function * Add comment --- help.go | 43 +++++++++++++++++++++++++++++++++++++------ help_test.go | 36 ++++++++++++++++++++++++++++++++++++ template.go | 8 ++++---- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/help.go b/help.go index 9a8d243..d6caea4 100644 --- a/help.go +++ b/help.go @@ -295,12 +295,14 @@ func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs const maxLineLength = 10000 funcMap := template.FuncMap{ - "join": strings.Join, - "indent": indent, - "nindent": nindent, - "trim": strings.TrimSpace, - "wrap": func(input string, offset int) string { return wrap(input, offset, maxLineLength) }, - "offset": offset, + "join": strings.Join, + "subtract": subtract, + "indent": indent, + "nindent": nindent, + "trim": strings.TrimSpace, + "wrap": func(input string, offset int) string { return wrap(input, offset, maxLineLength) }, + "offset": offset, + "offsetCommands": offsetCommands, } if customFuncs["wrapAt"] != nil { @@ -416,6 +418,10 @@ func checkCommandCompletions(c *Context, name string) bool { return true } +func subtract(a, b int) int { + return a - b +} + func indent(spaces int, v string) string { pad := strings.Repeat(" ", spaces) return pad + strings.Replace(v, "\n", "\n"+pad, -1) @@ -476,3 +482,28 @@ func wrapLine(input string, offset int, wrapAt int, padding string) string { func offset(input string, fixed int) int { return len(input) + fixed } + +// this function tries to find the max width of the names column +// so say we have the following rows for help +// +// foo1, foo2, foo3 some string here +// bar1, b2 some other string here +// +// We want to offset the 2nd row usage by some amount so that everything +// is aligned +// +// foo1, foo2, foo3 some string here +// bar1, b2 some other string here +// +// to find that offset we find the length of all the rows and use the max +// to calculate the offset +func offsetCommands(cmds []*Command, fixed int) int { + var max int = 0 + for _, cmd := range cmds { + s := strings.Join(cmd.Names(), ", ") + if len(s) > max { + max = len(s) + } + } + return max + fixed +} diff --git a/help_test.go b/help_test.go index 4feb7f0..9422b4a 100644 --- a/help_test.go +++ b/help_test.go @@ -895,6 +895,42 @@ App UsageText`, } } +func TestShowAppHelp_CommandMultiLine_UsageText(t *testing.T) { + app := &App{ + UsageText: `This is a +multi +line +App UsageText`, + Commands: []*Command{ + { + Name: "frobbly", + Aliases: []string{"frb1", "frbb2", "frl2"}, + Usage: "this is a long help output for the run command, long usage \noutput, long usage output, long usage output, long usage output\noutput, long usage output, long usage output", + }, + { + Name: "grobbly", + Aliases: []string{"grb1", "grbb2"}, + Usage: "this is another long help output for the run command, long usage \noutput, long usage output", + }, + }, + } + + output := &bytes.Buffer{} + app.Writer = output + + _ = app.Run([]string{"foo"}) + + expected := "COMMANDS:\n" + + " frobbly, frb1, frbb2, frl2 this is a long help output for the run command, long usage \n" + + " output, long usage output, long usage output, long usage output\n" + + " output, long usage output, long usage output\n" + + " grobbly, grb1, grbb2 this is another long help output for the run command, long usage \n" + + " output, long usage output" + if !strings.Contains(output.String(), expected) { + t.Errorf("expected output to include usage text; got: %q", output.String()) + } +} + func TestHideHelpCommand(t *testing.T) { app := &App{ HideHelpCommand: true, diff --git a/template.go b/template.go index f3116fd..7ed2370 100644 --- a/template.go +++ b/template.go @@ -21,8 +21,8 @@ AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + {{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}} GLOBAL OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} @@ -76,8 +76,8 @@ DESCRIPTION: COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{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}} OPTIONS: {{range .VisibleFlags}}{{.}}