Add custom help function to command
This commit is contained in:
parent
cf1ace3a73
commit
4cb9eec257
3 changed files with 82 additions and 10 deletions
|
@ -4,18 +4,20 @@ package cli
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Command structure contains program/command information (command name and description).
|
||||
type Command struct {
|
||||
Name string
|
||||
Description string
|
||||
Configuration interface{}
|
||||
Resources []ResourceLoader
|
||||
Run func([]string) error
|
||||
Hidden bool
|
||||
Name string
|
||||
Description string
|
||||
Configuration interface{}
|
||||
Resources []ResourceLoader
|
||||
Run func([]string) error
|
||||
CustomHelpFunc func(io.Writer, *Command) error
|
||||
Hidden bool
|
||||
// AllowArg if not set, disallows any argument that is not a known command or a sub-command.
|
||||
AllowArg bool
|
||||
subCommands []*Command
|
||||
|
@ -35,6 +37,15 @@ func (c *Command) AddCommand(cmd *Command) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PrintHelp calls the custom help function of the command if it's set.
|
||||
// Otherwise, it calls the default help function.
|
||||
func (c *Command) PrintHelp(w io.Writer) error {
|
||||
if c.CustomHelpFunc != nil {
|
||||
return c.CustomHelpFunc(w, c)
|
||||
}
|
||||
return PrintHelp(w, c)
|
||||
}
|
||||
|
||||
// Execute Executes a command.
|
||||
func Execute(cmd *Command) error {
|
||||
return execute(cmd, os.Args, true)
|
||||
|
@ -92,16 +103,16 @@ func execute(cmd *Command, args []string, root bool) error {
|
|||
|
||||
func run(cmd *Command, args []string) error {
|
||||
if len(args) > 0 && !isFlag(args[0]) && !cmd.AllowArg {
|
||||
_ = PrintHelp(os.Stdout, cmd)
|
||||
_ = cmd.PrintHelp(os.Stdout)
|
||||
return fmt.Errorf("command not found: %s", args[0])
|
||||
}
|
||||
|
||||
if isHelp(args) {
|
||||
return PrintHelp(os.Stdout, cmd)
|
||||
return cmd.PrintHelp(os.Stdout)
|
||||
}
|
||||
|
||||
if cmd.Run == nil {
|
||||
_ = PrintHelp(os.Stdout, cmd)
|
||||
_ = cmd.PrintHelp(os.Stdout)
|
||||
return fmt.Errorf("command %s is not runnable", cmd.Name)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -55,6 +59,63 @@ func TestCommand_AddCommand(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCommand_PrintHelp(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
command *Command
|
||||
expectedOutput string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
desc: "print default help",
|
||||
command: &Command{},
|
||||
expectedOutput: " \n\nUsage: [command] [flags] [arguments]\n\nUse \" [command] --help\" for help on any command.\n\n",
|
||||
},
|
||||
{
|
||||
desc: "print custom help",
|
||||
command: &Command{
|
||||
Name: "root",
|
||||
Description: "Description for root",
|
||||
Configuration: &struct {
|
||||
Foo []struct {
|
||||
Field string
|
||||
}
|
||||
}{},
|
||||
Run: func(args []string) error {
|
||||
return nil
|
||||
},
|
||||
CustomHelpFunc: func(w io.Writer, _ *Command) error {
|
||||
_, _ = fmt.Fprintln(w, "test")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
expectedOutput: "test\n",
|
||||
},
|
||||
{
|
||||
desc: "error is returned from called help",
|
||||
command: &Command{
|
||||
CustomHelpFunc: func(_ io.Writer, _ *Command) error {
|
||||
return errors.New("test")
|
||||
},
|
||||
},
|
||||
expectedError: errors.New("test"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
buffer := &bytes.Buffer{}
|
||||
err := test.command.PrintHelp(buffer)
|
||||
|
||||
assert.Equal(t, test.expectedError, err)
|
||||
assert.Equal(t, test.expectedOutput, buffer.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_execute(t *testing.T) {
|
||||
var called string
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ func (f *FileLoader) GetFilename() string {
|
|||
func (f *FileLoader) Load(args []string, cmd *Command) (bool, error) {
|
||||
ref, err := flag.Parse(args, cmd.Configuration)
|
||||
if err != nil {
|
||||
_ = PrintHelp(os.Stdout, cmd)
|
||||
_ = cmd.PrintHelp(os.Stdout)
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue