Merge pull request #17 from codegangsta/JMS-14

Jms 14
main
Jeremy Saenz 11 years ago
commit 2aab39bf49

@ -0,0 +1,52 @@
package cli
import (
"os"
)
type App struct {
// The name of the program. Defaults to os.Args[0]
Name string
// Description of the program.
Usage string
// Version of the program
Version string
// List of commands to execute
Commands []Command
Flags []Flag
// The action to execute when no subcommands are specified
Action Handler
}
func NewApp() *App {
return &App{
Name: os.Args[0],
Usage: "A new cli application",
Version: "0.0.0",
Action: helpCommand.Action,
}
}
func (a *App) Run(arguments []string) {
// parse flags
set := flagSet(a.Flags)
set.Parse(arguments[1:])
// append help to commands
a.Commands = append(a.Commands, helpCommand)
context := NewContext(a, set, set)
args := context.Args()
if len(args) > 0 {
name := args[0]
for _, c := range a.Commands {
if c.HasName(name) {
c.Run(context)
return
}
}
}
// Run default Action
a.Action(context)
}

@ -1,43 +1,3 @@
package cli package cli
import "os"
// The name of the program. Defaults to os.Args[0]
var Name = os.Args[0]
// Description of the program.
var Usage = "<No Description>"
// Version of the program
var Version = "0.0.0"
// List of commands to execute
var Commands []Command
var Flags []Flag
// The action to execute when no subcommands are specified
var Action = ShowHelp
func Run(arguments []string) {
set := flagSet(Flags)
set.Parse(arguments[1:])
context := NewContext(set, set)
args := context.Args()
if len(args) > 0 {
name := args[0]
for _, c := range append(Commands, HelpCommand) {
if c.HasName(name) {
c.Run(context)
return
}
}
}
// Run default Action
Action(context)
}
type Handler func(context *Context) type Handler func(context *Context)

