From 122c0a9f1de7ec9a2c6bcd0264865db66760e0de Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Sat, 20 Aug 2022 18:13:06 -0400 Subject: [PATCH 1/5] Fix:(issue_1293) Wrap usage text for commands --- help_test.go | 29 +++++++++++++++++++++++++++++ template.go | 4 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/help_test.go b/help_test.go index 4feb7f05a0..c3451d9f6b 100644 --- a/help_test.go +++ b/help_test.go @@ -895,6 +895,35 @@ 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", + }, + }, + } + + output := &bytes.Buffer{} + app.Writer = output + + _ = app.Run([]string{"foo"}) + + expected := `frobbly, frb1, frbb2, frl2 this is a long help output for the run command, long usage + output, long usage output, long usage output, long usage output + output, long usage 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 f3116fd2c9..ac5a6a03b0 100644 --- a/template.go +++ b/template.go @@ -22,7 +22,7 @@ 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}} + {{$s := join .Names ", "}}{{$v := offset $s 5}}{{$s}}{{"\t"}}{{wrap .Usage $v}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} GLOBAL OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} @@ -77,7 +77,7 @@ 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}} + {{$s := join .Names ", "}}{{$v := offset $s 5}}{{$s}}{{"\t"}}{{wrap .Usage $v}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} OPTIONS: {{range .VisibleFlags}}{{.}} From 5315e9c5773a356a55fb12ef97e2ea899d7dc03a Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 24 Aug 2022 09:12:05 -0400 Subject: [PATCH 2/5] Change way to calculate offset --- help.go | 34 ++++++++++++++++++++++++++++------ template.go | 8 ++++---- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/help.go b/help.go index 9a8d2437d5..881464551b 100644 --- a/help.go +++ b/help.go @@ -295,12 +295,15 @@ 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, + "add": add, + "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 +419,14 @@ func checkCommandCompletions(c *Context, name string) bool { return true } +func subtract(a, b int) int { + return a - b +} + +func add(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 +487,14 @@ func wrapLine(input string, offset int, wrapAt int, padding string) string { func offset(input string, fixed int) int { return len(input) + fixed } + +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/template.go b/template.go index ac5a6a03b0..dd6955c117 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}} - {{$s := join .Names ", "}}{{$v := offset $s 5}}{{$s}}{{"\t"}}{{wrap .Usage $v}}{{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 (add (len $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}} - {{$s := join .Names ", "}}{{$v := offset $s 5}}{{$s}}{{"\t"}}{{wrap .Usage $v}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (add (len $s) 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} OPTIONS: {{range .VisibleFlags}}{{.}} From 7978b327683cbd4420886a3b43ede12d086f147c Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 24 Aug 2022 21:20:43 -0400 Subject: [PATCH 3/5] Make test case more robust --- help.go | 1 - help_test.go | 15 +++++++++++---- template.go | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/help.go b/help.go index 881464551b..14f0ff4c05 100644 --- a/help.go +++ b/help.go @@ -297,7 +297,6 @@ func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs funcMap := template.FuncMap{ "join": strings.Join, "subtract": subtract, - "add": add, "indent": indent, "nindent": nindent, "trim": strings.TrimSpace, diff --git a/help_test.go b/help_test.go index c3451d9f6b..9422b4a105 100644 --- a/help_test.go +++ b/help_test.go @@ -907,6 +907,11 @@ App UsageText`, 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", + }, }, } @@ -915,10 +920,12 @@ App UsageText`, _ = app.Run([]string{"foo"}) - expected := `frobbly, frb1, frbb2, frl2 this is a long help output for the run command, long usage - output, long usage output, long usage output, long usage output - output, long usage output, long usage output` - + 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()) } diff --git a/template.go b/template.go index dd6955c117..7ed2370994 100644 --- a/template.go +++ b/template.go @@ -22,7 +22,7 @@ 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}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (add (len $s) 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + {{$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}} @@ -77,7 +77,7 @@ DESCRIPTION: 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 (add (len $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}}{{if .VisibleFlags}} OPTIONS: {{range .VisibleFlags}}{{.}} From 3fa0334b61288eab160d3c877e4c6ae7adc0d8e1 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 26 Aug 2022 21:00:38 -0400 Subject: [PATCH 4/5] Remove add function --- help.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/help.go b/help.go index 14f0ff4c05..814922f8b3 100644 --- a/help.go +++ b/help.go @@ -422,10 +422,6 @@ func subtract(a, b int) int { return a - b } -func add(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) From ac21294ffc2c8dc1c7240b3e67542294ddde9c0b Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Tue, 30 Aug 2022 06:59:41 -0400 Subject: [PATCH 5/5] Add comment --- help.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/help.go b/help.go index 814922f8b3..d6caea4263 100644 --- a/help.go +++ b/help.go @@ -483,6 +483,20 @@ 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 {