Rework of hidden flag impl plus some Action func corrections

This commit is contained in:
Dan Buch 2016-05-01 08:36:17 -04:00
parent 99431669d0
commit fed78b8bab
No known key found for this signature in database
GPG Key ID: FAEF12936DD3E3EC
7 changed files with 62 additions and 92 deletions

View File

@ -302,6 +302,7 @@ Here is a more complete sample of a command using YAML support:
Description: "testing", Description: "testing",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
// Action to run // Action to run
return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test"}), NewIntFlag(cli.IntFlag{Name: "test"}),
@ -322,16 +323,18 @@ 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) { Action: func(c *cli.Context) error {
fmt.Println("added task: ", c.Args().First()) fmt.Println("added task: ", c.Args().First())
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) { Action: func(c *cli.Context) error {
fmt.Println("completed task: ", c.Args().First()) fmt.Println("completed task: ", c.Args().First())
return nil
}, },
}, },
{ {
@ -342,15 +345,17 @@ app.Commands = []cli.Command{
{ {
Name: "add", Name: "add",
Usage: "add a new template", Usage: "add a new template",
Action: func(c *cli.Context) { Action: func(c *cli.Context) error {
fmt.Println("new task template: ", c.Args().First()) fmt.Println("new task template: ", c.Args().First())
return nil
}, },
}, },
{ {
Name: "remove", Name: "remove",
Usage: "remove an existing template", Usage: "remove an existing template",
Action: func(c *cli.Context) { Action: func(c *cli.Context) error {
fmt.Println("removed task template: ", c.Args().First()) fmt.Println("removed task template: ", c.Args().First())
return nil
}, },
}, },
}, },
@ -450,8 +455,9 @@ app.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) { Action: func(c *cli.Context) error {
fmt.Println("completed task: ", c.Args().First()) fmt.Println("completed task: ", c.Args().First())
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

View File

@ -97,9 +97,10 @@ func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) {
Aliases: []string{"tc"}, Aliases: []string{"tc"},
Usage: "this is for testing", Usage: "this is for testing",
Description: "testing", Description: "testing",
Action: func(c *cli.Context) { Action: func(c *cli.Context) error {
val := c.Int("top.test") val := c.Int("top.test")
expect(t, val, 10) expect(t, val, 10)
return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}), NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}),
@ -161,9 +162,10 @@ func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) {
Aliases: []string{"tc"}, Aliases: []string{"tc"},
Usage: "this is for testing", Usage: "this is for testing",
Description: "testing", Description: "testing",
Action: func(c *cli.Context) { Action: func(c *cli.Context) error {
val := c.Int("top.test") val := c.Int("top.test")
expect(t, val, 7) expect(t, val, 7)
return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test"}), NewIntFlag(cli.IntFlag{Name: "top.test"}),
@ -225,9 +227,10 @@ func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) {
Aliases: []string{"tc"}, Aliases: []string{"tc"},
Usage: "this is for testing", Usage: "this is for testing",
Description: "testing", Description: "testing",
Action: func(c *cli.Context) { Action: func(c *cli.Context) error {
val := c.Int("top.test") val := c.Int("top.test")
expect(t, val, 15) expect(t, val, 15)
return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}), NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}),
@ -294,9 +297,10 @@ func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *tes
Aliases: []string{"tc"}, Aliases: []string{"tc"},
Usage: "this is for testing", Usage: "this is for testing",
Description: "testing", Description: "testing",
Action: func(c *cli.Context) { Action: func(c *cli.Context) error {
val := c.Int("top.test") val := c.Int("top.test")
expect(t, val, 11) expect(t, val, 11)
return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}), NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}),

5
app.go
View File

