diff options
author | Gibheer <gibheer@gmail.com> | 2015-03-19 01:35:18 +0100 |
---|---|---|
committer | Gibheer <gibheer@gmail.com> | 2015-03-19 01:35:18 +0100 |
commit | 9e351c05d5c067e20a9a6a34798dccd19dbd7296 (patch) | |
tree | bf1640b7be679422b1901406d762e7f750b78405 /command.go | |
parent | c0cc30089f85dc439398d14399a31da8169d471e (diff) |
add command flag parser
This is a small command flag parser hacked away in a couple hours. It is
built after cobra (https://github.com/spf13/cobra), but with some small
details changed.
Instead of breaking with the go flag API (single and double dashes) this
uses the golang flags package. This means, that single character flags
do not work, but in this case it wouldn't make much sense to replace
long clear argument names with short nothing saying arguments (-p for
--private-key or --public-key?).
This should definitely help with the help and error messages.
Diffstat (limited to 'command.go')
-rw-r--r-- | command.go | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/command.go b/command.go new file mode 100644 index 0000000..7d36ce0 --- /dev/null +++ b/command.go @@ -0,0 +1,112 @@ +package main + +// handle the command infrastructure + +import ( + "fmt" + "flag" + "os" +) + +type ( + Command struct { + Use string // command name (used for matching) + Short string // a short description to display + Long string // a long help text + Example string // an example string + Run func(*Command, []string) + + flagSet *flag.FlagSet + commands []*Command + } +) + +func (c *Command) AddCommand(cmds... *Command) { + res := c.commands + for _, cmd := range cmds { + res = append(res, cmd) + } + c.commands = res +} + +func (c *Command) eval(args []string) error { + var name string = "" + var rest []string = []string{} + + if len(args) > 0 { + name = args[0] + } + if len(args) > 1 { + rest = args[1:] + } + + if name == "help" { + c.Help(rest) + return nil + } + + for _, cmd := range c.commands { + if cmd.Use == name { + return cmd.eval(rest) + } + } + if err := c.Flags().Parse(rest); err != nil { return err } + if c.Run != nil { + c.Run(c, rest) + } else { + c.Help(rest) + } + return nil +} + +func (c *Command) Execute() error { + return c.eval(os.Args[1:]) +} + +func (c *Command) Flags() *flag.FlagSet { + if c.flagSet == nil { c.flagSet = flag.NewFlagSet(c.Use, flag.ContinueOnError) } + return c.flagSet +} + +func (c *Command) Help(args []string) { + if len(args) > 0 { + for _, cmd := range c.commands { + if args[0] == cmd.Use { + cmd.Help([]string{}) + return + } + } + } + if c.Long != "" { fmt.Println(c.Long, "\n") } + c.Usage() +} + +func (c *Command) Usage() { + usage := "" + if c.Use != "" { + usage = usage + " " + c.Use + } + if len(c.commands) > 0 { + usage = usage + " command" + } + if c.flagSet != nil { + usage = usage + " [flags]" + } + fmt.Printf("Usage: %s%s\n", os.Args[0], usage) + + if len(c.commands) > 0 { + fmt.Printf("\nwhere command is one of:\n") + for _, cmd := range c.commands { + fmt.Printf("\t%s\t\t%s\n", cmd.Use, cmd.Short) + } + } + if c.flagSet != nil { + fmt.Printf("\nwhere flags is any of:\n") + c.Flags().SetOutput(os.Stdout) + c.Flags().PrintDefaults() + } + if c.Example != "" { + fmt.Println("\nexample:") + fmt.Printf("\t%s\n", c.Example) + } +} |