Remove `NewApp` initializer

and move defaulting to `App.Setup`
main
Dan Buch 8 years ago
parent b5f16ff767
commit df685fbacc
No known key found for this signature in database
GPG Key ID: FAEF12936DD3E3EC

@ -146,7 +146,7 @@ import (
) )
func main() { func main() {
cli.NewApp().Run(os.Args) (&cli.App{}).Run(os.Args)
} }
``` ```
@ -167,12 +167,13 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
app.Name = "boom" Name: "boom",
app.Usage = "make an explosive entrance" Usage: "make an explosive entrance",
app.Action = func(c *cli.Context) error { Action: func(c *cli.Context) error {
fmt.Println("boom! I say!") fmt.Println("boom! I say!")
return nil return nil
},
} }
app.Run(os.Args) app.Run(os.Args)
@ -205,12 +206,13 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
app.Name = "greet" Name: "greet",
app.Usage = "fight the loneliness!" Usage: "fight the loneliness!",
app.Action = func(c *cli.Context) error { Action: func(c *cli.Context) error {
fmt.Println("Hello friend!") fmt.Println("Hello friend!")
return nil return nil
},
} }
app.Run(os.Args) app.Run(os.Args)
@ -268,11 +270,11 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Action: func(c *cli.Context) error {
app.Action = func(c *cli.Context) error { fmt.Printf("Hello %q", c.Args().Get(0))
fmt.Printf("Hello %q", c.Args().Get(0)) return nil
return nil },
} }
app.Run(os.Args) app.Run(os.Args)
@ -297,27 +299,26 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Flags: []cli.Flag {
app.Flags = []cli.Flag { &cli.StringFlag{
&cli.StringFlag{ Name: "lang",
Name: "lang", Value: "english",
Value: "english", Usage: "language for the greeting",
Usage: "language for the greeting", },
},
Action: func(c *cli.Context) error {
name := "Nefertiti"
if c.NArg() > 0 {
name = c.Args().Get(0)
}
if c.String("lang") == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
}, },
}
app.Action = func(c *cli.Context) error {
name := "Nefertiti"
if c.NArg() > 0 {
name = c.Args().Get(0)
}
if c.String("lang") == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
} }
app.Run(os.Args) app.Run(os.Args)
@ -343,28 +344,27 @@ import (
func main() { func main() {
var language string var language string
app := cli.NewApp() app := &cli.App{
Flags: []cli.Flag {
app.Flags = []cli.Flag { &cli.StringFlag{
&cli.StringFlag{ Name: "lang",
Name: "lang", Value: "english",
Value: "english", Usage: "language for the greeting",
Usage: "language for the greeting", Destination: &language,
Destination: &language, },
},
Action: func(c *cli.Context) error {
name := "someone"
if c.NArg() > 0 {
name = c.Args().Get(0)
}
if language == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
}, },
}
app.Action = func(c *cli.Context) error {
name := "someone"
if c.NArg() > 0 {
name = c.Args().Get(0)
}
if language == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
} }
app.Run(os.Args) app.Run(os.Args)
@ -394,13 +394,13 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Flags: []cli.Flag{
app.Flags = []cli.Flag{ &cli.StringFlag{
&cli.StringFlag{ Name: "config",
Name: "config", Aliases: []string{"c"},
Aliases: []string{"c"}, Usage: "Load configuration from `FILE`",
Usage: "Load configuration from `FILE`", },
}, },
} }
@ -436,14 +436,14 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Flags: []cli.Flag {
app.Flags = []cli.Flag { &cli.StringFlag{
&cli.StringFlag{ Name: "lang",
Name: "lang", Aliases: []string{"l"},
Aliases: []string{"l"}, Value: "english",
Value: "english", Usage: "language for the greeting",
Usage: "language for the greeting", },
}, },
} }
@ -473,15 +473,15 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Flags: []cli.Flag {
app.Flags = []cli.Flag { &cli.StringFlag{
&cli.StringFlag{ Name: "lang",
Name: "lang", Aliases: []string{"l"},
Aliases: []string{"l"}, Value: "english",
Value: "english", Usage: "language for the greeting",
Usage: "language for the greeting", EnvVars: []string{"APP_LANG"},
EnvVars: []string{"APP_LANG"}, },
}, },
} }
@ -506,15 +506,15 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Flags: []cli.Flag{
app.Flags = []cli.Flag{ &cli.StringFlag{
&cli.StringFlag{ Name: "lang",
Name: "lang", Aliases: []string{"l"},
Aliases: []string{"l"}, Value: "english",
Value: "english", Usage: "language for the greeting",
Usage: "language for the greeting", EnvVars: []string{"LEGACY_COMPAT_LANG", "APP_LANG", "LANG"},
EnvVars: []string{"LEGACY_COMPAT_LANG", "APP_LANG", "LANG"}, },
}, },
} }
@ -569,21 +569,20 @@ import (
) )
func main() { func main() {
app := cli.NewApp()
flags := []cli.Flag{ flags := []cli.Flag{
altsrc.NewIntFlag(&cli.IntFlag{Name: "test"}), altsrc.NewIntFlag(&cli.IntFlag{Name: "test"}),
&cli.StringFlag{Name: "load"}, &cli.StringFlag{Name: "load"},
} }
app.Action = func(c *cli.Context) error { app := &cli.App{
fmt.Println("yaml ist rad") Action: func(c *cli.Context) error {
return nil fmt.Println("yaml ist rad")
return nil
},
Before: altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load")),
Flags: flags,
} }
app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load"))
app.Flags = flags
app.Run(os.Args) app.Run(os.Args)
} }
``` ```
@ -607,46 +606,46 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Commands: []*cli.Command{
app.Commands = []*cli.Command{ {
{ Name: "add",
Name: "add", Aliases: []string{"a"},
Aliases: []string{"a"}, Usage: "add a task to the list",
Usage: "add a task to the list", Action: func(c *cli.Context) error {
Action: func(c *cli.Context) error { fmt.Println("added task: ", c.Args().First())
fmt.Println("added task: ", c.Args().First()) return nil
return nil },
}, },
}, {
{ Name: "complete",
Name: "complete", Aliases: []string{"c"},
Aliases: []string{"c"}, Usage: "complete a task on the list",
Usage: "complete a task on the list", Action: func(c *cli.Context) error {
Action: func(c *cli.Context) error { fmt.Println("completed task: ", c.Args().First())
fmt.Println("completed task: ", c.Args().First()) return nil
return nil },
}, },
}, {
{ Name: "template",
Name: "template", Aliases: []string{"t"},
Aliases: []string{"t"}, Usage: "options for task templates",
Usage: "options for task templates", Subcommands: []*cli.Command{
Subcommands: []*cli.Command{ {
{ Name: "add",
Name: "add", Usage: "add a new template",
Usage: "add a new template", Action: func(c *cli.Context) error {
Action: func(c *cli.Context) error { fmt.Println("new task template: ", c.Args().First())
fmt.Println("new task template: ", c.Args().First()) return nil
return nil },
}, },
}, {
{ Name: "remove",
Name: "remove", Usage: "remove an existing template",
Usage: "remove an existing template", Action: func(c *cli.Context) error {
Action: func(c *cli.Context) error { fmt.Println("removed task template: ", c.Args().First())
fmt.Println("removed task template: ", c.Args().First()) return nil
return nil },
}, },
}, },
}, },
@ -675,19 +674,19 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
Commands: []*cli.Command{
app.Commands = []*cli.Command{ {
{ Name: "noop",
Name: "noop", },
}, {
{ Name: "add",
Name: "add", Category: "template",
Category: "template", },
}, {
{ Name: "remove",
Name: "remove", Category: "template",
Category: "template", },
}, },
} }
@ -723,19 +722,20 @@ import (
) )
func main() { func main() {
app := cli.NewApp() app := &cli.App{
app.Flags = []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{ &cli.BoolFlag{
Name: "ginger-crouton", Name: "ginger-crouton",
Value: true, Value: true,
Usage: "is it in the soup?", Usage: "is it in the soup?",
},
},
Action: func(ctx *cli.Context) error {
if !ctx.Bool("ginger-crouton") {
return cli.Exit("it is not in the soup", 86)
}
return nil
}, },
}
app.Action = func(ctx *cli.Context) error {
if !ctx.Bool("ginger-crouton") {
return cli.Exit("it is not in the soup", 86)
}
return nil
} }
app.Run(os.Args) app.Run(os.Args)
@ -766,25 +766,26 @@ import (
func main() { func main() {
tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"} tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
app := cli.NewApp() app := &cli.App{
app.EnableBashCompletion = true EnableBashCompletion: true,
app.Commands = []*cli.Command{ Commands: []*cli.Command{
{ {
Name: "complete", Name: "complete",
Aliases: []string{"c"}, Aliases: []string{"c"},
Usage: "complete a task on the list", Usage: "complete a task on the list",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
fmt.Println("completed task: ", c.Args().First()) fmt.Println("completed task: ", c.Args().First())
return nil return nil
}, },
BashComplete: func(c *cli.Context) { BashComplete: func(c *cli.Context) {
// This will complete if no args are passed // This will complete if no args are passed
if c.NArg() > 0 { if c.NArg() > 0 {
return return
} }
for _, t := range tasks { for _, t := range tasks {
fmt.Println(t) fmt.Println(t)
} }
},
}, },
}, },
} }
@ -840,11 +841,12 @@ func main() {
Hidden: true, Hidden: true,
} }
app := cli.NewApp() app := &cli.App{
app.EnableBashCompletion = true EnableBashCompletion: true,
app.Commands = []*cli.Command{ Commands: []*cli.Command{
{ {
Name: "wat", Name: "wat",
},
}, },
} }
app.Run(os.Args) app.Run(os.Args)
@ -919,7 +921,7 @@ VERSION:
fmt.Println("Ha HA. I pwnd the help!!1") fmt.Println("Ha HA. I pwnd the help!!1")
} }
cli.NewApp().Run(os.Args) (&cli.App{}).Run(os.Args)
} }
``` ```
@ -946,7 +948,7 @@ func main() {
EnvVars: []string{"SHOW_HALP", "HALPPLZ"}, EnvVars: []string{"SHOW_HALP", "HALPPLZ"},
} }
cli.NewApp().Run(os.Args) (&cli.App{}).Run(os.Args)
} }
``` ```
@ -980,9 +982,10 @@ func main() {
Usage: "print only the version", Usage: "print only the version",
} }
app := cli.NewApp() app := &cli.App{
app.Name = "partay" Name: "partay",
app.Version = "v19.99.0" Version: "v19.99.0",
}
app.Run(os.Args) app.Run(os.Args)
} }
``` ```
@ -1012,9 +1015,10 @@ func main() {
fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision) fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
} }
app := cli.NewApp() app := &cli.App{
app.Name = "partay" Name: "partay",
app.Version = "v19.99.0" Version: "v19.99.0",
}
app.Run(os.Args) app.Run(os.Args)
} }
``` ```
@ -1091,183 +1095,189 @@ func (g *genericType) String() string {
} }
func main() { func main() {
app := cli.NewApp() app := cli.App{
app.Name = "kənˈtrīv" Name: "kənˈtrīv",
app.Version = "v19.99.0" Version: "v19.99.0",
app.Compiled = time.Now() Compiled: time.Now(),
app.Authors = []*cli.Author{ Authors: []*cli.Author{
&cli.Author{ &cli.Author{
Name: "Example Human", Name: "Example Human",
Email: "human@example.com", Email: "human@example.com",
},
}
app.Copyright = "(c) 1999 Serious Enterprise"
app.HelpName = "contrive"
app.Usage = "demonstrate available API"
app.UsageText = "contrive - demonstrating the available API"
app.ArgsUsage = "[args and such]"
app.Commands = []*cli.Command{
&cli.Command{
Name: "doo",
Aliases: []string{"do"},
Category: "motion",
Usage: "do the doo",
UsageText: "doo - does the dooing",
Description: "no really, there is a lot of dooing to be done",
ArgsUsage: "[arrgh]",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "forever", Aliases: []string{"forevvarr"}},
}, },
Subcommands: []*cli.Command{ },
&cli.Command{ Copyright: "(c) 1999 Serious Enterprise",
Name: "wop", HelpName: "contrive",
Action: wopAction, Usage: "demonstrate available API",
UsageText: "contrive - demonstrating the available API",
ArgsUsage: "[args and such]",
Commands: []*cli.Command{
&cli.Command{
Name: "doo",
Aliases: []string{"do"},
Category: "motion",
Usage: "do the doo",
UsageText: "doo - does the dooing",
Description: "no really, there is a lot of dooing to be done",
ArgsUsage: "[arrgh]",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "forever", Aliases: []string{"forevvarr"}},
},
Subcommands: []*cli.Command{
&cli.Command{
Name: "wop",
Action: wopAction,
},
},
SkipFlagParsing: false,
HideHelp: false,
Hidden: false,
HelpName: "doo!",
BashComplete: func(c *cli.Context) {
fmt.Fprintf(c.App.Writer, "--better\n")
},
Before: func(c *cli.Context) error {
fmt.Fprintf(c.App.Writer, "brace for impact\n")
return nil
},
After: func(c *cli.Context) error {
fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
return nil
},
Action: func(c *cli.Context) error {
c.Command.FullName()
c.Command.HasName("wop")
c.Command.Names()
c.Command.VisibleFlags()
fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
if c.Bool("forever") {
c.Command.Run(c)
}
return nil
},
OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
fmt.Fprintf(c.App.Writer, "for shame\n")
return err
}, },
},
SkipFlagParsing: false,
HideHelp: false,
Hidden: false,
HelpName: "doo!",
BashComplete: func(c *cli.Context) {
fmt.Fprintf(c.App.Writer, "--better\n")
},
Before: func(c *cli.Context) error {
fmt.Fprintf(c.App.Writer, "brace for impact\n")
return nil
},
After: func(c *cli.Context) error {
fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
return nil
},
Action: func(c *cli.Context) error {
c.Command.FullName()
c.Command.HasName("wop")
c.Command.Names()
c.Command.VisibleFlags()
fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
if c.Bool("forever") {
c.Command.Run(c)
}
return nil
},
OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
fmt.Fprintf(c.App.Writer, "for shame\n")
return err
}, },
}, },
} Flags: []cli.Flag{
app.Flags = []cli.Flag{ &cli.BoolFlag{Name: "fancy"},
&cli.BoolFlag{Name: "fancy"}, &cli.BoolFlag{Value: true, Name: "fancier"},
&cli.BoolFlag{Value: true, Name: "fancier"}, &cli.DurationFlag{Name: "howlong", Aliases: []string{"H"}, Value: time.Second * 3},
&cli.DurationFlag{Name: "howlong", Aliases: []string{"H"}, Value: time.Second * 3}, &cli.Float64Flag{Name: "howmuch"},
&cli.Float64Flag{Name: "howmuch"}, &cli.GenericFlag{Name: "wat", Value: &genericType{}},
&cli.GenericFlag{Name: "wat", Value: &genericType{}}, &cli.Int64Flag{Name: "longdistance"},
&cli.Int64Flag{Name: "longdistance"}, &cli.Int64SliceFlag{Name: "intervals"},
&cli.Int64SliceFlag{Name: "intervals"}, &cli.IntFlag{Name: "distance"},
&cli.IntFlag{Name: "distance"}, &cli.IntSliceFlag{Name: "times"},
&cli.IntSliceFlag{Name: "times"}, &cli.StringFlag{Name: "dance-move", Aliases: []string{"d"}},
&cli.StringFlag{Name: "dance-move", Aliases: []string{"d"}}, &cli.StringSliceFlag{Name: "names", Aliases: []string{"N"}},
&cli.StringSliceFlag{Name: "names", Aliases: []string{"N"}}, &cli.UintFlag{Name: "age"},
&cli.UintFlag{Name: "age"}, &cli.Uint64Flag{Name: "bigage"},
&cli.Uint64Flag{Name: "bigage"}, },
} EnableBashCompletion: true,
app.EnableBashCompletion = true HideHelp: false,
app.HideHelp = false HideVersion: false,
app.HideVersion = false BashComplete: func(c *cli.Context) {
app.BashComplete = func(c *cli.Context) { fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n") },
} Before: func(c *cli.Context) error {
app.Before = func(c *cli.Context) error { fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n")
fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n") return nil
return nil },
} After: func(c *cli.Context) error {
app.After = func(c *cli.Context) error { fmt.Fprintf(c.App.Writer, "Phew!\n")
fmt.Fprintf(c.App.Writer, "Phew!\n") return nil
return nil },
} CommandNotFound: func(c *cli.Context, command string) {
app.CommandNotFound = func(c *cli.Context, command string) { fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command)
fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command) },
} OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
app.OnUsageError = func(c *cli.Context, err error, isSubcommand bool) error { if isSubcommand {
if isSubcommand { return err
return err }
}
fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err) fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err)
return nil return nil
} },
app.Action = func(c *cli.Context) error { Action: func(c *cli.Context) error {
cli.DefaultAppComplete(c) cli.DefaultAppComplete(c)
cli.HandleExitCoder(errors.New("not an exit coder, though")) cli.HandleExitCoder(errors.New("not an exit coder, though"))
cli.ShowAppHelp(c) cli.ShowAppHelp(c)
cli.ShowCommandCompletions(c, "nope") cli.ShowCommandCompletions(c, "nope")
cli.ShowCommandHelp(c, "also-nope") cli.ShowCommandHelp(c, "also-nope")
cli.ShowCompletions(c) cli.ShowCompletions(c)
cli.ShowSubcommandHelp(c) cli.ShowSubcommandHelp(c)
cli.ShowVersion(c) cli.ShowVersion(c)
categories := c.App.Categories categories := c.App.Categories
categories.AddCommand("sounds", &cli.Command{ categories.AddCommand("sounds", &cli.Command{
Name: "bloop", Name: "bloop",
}) })
for _, category := range c.App.Categories.Categories() { for _, category := range c.App.Categories.Categories() {
fmt.Fprintf(c.App.Writer, "%s\n", category.Name) fmt.Fprintf(c.App.Writer, "%s\n", category.Name)
fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands()) fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands()) fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
} }
fmt.Printf("%#v\n", c.App.Command("doo")) fmt.Printf("%#v\n", c.App.Command("doo"))
if c.Bool("infinite") { if c.Bool("infinite") {
c.App.Run([]string{"app", "doo", "wop"}) c.App.Run([]string{"app", "doo", "wop"})
} }
if c.Bool("forevar") { if c.Bool("forevar") {
c.App.RunAsSubcommand(c) c.App.RunAsSubcommand(c)
} }
c.App.Setup() c.App.Setup()
fmt.Printf("%#v\n", c.App.VisibleCategories()) fmt.Printf("%#v\n", c.App.VisibleCategories())
fmt.Printf("%#v\n", c.App.VisibleCommands()) fmt.Printf("%#v\n", c.App.VisibleCommands())
fmt.Printf("%#v\n", c.App.VisibleFlags()) fmt.Printf("%#v\n", c.App.VisibleFlags())
fmt.Printf("%#v\n", c.Args().First()) fmt.Printf("%#v\n", c.Args().First())
if c.Args().Len() > 0 { if c.Args().Len() > 0 {
fmt.Printf("%#v\n", c.Args().Get(1)) fmt.Printf("%#v\n", c.Args().Get(1))
} }
fmt.Printf("%#v\n", c.Args().Present()) fmt.Printf("%#v\n", c.Args().Present())
fmt.Printf("%#v\n", c.Args().Tail()) fmt.Printf("%#v\n", c.Args().Tail())
set := flag.NewFlagSet("contrive", 0) set := flag.NewFlagSet("contrive", 0)
nc := cli.NewContext(c.App, set, c) nc := cli.NewContext(c.App, set, c)
fmt.Printf("%#v\n", nc.Args()) fmt.Printf("%#v\n", nc.Args())
fmt.Printf("%#v\n", nc.Bool("nope")) fmt.Printf("%#v\n", nc.Bool("nope"))
fmt.Printf("%#v\n", !nc.Bool("nerp")) fmt.Printf("%#v\n", !nc.Bool("nerp"))
fmt.Printf("%#v\n", nc.Duration("howlong")) fmt.Printf("%#v\n", nc.Duration("howlong"))
fmt.Printf("%#v\n", nc.Float64("hay")) fmt.Printf("%#v\n", nc.Float64("hay"))
fmt.Printf("%#v\n", nc.Generic("bloop")) fmt.Printf("%#v\n", nc.Generic("bloop"))
fmt.Printf("%#v\n", nc.Int64("bonk")) fmt.Printf("%#v\n", nc.Int64("bonk"))
fmt.Printf("%#v\n", nc.Int64Slice("burnks")) fmt.Printf("%#v\n", nc.Int64Slice("burnks"))
fmt.Printf("%#v\n", nc.Int("bips")) fmt.Printf("%#v\n", nc.Int("bips"))
fmt.Printf("%#v\n", nc.IntSlice("blups")) fmt.Printf("%#v\n", nc.IntSlice("blups"))
fmt.Printf("%#v\n", nc.String("snurt")) fmt.Printf("%#v\n", nc.String("snurt"))
fmt.Printf("%#v\n", nc.StringSlice("snurkles")) fmt.Printf("%#v\n", nc.StringSlice("snurkles"))
fmt.Printf("%#v\n", nc.Uint("flub")) fmt.Printf("%#v\n", nc.Uint("flub"))
fmt.Printf("%#v\n", nc.Uint64("florb")) fmt.Printf("%#v\n", nc.Uint64("florb"))
fmt.Printf("%#v\n", nc.FlagNames()) fmt.Printf("%#v\n", nc.FlagNames())
fmt.Printf("%#v\n", nc.IsSet("wat")) fmt.Printf("%#v\n", nc.IsSet("wat"))
fmt.Printf("%#v\n", nc.Set("wat", "nope")) fmt.Printf("%#v\n", nc.Set("wat", "nope"))
fmt.Printf("%#v\n", nc.NArg()) fmt.Printf("%#v\n", nc.NArg())
fmt.Printf("%#v\n", nc.NumFlags()) fmt.Printf("%#v\n", nc.NumFlags())
fmt.Printf("%#v\n", nc.Lineage()[1]) fmt.Printf("%#v\n", nc.Lineage()[1])
nc.Set("wat", "also-nope") nc.Set("wat", "also-nope")
ec := cli.Exit("ohwell", 86) ec := cli.Exit("ohwell", 86)
fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode()) fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
fmt.Printf("made it!\n") fmt.Printf("made it!\n")
return ec return ec
},
Metadata: map[string]interface{}{
"layers": "many",
"explicable": false,
"whatever-values": 19.99,
},
} }
if os.Getenv("HEXY") != "" { if os.Getenv("HEXY") != "" {
@ -1275,12 +1285,6 @@ func main() {
app.ErrWriter = &hexWriter{} app.ErrWriter = &hexWriter{}
} }
app.Metadata = map[string]interface{}{
"layers": "many",
"explicable": false,
"whatever-values": 19.99,
}
app.Run(os.Args) app.Run(os.Args)
} }