@ -366,6 +366,11 @@ func (a *App) Categories() CommandCategories {
return a.categories return a.categories
} }
// VisibleFlags returns a slice of the Flags with Hidden=false
func (a *App) VisibleFlags() []Flag {
return visibleFlags(a.Flags)
}
func (a *App) hasFlag(flag Flag) bool { func (a *App) hasFlag(flag Flag) bool {
for _, f := range a.Flags { for _, f := range a.Flags {
if flag == f { if flag == f {

2
cli.go
View File

@ -10,7 +10,7 @@
// app := cli.NewApp() // app := cli.NewApp()
// app.Name = "greet" // app.Name = "greet"
// app.Usage = "say a greeting" // app.Usage = "say a greeting"
// app.Action = func(c *cli.Context) { // app.Action = func(c *cli.Context) error {
// println("Greetings") // println("Greetings")
// } // }
// //

View File

@ -269,3 +269,8 @@ func (c Command) startApp(ctx *Context) error {
return app.RunAsSubcommand(ctx) return app.RunAsSubcommand(ctx)
} }
// VisibleFlags returns a slice of the Flags with Hidden=false
func (c Command) VisibleFlags() []Flag {
return visibleFlags(c.Flags)
}

66
flag.go
View File

@ -4,6 +4,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"reflect"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -12,8 +13,8 @@ import (
// This flag enables bash-completion for all commands and subcommands // This flag enables bash-completion for all commands and subcommands
var BashCompletionFlag = BoolFlag{ var BashCompletionFlag = BoolFlag{
Name: "generate-bash-completion", Name: "generate-bash-completion",
Hide: true, Hidden: true,
} }
// This flag prints the version for the application // This flag prints the version for the application
@ -38,7 +39,6 @@ type Flag interface {
// Apply Flag settings to the given flag set // Apply Flag settings to the given flag set
Apply(*flag.FlagSet) Apply(*flag.FlagSet)
GetName() string GetName() string
isNotHidden() bool
} }
func flagSet(name string, flags []Flag) *flag.FlagSet { func flagSet(name string, flags []Flag) *flag.FlagSet {
@ -70,7 +70,7 @@ type GenericFlag struct {
Value Generic Value Generic
Usage string Usage string
EnvVar string EnvVar string
Hide bool Hidden bool
} }
// String returns the string representation of the generic flag to display the // String returns the string representation of the generic flag to display the
@ -115,10 +115,6 @@ func (f GenericFlag) GetName() string {
return f.Name return f.Name
} }
func (f GenericFlag) isNotHidden() bool {
return !f.Hide
}
// StringSlice is an opaque type for []string to satisfy flag.Value // StringSlice is an opaque type for []string to satisfy flag.Value
type StringSlice []string type StringSlice []string
@ -145,7 +141,7 @@ type StringSliceFlag struct {
Value *StringSlice Value *StringSlice
Usage string Usage string
EnvVar string EnvVar string
Hide bool Hidden bool
} }
// String returns the usage // String returns the usage
@ -185,10 +181,6 @@ func (f StringSliceFlag) GetName() string {
return f.Name return f.Name
} }
func (f StringSliceFlag) isNotHidden() bool {
return !f.Hide
}
// StringSlice is an opaque type for []int to satisfy flag.Value // StringSlice is an opaque type for []int to satisfy flag.Value
type IntSlice []int type IntSlice []int
@ -220,7 +212,7 @@ type IntSliceFlag struct {
Value *IntSlice Value *IntSlice
Usage string Usage string
EnvVar string EnvVar string
Hide bool Hidden bool
} }
// String returns the usage // String returns the usage
@ -263,17 +255,13 @@ func (f IntSliceFlag) GetName() string {
return f.Name return f.Name
} }
func (f IntSliceFlag) isNotHidden() bool {
return !f.Hide
}
// BoolFlag is a switch that defaults to false // BoolFlag is a switch that defaults to false
type BoolFlag struct { type BoolFlag struct {
Name string Name string
Usage string Usage string
EnvVar string EnvVar string
Destination *bool Destination *bool
Hide bool Hidden bool
} }
// String returns a readable representation of this value (for usage defaults) // String returns a readable representation of this value (for usage defaults)
@ -311,10 +299,6 @@ func (f BoolFlag) GetName() string {
return f.Name return f.Name
} }
func (f BoolFlag) isNotHidden() bool {
return !f.Hide
}
// BoolTFlag this represents a boolean flag that is true by default, but can // BoolTFlag this represents a boolean flag that is true by default, but can
// still be set to false by --some-flag=false // still be set to false by --some-flag=false
type BoolTFlag struct { type BoolTFlag struct {
@ -322,7 +306,7 @@ type BoolTFlag struct {
Usage string Usage string
EnvVar string EnvVar string
Destination *bool Destination *bool
Hide bool Hidden bool
} }
// String returns a readable representation of this value (for usage defaults) // String returns a readable representation of this value (for usage defaults)
@ -360,10 +344,6 @@ func (f BoolTFlag) GetName() string {
return f.Name return f.Name
} }
func (f BoolTFlag) isNotHidden() bool {
return !f.Hide
}
// StringFlag represents a flag that takes as string value // StringFlag represents a flag that takes as string value
type StringFlag struct { type StringFlag struct {
Name string Name string
@ -371,7 +351,7 @@ type StringFlag struct {
Usage string Usage string
EnvVar string EnvVar string
Destination *string Destination *string
Hide bool Hidden bool
} }
// String returns the usage // String returns the usage
@ -413,10 +393,6 @@ func (f StringFlag) GetName() string {
return f.Name return f.Name
} }
func (f StringFlag) isNotHidden() bool {
return !f.Hide
}
// IntFlag is a flag that takes an integer // IntFlag is a flag that takes an integer
// Errors if the value provided cannot be parsed // Errors if the value provided cannot be parsed
type IntFlag struct { type IntFlag struct {
@ -425,7 +401,7 @@ type IntFlag struct {
Usage string Usage string
EnvVar string EnvVar string
Destination *int Destination *int
Hide bool Hidden bool
} }
// String returns the usage // String returns the usage
@ -462,10 +438,6 @@ func (f IntFlag) GetName() string {
return f.Name return f.Name
} }
func (f IntFlag) isNotHidden() bool {
return !f.Hide
}
// DurationFlag is a flag that takes a duration specified in Go's duration // DurationFlag is a flag that takes a duration specified in Go's duration
// format: https://golang.org/pkg/time/#ParseDuration // format: https://golang.org/pkg/time/#ParseDuration
type DurationFlag struct { type DurationFlag struct {
@ -474,7 +446,7 @@ type DurationFlag struct {
Usage string Usage string
EnvVar string EnvVar string
Destination *time.Duration Destination *time.Duration
Hide bool Hidden bool
} }
// String returns a readable representation of this value (for usage defaults) // String returns a readable representation of this value (for usage defaults)
@ -511,10 +483,6 @@ func (f DurationFlag) GetName() string {
return f.Name return f.Name
} }
func (f DurationFlag) isNotHidden() bool {
return !f.Hide
}
// Float64Flag is a flag that takes an float value // Float64Flag is a flag that takes an float value
// Errors if the value provided cannot be parsed // Errors if the value provided cannot be parsed
type Float64Flag struct { type Float64Flag struct {
@ -523,7 +491,7 @@ type Float64Flag struct {
Usage string Usage string
EnvVar string EnvVar string
Destination *float64 Destination *float64
Hide bool Hidden bool
} }
// String returns the usage // String returns the usage
@ -559,8 +527,14 @@ func (f Float64Flag) GetName() string {
return f.Name return f.Name
} }
func (f Float64Flag) isNotHidden() bool { func visibleFlags(fl []Flag) []Flag {
return !f.Hide visible := []Flag{}
for _, flag := range fl {
if !reflect.ValueOf(flag).FieldByName("Hidden").Bool() {
visible = append(visible, flag)
}
}
return visible
} }
func prefixFor(name string) (prefix string) { func prefixFor(name string) (prefix string) {

48
help.go
View File

@ -15,7 +15,7 @@ var AppHelpTemplate = `NAME:
{{.Name}} - {{.Usage}} {{.Name}} - {{.Usage}}
USAGE: USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .Flags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
{{if .Version}}{{if not .HideVersion}} {{if .Version}}{{if not .HideVersion}}
VERSION: VERSION:
{{.Version}} {{.Version}}
@ -26,9 +26,9 @@ AUTHOR(S):
COMMANDS:{{range .Categories}}{{if .Name}} COMMANDS:{{range .Categories}}{{if .Name}}
{{.Name}}{{ ":" }}{{end}}{{range .Commands}} {{.Name}}{{ ":" }}{{end}}{{range .Commands}}
{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}} {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}}
{{end}}{{end}}{{if .Flags}} {{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS: GLOBAL OPTIONS:
{{range .Flags}}{{.}} {{range .VisibleFlags}}{{.}}
{{end}}{{end}}{{if .Copyright }} {{end}}{{end}}{{if .Copyright }}
COPYRIGHT: COPYRIGHT:
{{.Copyright}} {{.Copyright}}
@ -42,16 +42,16 @@ var CommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}} {{.HelpName}} - {{.Usage}}
USAGE: USAGE:
{{.HelpName}}{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}} {{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
CATEGORY: CATEGORY:
{{.Category}}{{end}}{{if .Description}} {{.Category}}{{end}}{{if .Description}}
DESCRIPTION: DESCRIPTION:
{{.Description}}{{end}}{{if .Flags}} {{.Description}}{{end}}{{if .VisibleFlags}}
OPTIONS: OPTIONS:
{{range .Flags}}{{.}} {{range .VisibleFlags}}{{.}}
{{end}}{{ end }} {{end}}{{ end }}
` `
@ -62,14 +62,14 @@ var SubcommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}} {{.HelpName}} - {{.Usage}}
USAGE: USAGE:
{{.HelpName}} command{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} {{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
COMMANDS:{{range .Categories}}{{if .Name}} COMMANDS:{{range .Categories}}{{if .Name}}
{{.Name}}{{ ":" }}{{end}}{{range .Commands}} {{.Name}}{{ ":" }}{{end}}{{range .Commands}}
{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}} {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}}
{{end}}{{if .Flags}} {{end}}{{if .VisibleFlags}}
OPTIONS: OPTIONS:
{{range .Flags}}{{.}} {{range .VisibleFlags}}{{.}}
{{end}}{{end}} {{end}}{{end}}
` `
@ -114,15 +114,7 @@ var HelpPrinter helpPrinter = printHelp
var VersionPrinter = printVersion var VersionPrinter = printVersion
func ShowAppHelp(c *Context) { func ShowAppHelp(c *Context) {
// Make a copy of c.App context HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
app := *c.App
app.Flags = make([]Flag, 0)
for _, flag := range c.App.Flags {
if flag.isNotHidden() {
app.Flags = append(app.Flags, flag)
}
}
HelpPrinter(c.App.Writer, AppHelpTemplate, app)
} }
// Prints the list of subcommands as the default app completion method // Prints the list of subcommands as the default app completion method
@ -138,29 +130,13 @@ func DefaultAppComplete(c *Context) {
func ShowCommandHelp(ctx *Context, command string) { func ShowCommandHelp(ctx *Context, command string) {
// show the subcommand help for a command with subcommands // show the subcommand help for a command with subcommands
if command == "" { if command == "" {
// Make a copy of c.App context HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
app := *c.App
app.Flags = make([]Flag, 0)
for _, flag := range c.App.Flags {
if flag.isNotHidden() {
app.Flags = append(app.Flags, flag)
}
}
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, app)
return return
} }
for _, c := range ctx.App.Commands { for _, c := range ctx.App.Commands {
if c.HasName(command) { if c.HasName(command) {
// Make a copy of command context HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
c0 := c
c0.Flags = make([]Flag, 0)
for _, flag := range c.Flags {
if flag.isNotHidden() {
c0.Flags = append(c0.Flags, flag)
}
}
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c0)
return return
} }
} }