Skip to content

Commit

Permalink
Support Addflags
Browse files Browse the repository at this point in the history
  • Loading branch information
leaanthony committed Oct 26, 2022
1 parent 9b3872f commit 14e1d2c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
6 changes: 5 additions & 1 deletion cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func (c *Cli) SetErrorFunction(fn func(string, error) error) {
// Abort - Prints the given error and terminates the application.
func (c *Cli) Abort(err error) {
log.Fatal(err)
os.Exit(1)
}

// AddCommand - Adds a command to the application.
Expand Down Expand Up @@ -120,6 +119,11 @@ func (c *Cli) IntFlag(name, description string, variable *int) *Cli {
return c
}

func (c *Cli) AddFlags(flags interface{}) *Cli {
c.rootCommand.AddFlags(flags)
return c
}

// Action - Define an action from this command.
func (c *Cli) Action(callback Action) *Cli {
c.rootCommand.Action(callback)
Expand Down
33 changes: 33 additions & 0 deletions cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,36 @@ func TestCli(t *testing.T) {
c.LongDescription("long description")
})
}

type testStruct struct {
Mode string `name:"mode" description:"The mode of build"`
}

func TestCli_AddFlags(t *testing.T) {
c := NewCli("test", "description", "0")

ts := &testStruct{}
c.AddFlags(ts)

modeFlag := c.rootCommand.flags.Lookup("mode")
if modeFlag == nil {
t.Errorf("expected flag mode to be added")
}
if modeFlag.Name != "mode" {
t.Errorf("expected flag name to be added")
}
if modeFlag.Usage != "The mode of build" {
t.Errorf("expected flag description to be added")
}

c.Action(func() error {
if ts.Mode != "123" {
t.Errorf("expected flag value to be set")
}
return nil
})
e := c.Run("-mode", "123")
if e != nil {
t.Errorf("expected no error, got %v", e)
}
}
37 changes: 37 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"os"
"reflect"
"strings"
)

Expand Down Expand Up @@ -221,6 +222,42 @@ func (c *Command) BoolFlag(name, description string, variable *bool) *Command {
return c
}

func (c *Command) AddFlags(optionStruct interface{}) *Command {
// use reflection to determine if this is a pointer to a struct
// if not, panic

t := reflect.TypeOf(optionStruct)
if t.Kind() != reflect.Ptr {
panic("AddFlags requires a pointer to a struct")
}

// Iterate through the fields of the struct reading the struct tags
// and adding the flags
v := reflect.ValueOf(optionStruct).Elem()
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
tag := t.Elem().Field(i).Tag
name := tag.Get("name")
description := tag.Get("description")
if name == "" {
name = strings.ToLower(t.Elem().Field(i).Name)
}
if description == "" {
description = "No description"
}
switch field.Kind() {
case reflect.Bool:
c.BoolFlag(name, description, field.Addr().Interface().(*bool))
case reflect.String:
c.StringFlag(name, description, field.Addr().Interface().(*string))
case reflect.Int:
c.IntFlag(name, description, field.Addr().Interface().(*int))
}
}

return c
}

// StringFlag - Adds a string flag to the command
func (c *Command) StringFlag(name, description string, variable *string) *Command {
c.flags.StringVar(variable, name, *variable, description)
Expand Down

0 comments on commit 14e1d2c

Please sign in to comment.