@ -15,7 +15,7 @@ import (
) )
func TestCommandYamlFileTest(t *testing.T) { func TestCommandYamlFileTest(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml") defer os.Remove("current.yaml")
@ -45,7 +45,7 @@ func TestCommandYamlFileTest(t *testing.T) {
} }
func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) { func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml") defer os.Remove("current.yaml")
@ -79,7 +79,7 @@ func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) {
} }
func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) { func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top: ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666) test: 15`), 0666)
@ -114,7 +114,7 @@ func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) {
} }
func TestCommandYamlFileTestSpecifiedFlagWins(t *testing.T) { func TestCommandYamlFileTestSpecifiedFlagWins(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml") defer os.Remove("current.yaml")
@ -146,7 +146,7 @@ func TestCommandYamlFileTestSpecifiedFlagWins(t *testing.T) {
} }
func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) { func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top: ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666) test: 15`), 0666)
@ -179,7 +179,7 @@ func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) {
} }
func TestCommandYamlFileTestDefaultValueFileWins(t *testing.T) { func TestCommandYamlFileTestDefaultValueFileWins(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml") defer os.Remove("current.yaml")
@ -211,7 +211,7 @@ func TestCommandYamlFileTestDefaultValueFileWins(t *testing.T) {
} }
func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) { func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top: ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666) test: 15`), 0666)
@ -244,7 +244,7 @@ func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) {
} }
func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T) { func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml") defer os.Remove("current.yaml")
@ -278,7 +278,7 @@ func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T
} }
func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *testing.T) { func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *testing.T) {
app := cli.NewApp() app := &cli.App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top: ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666) test: 15`), 0666)

