aboutsummaryrefslogtreecommitdiff
path: root/command.go
diff options
context:
space:
mode:
authorGibheer <gibheer@gmail.com>2015-03-19 01:35:18 +0100
committerGibheer <gibheer@gmail.com>2015-03-19 01:35:18 +0100
commit9e351c05d5c067e20a9a6a34798dccd19dbd7296 (patch)
treebf1640b7be679422b1901406d762e7f750b78405 /command.go
parentc0cc30089f85dc439398d14399a31da8169d471e (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.go112
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)
+ }
+}