@ -6,38 +6,47 @@ import (
) )
func Test_SettingFlags(t *testing.T) { func Test_SettingFlags(t *testing.T) {
Flags = []Flag{ msg := ""
app := NewApp()
app.Flags = []Flag{
StringFlag{"foo", "default", "a string flag"}, StringFlag{"foo", "default", "a string flag"},
IntFlag{"bar", 42, "an int flag"}, IntFlag{"bar", 42, "an int flag"},
BoolFlag{"bat", "a bool flag"}, BoolFlag{"bat", "a bool flag"},
} }
Action = func(c *Context) { app.Action = func(c *Context) {
expect(t, c.String("foo"), "hello world") expect(t, c.String("foo"), "hello world")
expect(t, c.Int("bar"), 245) expect(t, c.Int("bar"), 245)
expect(t, c.Bool("bat"), true) expect(t, c.Bool("bat"), true)
msg = "foobar"
} }
Run([]string{"command", "--foo", "hello world", "--bar", "245", "--bat"}) app.Run([]string{"command", "--foo", "hello world", "--bar", "245", "--bat"})
expect(t, msg, "foobar")
} }
func Test_FlagDefaults(t *testing.T) { func Test_FlagDefaults(t *testing.T) {
Flags = []Flag{ msg := ""
app := NewApp()
app.Flags = []Flag{
StringFlag{"foo", "default", "a string flag"}, StringFlag{"foo", "default", "a string flag"},
IntFlag{"bar", 42, "an int flag"}, IntFlag{"bar", 42, "an int flag"},
BoolFlag{"bat", "a bool flag"}, BoolFlag{"bat", "a bool flag"},
} }
Action = func(c *Context) { app.Action = func(c *Context) {
expect(t, c.String("foo"), "default") expect(t, c.String("foo"), "default")
expect(t, c.Int("bar"), 42) expect(t, c.Int("bar"), 42)
expect(t, c.Bool("bat"), false) expect(t, c.Bool("bat"), false)
msg = "foobar"
} }
Run([]string{"command"}) app.Run([]string{"command"})
expect(t, msg, "foobar")
} }
func TestCommands(t *testing.T) { func TestCommands(t *testing.T) {
Flags = []Flag{ app := NewApp()
app.Flags = []Flag{
StringFlag{"name", "jeremy", "a name to print"}, StringFlag{"name", "jeremy", "a name to print"},
} }
Commands = []Command{ app.Commands = []Command{
{ {
Name: "print", Name: "print",
Flags: []Flag{ Flags: []Flag{
@ -49,10 +58,10 @@ func TestCommands(t *testing.T) {
}, },
}, },
} }
Action = func(c *Context) { app.Action = func(c *Context) {
t.Error("default action should not be called") t.Error("default action should not be called")
} }
Run([]string{"command", "--name", "jordie", "print", "--age", "21"}) app.Run([]string{"command", "--name", "jordie", "print", "--age", "21"})
} }
/* Test Helpers */ /* Test Helpers */

@ -12,7 +12,7 @@ type Command struct {
func (command Command) Run(c *Context) { func (command Command) Run(c *Context) {
set := flagSet(command.Flags) set := flagSet(command.Flags)
set.Parse(c.Args()[1:]) set.Parse(c.Args()[1:])
command.Action(NewContext(set, c.globalSet)) command.Action(NewContext(c.App, set, c.globalSet))
} }
func (command Command) HasName(name string) bool { func (command Command) HasName(name string) bool {

@ -10,12 +10,13 @@ import (
// can be used to retrieve context-specific Args and // can be used to retrieve context-specific Args and
// parsed command-line options. // parsed command-line options.
type Context struct { type Context struct {
App *App
flagSet *flag.FlagSet flagSet *flag.FlagSet
globalSet *flag.FlagSet globalSet *flag.FlagSet
} }
func NewContext(set *flag.FlagSet, globalSet *flag.FlagSet) *Context { func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
return &Context{set, globalSet} return &Context{app, set, globalSet}
} }
// Looks up the value of a local int flag, returns 0 if no int flag exists // Looks up the value of a local int flag, returns 0 if no int flag exists

@ -10,7 +10,7 @@ func Test_New(t *testing.T) {
set.Int("myflag", 12, "doc") set.Int("myflag", 12, "doc")
globalSet := flag.NewFlagSet("test", 0) globalSet := flag.NewFlagSet("test", 0)
globalSet.Int("myflag", 42, "doc") globalSet.Int("myflag", 42, "doc")
c := NewContext(set, globalSet) c := NewContext(nil, set, globalSet)
expect(t, c.Int("myflag"), 12) expect(t, c.Int("myflag"), 12)
expect(t, c.GlobalInt("myflag"), 42) expect(t, c.GlobalInt("myflag"), 42)
} }
@ -18,28 +18,28 @@ func Test_New(t *testing.T) {
func Test_Int(t *testing.T) { func Test_Int(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc") set.Int("myflag", 12, "doc")
c := NewContext(set, set) c := NewContext(nil, set, set)
expect(t, c.Int("myflag"), 12) expect(t, c.Int("myflag"), 12)
} }
func Test_String(t *testing.T) { func Test_String(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.String("myflag", "hello world", "doc") set.String("myflag", "hello world", "doc")
c := NewContext(set, set) c := NewContext(nil, set, set)
expect(t, c.String("myflag"), "hello world") expect(t, c.String("myflag"), "hello world")
} }
func Test_Bool(t *testing.T) { func Test_Bool(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc") set.Bool("myflag", false, "doc")
c := NewContext(set, set) c := NewContext(nil, set, set)
expect(t, c.Bool("myflag"), false) expect(t, c.Bool("myflag"), false)
} }
func Test_Args(t *testing.T) { func Test_Args(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc") set.Bool("myflag", false, "doc")
c := NewContext(set, set) c := NewContext(nil, set, set)
set.Parse([]string{"--myflag", "bat", "baz"}) set.Parse([]string{"--myflag", "bat", "baz"})
expect(t, len(c.Args()), 2) expect(t, len(c.Args()), 2)
expect(t, c.Bool("myflag"), true) expect(t, c.Bool("myflag"), true)

@ -9,7 +9,7 @@ type Flag interface {
} }
func flagSet(flags []Flag) *flag.FlagSet { func flagSet(flags []Flag) *flag.FlagSet {
set := flag.NewFlagSet(Name, flag.ExitOnError) set := flag.NewFlagSet("cli", flag.ExitOnError)
for _, f := range flags { for _, f := range flags {
f.Apply(set) f.Apply(set)
} }

@ -4,51 +4,31 @@ import "os"
import "text/tabwriter" import "text/tabwriter"
import "text/template" import "text/template"
type HelpData struct { var helpCommand = Command{
Name string
Usage string
Version string
Commands []Command
Flags []Flag
}
var HelpCommand = Command{
Name: "help", Name: "help",
ShortName: "h", ShortName: "h",
Usage: "Shows a list of commands or help for one command", Usage: "Shows a list of commands or help for one command",
} Action: func(c *Context) {
helpTemplate := `NAME:
func init() { {{.Name}} - {{.Usage}}
HelpCommand.Action = ShowHelp
}
func ShowHelp(c *Context) {
helpTemplate := `NAME:
{{.Name}} - {{.Usage}}
USAGE: USAGE:
{{.Name}} [global options] command [command options] [arguments...] {{.Name}} [global options] command [command options] [arguments...]
VERSION: VERSION:
{{.Version}} {{.Version}}
COMMANDS: COMMANDS:
{{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
{{end}} {{end}}
GLOBAL OPTIONS GLOBAL OPTIONS:
{{range .Flags}}{{.}} {{range .Flags}}{{.}}
{{end}} {{end}}
` `
data := HelpData{
Name,
Usage,
Version,
append(Commands, HelpCommand),
Flags,
}
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
t := template.Must(template.New("help").Parse(helpTemplate)) t := template.Must(template.New("help").Parse(helpTemplate))
t.Execute(w, data) t.Execute(w, c.App)
w.Flush() w.Flush()
},
} }

Loading…
Cancel
Save