JMS #14: Moving toward having and app object
This commit is contained in:
parent
435c4d704c
commit
6664835bc1
48
app.go
Normal file
48
app.go
Normal file
@ -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)
|
||||
}
|
40
cli.go
40
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 = "<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)
|
||||
|
23
cli_test.go
23
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 */
|
||||
|
@ -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)
|
||||
|
2
flag.go
2
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)
|
||||
}
|
||||
|
17
help.go
17
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()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user