Skip to content

Commit

Permalink
Keep nested pointers and allow multiple renamers (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wes Dean committed Sep 24, 2021
1 parent 33a96ab commit 5a278be
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
13 changes: 9 additions & 4 deletions flagset.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ func (f *FlagSetFiller) walkFields(flagSet *flag.FlagSet, prefix string,

case reflect.Ptr:
if fieldValue.CanSet() && field.Type.Elem().Kind() == reflect.Struct {
// fill the pointer with a new struct of their type
fieldValue.Set(reflect.New(field.Type.Elem()))
// fill the pointer with a new struct of their type if it is nil
if fieldValue.IsNil() {
fieldValue.Set(reflect.New(field.Type.Elem()))
}

err := f.walkFields(flagSet, field.Name, fieldValue.Elem(), field.Type.Elem())
if err != nil {
Expand Down Expand Up @@ -101,8 +103,11 @@ func (f *FlagSetFiller) processField(flagSet *flag.FlagSet, fieldRef interface{}
var envName string
if override, exists := tag.Lookup("env"); exists {
envName = override
} else if f.options.envRenamer != nil {
envName = f.options.envRenamer(name)
} else if len(f.options.envRenamer) > 0 {
envName = name
for _, renamer := range f.options.envRenamer {
envName = renamer(envName)
}
}

usage := requoteUsage(tag.Get("usage"))
Expand Down
20 changes: 17 additions & 3 deletions flagset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"bytes"
"flag"
"fmt"
"os"
"testing"
"time"

"github.com/iancoleman/strcase"
"github.com/itzg/go-flagsfiller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)

func TestStringFields(t *testing.T) {
Expand Down Expand Up @@ -289,16 +290,25 @@ func TestNumbers(t *testing.T) {
}

func TestDefaultsViaLiteral(t *testing.T) {
type Nested struct {
Exported string
unExported string
}
type Config struct {
Host string
Enabled bool
Timeout time.Duration
Nested *Nested
}

var config = Config{
Host: "h1",
Enabled: true,
Timeout: 5 * time.Second,
Nested: &Nested{
Exported: "exported",
unExported: "un-exported",
},
}

filler := flagsfiller.New()
Expand All @@ -309,11 +319,15 @@ func TestDefaultsViaLiteral(t *testing.T) {

buf := grabUsage(flagset)

assert.Equal(t, "un-exported", config.Nested.unExported)

assert.Equal(t, `
-enabled
(default true)
-host string
(default "h1")
-nested-exported string
(default "exported")
-timeout duration
(default 5s)
`, buf.String())
Expand Down
15 changes: 9 additions & 6 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ var DefaultFieldRenamer = KebabRenamer()
type FillerOption func(opt *fillerOptions)

type fillerOptions struct {
fieldRenamer Renamer
envRenamer Renamer
fieldRenamer []Renamer
envRenamer []Renamer
}

// WithFieldRenamer declares an option to customize the Renamer used to convert field names
// to flag names.
func WithFieldRenamer(renamer Renamer) FillerOption {
return func(opt *fillerOptions) {
opt.fieldRenamer = renamer
opt.fieldRenamer = append(opt.fieldRenamer, renamer)
}
}

Expand All @@ -37,15 +37,18 @@ func WithEnv(prefix string) FillerOption {
// are mapped to environment variable names by applying the given Renamer
func WithEnvRenamer(renamer Renamer) FillerOption {
return func(opt *fillerOptions) {
opt.envRenamer = renamer
opt.envRenamer = append(opt.envRenamer, renamer)
}
}

func (o *fillerOptions) renameLongName(name string) string {
if o.fieldRenamer == nil {
if len(o.fieldRenamer) == 0 {
return DefaultFieldRenamer(name)
} else {
return o.fieldRenamer(name)
for _, renamer := range o.fieldRenamer {
name = renamer(name)
}
return name
}
}

Expand Down

0 comments on commit 5a278be

Please sign in to comment.