Skip to content

Commit

Permalink
feat: flag action
Browse files Browse the repository at this point in the history
  • Loading branch information
xwjdsh committed Apr 30, 2022
1 parent 76418f2 commit e132f01
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 0 deletions.
26 changes: 26 additions & 0 deletions app.go
Expand Up @@ -305,6 +305,10 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
}
}

if err = runFlagActions(cCtx, a.Flags); err != nil {
return err
}

args := cCtx.Args()
if args.Present() {
name := args.First()
Expand Down Expand Up @@ -426,6 +430,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()
Expand Down Expand Up @@ -506,6 +514,24 @@ func (a *App) handleExitCoder(cCtx *Context, err error) {
}
}

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
Expand Down
67 changes: 67 additions & 0 deletions app_test.go
Expand Up @@ -2068,6 +2068,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
}
Expand Down Expand Up @@ -2287,3 +2291,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)
}
}
4 changes: 4 additions & 0 deletions command.go
Expand Up @@ -155,6 +155,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
}
Expand Down
1 change: 1 addition & 0 deletions flag.go
Expand Up @@ -93,6 +93,7 @@ type Flag interface {
Apply(*flag.FlagSet) error
Names() []string
IsSet() bool
RunAction(*Context) error
}

// RequiredFlag is an interface that allows us to mark flags as required
Expand Down
10 changes: 10 additions & 0 deletions flag_bool.go
Expand Up @@ -19,6 +19,7 @@ type BoolFlag struct {
DefaultText string
Destination *bool
HasBeenSet bool
Action func(*Context, bool) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -76,6 +77,15 @@ func (f *BoolFlag) GetEnvVars() []string {
return f.EnvVars
}

// 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, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
10 changes: 10 additions & 0 deletions flag_duration.go
Expand Up @@ -19,6 +19,7 @@ type DurationFlag struct {
DefaultText string
Destination *time.Duration
HasBeenSet bool
Action func(*Context, time.Duration) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -101,6 +102,15 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_float64.go
Expand Up @@ -19,6 +19,7 @@ type Float64Flag struct {
DefaultText string
Destination *float64
HasBeenSet bool
Action func(*Context, float64) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -101,6 +102,15 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_float64_slice.go
Expand Up @@ -87,6 +87,7 @@ type Float64SliceFlag struct {
Value *Float64Slice
DefaultText string
HasBeenSet bool
Action func(*Context, []float64) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -177,6 +178,15 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_generic.go
Expand Up @@ -24,6 +24,7 @@ type GenericFlag struct {
Value Generic
DefaultText string
HasBeenSet bool
Action func(*Context, interface{}) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -104,6 +105,15 @@ func (f GenericFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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{} {
Expand Down
10 changes: 10 additions & 0 deletions flag_int.go
Expand Up @@ -19,6 +19,7 @@ type IntFlag struct {
DefaultText string
Destination *int
HasBeenSet bool
Action func(*Context, int) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -102,6 +103,15 @@ func (f *IntFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_int64.go
Expand Up @@ -19,6 +19,7 @@ type Int64Flag struct {
DefaultText string
Destination *int64
HasBeenSet bool
Action func(*Context, int64) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -101,6 +102,15 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_int64_slice.go
Expand Up @@ -88,6 +88,7 @@ type Int64SliceFlag struct {
Value *Int64Slice
DefaultText string
HasBeenSet bool
Action func(*Context, []int64) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -176,6 +177,15 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_int_slice.go
Expand Up @@ -99,6 +99,7 @@ type IntSliceFlag struct {
Value *IntSlice
DefaultText string
HasBeenSet bool
Action func(*Context, []int) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -187,6 +188,15 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down
10 changes: 10 additions & 0 deletions flag_path.go
Expand Up @@ -18,6 +18,7 @@ type PathFlag struct {
DefaultText string
Destination *string
HasBeenSet bool
Action func(*Context, string) error
}

// IsSet returns whether or not the flag has been set through env or file
Expand Down Expand Up @@ -96,6 +97,15 @@ func (f *PathFlag) Apply(set *flag.FlagSet) error {
return nil
}

// 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 {
Expand Down

0 comments on commit e132f01

Please sign in to comment.