Merge remote-tracking branch 'origin/master' into multi-env-var

This commit is contained in:
Dan Buch 2014-12-01 22:44:36 -05:00
commit dca23da84b
5 changed files with 64 additions and 15 deletions

View File

@ -68,8 +68,9 @@ Running this already gives you a ton of functionality, plus support for things l
Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness! Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness!
Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
``` go ``` go
/* greet.go */
package main package main
import ( import (
@ -84,7 +85,7 @@ func main() {
app.Action = func(c *cli.Context) { app.Action = func(c *cli.Context) {
println("Hello friend!") println("Hello friend!")
} }
app.Run(os.Args) app.Run(os.Args)
} }
``` ```
@ -260,7 +261,7 @@ app.Commands = []cli.Command{
return return
} }
for _, t := range tasks { for _, t := range tasks {
println(t) fmt.Println(t)
} }
}, },
} }
@ -282,6 +283,3 @@ Feel free to put up a pull request to fix a bug or maybe add a feature. I will g
If you are have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together. If you are have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together.
If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out. If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out.
## About
cli.go is written by none other than the [Code Gangsta](http://codegangsta.io)

7
app.go
View File

@ -24,6 +24,8 @@ type App struct {
EnableBashCompletion bool EnableBashCompletion bool
// Boolean to hide built-in help command // Boolean to hide built-in help command
HideHelp bool HideHelp bool
// Boolean to hide built-in version flag
HideVersion bool
// An action to execute when the bash-completion flag is set // An action to execute when the bash-completion flag is set
BashComplete func(context *Context) BashComplete func(context *Context)
// An action to execute before any subcommands are run, but after the context is ready // An action to execute before any subcommands are run, but after the context is ready
@ -75,7 +77,10 @@ func (a *App) Run(arguments []string) error {
if a.EnableBashCompletion { if a.EnableBashCompletion {
a.appendFlag(BashCompletionFlag) a.appendFlag(BashCompletionFlag)
} }
a.appendFlag(VersionFlag)
if !a.HideVersion {
a.appendFlag(VersionFlag)
}
// parse flags // parse flags
set := flagSet(a.Name, a.Flags) set := flagSet(a.Name, a.Flags)

View File

@ -13,11 +13,12 @@ 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 App *App
Command Command Command Command
flagSet *flag.FlagSet flagSet *flag.FlagSet
globalSet *flag.FlagSet globalSet *flag.FlagSet
setFlags map[string]bool setFlags map[string]bool
globalSetFlags map[string]bool
} }
// Creates a new context. For use in when invoking an App or Command action. // Creates a new context. For use in when invoking an App or Command action.
@ -105,7 +106,7 @@ func (c *Context) GlobalGeneric(name string) interface{} {
return lookupGeneric(name, c.globalSet) return lookupGeneric(name, c.globalSet)
} }
// Determines if the flag was actually set exists // Determines if the flag was actually set
func (c *Context) IsSet(name string) bool { func (c *Context) IsSet(name string) bool {
if c.setFlags == nil { if c.setFlags == nil {
c.setFlags = make(map[string]bool) c.setFlags = make(map[string]bool)
@ -116,6 +117,17 @@ func (c *Context) IsSet(name string) bool {
return c.setFlags[name] == true return c.setFlags[name] == true
} }
// Determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool {
if c.globalSetFlags == nil {
c.globalSetFlags = make(map[string]bool)
c.globalSet.Visit(func(f *flag.Flag) {
c.globalSetFlags[f.Name] = true
})
}
return c.globalSetFlags[name] == true
}
// Returns a slice of flag names used in this context. // Returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) { func (c *Context) FlagNames() (names []string) {
for _, flag := range c.Command.Flags { for _, flag := range c.Command.Flags {
@ -128,6 +140,18 @@ func (c *Context) FlagNames() (names []string) {
return return
} }
// Returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) {
for _, flag := range c.App.Flags {
name := strings.Split(flag.getName(), ",")[0]
if name == "help" || name == "version" {
continue
}
names = append(names, name)
}
return
}
type Args []string type Args []string
// Returns the command line arguments associated with the context. // Returns the command line arguments associated with the context.

View File

@ -69,9 +69,31 @@ func TestContext_IsSet(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc") set.Bool("myflag", false, "doc")
set.String("otherflag", "hello world", "doc") set.String("otherflag", "hello world", "doc")
c := cli.NewContext(nil, set, set) globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("myflagGlobal", true, "doc")
c := cli.NewContext(nil, set, globalSet)
set.Parse([]string{"--myflag", "bat", "baz"}) set.Parse([]string{"--myflag", "bat", "baz"})
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
expect(t, c.IsSet("myflag"), true) expect(t, c.IsSet("myflag"), true)
expect(t, c.IsSet("otherflag"), false) expect(t, c.IsSet("otherflag"), false)
expect(t, c.IsSet("bogusflag"), false) expect(t, c.IsSet("bogusflag"), false)
expect(t, c.IsSet("myflagGlobal"), false)
}
func TestContext_GlobalIsSet(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
set.String("otherflag", "hello world", "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("myflagGlobal", true, "doc")
globalSet.Bool("myflagGlobalUnset", true, "doc")
c := cli.NewContext(nil, set, globalSet)
set.Parse([]string{"--myflag", "bat", "baz"})
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
expect(t, c.GlobalIsSet("myflag"), false)
expect(t, c.GlobalIsSet("otherflag"), false)
expect(t, c.GlobalIsSet("bogusflag"), false)
expect(t, c.GlobalIsSet("myflagGlobal"), true)
expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
expect(t, c.GlobalIsSet("bogusGlobal"), false)
} }

View File

@ -206,7 +206,7 @@ func checkSubcommandHelp(c *Context) bool {
} }
func checkCompletions(c *Context) bool { func checkCompletions(c *Context) bool {
if c.GlobalBool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
ShowCompletions(c) ShowCompletions(c)
return true return true
} }