0
0
Fork 0

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.
This commit is contained in:
Gibheer 2015-03-19 01:35:18 +01:00
parent c0cc30089f
commit 9e351c05d5
1 changed files with 112 additions and 0 deletions

112
command.go Normal file
View File

@ -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)
}
}