Skip to content

Commit 5f296a5

Browse files
authored
Allow value splitting pattern to be customized (#32)
1 parent 3af1ed6 commit 5f296a5

File tree

3 files changed

+60
-13
lines changed

3 files changed

+60
-13
lines changed

flagset.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ func (f *FlagSetFiller) processStringSlice(fieldRef interface{}, hasDefaultTag b
302302
_ = f.processCustom(
303303
fieldRef,
304304
func(s string) (interface{}, error) {
305-
return parseStringSlice(s), nil
305+
return parseStringSlice(s, f.options.valueSplitPattern), nil
306306
},
307307
hasDefaultTag,
308308
tagDefault,
@@ -314,12 +314,20 @@ func (f *FlagSetFiller) processStringSlice(fieldRef interface{}, hasDefaultTag b
314314
return
315315
}
316316
if hasDefaultTag {
317-
*casted = parseStringSlice(tagDefault)
317+
*casted = parseStringSlice(tagDefault, f.options.valueSplitPattern)
318318
}
319-
flagSet.Var(&strSliceVar{ref: casted, override: override}, renamed, usage)
319+
flagSet.Var(&strSliceVar{
320+
ref: casted,
321+
override: override,
322+
valueSplitPattern: f.options.valueSplitPattern,
323+
}, renamed, usage)
320324
if aliases != "" {
321325
for _, alias := range strings.Split(aliases, ",") {
322-
flagSet.Var(&strSliceVar{ref: casted, override: override}, alias, usage)
326+
flagSet.Var(&strSliceVar{
327+
ref: casted,
328+
override: override,
329+
valueSplitPattern: f.options.valueSplitPattern,
330+
}, alias, usage)
323331
}
324332
}
325333
}
@@ -634,8 +642,9 @@ func (f *FlagSetFiller) processCustom(fieldRef interface{}, converter func(strin
634642
}
635643

636644
type strSliceVar struct {
637-
ref *[]string
638-
override bool
645+
ref *[]string
646+
override bool
647+
valueSplitPattern string
639648
}
640649

641650
func (s *strSliceVar) String() string {
@@ -646,7 +655,7 @@ func (s *strSliceVar) String() string {
646655
}
647656

648657
func (s *strSliceVar) Set(val string) error {
649-
parts := parseStringSlice(val)
658+
parts := parseStringSlice(val, s.valueSplitPattern)
650659

651660
if s.override {
652661
*s.ref = parts
@@ -658,8 +667,12 @@ func (s *strSliceVar) Set(val string) error {
658667
return nil
659668
}
660669

661-
func parseStringSlice(val string) []string {
662-
splitter := regexp.MustCompile("[\n,]")
670+
func parseStringSlice(val string, valueSplitPattern string) []string {
671+
if valueSplitPattern == "" {
672+
return []string{val}
673+
}
674+
675+
splitter := regexp.MustCompile(valueSplitPattern)
663676
parts := splitter.Split(val, -1)
664677

665678
// trim out blank parts

flagset_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,29 @@ func TestStringSlice(t *testing.T) {
572572
assert.Equal(t, []string{"three"}, config.TagOverride)
573573
}
574574

575+
func TestStringSliceWithEmptyValuePattern(t *testing.T) {
576+
type Config struct {
577+
NoDefault []string
578+
TagDefault []string `default:"one,two"`
579+
}
580+
581+
var config Config
582+
filler := flagsfiller.New(flagsfiller.WithValueSplitPattern(""))
583+
584+
var flagset flag.FlagSet
585+
err := filler.Fill(&flagset, &config)
586+
require.NoError(t, err)
587+
588+
err = flagset.Parse([]string{
589+
"--no-default", "nd1,nd2",
590+
"--no-default", "nd3",
591+
})
592+
require.NoError(t, err)
593+
594+
assert.Equal(t, []string{"nd1,nd2", "nd3"}, config.NoDefault)
595+
assert.Equal(t, []string{"one,two"}, config.TagDefault)
596+
}
597+
575598
func TestStringToStringMap(t *testing.T) {
576599
type Config struct {
577600
NoDefault map[string]string

options.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ var DefaultFieldRenamer = KebabRenamer()
1313
type FillerOption func(opt *fillerOptions)
1414

1515
type fillerOptions struct {
16-
fieldRenamer []Renamer
17-
envRenamer []Renamer
18-
noSetFromEnv bool
16+
fieldRenamer []Renamer
17+
envRenamer []Renamer
18+
noSetFromEnv bool
19+
valueSplitPattern string
1920
}
2021

2122
// WithFieldRenamer declares an option to customize the Renamer used to convert field names
@@ -51,6 +52,14 @@ func NoSetFromEnv() FillerOption {
5152
}
5253
}
5354

55+
// WithValueSplitPattern allows for changing the default value splitting regex pattern from newlines and commas.
56+
// Any empty string can be provided for pattern to disable value splitting.
57+
func WithValueSplitPattern(pattern string) FillerOption {
58+
return func(opt *fillerOptions) {
59+
opt.valueSplitPattern = pattern
60+
}
61+
}
62+
5463
func (o *fillerOptions) renameLongName(name string) string {
5564
if len(o.fieldRenamer) == 0 {
5665
return DefaultFieldRenamer(name)
@@ -63,7 +72,9 @@ func (o *fillerOptions) renameLongName(name string) string {
6372
}
6473

6574
func newFillerOptions(options ...FillerOption) *fillerOptions {
66-
v := &fillerOptions{}
75+
v := &fillerOptions{
76+
valueSplitPattern: "[\n,]",
77+
}
6778
for _, opt := range options {
6879
opt(v)
6980
}

0 commit comments

Comments
 (0)