Merge remote-tracking branch 'origin/master' into coverage
This commit is contained in:
commit
2b4b13096f
@ -3,6 +3,8 @@
|
||||
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.17.0] - 2016-05-09
|
||||
### Added
|
||||
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
|
||||
- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
|
||||
@ -21,6 +23,8 @@
|
||||
(previously they printed "No help topic for...", but still exited 0. This
|
||||
makes it easier to script around apps built using `cli` since they can trust
|
||||
that a 0 exit code indicated a successful execution.
|
||||
- cleanups based on [Go Report Card
|
||||
feedback](https://goreportcard.com/report/github.com/codegangsta/cli)
|
||||
|
||||
## [1.16.0] - 2016-05-02
|
||||
### Added
|
||||
@ -280,7 +284,8 @@ signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
||||
### Added
|
||||
- Initial implementation.
|
||||
|
||||
[Unreleased]: https://github.com/codegangsta/cli/compare/v1.16.0...HEAD
|
||||
[Unreleased]: https://github.com/codegangsta/cli/compare/v1.17.0...HEAD
|
||||
[1.17.0]: https://github.com/codegangsta/cli/compare/v1.16.0...v1.17.0
|
||||
[1.16.0]: https://github.com/codegangsta/cli/compare/v1.15.0...v1.16.0
|
||||
[1.15.0]: https://github.com/codegangsta/cli/compare/v1.14.0...v1.15.0
|
||||
[1.14.0]: https://github.com/codegangsta/cli/compare/v1.13.0...v1.14.0
|
||||
|
27
app.go
27
app.go
@ -51,7 +51,7 @@ type App struct {
|
||||
HideHelp bool
|
||||
// Boolean to hide built-in version flag and the VERSION section of help
|
||||
HideVersion bool
|
||||
// Populate on app startup, only gettable throught method Categories()
|
||||
// Populate on app startup, only gettable through method Categories()
|
||||
categories CommandCategories
|
||||
// An action to execute when the bash-completion flag is set
|
||||
BashComplete BashCompleteFunc
|
||||
@ -100,7 +100,8 @@ func compileTime() time.Time {
|
||||
return info.ModTime()
|
||||
}
|
||||
|
||||
// Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
|
||||
// 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]),
|
||||
@ -162,7 +163,8 @@ func (a *App) Setup() {
|
||||
}
|
||||
}
|
||||
|
||||
// Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
|
||||
// Run is the entry point to the cli app. Parses the arguments slice and routes
|
||||
// to the proper flag/args combination
|
||||
func (a *App) Run(arguments []string) (err error) {
|
||||
a.Setup()
|
||||
|
||||
@ -187,11 +189,10 @@ func (a *App) Run(arguments []string) (err error) {
|
||||
err := a.OnUsageError(context, err, false)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
} else {
|
||||
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
|
||||
ShowAppHelp(context)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
|
||||
ShowAppHelp(context)
|
||||
return err
|
||||
}
|
||||
|
||||
if !a.HideHelp && checkHelp(context) {
|
||||
@ -254,7 +255,8 @@ func (a *App) RunAndExitOnError() {
|
||||
}
|
||||
}
|
||||
|
||||
// Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
|
||||
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
|
||||
// generate command-specific flags
|
||||
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
// append help to commands
|
||||
if len(a.Commands) > 0 {
|
||||
@ -307,11 +309,10 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
err = a.OnUsageError(context, err, true)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
} else {
|
||||
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
|
||||
ShowSubcommandHelp(context)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
|
||||
ShowSubcommandHelp(context)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(a.Commands) > 0 {
|
||||
@ -363,7 +364,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Returns the named command on App. Returns nil if the command does not exist
|
||||
// Command returns the named command on App. Returns nil if the command does not exist
|
||||
func (a *App) Command(name string) *Command {
|
||||
for _, c := range a.Commands {
|
||||
if c.HasName(name) {
|
||||
|
52
app_test.go
52
app_test.go
@ -33,7 +33,7 @@ func ExampleApp_Run() {
|
||||
app.UsageText = "app [first_arg] [second_arg]"
|
||||
app.Author = "Harrison"
|
||||
app.Email = "harrison@lolwut.com"
|
||||
app.Authors = []Author{Author{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
|
||||
app.Authors = []Author{{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// Hello Jeremy
|
||||
@ -307,12 +307,12 @@ func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
|
||||
func TestApp_VisibleCommands(t *testing.T) {
|
||||
app := NewApp()
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "frob",
|
||||
HelpName: "foo frob",
|
||||
Action: func(_ *Context) error { return nil },
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "frib",
|
||||
HelpName: "foo frib",
|
||||
Hidden: true,
|
||||
@ -517,7 +517,7 @@ func TestApp_BeforeFunc(t *testing.T) {
|
||||
}
|
||||
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "sub",
|
||||
Action: func(c *Context) error {
|
||||
counts.Total++
|
||||
@ -609,7 +609,7 @@ func TestApp_AfterFunc(t *testing.T) {
|
||||
}
|
||||
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "sub",
|
||||
Action: func(c *Context) error {
|
||||
counts.Total++
|
||||
@ -724,7 +724,7 @@ func TestApp_CommandNotFound(t *testing.T) {
|
||||
}
|
||||
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Action: func(c *Context) error {
|
||||
counts.Total++
|
||||
@ -791,7 +791,7 @@ func TestApp_OrderOfOperations(t *testing.T) {
|
||||
|
||||
app.After = afterNoError
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Action: func(c *Context) error {
|
||||
counts.Total++
|
||||
@ -1126,15 +1126,15 @@ func TestApp_Run_Categories(t *testing.T) {
|
||||
app := NewApp()
|
||||
app.Name = "categories"
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "command1",
|
||||
Category: "1",
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command2",
|
||||
Category: "1",
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command3",
|
||||
Category: "2",
|
||||
},
|
||||
@ -1175,18 +1175,18 @@ func TestApp_VisibleCategories(t *testing.T) {
|
||||
app := NewApp()
|
||||
app.Name = "visible-categories"
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "command1",
|
||||
Category: "1",
|
||||
HelpName: "foo command1",
|
||||
Hidden: true,
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command2",
|
||||
Category: "2",
|
||||
HelpName: "foo command2",
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command3",
|
||||
Category: "3",
|
||||
HelpName: "foo command3",
|
||||
@ -1194,13 +1194,13 @@ func TestApp_VisibleCategories(t *testing.T) {
|
||||
}
|
||||
|
||||
expected := []*CommandCategory{
|
||||
&CommandCategory{
|
||||
{
|
||||
Name: "2",
|
||||
Commands: []Command{
|
||||
app.Commands[1],
|
||||
},
|
||||
},
|
||||
&CommandCategory{
|
||||
{
|
||||
Name: "3",
|
||||
Commands: []Command{
|
||||
app.Commands[2],
|
||||
@ -1214,19 +1214,19 @@ func TestApp_VisibleCategories(t *testing.T) {
|
||||
app = NewApp()
|
||||
app.Name = "visible-categories"
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "command1",
|
||||
Category: "1",
|
||||
HelpName: "foo command1",
|
||||
Hidden: true,
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command2",
|
||||
Category: "2",
|
||||
HelpName: "foo command2",
|
||||
Hidden: true,
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command3",
|
||||
Category: "3",
|
||||
HelpName: "foo command3",
|
||||
@ -1234,7 +1234,7 @@ func TestApp_VisibleCategories(t *testing.T) {
|
||||
}
|
||||
|
||||
expected = []*CommandCategory{
|
||||
&CommandCategory{
|
||||
{
|
||||
Name: "3",
|
||||
Commands: []Command{
|
||||
app.Commands[2],
|
||||
@ -1248,19 +1248,19 @@ func TestApp_VisibleCategories(t *testing.T) {
|
||||
app = NewApp()
|
||||
app.Name = "visible-categories"
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "command1",
|
||||
Category: "1",
|
||||
HelpName: "foo command1",
|
||||
Hidden: true,
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command2",
|
||||
Category: "2",
|
||||
HelpName: "foo command2",
|
||||
Hidden: true,
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "command3",
|
||||
Category: "3",
|
||||
HelpName: "foo command3",
|
||||
@ -1296,9 +1296,9 @@ func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
|
||||
func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
|
||||
app := NewApp()
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Subcommands: []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "sub",
|
||||
},
|
||||
},
|
||||
@ -1336,7 +1336,7 @@ func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) {
|
||||
return errors.New("intercepted: " + err.Error())
|
||||
}
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
}
|
||||
@ -1366,7 +1366,7 @@ func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) {
|
||||
return errors.New("intercepted: " + err.Error())
|
||||
}
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
package cli
|
||||
|
||||
// CommandCategories is a slice of *CommandCategory.
|
||||
type CommandCategories []*CommandCategory
|
||||
|
||||
// CommandCategory is a category containing commands.
|
||||
type CommandCategory struct {
|
||||
Name string
|
||||
Commands Commands
|
||||
@ -19,6 +21,7 @@ func (c CommandCategories) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
||||
|
||||
// AddCommand adds a command to a category.
|
||||
func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
|
||||
for _, commandCategory := range c {
|
||||
if commandCategory.Name == category {
|
||||
|
17
command.go
17
command.go
@ -56,7 +56,7 @@ type Command struct {
|
||||
commandNamePath []string
|
||||
}
|
||||
|
||||
// Returns the full name of the command.
|
||||
// FullName returns the full name of the command.
|
||||
// For subcommands this ensures that parent commands are part of the command path
|
||||
func (c Command) FullName() string {
|
||||
if c.commandNamePath == nil {
|
||||
@ -65,9 +65,10 @@ func (c Command) FullName() string {
|
||||
return strings.Join(c.commandNamePath, " ")
|
||||
}
|
||||
|
||||
// Commands is a slice of Command
|
||||
type Commands []Command
|
||||
|
||||
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
||||
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
||||
func (c Command) Run(ctx *Context) (err error) {
|
||||
if len(c.Subcommands) > 0 {
|
||||
return c.startApp(ctx)
|
||||
@ -131,12 +132,11 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||
err := c.OnUsageError(ctx, err, false)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
} else {
|
||||
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
nerr := normalizeFlags(c.Flags, set)
|
||||
@ -191,6 +191,7 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Names returns the names including short names and aliases.
|
||||
func (c Command) Names() []string {
|
||||
names := []string{c.Name}
|
||||
|
||||
@ -201,7 +202,7 @@ func (c Command) Names() []string {
|
||||
return append(names, c.Aliases...)
|
||||
}
|
||||
|
||||
// Returns true if Command.Name or Command.ShortName matches given name
|
||||
// HasName returns true if Command.Name or Command.ShortName matches given name
|
||||
func (c Command) HasName(name string) bool {
|
||||
for _, n := range c.Names() {
|
||||
if n == name {
|
||||
|
@ -49,7 +49,7 @@ func TestCommandFlagParsing(t *testing.T) {
|
||||
func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
|
||||
app := NewApp()
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Before: func(c *Context) error {
|
||||
return fmt.Errorf("before error")
|
||||
@ -76,7 +76,7 @@ func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
|
||||
func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) {
|
||||
app := NewApp()
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Flags: []Flag{
|
||||
IntFlag{Name: "flag"},
|
||||
|
79
context.go
79
context.go
@ -21,57 +21,62 @@ type Context struct {
|
||||
parentContext *Context
|
||||
}
|
||||
|
||||
// Creates a new context. For use in when invoking an App or Command action.
|
||||
// NewContext creates a new context. For use in when invoking an App or Command action.
|
||||
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
|
||||
return &Context{App: app, flagSet: set, parentContext: parentCtx}
|
||||
}
|
||||
|
||||
// Looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
// Int looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Int(name string) int {
|
||||
return lookupInt(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
|
||||
// Duration looks up the value of a local time.Duration flag, returns 0 if no
|
||||
// time.Duration flag exists
|
||||
func (c *Context) Duration(name string) time.Duration {
|
||||
return lookupDuration(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
|
||||
// Float64 looks up the value of a local float64 flag, returns 0 if no float64
|
||||
// flag exists
|
||||
func (c *Context) Float64(name string) float64 {
|
||||
return lookupFloat64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local bool flag, returns false if no bool flag exists
|
||||
// Bool looks up the value of a local bool flag, returns false if no bool flag exists
|
||||
func (c *Context) Bool(name string) bool {
|
||||
return lookupBool(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local boolT flag, returns false if no bool flag exists
|
||||
// BoolT looks up the value of a local boolT flag, returns false if no bool flag exists
|
||||
func (c *Context) BoolT(name string) bool {
|
||||
return lookupBoolT(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local string flag, returns "" if no string flag exists
|
||||
// String looks up the value of a local string flag, returns "" if no string flag exists
|
||||
func (c *Context) String(name string) string {
|
||||
return lookupString(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
|
||||
// StringSlice looks up the value of a local string slice flag, returns nil if no
|
||||
// string slice flag exists
|
||||
func (c *Context) StringSlice(name string) []string {
|
||||
return lookupStringSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
|
||||
// IntSlice looks up the value of a local int slice flag, returns nil if no int
|
||||
// slice flag exists
|
||||
func (c *Context) IntSlice(name string) []int {
|
||||
return lookupIntSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local generic flag, returns nil if no generic flag exists
|
||||
// Generic looks up the value of a local generic flag, returns nil if no generic
|
||||
// flag exists
|
||||
func (c *Context) Generic(name string) interface{} {
|
||||
return lookupGeneric(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
// GlobalInt looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalInt(name string) int {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt(name, fs)
|
||||
@ -79,8 +84,8 @@ func (c *Context) GlobalInt(name string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Looks up the value of a global float64 flag, returns float64(0) if no float64
|
||||
// flag exists
|
||||
// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0)
|
||||
// if no float64 flag exists
|
||||
func (c *Context) GlobalFloat64(name string) float64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupFloat64(name, fs)
|
||||
@ -88,7 +93,8 @@ func (c *Context) GlobalFloat64(name string) float64 {
|
||||
return float64(0)
|
||||
}
|
||||
|
||||
// Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
|
||||
// GlobalDuration looks up the value of a global time.Duration flag, returns 0
|
||||
// if no time.Duration flag exists
|
||||
func (c *Context) GlobalDuration(name string) time.Duration {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupDuration(name, fs)
|
||||
@ -96,7 +102,8 @@ func (c *Context) GlobalDuration(name string) time.Duration {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Looks up the value of a global bool flag, returns false if no bool flag exists
|
||||
// GlobalBool looks up the value of a global bool flag, returns false if no bool
|
||||
// flag exists
|
||||
func (c *Context) GlobalBool(name string) bool {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupBool(name, fs)
|
||||
@ -104,7 +111,8 @@ func (c *Context) GlobalBool(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Looks up the value of a global bool flag, returns true if no bool flag exists
|
||||
// GlobalBoolT looks up the value of a global bool flag, returns true if no bool
|
||||
// flag exists
|
||||
func (c *Context) GlobalBoolT(name string) bool {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupBoolT(name, fs)
|
||||
@ -112,7 +120,8 @@ func (c *Context) GlobalBoolT(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Looks up the value of a global string flag, returns "" if no string flag exists
|
||||
// GlobalString looks up the value of a global string flag, returns "" if no
|
||||
// string flag exists
|
||||
func (c *Context) GlobalString(name string) string {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupString(name, fs)
|
||||
@ -120,7 +129,8 @@ func (c *Context) GlobalString(name string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
|
||||
// GlobalStringSlice looks up the value of a global string slice flag, returns
|
||||
// nil if no string slice flag exists
|
||||
func (c *Context) GlobalStringSlice(name string) []string {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupStringSlice(name, fs)
|
||||
@ -128,7 +138,8 @@ func (c *Context) GlobalStringSlice(name string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
|
||||
// GlobalIntSlice looks up the value of a global int slice flag, returns nil if
|
||||
// no int slice flag exists
|
||||
func (c *Context) GlobalIntSlice(name string) []int {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupIntSlice(name, fs)
|
||||
@ -136,7 +147,8 @@ func (c *Context) GlobalIntSlice(name string) []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Looks up the value of a global generic flag, returns nil if no generic flag exists
|
||||
// GlobalGeneric looks up the value of a global generic flag, returns nil if no
|
||||
// generic flag exists
|
||||
func (c *Context) GlobalGeneric(name string) interface{} {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupGeneric(name, fs)
|
||||
@ -144,7 +156,7 @@ func (c *Context) GlobalGeneric(name string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns the number of flags set
|
||||
// NumFlags returns the number of flags set
|
||||
func (c *Context) NumFlags() int {
|
||||
return c.flagSet.NFlag()
|
||||
}
|
||||
@ -159,7 +171,7 @@ func (c *Context) GlobalSet(name, value string) error {
|
||||
return globalContext(c).flagSet.Set(name, value)
|
||||
}
|
||||
|
||||
// Determines if the flag was actually set
|
||||
// IsSet determines if the flag was actually set
|
||||
func (c *Context) IsSet(name string) bool {
|
||||
if c.setFlags == nil {
|
||||
c.setFlags = make(map[string]bool)
|
||||
@ -170,7 +182,7 @@ func (c *Context) IsSet(name string) bool {
|
||||
return c.setFlags[name] == true
|
||||
}
|
||||
|
||||
// Determines if the global flag was actually set
|
||||
// GlobalIsSet 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)
|
||||
@ -187,7 +199,7 @@ func (c *Context) GlobalIsSet(name string) bool {
|
||||
return c.globalSetFlags[name]
|
||||
}
|
||||
|
||||
// Returns a slice of flag names used in this context.
|
||||
// FlagNames returns a slice of flag names used in this context.
|
||||
func (c *Context) FlagNames() (names []string) {
|
||||
for _, flag := range c.Command.Flags {
|
||||
name := strings.Split(flag.GetName(), ",")[0]
|
||||
@ -199,7 +211,7 @@ func (c *Context) FlagNames() (names []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// Returns a slice of global flag names used by the app.
|
||||
// GlobalFlagNames 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]
|
||||
@ -211,25 +223,26 @@ func (c *Context) GlobalFlagNames() (names []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// Returns the parent context, if any
|
||||
// Parent returns the parent context, if any
|
||||
func (c *Context) Parent() *Context {
|
||||
return c.parentContext
|
||||
}
|
||||
|
||||
// Args contains apps console arguments
|
||||
type Args []string
|
||||
|
||||
// Returns the command line arguments associated with the context.
|
||||
// Args returns the command line arguments associated with the context.
|
||||
func (c *Context) Args() Args {
|
||||
args := Args(c.flagSet.Args())
|
||||
return args
|
||||
}
|
||||
|
||||
// Returns the number of the command line arguments.
|
||||
// NArg returns the number of the command line arguments.
|
||||
func (c *Context) NArg() int {
|
||||
return len(c.Args())
|
||||
}
|
||||
|
||||
// Returns the nth argument, or else a blank string
|
||||
// Get returns the nth argument, or else a blank string
|
||||
func (a Args) Get(n int) string {
|
||||
if len(a) > n {
|
||||
return a[n]
|
||||
@ -237,12 +250,12 @@ func (a Args) Get(n int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Returns the first argument, or else a blank string
|
||||
// First returns the first argument, or else a blank string
|
||||
func (a Args) First() string {
|
||||
return a.Get(0)
|
||||
}
|
||||
|
||||
// Return the rest of the arguments (not the first one)
|
||||
// Tail returns the rest of the arguments (not the first one)
|
||||
// or else an empty string slice
|
||||
func (a Args) Tail() []string {
|
||||
if len(a) >= 2 {
|
||||
@ -251,12 +264,12 @@ func (a Args) Tail() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Checks if there are any arguments present
|
||||
// Present checks if there are any arguments present
|
||||
func (a Args) Present() bool {
|
||||
return len(a) != 0
|
||||
}
|
||||
|
||||
// Swaps arguments at the given indexes
|
||||
// Swap swaps arguments at the given indexes
|
||||
func (a Args) Swap(from, to int) error {
|
||||
if from >= len(a) || to >= len(a) {
|
||||
return errors.New("index out of range")
|
||||
|
@ -199,7 +199,7 @@ func TestContext_GlobalFlagsInSubcommands(t *testing.T) {
|
||||
}
|
||||
|
||||
app.Commands = []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "foo",
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "parent, p", Usage: "Parent flag"},
|
||||
|
@ -7,20 +7,24 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
|
||||
var OsExiter = os.Exit
|
||||
|
||||
// ErrWriter is used to write errors to the user. This can be anything
|
||||
// implementing the io.Writer interface and defaults to os.Stderr.
|
||||
var ErrWriter io.Writer = os.Stderr
|
||||
|
||||
// MultiError is an error that wraps multiple errors.
|
||||
type MultiError struct {
|
||||
Errors []error
|
||||
}
|
||||
|
||||
// NewMultiError creates a new MultiError. Pass in one or more errors.
|
||||
func NewMultiError(err ...error) MultiError {
|
||||
return MultiError{Errors: err}
|
||||
}
|
||||
|
||||
// Error implents the error interface.
|
||||
func (m MultiError) Error() string {
|
||||
errs := make([]string, len(m.Errors))
|
||||
for i, err := range m.Errors {
|
||||
|
24
flag.go
24
flag.go
@ -13,19 +13,19 @@ import (
|
||||
|
||||
const defaultPlaceholder = "value"
|
||||
|
||||
// This flag enables bash-completion for all commands and subcommands
|
||||
// BashCompletionFlag enables bash-completion for all commands and subcommands
|
||||
var BashCompletionFlag = BoolFlag{
|
||||
Name: "generate-bash-completion",
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
// This flag prints the version for the application
|
||||
// VersionFlag prints the version for the application
|
||||
var VersionFlag = BoolFlag{
|
||||
Name: "version, v",
|
||||
Usage: "print the version",
|
||||
}
|
||||
|
||||
// This flag prints the help for all commands and subcommands
|
||||
// HelpFlag prints the help for all commands and subcommands
|
||||
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
||||
// unless HideHelp is set to true)
|
||||
var HelpFlag = BoolFlag{
|
||||
@ -33,6 +33,8 @@ var HelpFlag = BoolFlag{
|
||||
Usage: "show help",
|
||||
}
|
||||
|
||||
// FlagStringer converts a flag definition to a string. This is used by help
|
||||
// to display a flag.
|
||||
var FlagStringer FlagStringFunc = stringifyFlag
|
||||
|
||||
// Flag is a common interface related to parsing flags in cli.
|
||||
@ -103,6 +105,7 @@ func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of a flag.
|
||||
func (f GenericFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -126,7 +129,7 @@ func (f *StringSlice) Value() []string {
|
||||
return *f
|
||||
}
|
||||
|
||||
// StringSlice is a string flag that can be specified multiple times on the
|
||||
// StringSliceFlag is a string flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type StringSliceFlag struct {
|
||||
Name string
|
||||
@ -166,11 +169,12 @@ func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of a flag.
|
||||
func (f StringSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// StringSlice is an opaque type for []int to satisfy flag.Value
|
||||
// IntSlice is an opaque type for []int to satisfy flag.Value
|
||||
type IntSlice []int
|
||||
|
||||
// Set parses the value into an integer and appends it to the list of values
|
||||
@ -178,9 +182,8 @@ func (f *IntSlice) Set(value string) error {
|
||||
tmp, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
*f = append(*f, tmp)
|
||||
}
|
||||
*f = append(*f, tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -237,6 +240,7 @@ func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f IntSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -280,6 +284,7 @@ func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f BoolFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -324,6 +329,7 @@ func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f BoolTFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -364,6 +370,7 @@ func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f StringFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -408,6 +415,7 @@ func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f IntFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -452,6 +460,7 @@ func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f DurationFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
@ -495,6 +504,7 @@ func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Float64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
16
funcs.go
16
funcs.go
@ -1,23 +1,23 @@
|
||||
package cli
|
||||
|
||||
// An action to execute when the bash-completion flag is set
|
||||
// BashCompleteFunc is an action to execute when the bash-completion flag is set
|
||||
type BashCompleteFunc func(*Context)
|
||||
|
||||
// An action to execute before any subcommands are run, but after the context is ready
|
||||
// If a non-nil error is returned, no subcommands are run
|
||||
// BeforeFunc is an action to execute before any subcommands are run, but after
|
||||
// the context is ready if a non-nil error is returned, no subcommands are run
|
||||
type BeforeFunc func(*Context) error
|
||||
|
||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||
// It is run even if Action() panics
|
||||
// AfterFunc is an action to execute after any subcommands are run, but after the
|
||||
// subcommand has finished it is run even if Action() panics
|
||||
type AfterFunc func(*Context) error
|
||||
|
||||
// The action to execute when no subcommands are specified
|
||||
// ActionFunc is the action to execute when no subcommands are specified
|
||||
type ActionFunc func(*Context) error
|
||||
|
||||
// Execute this function if the proper command cannot be found
|
||||
// CommandNotFoundFunc is executed if the proper command cannot be found
|
||||
type CommandNotFoundFunc func(*Context, string)
|
||||
|
||||
// Execute this function if an usage error occurs. This is useful for displaying
|
||||
// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
|
||||
// customized usage error messages. This function is able to replace the
|
||||
// original error messages. If this function is not set, the "Incorrect usage"
|
||||
// is displayed and the execution is interrupted.
|
||||
|
24
help.go
24
help.go
@ -9,7 +9,7 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// The text template for the Default help topic.
|
||||
// AppHelpTemplate is the text template for the Default help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var AppHelpTemplate = `NAME:
|
||||
@ -36,7 +36,7 @@ COPYRIGHT:
|
||||
{{end}}
|
||||
`
|
||||
|
||||
// The text template for the command help topic.
|
||||
// CommandHelpTemplate is the text template for the command help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var CommandHelpTemplate = `NAME:
|
||||
@ -56,7 +56,7 @@ OPTIONS:
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
// The text template for the subcommand help topic.
|
||||
// SubcommandHelpTemplate is the text template for the subcommand help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var SubcommandHelpTemplate = `NAME:
|
||||
@ -108,16 +108,20 @@ var helpSubcommand = Command{
|
||||
// Prints help for the App or Command
|
||||
type helpPrinter func(w io.Writer, templ string, data interface{})
|
||||
|
||||
// HelpPrinter is a function that writes the help output. If not set a default
|
||||
// is used. The function signature is:
|
||||
// func(w io.Writer, templ string, data interface{})
|
||||
var HelpPrinter helpPrinter = printHelp
|
||||
|
||||
// Prints version for the App
|
||||
// VersionPrinter prints the version for the App
|
||||
var VersionPrinter = printVersion
|
||||
|
||||
// ShowAppHelp is an action that displays the help.
|
||||
func ShowAppHelp(c *Context) {
|
||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
||||
}
|
||||
|
||||
// Prints the list of subcommands as the default app completion method
|
||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||
func DefaultAppComplete(c *Context) {
|
||||
for _, command := range c.App.Commands {
|
||||
if command.Hidden {
|
||||
@ -129,7 +133,7 @@ func DefaultAppComplete(c *Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Prints help for the given command
|
||||
// ShowCommandHelp prints help for the given command
|
||||
func ShowCommandHelp(ctx *Context, command string) error {
|
||||
// show the subcommand help for a command with subcommands
|
||||
if command == "" {
|
||||
@ -152,12 +156,12 @@ func ShowCommandHelp(ctx *Context, command string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Prints help for the given subcommand
|
||||
// ShowSubcommandHelp prints help for the given subcommand
|
||||
func ShowSubcommandHelp(c *Context) error {
|
||||
return ShowCommandHelp(c, c.Command.Name)
|
||||
}
|
||||
|
||||
// Prints the version number of the App
|
||||
// ShowVersion prints the version number of the App
|
||||
func ShowVersion(c *Context) {
|
||||
VersionPrinter(c)
|
||||
}
|
||||
@ -166,7 +170,7 @@ func printVersion(c *Context) {
|
||||
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
|
||||
}
|
||||
|
||||
// Prints the lists of commands within a given context
|
||||
// ShowCompletions prints the lists of commands within a given context
|
||||
func ShowCompletions(c *Context) {
|
||||
a := c.App
|
||||
if a != nil && a.BashComplete != nil {
|
||||
@ -174,7 +178,7 @@ func ShowCompletions(c *Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the custom completions for a given command
|
||||
// ShowCommandCompletions prints the custom completions for a given command
|
||||
func ShowCommandCompletions(ctx *Context, command string) {
|
||||
c := ctx.App.Command(command)
|
||||
if c != nil && c.BashComplete != nil {
|
||||
|
@ -172,13 +172,13 @@ func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
|
||||
func TestShowAppHelp_HiddenCommand(t *testing.T) {
|
||||
app := &App{
|
||||
Commands: []Command{
|
||||
Command{
|
||||
{
|
||||
Name: "frobbly",
|
||||
Action: func(ctx *Context) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
Command{
|
||||
{
|
||||
Name: "secretfrob",
|
||||
Hidden: true,
|
||||
Action: func(ctx *Context) error {
|
||||
|
Loading…
Reference in New Issue
Block a user