From 6664835bc1e02caa4c3d4cd43e3b3033166c7489 Mon Sep 17 00:00:00 2001 From: Jeremy Saenz Date: Fri, 19 Jul 2013 08:34:01 -0700 Subject: [PATCH] JMS #14: Moving toward having and app object --- app.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ cli.go | 40 ---------------------------------------- cli_test.go | 23 +++++++++++++---------- command.go | 2 +- context.go | 5 +++-- context_test.go | 10 +++++----- flag.go | 2 +- help.go | 17 +---------------- 8 files changed, 72 insertions(+), 75 deletions(-) create mode 100644 app.go diff --git a/app.go b/app.go new file mode 100644 index 0000000..ebbdd4b --- /dev/null +++ b/app.go @@ -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) +} diff --git a/cli.go b/cli.go index e97e18e..567e04a 100644 --- a/cli.go +++ b/cli.go @@ -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 = "" - -// 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) diff --git a/cli_test.go b/cli_test.go index 1c083bb..813bfe7 100644 --- a/cli_test.go +++ b/cli_test.go @@ -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 */ diff --git a/command.go b/command.go index 0a9a7ec..d8e2011 100644 --- a/command.go +++ b/command.go @@ -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 { diff --git a/context.go b/context.go index ae50463..6c4cbad 100644 --- a/context.go +++ b/context.go @@ -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 diff --git a/context_test.go b/context_test.go index d859179..3c6bab5 100644 --- a/context_test.go +++ b/context_test.go @@ -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) diff --git a/flag.go b/flag.go index 0e28ea0..4601236 100644 --- a/flag.go +++ b/flag.go @@ -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) } diff --git a/help.go b/help.go index b5cb95e..ffe5b28 100644 --- a/help.go +++ b/help.go @@ -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() }