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
|
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)
|
||||||
|
23
cli_test.go
23
cli_test.go
@ -6,38 +6,41 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_SettingFlags(t *testing.T) {
|
func Test_SettingFlags(t *testing.T) {
|
||||||
Flags = []Flag{
|
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)
|
||||||
}
|
}
|
||||||
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) {
|
func Test_FlagDefaults(t *testing.T) {
|
||||||
Flags = []Flag{
|
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)
|
||||||
}
|
}
|
||||||
Run([]string{"command"})
|
app.Run([]string{"command"})
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +52,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)
|
||||||
|
2
flag.go
2
flag.go
@ -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)
|
||||||
}
|
}
|
||||||
|
17
help.go
17
help.go
@ -4,14 +4,6 @@ import "os"
|
|||||||
import "text/tabwriter"
|
import "text/tabwriter"
|
||||||
import "text/template"
|
import "text/template"
|
||||||
|
|
||||||
type HelpData struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
Version string
|
|
||||||
Commands []Command
|
|
||||||
Flags []Flag
|
|
||||||
}
|
|
||||||
|
|
||||||
var HelpCommand = Command{
|
var HelpCommand = Command{
|
||||||
Name: "help",
|
Name: "help",
|
||||||
ShortName: "h",
|
ShortName: "h",
|
||||||
@ -39,16 +31,9 @@ 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…
Reference in New Issue
Block a user