feat: flag action
This commit is contained in:
parent
880a802dc8
commit
14366f7030
26
app.go
26
app.go
@ -342,6 +342,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
|
var c *Command
|
||||||
args := cCtx.Args()
|
args := cCtx.Args()
|
||||||
if args.Present() {
|
if args.Present() {
|
||||||
@ -523,6 +527,10 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = runFlagActions(cCtx, a.Flags); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
args := cCtx.Args()
|
args := cCtx.Args()
|
||||||
if args.Present() {
|
if args.Present() {
|
||||||
name := args.First()
|
name := args.First()
|
||||||
@ -646,6 +654,24 @@ func (a *App) argsWithDefaultCommand(oldArgs Args) Args {
|
|||||||
return oldArgs
|
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.
|
// Author represents someone who has contributed to a cli project.
|
||||||
type Author struct {
|
type Author struct {
|
||||||
Name string // The Authors name
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *customBoolFlag) RunAction(*Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *customBoolFlag) IsSet() bool {
|
func (c *customBoolFlag) IsSet() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -2576,3 +2580,66 @@ func TestSetupInitializesOnlyNilWriters(t *testing.T) {
|
|||||||
t.Errorf("expected a.Writer to be os.Stdout")
|
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 {
|
if c.Action == nil {
|
||||||
c.Action = helpSubcommand.Action
|
c.Action = helpSubcommand.Action
|
||||||
}
|
}
|
||||||
|
1
flag.go
1
flag.go
@ -92,6 +92,7 @@ type Flag interface {
|
|||||||
Apply(*flag.FlagSet) error
|
Apply(*flag.FlagSet) error
|
||||||
Names() []string
|
Names() []string
|
||||||
IsSet() bool
|
IsSet() bool
|
||||||
|
RunAction(*Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiredFlag is an interface that allows us to mark flags as required
|
// RequiredFlag is an interface that allows us to mark flags as required
|
||||||
|
@ -92,6 +92,15 @@ func (f *BoolFlag) GetEnvVars() []string {
|
|||||||
return f.EnvVars
|
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
|
// Apply populates the flag given the flag set and environment
|
||||||
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
|
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
|
||||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||||
|
@ -70,6 +70,15 @@ func (f *DurationFlag) Get(ctx *Context) time.Duration {
|
|||||||
return ctx.Duration(f.Name)
|
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
|
// Duration looks up the value of a local DurationFlag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (cCtx *Context) Duration(name string) time.Duration {
|
func (cCtx *Context) Duration(name string) time.Duration {
|
||||||
|
@ -70,6 +70,15 @@ func (f *Float64Flag) Get(ctx *Context) float64 {
|
|||||||
return ctx.Float64(f.Name)
|
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
|
// Float64 looks up the value of a local Float64Flag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (cCtx *Context) Float64(name string) float64 {
|
func (cCtx *Context) Float64(name string) float64 {
|
||||||
|
@ -181,6 +181,15 @@ func (f *Float64SliceFlag) stringify() string {
|
|||||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
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
|
// Float64Slice looks up the value of a local Float64SliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (cCtx *Context) Float64Slice(name string) []float64 {
|
func (cCtx *Context) Float64Slice(name string) []float64 {
|
||||||
|
@ -73,6 +73,15 @@ func (f *GenericFlag) Get(ctx *Context) interface{} {
|
|||||||
return ctx.Generic(f.Name)
|
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
|
// Generic looks up the value of a local GenericFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (cCtx *Context) Generic(name string) interface{} {
|
func (cCtx *Context) Generic(name string) interface{} {
|
||||||
|
@ -71,6 +71,15 @@ func (f *IntFlag) Get(ctx *Context) int {
|
|||||||
return ctx.Int(f.Name)
|
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
|
// Int looks up the value of a local IntFlag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (cCtx *Context) Int(name string) int {
|
func (cCtx *Context) Int(name string) int {
|
||||||
|
@ -70,6 +70,15 @@ func (f *Int64Flag) Get(ctx *Context) int64 {
|
|||||||
return ctx.Int64(f.Name)
|
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
|
// Int64 looks up the value of a local Int64Flag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (cCtx *Context) Int64(name string) int64 {
|
func (cCtx *Context) Int64(name string) int64 {
|
||||||
|
@ -179,6 +179,15 @@ func (f *Int64SliceFlag) stringify() string {
|
|||||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
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
|
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (cCtx *Context) Int64Slice(name string) []int64 {
|
func (cCtx *Context) Int64Slice(name string) []int64 {
|
||||||
|
@ -92,6 +92,29 @@ func (i *IntSlice) Get() interface{} {
|
|||||||
return *i
|
return *i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
// IntSliceFlag is a flag with type *IntSlice
|
||||||
|
type IntSliceFlag struct {
|
||||||
|
Name string
|
||||||
|
Aliases []string
|
||||||
|
Usage string
|
||||||
|
EnvVars []string
|
||||||
|
FilePath string
|
||||||
|
Required bool
|
||||||
|
Hidden bool
|
||||||
|
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
|
||||||
|
func (f *IntSliceFlag) IsSet() bool {
|
||||||
|
return f.HasBeenSet
|
||||||
|
}
|
||||||
|
|
||||||
|
>>>>>>> e132f01 (feat: flag action)
|
||||||
// String returns a readable representation of this value
|
// String returns a readable representation of this value
|
||||||
// (for usage defaults)
|
// (for usage defaults)
|
||||||
func (f *IntSliceFlag) String() string {
|
func (f *IntSliceFlag) String() string {
|
||||||
@ -174,9 +197,19 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// Get returns the flag’s value in the given Context.
|
// Get returns the flag’s value in the given Context.
|
||||||
func (f *IntSliceFlag) Get(ctx *Context) []int {
|
func (f *IntSliceFlag) Get(ctx *Context) []int {
|
||||||
return ctx.IntSlice(f.Name)
|
return ctx.IntSlice(f.Name)
|
||||||
|
=======
|
||||||
|
// 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
|
||||||
|
>>>>>>> e132f01 (feat: flag action)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *IntSliceFlag) stringify() string {
|
func (f *IntSliceFlag) stringify() string {
|
||||||
|
@ -67,6 +67,15 @@ func (f *PathFlag) Get(ctx *Context) string {
|
|||||||
return ctx.Path(f.Name)
|
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
|
// Path looks up the value of a local PathFlag, returns
|
||||||
// "" if not found
|
// "" if not found
|
||||||
func (cCtx *Context) Path(name string) string {
|
func (cCtx *Context) Path(name string) string {
|
||||||
|
@ -65,6 +65,15 @@ func (f *StringFlag) Get(ctx *Context) string {
|
|||||||
return ctx.String(f.Name)
|
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
|
// String looks up the value of a local StringFlag, returns
|
||||||
// "" if not found
|
// "" if not found
|
||||||
func (cCtx *Context) String(name string) string {
|
func (cCtx *Context) String(name string) string {
|
||||||
|
@ -171,6 +171,15 @@ func (f *StringSliceFlag) stringify() string {
|
|||||||
return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
|
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
|
// StringSlice looks up the value of a local StringSliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (cCtx *Context) StringSlice(name string) []string {
|
func (cCtx *Context) StringSlice(name string) []string {
|
||||||
|
@ -148,6 +148,15 @@ func (f *TimestampFlag) Get(ctx *Context) *time.Time {
|
|||||||
return ctx.Timestamp(f.Name)
|
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
|
// Timestamp gets the timestamp from a flag name
|
||||||
func (cCtx *Context) Timestamp(name string) *time.Time {
|
func (cCtx *Context) Timestamp(name string) *time.Time {
|
||||||
if fs := cCtx.lookupFlagSet(name); fs != nil {
|
if fs := cCtx.lookupFlagSet(name); fs != nil {
|
||||||
|
@ -46,6 +46,15 @@ func (f *UintFlag) Apply(set *flag.FlagSet) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
// GetValue returns the flags value as string representation and an empty
|
// GetValue returns the flags value as string representation and an empty
|
||||||
// string if the flag takes no value at all.
|
// string if the flag takes no value at all.
|
||||||
func (f *UintFlag) GetValue() string {
|
func (f *UintFlag) GetValue() string {
|
||||||
|
@ -46,6 +46,15 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
// GetValue returns the flags value as string representation and an empty
|
// GetValue returns the flags value as string representation and an empty
|
||||||
// string if the flag takes no value at all.
|
// string if the flag takes no value at all.
|
||||||
func (f *Uint64Flag) GetValue() string {
|
func (f *Uint64Flag) GetValue() string {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user