Skip to content

Commit

Permalink
Make app help behavior consistent with commands
Browse files Browse the repository at this point in the history
  • Loading branch information
rliebz committed Oct 17, 2019
1 parent bab428a commit 9ab178d
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 13 deletions.
37 changes: 24 additions & 13 deletions help.go
Expand Up @@ -49,13 +49,16 @@ type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customF

// HelpPrinter is a function that writes the help output. If not set explicitly,
// this calls HelpPrinterCustom using only the default template functions.
//
// If custom logic for printing help is required, this function can be
// overridden. If the ExtraInfo field is defined on an App, this function
// should not be modified, as HelpPrinterCustom will be used directly in order
// to capture the extra information.
var HelpPrinter helpPrinter = printHelp

// HelpPrinterCustom is a function that writes the help output. If not set
// explicitly, a default is used.
//
// The customFuncs map will be combined with a default template.FuncMap to
// allow using arbitrary functions in template rendering.
// HelpPrinterCustom is a function that writes the help output. It is used as
// the default implementation of HelpPrinter, and may be called directly if
// the ExtraInfo field is set on an App.
var HelpPrinterCustom helpPrinterCustom = printHelpCustom

// VersionPrinter prints the version for the App
Expand All @@ -68,20 +71,24 @@ func ShowAppHelpAndExit(c *Context, exitCode int) {
}

// ShowAppHelp is an action that displays the help.
func ShowAppHelp(c *Context) (err error) {
if c.App.CustomAppHelpTemplate == "" {
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
return
func ShowAppHelp(c *Context) error {
template := c.App.CustomAppHelpTemplate
if template == "" {
template = AppHelpTemplate
}

if c.App.ExtraInfo == nil {
HelpPrinter(c.App.Writer, template, c.App)
return nil
}

customAppData := func() map[string]interface{} {
if c.App.ExtraInfo == nil {
return nil
}
return map[string]interface{}{
"ExtraInfo": c.App.ExtraInfo,
}
}
HelpPrinterCustom(c.App.Writer, c.App.CustomAppHelpTemplate, c.App, customAppData())
HelpPrinterCustom(c.App.Writer, template, c.App, customAppData())

return nil
}

Expand Down Expand Up @@ -242,6 +249,10 @@ func ShowCommandCompletions(ctx *Context, command string) {

}

// printHelpCustom is the default implementation of HelpPrinterCustom.
//
// The customFuncs map will be combined with a default template.FuncMap to
// allow using arbitrary functions in template rendering.
func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) {
funcMap := template.FuncMap{
"join": strings.Join,
Expand Down
139 changes: 139 additions & 0 deletions help_test.go
Expand Up @@ -295,6 +295,7 @@ func TestShowCommandHelp_HelpPrinter(t *testing.T) {
})
}
}

func TestShowCommandHelp_HelpPrinterCustom(t *testing.T) {
doublecho := func(text string) string {
return text + " " + text
Expand Down Expand Up @@ -550,6 +551,144 @@ func TestShowAppHelp_HiddenCommand(t *testing.T) {
}
}

func TestShowAppHelp_HelpPrinter(t *testing.T) {
doublecho := func(text string) string {
return text + " " + text
}

tests := []struct {
name string
template string
printer helpPrinter
wantTemplate string
wantOutput string
}{
{
name: "standard-command",
template: "",
printer: func(w io.Writer, templ string, data interface{}) {
fmt.Fprint(w, "yo")
},
wantTemplate: AppHelpTemplate,
wantOutput: "yo",
},
{
name: "custom-template-command",
template: "{{doublecho .Name}}",
printer: func(w io.Writer, templ string, data interface{}) {
// Pass a custom function to ensure it gets used
fm := map[string]interface{}{"doublecho": doublecho}
printHelpCustom(w, templ, data, fm)
},
wantTemplate: "{{doublecho .Name}}",
wantOutput: "my-app my-app",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func(old helpPrinter) {
HelpPrinter = old
}(HelpPrinter)
HelpPrinter = func(w io.Writer, templ string, data interface{}) {
if templ != tt.wantTemplate {
t.Errorf("want template:\n%s\ngot template:\n%s", tt.wantTemplate, templ)
}

tt.printer(w, templ, data)
}

var buf bytes.Buffer
app := &App{
Name: "my-app",
Writer: &buf,
CustomAppHelpTemplate: tt.template,
}

err := app.Run([]string{"my-app", "help"})
if err != nil {
t.Fatal(err)
}

got := buf.String()
if got != tt.wantOutput {
t.Errorf("want output %q, got %q", tt.wantOutput, got)
}
})
}
}

func TestShowAppHelp_HelpPrinterCustom(t *testing.T) {
doublecho := func(text string) string {
return text + " " + text
}

tests := []struct {
name string
template string
printer helpPrinterCustom
wantTemplate string
wantOutput string
}{
{
name: "standard-command",
template: "",
printer: func(w io.Writer, templ string, data interface{}, fm map[string]interface{}) {
fmt.Fprint(w, "yo")
},
wantTemplate: AppHelpTemplate,
wantOutput: "yo",
},
{
name: "custom-template-command",
template: "{{doublecho .Name}}",
printer: func(w io.Writer, templ string, data interface{}, _ map[string]interface{}) {
// Pass a custom function to ensure it gets used
fm := map[string]interface{}{"doublecho": doublecho}
printHelpCustom(w, templ, data, fm)
},
wantTemplate: "{{doublecho .Name}}",
wantOutput: "my-app my-app",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func(old helpPrinterCustom) {
HelpPrinterCustom = old
}(HelpPrinterCustom)
HelpPrinterCustom = func(w io.Writer, templ string, data interface{}, fm map[string]interface{}) {
if fm != nil {
t.Error("unexpected function map passed")
}

if templ != tt.wantTemplate {
t.Errorf("want template:\n%s\ngot template:\n%s", tt.wantTemplate, templ)
}

tt.printer(w, templ, data, fm)
}

var buf bytes.Buffer
app := &App{
Name: "my-app",
Writer: &buf,
CustomAppHelpTemplate: tt.template,
}

err := app.Run([]string{"my-app", "help"})
if err != nil {
t.Fatal(err)
}

got := buf.String()
if got != tt.wantOutput {
t.Errorf("want output %q, got %q", tt.wantOutput, got)
}
})
}
}

func TestShowAppHelp_CustomAppTemplate(t *testing.T) {
app := &App{
Commands: []Command{
Expand Down

0 comments on commit 9ab178d

Please sign in to comment.