feat: flag action
This commit is contained in:
parent
a2c3729797
commit
e2e14ec6ef
26
app.go
26
app.go
@ -340,6 +340,10 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = runFlagActions(cCtx, a.Flags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var c *Command
|
||||
args := cCtx.Args()
|
||||
if args.Present() {
|
||||
@ -521,6 +525,10 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = runFlagActions(cCtx, a.Flags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := cCtx.Args()
|
||||
if args.Present() {
|
||||
name := args.First()
|
||||
@ -644,6 +652,24 @@ func (a *App) argsWithDefaultCommand(oldArgs Args) Args {
|
||||
return oldArgs
|
||||
}
|
||||
|
||||
func runFlagActions(c *Context, fs []Flag) error {
|
||||
for _, f := range fs {
|
||||
isSet := false
|
||||
for _, name := range f.Names() {
|
||||
if c.IsSet(name) {
|
||||
isSet = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if isSet {
|
||||
if err := f.RunAction(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Author represents someone who has contributed to a cli project.
|
||||
type Author struct {
|
||||
Name string // The Authors name
|
||||
|
67
app_test.go
67
app_test.go
@ -2357,6 +2357,10 @@ func (c *customBoolFlag) Apply(set *flag.FlagSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *customBoolFlag) RunAction(*Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *customBoolFlag) IsSet() bool {
|
||||
return false
|
||||
}
|
||||
@ -2596,3 +2600,66 @@ func TestSetupInitializesOnlyNilWriters(t *testing.T) {
|
||||
t.Errorf("expected a.Writer to be os.Stdout")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlagAction(t *testing.T) {
|
||||
r := []string{}
|
||||
actionFunc := func(c *Context, s string) error {
|
||||
r = append(r, s)
|
||||
return nil
|
||||
}
|
||||
|
||||
app := &App{
|
||||
Name: "command",
|
||||
Writer: io.Discard,
|
||||
Flags: []Flag{&StringFlag{Name: "flag", Action: actionFunc}},
|
||||
Commands: []*Command{
|
||||
{
|
||||
Name: "command1",
|
||||
Flags: []Flag{&StringFlag{Name: "flag1", Aliases: []string{"f1"}, Action: actionFunc}},
|
||||
Subcommands: []*Command{
|
||||
{
|
||||
Name: "command2",
|
||||
Flags: []Flag{&StringFlag{Name: "flag2", Action: actionFunc}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
args []string
|
||||
exp []string
|
||||
}{
|
||||
{
|
||||
args: []string{"command", "--flag=f"},
|
||||
exp: []string{"f"},
|
||||
},
|
||||
{
|
||||
args: []string{"command", "command1", "-f1=f1", "command2"},
|
||||
exp: []string{"f1"},
|
||||
},
|
||||
{
|
||||
args: []string{"command", "command1", "-f1=f1", "command2", "--flag2=f2"},
|
||||
exp: []string{"f1", "f2"},
|
||||
},
|
||||
{
|
||||
args: []string{"command", "--flag=f", "command1", "-flag1=f1"},
|
||||
exp: []string{"f", "f1"},
|
||||
},
|
||||
{
|
||||
args: []string{"command", "--flag=f", "command1", "-f1=f1"},
|
||||
exp: []string{"f", "f1"},
|
||||
},
|
||||
{
|
||||
args: []string{"command", "--flag=f", "command1", "-f1=f1", "command2", "--flag2=f2"},
|
||||
exp: []string{"f", "f1", "f2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
r = []string{}
|
||||
err := app.Run(test.args)
|
||||
expect(t, err, nil)
|
||||
expect(t, r, test.exp)
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +165,10 @@ func (c *Command) Run(ctx *Context) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = runFlagActions(cCtx, c.Flags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Action == nil {
|
||||
c.Action = helpSubcommand.Action
|
||||
}
|
||||
|
2
flag.go
2
flag.go
@ -122,6 +122,8 @@ type Flag interface {
|
||||
// GetValue returns the flags value as string representation and an empty
|
||||
// string if the flag takes no value at all.
|
||||
GetValue() string
|
||||
|
||||
RunAction(*Context) error
|
||||
}
|
||||
|
||||
// Countable is an interface to enable detection of flag values which support
|
||||
|
@ -72,6 +72,15 @@ func (f *BoolFlag) GetDefaultText() string {
|
||||
return fmt.Sprintf("%v", f.Value)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *BoolFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Bool(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
|
||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||
|
@ -42,6 +42,15 @@ func (f *DurationFlag) Get(ctx *Context) time.Duration {
|
||||
return ctx.Duration(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *DurationFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Duration(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Duration looks up the value of a local DurationFlag, returns
|
||||
// 0 if not found
|
||||
func (cCtx *Context) Duration(name string) time.Duration {
|
||||
|
@ -42,6 +42,15 @@ func (f *Float64Flag) Get(ctx *Context) float64 {
|
||||
return ctx.Float64(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Float64Flag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Float64(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Float64 looks up the value of a local Float64Flag, returns
|
||||
// 0 if not found
|
||||
func (cCtx *Context) Float64(name string) float64 {
|
||||
|
@ -153,6 +153,15 @@ func (f *Float64SliceFlag) stringify() string {
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Float64SliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Float64Slice(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Float64Slice looks up the value of a local Float64SliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) Float64Slice(name string) []float64 {
|
||||
|
@ -45,6 +45,15 @@ func (f *GenericFlag) Get(ctx *Context) interface{} {
|
||||
return ctx.Generic(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *GenericFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Generic(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generic looks up the value of a local GenericFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) Generic(name string) interface{} {
|
||||
|
@ -43,6 +43,15 @@ func (f *IntFlag) Get(ctx *Context) int {
|
||||
return ctx.Int(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *IntFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Int(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int looks up the value of a local IntFlag, returns
|
||||
// 0 if not found
|
||||
func (cCtx *Context) Int(name string) int {
|
||||
|
@ -42,6 +42,15 @@ func (f *Int64Flag) Get(ctx *Context) int64 {
|
||||
return ctx.Int64(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Int64Flag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Int64(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int64 looks up the value of a local Int64Flag, returns
|
||||
// 0 if not found
|
||||
func (cCtx *Context) Int64(name string) int64 {
|
||||
|
@ -151,6 +151,15 @@ func (f *Int64SliceFlag) stringify() string {
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Int64SliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Int64Slice(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) Int64Slice(name string) []int64 {
|
||||
|
@ -162,6 +162,15 @@ func (f *IntSliceFlag) stringify() string {
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *IntSliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.IntSlice(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IntSlice looks up the value of a local IntSliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) IntSlice(name string) []int {
|
||||
|
@ -47,6 +47,15 @@ func (f *PathFlag) Get(ctx *Context) string {
|
||||
return ctx.Path(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *PathFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Path(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Path looks up the value of a local PathFlag, returns
|
||||
// "" if not found
|
||||
func (cCtx *Context) Path(name string) string {
|
||||
|
@ -45,6 +45,15 @@ func (f *StringFlag) Get(ctx *Context) string {
|
||||
return ctx.String(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *StringFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.String(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String looks up the value of a local StringFlag, returns
|
||||
// "" if not found
|
||||
func (cCtx *Context) String(name string) string {
|
||||
|
@ -143,6 +143,15 @@ func (f *StringSliceFlag) stringify() string {
|
||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *StringSliceFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.StringSlice(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringSlice looks up the value of a local StringSliceFlag, returns
|
||||
// nil if not found
|
||||
func (cCtx *Context) StringSlice(name string) []string {
|
||||
|
@ -120,6 +120,15 @@ func (f *TimestampFlag) Get(ctx *Context) *time.Time {
|
||||
return ctx.Timestamp(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *TimestampFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Timestamp(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamp gets the timestamp from a flag name
|
||||
func (cCtx *Context) Timestamp(name string) *time.Time {
|
||||
if fs := cCtx.lookupFlagSet(name); fs != nil {
|
||||
|
@ -42,6 +42,15 @@ func (f *UintFlag) Get(ctx *Context) uint {
|
||||
return ctx.Uint(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *UintFlag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Uint(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint looks up the value of a local UintFlag, returns
|
||||
// 0 if not found
|
||||
func (cCtx *Context) Uint(name string) uint {
|
||||
|
@ -42,6 +42,15 @@ func (f *Uint64Flag) Get(ctx *Context) uint64 {
|
||||
return ctx.Uint64(f.Name)
|
||||
}
|
||||
|
||||
// RunAction executes flag action if set
|
||||
func (f *Uint64Flag) RunAction(c *Context) error {
|
||||
if f.Action != nil {
|
||||
return f.Action(c, c.Uint64(f.Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint64 looks up the value of a local Uint64Flag, returns
|
||||
// 0 if not found
|
||||
func (cCtx *Context) Uint64(name string) uint64 {
|
||||
|
Loading…
Reference in New Issue
Block a user