@ -11,8 +11,7 @@ import (
"time" "time"
) )
// App is the main structure of a cli application. It is recommended that // App is the main structure of a cli application.
// an app be created with the cli.NewApp() function
type App struct { type App struct {
// The name of the program. Defaults to path.Base(os.Args[0]) // The name of the program. Defaults to path.Base(os.Args[0])
Name string Name string
@ -78,22 +77,6 @@ func compileTime() time.Time {
return info.ModTime() return info.ModTime()
} }
// NewApp creates a new cli Application with some reasonable defaults for Name,
// Usage, Version and Action.
func NewApp() *App {
return &App{
Name: filepath.Base(os.Args[0]),
HelpName: filepath.Base(os.Args[0]),
Usage: "A new cli application",
UsageText: "",
Version: "0.0.0",
BashComplete: DefaultAppComplete,
Action: helpCommand.Action,
Compiled: compileTime(),
Writer: os.Stdout,
}
}
// Setup runs initialization code to ensure all data structures are ready for // Setup runs initialization code to ensure all data structures are ready for
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but // `Run` or inspection prior to `Run`. It is internally called by `Run`, but
// will return early if setup has already happened. // will return early if setup has already happened.
@ -104,6 +87,38 @@ func (a *App) Setup() {
a.didSetup = true a.didSetup = true
if a.Name == "" {
a.Name = filepath.Base(os.Args[0])
}
if a.HelpName == "" {
a.HelpName = filepath.Base(os.Args[0])
}
if a.Usage == "" {
a.Usage = "A new cli application"
}
if a.Version == "" {
a.Version = "0.0.0"
}
if a.BashComplete == nil {
a.BashComplete = DefaultAppComplete
}
if a.Action == nil {
a.Action = helpCommand.Action
}
if a.Compiled == (time.Time{}) {
a.Compiled = compileTime()
}
if a.Writer == nil {
a.Writer = os.Stdout
}
newCmds := []*Command{} newCmds := []*Command{}
for _, c := range a.Commands { for _, c := range a.Commands {
if c.HelpName == "" { if c.HelpName == "" {

@ -21,17 +21,19 @@ func ExampleApp_Run() {
// set args for examples sake // set args for examples sake
os.Args = []string{"greet", "--name", "Jeremy"} os.Args = []string{"greet", "--name", "Jeremy"}
app := NewApp() app := &App{
app.Name = "greet" Name: "greet",
app.Flags = []Flag{ Flags: []Flag{
&StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, &StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
} },
app.Action = func(c *Context) error { Action: func(c *Context) error {
fmt.Printf("Hello %v\n", c.String("name")) fmt.Printf("Hello %v\n", c.String("name"))
return nil return nil
},
UsageText: "app [first_arg] [second_arg]",
Authors: []*Author{{Name: "Oliver Allen", Email: "oliver@toyshop.example.com"}},
} }
app.UsageText = "app [first_arg] [second_arg]"
app.Authors = []*Author{{Name: "Oliver Allen", Email: "oliver@toyshop.example.com"}}
app.Run(os.Args) app.Run(os.Args)
// Output: // Output:
// Hello Jeremy // Hello Jeremy
@ -40,30 +42,31 @@ func ExampleApp_Run() {
func ExampleApp_Run_subcommand() { func ExampleApp_Run_subcommand() {
// set args for examples sake // set args for examples sake
os.Args = []string{"say", "hi", "english", "--name", "Jeremy"} os.Args = []string{"say", "hi", "english", "--name", "Jeremy"}
app := NewApp() app := &App{
app.Name = "say" Name: "say",
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "hello", Name: "hello",
Aliases: []string{"hi"}, Aliases: []string{"hi"},
Usage: "use it to see a description", Usage: "use it to see a description",
Description: "This is how we describe hello the function", Description: "This is how we describe hello the function",
Subcommands: []*Command{ Subcommands: []*Command{
{ {
Name: "english", Name: "english",
Aliases: []string{"en"}, Aliases: []string{"en"},
Usage: "sends a greeting in english", Usage: "sends a greeting in english",
Description: "greets someone in english", Description: "greets someone in english",
Flags: []Flag{ Flags: []Flag{
&StringFlag{ &StringFlag{
Name: "name", Name: "name",
Value: "Bob", Value: "Bob",
Usage: "Name of the person to greet", Usage: "Name of the person to greet",
},
},
Action: func(c *Context) error {
fmt.Println("Hello,", c.String("name"))
return nil
}, },
},
Action: func(c *Context) error {
fmt.Println("Hello,", c.String("name"))
return nil
}, },
}, },
}, },
@ -79,20 +82,21 @@ func ExampleApp_Run_help() {
// set args for examples sake // set args for examples sake
os.Args = []string{"greet", "h", "describeit"} os.Args = []string{"greet", "h", "describeit"}
app := NewApp() app := &App{
app.Name = "greet" Name: "greet",
app.Flags = []Flag{ Flags: []Flag{
&StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, &StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
} },
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "describeit", Name: "describeit",
Aliases: []string{"d"}, Aliases: []string{"d"},
Usage: "use it to see a description", Usage: "use it to see a description",
Description: "This is how we describe describeit the function", Description: "This is how we describe describeit the function",
Action: func(c *Context) error { Action: func(c *Context) error {
fmt.Printf("i like to describe things") fmt.Printf("i like to describe things")
return nil return nil
},
}, },
}, },
} }
@ -112,26 +116,27 @@ func ExampleApp_Run_bashComplete() {
// set args for examples sake // set args for examples sake
os.Args = []string{"greet", "--generate-bash-completion"} os.Args = []string{"greet", "--generate-bash-completion"}
app := NewApp() app := &App{
app.Name = "greet" Name: "greet",
app.EnableBashCompletion = true EnableBashCompletion: true,
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "describeit", Name: "describeit",
Aliases: []string{"d"}, Aliases: []string{"d"},
Usage: "use it to see a description", Usage: "use it to see a description",
Description: "This is how we describe describeit the function", Description: "This is how we describe describeit the function",
Action: func(c *Context) error { Action: func(c *Context) error {
fmt.Printf("i like to describe things") fmt.Printf("i like to describe things")
return nil return nil
}, },
}, { }, {
Name: "next", Name: "next",
Usage: "next example", Usage: "next example",
Description: "more stuff to see when generating bash completion", Description: "more stuff to see when generating bash completion",
Action: func(c *Context) error { Action: func(c *Context) error {
fmt.Printf("the next example") fmt.Printf("the next example")
return nil return nil
},
}, },
}, },
} }
@ -148,10 +153,11 @@ func ExampleApp_Run_bashComplete() {
func TestApp_Run(t *testing.T) { func TestApp_Run(t *testing.T) {
s := "" s := ""
app := NewApp() app := &App{
app.Action = func(c *Context) error { Action: func(c *Context) error {
s = s + c.Args().First() s = s + c.Args().First()
return nil return nil
},
} }
err := app.Run([]string{"command", "foo"}) err := app.Run([]string{"command", "foo"})
@ -174,7 +180,7 @@ var commandAppTests = []struct {
} }
func TestApp_Command(t *testing.T) { func TestApp_Command(t *testing.T) {
app := NewApp() app := &App{}
fooCommand := &Command{Name: "foobar", Aliases: []string{"f"}} fooCommand := &Command{Name: "foobar", Aliases: []string{"f"}}
batCommand := &Command{Name: "batbaz", Aliases: []string{"b"}} batCommand := &Command{Name: "batbaz", Aliases: []string{"b"}}
app.Commands = []*Command{ app.Commands = []*Command{
@ -190,22 +196,23 @@ func TestApp_Command(t *testing.T) {
func TestApp_RunAsSubcommandParseFlags(t *testing.T) { func TestApp_RunAsSubcommandParseFlags(t *testing.T) {
var context *Context var context *Context
a := NewApp() a := &App{
a.Commands = []*Command{ Commands: []*Command{
{ {
Name: "foo", Name: "foo",
Action: func(c *Context) error { Action: func(c *Context) error {
context = c context = c
return nil return nil
}, },
Flags: []Flag{ Flags: []Flag{
&StringFlag{ &StringFlag{
Name: "lang", Name: "lang",
Value: "english", Value: "english",
Usage: "language for the greeting", Usage: "language for the greeting",
},
}, },
Before: func(_ *Context) error { return nil },
}, },
Before: func(_ *Context) error { return nil },
}, },
} }
a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) a.Run([]string{"", "foo", "--lang", "spanish", "abcd"})
@ -218,7 +225,7 @@ func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
var parsedOption string var parsedOption string
var args Args var args Args
app := NewApp() app := &App{}
command := &Command{ command := &Command{
Name: "cmd", Name: "cmd",
Flags: []Flag{ Flags: []Flag{
@ -243,7 +250,7 @@ func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
func TestApp_CommandWithDash(t *testing.T) { func TestApp_CommandWithDash(t *testing.T) {
var args Args var args Args
app := NewApp() app := &App{}
command := &Command{ command := &Command{
Name: "cmd", Name: "cmd",
Action: func(c *Context) error { Action: func(c *Context) error {
@ -262,7 +269,7 @@ func TestApp_CommandWithDash(t *testing.T) {
func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) { func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
var args Args var args Args
app := NewApp() app := &App{}
command := &Command{ command := &Command{
Name: "cmd", Name: "cmd",
Action: func(c *Context) error { Action: func(c *Context) error {
@ -280,18 +287,19 @@ func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
} }
func TestApp_VisibleCommands(t *testing.T) { func TestApp_VisibleCommands(t *testing.T) {
app := NewApp() app := &App{
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "frob", Name: "frob",
HelpName: "foo frob", HelpName: "foo frob",
Action: func(_ *Context) error { return nil }, Action: func(_ *Context) error { return nil },
}, },
{ {
Name: "frib", Name: "frib",
HelpName: "foo frib", HelpName: "foo frib",
Hidden: true, Hidden: true,
Action: func(_ *Context) error { return nil }, Action: func(_ *Context) error { return nil },
},
}, },
} }
@ -332,13 +340,14 @@ func TestApp_VisibleCommands(t *testing.T) {
func TestApp_Float64Flag(t *testing.T) { func TestApp_Float64Flag(t *testing.T) {
var meters float64 var meters float64
app := NewApp() app := &App{
app.Flags = []Flag{ Flags: []Flag{
&Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"}, &Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"},
} },
app.Action = func(c *Context) error { Action: func(c *Context) error {
meters = c.Float64("height") meters = c.Float64("height")
return nil return nil
},
} }
app.Run([]string{"", "--height", "1.93"}) app.Run([]string{"", "--height", "1.93"})
@ -350,7 +359,7 @@ func TestApp_ParseSliceFlags(t *testing.T) {
var parsedIntSlice []int var parsedIntSlice []int
var parsedStringSlice []string var parsedStringSlice []string
app := NewApp() app := &App{}
command := &Command{ command := &Command{
Name: "cmd", Name: "cmd",
Flags: []Flag{ Flags: []Flag{
@ -408,7 +417,7 @@ func TestApp_ParseSliceFlagsWithMissingValue(t *testing.T) {
var parsedIntSlice []int var parsedIntSlice []int
var parsedStringSlice []string var parsedStringSlice []string
app := NewApp() app := &App{}
command := &Command{ command := &Command{
Name: "cmd", Name: "cmd",
Flags: []Flag{ Flags: []Flag{
@ -438,7 +447,8 @@ func TestApp_ParseSliceFlagsWithMissingValue(t *testing.T) {
} }
func TestApp_DefaultStdout(t *testing.T) { func TestApp_DefaultStdout(t *testing.T) {
app := NewApp() app := &App{}
app.Setup()
if app.Writer != os.Stdout { if app.Writer != os.Stdout {
t.Error("Default output writer not set.") t.Error("Default output writer not set.")
@ -466,9 +476,10 @@ func (fw *mockWriter) GetWritten() (b []byte) {
func TestApp_SetStdout(t *testing.T) { func TestApp_SetStdout(t *testing.T) {
w := &mockWriter{} w := &mockWriter{}
app := NewApp() app := &App{
app.Name = "test" Name: "test",
app.Writer = w Writer: w,
}
err := app.Run([]string{"help"}) err := app.Run([]string{"help"})
@ -486,32 +497,30 @@ func TestApp_BeforeFunc(t *testing.T) {
beforeError := fmt.Errorf("fail") beforeError := fmt.Errorf("fail")
var err error var err error
app := NewApp() app := &App{
Before: func(c *Context) error {
app.Before = func(c *Context) error { counts.Total++
counts.Total++ counts.Before = counts.Total
counts.Before = counts.Total s := c.String("opt")
s := c.String("opt") if s == "fail" {
if s == "fail" { return beforeError
return beforeError }
}
return nil
}
app.Commands = []*Command{ return nil
{ },
Name: "sub", Commands: []*Command{
Action: func(c *Context) error { {
counts.Total++ Name: "sub",
counts.SubCommand = counts.Total Action: func(c *Context) error {
return nil counts.Total++
counts.SubCommand = counts.Total
return nil
},
}, },
}, },
} Flags: []Flag{
&StringFlag{Name: "opt"},
app.Flags = []Flag{ },
&StringFlag{Name: "opt"},
} }
// run with the Before() func succeeding // run with the Before() func succeeding
@ -578,32 +587,30 @@ func TestApp_AfterFunc(t *testing.T) {
afterError := fmt.Errorf("fail") afterError := fmt.Errorf("fail")
var err error var err error
app := NewApp() app := &App{
After: func(c *Context) error {
app.After = func(c *Context) error { counts.Total++
counts.Total++ counts.After = counts.Total
counts.After = counts.Total s := c.String("opt")
s := c.String("opt") if s == "fail" {
if s == "fail" { return afterError
return afterError }
}
return nil
}
app.Commands = []*Command{ return nil
{ },
Name: "sub", Commands: []*Command{
Action: func(c *Context) error { {
counts.Total++ Name: "sub",
counts.SubCommand = counts.Total Action: func(c *Context) error {
return nil counts.Total++
counts.SubCommand = counts.Total
return nil
},
}, },
}, },
} Flags: []Flag{
&StringFlag{Name: "opt"},
app.Flags = []Flag{ },
&StringFlag{Name: "opt"},
} }
// run with the After() func succeeding // run with the After() func succeeding
@ -649,8 +656,7 @@ func TestAppNoHelpFlag(t *testing.T) {
HelpFlag = nil HelpFlag = nil
app := NewApp() app := &App{Writer: ioutil.Discard}
app.Writer = ioutil.Discard
err := app.Run([]string{"test", "-h"}) err := app.Run([]string{"test", "-h"})
if err != flag.ErrHelp { if err != flag.ErrHelp {
@ -669,7 +675,7 @@ func TestAppHelpPrinter(t *testing.T) {
wasCalled = true wasCalled = true
} }
app := NewApp() app := &App{}
app.Run([]string{"-h"}) app.Run([]string{"-h"})
if wasCalled == false { if wasCalled == false {
@ -688,7 +694,7 @@ func TestApp_VersionPrinter(t *testing.T) {
wasCalled = true wasCalled = true
} }
app := NewApp() app := &App{}
ctx := NewContext(app, nil, nil) ctx := NewContext(app, nil, nil)
ShowVersion(ctx) ShowVersion(ctx)
@ -699,20 +705,19 @@ func TestApp_VersionPrinter(t *testing.T) {
func TestApp_CommandNotFound(t *testing.T) { func TestApp_CommandNotFound(t *testing.T) {
counts := &opCounts{} counts := &opCounts{}
app := NewApp() app := &App{
CommandNotFound: func(c *Context, command string) {
app.CommandNotFound = func(c *Context, command string) { counts.Total++
counts.Total++ counts.CommandNotFound = counts.Total
counts.CommandNotFound = counts.Total },
} Commands: []*Command{
{
app.Commands = []*Command{ Name: "bar",
{ Action: func(c *Context) error {
Name: "bar", counts.Total++
Action: func(c *Context) error { counts.SubCommand = counts.Total
counts.Total++ return nil
counts.SubCommand = counts.Total },
return nil
}, },
}, },
} }
@ -729,17 +734,17 @@ func TestApp_OrderOfOperations(t *testing.T) {
resetCounts := func() { counts = &opCounts{} } resetCounts := func() { counts = &opCounts{} }
app := NewApp() app := &App{
app.EnableBashCompletion = true EnableBashCompletion: true,
app.BashComplete = func(c *Context) { BashComplete: func(c *Context) {
counts.Total++ counts.Total++
counts.BashComplete = counts.Total counts.BashComplete = counts.Total
} },
OnUsageError: func(c *Context, err error, isSubcommand bool) error {
app.OnUsageError = func(c *Context, err error, isSubcommand bool) error { counts.Total++
counts.Total++ counts.OnUsageError = counts.Total
counts.OnUsageError = counts.Total return errors.New("hay OnUsageError")
return errors.New("hay OnUsageError") },
} }
beforeNoError := func(c *Context) error { beforeNoError := func(c *Context) error {
@ -875,7 +880,7 @@ func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {
for _, flagSet := range subcommandHelpTopics { for _, flagSet := range subcommandHelpTopics {
t.Logf("==> checking with flags %v", flagSet) t.Logf("==> checking with flags %v", flagSet)
app := NewApp() app := &App{}
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
app.Writer = buf app.Writer = buf
@ -920,7 +925,7 @@ func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {
} }
func TestApp_Run_SubcommandFullPath(t *testing.T) { func TestApp_Run_SubcommandFullPath(t *testing.T) {
app := NewApp() app := &App{}
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
app.Writer = buf app.Writer = buf
app.Name = "command" app.Name = "command"
@ -953,7 +958,7 @@ func TestApp_Run_SubcommandFullPath(t *testing.T) {
} }
func TestApp_Run_SubcommandHelpName(t *testing.T) { func TestApp_Run_SubcommandHelpName(t *testing.T) {
app := NewApp() app := &App{}
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
app.Writer = buf app.Writer = buf
app.Name = "command" app.Name = "command"
@ -988,7 +993,7 @@ func TestApp_Run_SubcommandHelpName(t *testing.T) {
} }
func TestApp_Run_CommandHelpName(t *testing.T) { func TestApp_Run_CommandHelpName(t *testing.T) {
app := NewApp() app := &App{}
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
app.Writer = buf app.Writer = buf
app.Name = "command" app.Name = "command"
@ -1023,7 +1028,7 @@ func TestApp_Run_CommandHelpName(t *testing.T) {
} }
func TestApp_Run_CommandSubcommandHelpName(t *testing.T) { func TestApp_Run_CommandSubcommandHelpName(t *testing.T) {
app := NewApp() app := &App{}
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
app.Writer = buf app.Writer = buf
app.Name = "base" app.Name = "base"
@ -1065,13 +1070,14 @@ func TestApp_Run_Help(t *testing.T) {
t.Logf("==> checking with arguments %v", args) t.Logf("==> checking with arguments %v", args)
app := NewApp() app := &App{
app.Name = "boom" Name: "boom",
app.Usage = "make an explosive entrance" Usage: "make an explosive entrance",
app.Writer = buf Writer: buf,
app.Action = func(c *Context) error { Action: func(c *Context) error {
buf.WriteString("boom I say!") buf.WriteString("boom I say!")
return nil return nil
},
} }
err := app.Run(args) err := app.Run(args)
@ -1096,14 +1102,15 @@ func TestApp_Run_Version(t *testing.T) {
t.Logf("==> checking with arguments %v", args) t.Logf("==> checking with arguments %v", args)
app := NewApp() app := &App{
app.Name = "boom" Name: "boom",
app.Usage = "make an explosive entrance" Usage: "make an explosive entrance",
app.Version = "0.1.0" Version: "0.1.0",
app.Writer = buf Writer: buf,
app.Action = func(c *Context) error { Action: func(c *Context) error {
buf.WriteString("boom I say!") buf.WriteString("boom I say!")
return nil return nil
},
} }
err := app.Run(args) err := app.Run(args)
@ -1121,24 +1128,26 @@ func TestApp_Run_Version(t *testing.T) {
} }
func TestApp_Run_Categories(t *testing.T) { func TestApp_Run_Categories(t *testing.T) {
app := NewApp() buf := new(bytes.Buffer)
app.Name = "categories"
app.Commands = []*Command{ app := &App{
{ Name: "categories",
Name: "command1", Commands: []*Command{
Category: "1", {
}, Name: "command1",
{ Category: "1",
Name: "command2", },
Category: "1", {
}, Name: "command2",
{ Category: "1",
Name: "command3", },
Category: "2", {
Name: "command3",
Category: "2",
},
}, },
Writer: buf,
} }
buf := new(bytes.Buffer)
app.Writer = buf
app.Run([]string{"categories"}) app.Run([]string{"categories"})
@ -1171,24 +1180,25 @@ func TestApp_Run_Categories(t *testing.T) {
} }
func TestApp_VisibleCategories(t *testing.T) { func TestApp_VisibleCategories(t *testing.T) {
app := NewApp() app := &App{
app.Name = "visible-categories" Name: "visible-categories",
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "command1", Name: "command1",
Category: "1", Category: "1",
HelpName: "foo command1", HelpName: "foo command1",
Hidden: true, Hidden: true,
}, },
{ {
Name: "command2", Name: "command2",
Category: "2", Category: "2",
HelpName: "foo command2", HelpName: "foo command2",
}, },
{ {
Name: "command3", Name: "command3",
Category: "3", Category: "3",
HelpName: "foo command3", HelpName: "foo command3",
},
}, },
} }
@ -1210,25 +1220,26 @@ func TestApp_VisibleCategories(t *testing.T) {
app.Setup() app.Setup()
expect(t, expected, app.VisibleCategories()) expect(t, expected, app.VisibleCategories())
app = NewApp() app = &App{
app.Name = "visible-categories" Name: "visible-categories",
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "command1", Name: "command1",
Category: "1", Category: "1",
HelpName: "foo command1", HelpName: "foo command1",
Hidden: true, Hidden: true,
}, },
{ {
Name: "command2", Name: "command2",
Category: "2", Category: "2",
HelpName: "foo command2", HelpName: "foo command2",
Hidden: true, Hidden: true,
}, },
{ {
Name: "command3", Name: "command3",
Category: "3", Category: "3",
HelpName: "foo command3", HelpName: "foo command3",
},
}, },
} }
@ -1244,26 +1255,27 @@ func TestApp_VisibleCategories(t *testing.T) {
app.Setup() app.Setup()
expect(t, expected, app.VisibleCategories()) expect(t, expected, app.VisibleCategories())
app = NewApp() app = &App{
app.Name = "visible-categories" Name: "visible-categories",
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "command1", Name: "command1",
Category: "1", Category: "1",
HelpName: "foo command1", HelpName: "foo command1",
Hidden: true, Hidden: true,
}, },
{ {
Name: "command2", Name: "command2",
Category: "2", Category: "2",
HelpName: "foo command2", HelpName: "foo command2",
Hidden: true, Hidden: true,
}, },
{ {
Name: "command3", Name: "command3",
Category: "3", Category: "3",
HelpName: "foo command3", HelpName: "foo command3",
Hidden: true, Hidden: true,
},
}, },
} }
@ -1272,10 +1284,11 @@ func TestApp_VisibleCategories(t *testing.T) {
} }
func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) { func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
app := NewApp() app := &App{
app.Action = func(c *Context) error { return nil } Action: func(c *Context) error { return nil },
app.Before = func(c *Context) error { return fmt.Errorf("before error") } Before: func(c *Context) error { return fmt.Errorf("before error") },
app.After = func(c *Context) error { return fmt.Errorf("after error") } After: func(c *Context) error { return fmt.Errorf("after error") },
}
err := app.Run([]string{"foo"}) err := app.Run([]string{"foo"})
if err == nil { if err == nil {
@ -1291,17 +1304,18 @@ func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
} }
func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) { func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
app := NewApp() app := &App{
app.Commands = []*Command{ Commands: []*Command{
{ {
Subcommands: []*Command{ Subcommands: []*Command{
{ {
Name: "sub", Name: "sub",
},
}, },
Name: "bar",
Before: func(c *Context) error { return fmt.Errorf("before error") },
After: func(c *Context) error { return fmt.Errorf("after error") },
}, },
Name: "bar",
Before: func(c *Context) error { return fmt.Errorf("before error") },
After: func(c *Context) error { return fmt.Errorf("after error") },
}, },
} }
@ -1319,22 +1333,23 @@ func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
} }
func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) { func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) {
app := NewApp() app := &App{
app.Flags = []Flag{ Flags: []Flag{
&IntFlag{Name: "flag"}, &IntFlag{Name: "flag"},
} },
app.OnUsageError = func(c *Context, err error, isSubcommand bool) error { OnUsageError: func(c *Context, err error, isSubcommand bool) error {
if isSubcommand { if isSubcommand {
t.Errorf("Expect no subcommand") t.Errorf("Expect no subcommand")
} }
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err) t.Errorf("Expect an invalid value error, but got \"%v\"", err)
} }
return errors.New("intercepted: " + err.Error()) return errors.New("intercepted: " + err.Error())
} },
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "bar", Name: "bar",
},
}, },
} }
@ -1349,22 +1364,23 @@ func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) {
} }
func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) { func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) {
app := NewApp() app := &App{
app.Flags = []Flag{ Flags: []Flag{
&IntFlag{Name: "flag"}, &IntFlag{Name: "flag"},
} },
app.OnUsageError = func(c *Context, err error, isSubcommand bool) error { OnUsageError: func(c *Context, err error, isSubcommand bool) error {
if isSubcommand { if isSubcommand {
t.Errorf("Expect subcommand") t.Errorf("Expect subcommand")
} }
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err) t.Errorf("Expect an invalid value error, but got \"%v\"", err)
} }
return errors.New("intercepted: " + err.Error()) return errors.New("intercepted: " + err.Error())
} },
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "bar", Name: "bar",
},
}, },
} }

@ -292,6 +292,11 @@ def _context_parent(source):
return re.sub('\\.Parent\\(\\)', '.Lineage()[1]', source, flags=re.UNICODE) return re.sub('\\.Parent\\(\\)', '.Lineage()[1]', source, flags=re.UNICODE)
@_migrator
def _app_init(source):
return re.sub('cli\\.NewApp\\(\\)', '(&cli.App{})', source, flags=re.UNICODE)
def test_migrators(): def test_migrators():
import difflib import difflib
@ -432,6 +437,13 @@ _MIGRATOR_TESTS = (
\t\t\t\tName: "tootles", Aliases: []string{"toots", "t"}, \t\t\t\tName: "tootles", Aliases: []string{"toots", "t"},
\t\t\t}, \t\t\t},
\t\t} \t\t}
"""),
("""
\t\tapp := cli.NewApp()
\t\tapp.HideHelp = true
""", """
\t\tapp := (&cli.App{})
\t\tapp.HideHelp = true
""") """)
) )

@ -2,17 +2,18 @@
// Go applications. cli is designed to be easy to understand and write, the most simple // Go applications. cli is designed to be easy to understand and write, the most simple
// cli application can be written as follows: // cli application can be written as follows:
// func main() { // func main() {
// cli.NewApp().Run(os.Args) // (&cli.App{}).Run(os.Args)
// } // }
// //
// Of course this application does not do much, so let's make this an actual application: // Of course this application does not do much, so let's make this an actual application:
// func main() { // func main() {
// app := cli.NewApp() // app := &cli.App{
// app.Name = "greet" // Name: "greet",
// app.Usage = "say a greeting" // Usage: "say a greeting",
// app.Action = func(c *cli.Context) error { // Action: func(c *cli.Context) error {
// println("Greetings") // println("Greetings")
// } // },
// }
// //
// app.Run(os.Args) // app.Run(os.Args)
// } // }

@ -164,10 +164,11 @@ func (c *Command) HasName(name string) bool {
} }
func (c *Command) startApp(ctx *Context) error { func (c *Command) startApp(ctx *Context) error {
app := NewApp() app := &App{
app.Metadata = ctx.App.Metadata Metadata: ctx.App.Metadata,
// set the name and usage Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name),
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) }
if c.HelpName == "" { if c.HelpName == "" {
app.HelpName = c.HelpName app.HelpName = c.HelpName
} else { } else {

@ -22,8 +22,7 @@ func TestCommandFlagParsing(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
app := NewApp() app := &App{Writer: ioutil.Discard}
app.Writer = ioutil.Discard
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Parse(c.testArgs) set.Parse(c.testArgs)
@ -47,15 +46,16 @@ func TestCommandFlagParsing(t *testing.T) {
} }
func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) { func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
app := NewApp() app := &App{
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "bar", Name: "bar",
Before: func(c *Context) error { Before: func(c *Context) error {
return fmt.Errorf("before error") return fmt.Errorf("before error")
}, },
After: func(c *Context) error { After: func(c *Context) error {
return fmt.Errorf("after error") return fmt.Errorf("after error")
},
}, },
}, },
} }
@ -74,18 +74,19 @@ func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
} }
func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) { func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) {
app := NewApp() app := &App{
app.Commands = []*Command{ Commands: []*Command{
{ {
Name: "bar", Name: "bar",
Flags: []Flag{ Flags: []Flag{
&IntFlag{Name: "flag"}, &IntFlag{Name: "flag"},
}, },
OnUsageError: func(c *Context, err error, _ bool) error { OnUsageError: func(c *Context, err error, _ bool) error {
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err) t.Errorf("Expect an invalid value error, but got \"%v\"", err)
} }
return errors.New("intercepted: " + err.Error()) return errors.New("intercepted: " + err.Error())
},
}, },
}, },
} }

@ -9,8 +9,7 @@ import (
func Test_ShowAppHelp_NoAuthor(t *testing.T) { func Test_ShowAppHelp_NoAuthor(t *testing.T) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
app := NewApp() app := &App{Writer: output}
app.Writer = output
c := NewContext(app, nil, nil) c := NewContext(app, nil, nil)
@ -23,8 +22,7 @@ func Test_ShowAppHelp_NoAuthor(t *testing.T) {
func Test_ShowAppHelp_NoVersion(t *testing.T) { func Test_ShowAppHelp_NoVersion(t *testing.T) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
app := NewApp() app := &App{Writer: output}
app.Writer = output
app.Version = "" app.Version = ""
@ -39,8 +37,7 @@ func Test_ShowAppHelp_NoVersion(t *testing.T) {
func Test_ShowAppHelp_HideVersion(t *testing.T) { func Test_ShowAppHelp_HideVersion(t *testing.T) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
app := NewApp() app := &App{Writer: output}
app.Writer = output
app.HideVersion = true app.HideVersion = true
@ -116,7 +113,7 @@ func Test_Version_Custom_Flags(t *testing.T) {
} }
func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) { func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) {
app := NewApp() app := &App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Parse([]string{"foo"}) set.Parse([]string{"foo"})
@ -144,7 +141,7 @@ func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) {
} }
func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) { func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
app := NewApp() app := &App{}
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Parse([]string{"foo"}) set.Parse([]string{"foo"})

Loading…
Cancel
Save