JMS #14: Moving toward having and app object

main
Jeremy Saenz 11 years ago
parent 435c4d704c
commit 6664835bc1

@ -0,0 +1,48 @@
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: ShowHelp,
}
}
func (a *App) Run(arguments []string) {
set := flagSet(a.Flags)
set.Parse(arguments[1:])
context := NewContext(a, set, set)
args := context.Args()
if len(args) > 0 {
name := args[0]
for _, c := range append(a.Commands, HelpCommand) {
if c.HasName(name) {
c.Run(context)
return
}
}
}
// Run default Action
a.Action(context)
}

@ -1,43 +1,3 @@
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)

@ -6,38 +6,41 @@ import (
)
func Test_SettingFlags(t *testing.T) {
Flags = []Flag{
app := NewApp()
app.Flags = []Flag{
StringFlag{"foo", "default", "a string flag"},
IntFlag{"bar", 42, "an int 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.Int("bar"), 245)
expect(t, c.Bool("bat"), true)
}
Run([]string{"command", "--foo", "hello world", "--bar", "245", "--bat"})
app.Run([]string{"command", "--foo", "hello world", "--bar", "245", "--bat"})
}
func Test_FlagDefaults(t *testing.T) {
Flags = []Flag{
app := NewApp()
app.Flags = []Flag{
StringFlag{"foo", "default", "a string flag"},
IntFlag{"bar", 42, "an int flag"},
BoolFlag{"bat", "a bool flag"},
}
Action = func(c *Context) {
app.Action = func(c *Context) {
expect(t, c.String("foo"), "default")
expect(t, c.Int("bar"), 42)
expect(t, c.Bool("bat"), false)
}
Run([]string{"command"})
app.Run([]string{"command"})
}
func TestCommands(t *testing.T) {
Flags = []Flag{
app := NewApp()
app.Flags = []Flag{
StringFlag{"name", "jeremy", "a name to print"},
}
Commands = []Command{
app.Commands = []Command{
{
Name: "print",
Flags: []Flag{
@ -49,10 +52,10 @@ func TestCommands(t *testing.T) {
},
},
}
Action = func(c *Context) {
app.Action = func(c *Context) {
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 */

@ -12,7 +12,7 @@ type Command struct {
func (command Command) Run(c *Context) {
set := flagSet(command.Flags)
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 {

@ -10,12 +10,13 @@ import (
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
App *App
flagSet *flag.FlagSet
globalSet *flag.FlagSet
}
func NewContext(set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
return &Context{set, globalSet}
func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
return &Context{app, set, globalSet}
}
// 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")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Int("myflag", 42, "doc")
c := NewContext(set, globalSet)
c := NewContext(nil, set, globalSet)
expect(t, c.Int("myflag"), 12)
expect(t, c.GlobalInt("myflag"), 42)
}
@ -18,28 +18,28 @@ func Test_New(t *testing.T) {
func Test_Int(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
c := NewContext(set, set)
c := NewContext(nil, set, set)
expect(t, c.Int("myflag"), 12)
}
func Test_String(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.String("myflag", "hello world", "doc")
c := NewContext(set, set)
c := NewContext(nil, set, set)
expect(t, c.String("myflag"), "hello world")
}
func Test_Bool(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
c := NewContext(set, set)
c := NewContext(nil, set, set)
expect(t, c.Bool("myflag"), false)
}
func Test_Args(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
c := NewContext(set, set)
c := NewContext(nil, set, set)
set.Parse([]string{"--myflag", "bat", "baz"})
expect(t, len(c.Args()), 2)
expect(t, c.Bool("myflag"), true)

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

@ -4,14 +4,6 @@ import "os"
import "text/tabwriter"
import "text/template"
type HelpData struct {
Name string
Usage string
Version string
Commands []Command
Flags []Flag
}
var HelpCommand = Command{
Name: "help",
ShortName: "h",
@ -39,16 +31,9 @@ GLOBAL OPTIONS
{{range .Flags}}{{.}}
{{end}}
`
data := HelpData{
Name,
Usage,
Version,
append(Commands, HelpCommand),
Flags,
}
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
t := template.Must(template.New("help").Parse(helpTemplate))
t.Execute(w, data)
t.Execute(w, c.App)
w.Flush()
}

Loading…
Cancel
Save