Skip to content

Commit

Permalink
Add StringConfig for all string flags
Browse files Browse the repository at this point in the history
This config allows configuring to automatically trim whitespace of
string value flags. This includes slices and maps.

I had to plumb this down to the string flag level, because of compiler
errors.
  • Loading branch information
avorima committed Dec 5, 2022
1 parent 21f28d7 commit 5dd5dd0
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 27 deletions.
35 changes: 28 additions & 7 deletions flag_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,31 @@ package cli

import (
"fmt"
"strings"
)

type StringFlag = FlagBase[string, NoConfig, stringValue]
type StringFlag = FlagBase[string, StringConfig, stringValue]

// StringConfig defines the configuration for string flags
type StringConfig struct {
// Whether to trim whitespace of parsed value
TrimSpace bool
}

// -- string Value
type stringValue string
type stringValue struct {
destination *string
trimSpace bool
}

// Below functions are to satisfy the ValueCreator interface

func (i stringValue) Create(val string, p *string, c NoConfig) Value {
func (i stringValue) Create(val string, p *string, c StringConfig) Value {
*p = val
return (*stringValue)(p)
return &stringValue{
destination: p,
trimSpace: c.TrimSpace,
}
}

func (i stringValue) ToString(b string) string {
Expand All @@ -26,13 +39,21 @@ func (i stringValue) ToString(b string) string {
// Below functions are to satisfy the flag.Value interface

func (s *stringValue) Set(val string) error {
*s = stringValue(val)
if s.trimSpace {
val = strings.TrimSpace(val)
}
*s.destination = val
return nil
}

func (s *stringValue) Get() any { return string(*s) }
func (s *stringValue) Get() any { return *s.destination }

func (s *stringValue) String() string { return string(*s) }
func (s *stringValue) String() string {
if s.destination != nil {
return *s.destination
}
return ""
}

func (cCtx *Context) String(name string) string {
if v, ok := cCtx.Value(name).(string); ok {
Expand Down
6 changes: 3 additions & 3 deletions flag_string_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package cli

import "flag"

type StringMap = MapBase[string, NoConfig, stringValue]
type StringMapFlag = FlagBase[map[string]string, NoConfig, StringMap]
type StringMap = MapBase[string, StringConfig, stringValue]
type StringMapFlag = FlagBase[map[string]string, StringConfig, StringMap]

var NewStringMap = NewMapBase[string, NoConfig, stringValue]
var NewStringMap = NewMapBase[string, StringConfig, stringValue]

// StringMap looks up the value of a local StringMapFlag, returns
// nil if not found
Expand Down
6 changes: 3 additions & 3 deletions flag_string_slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"flag"
)

type StringSlice = SliceBase[string, NoConfig, stringValue]
type StringSliceFlag = FlagBase[[]string, NoConfig, StringSlice]
type StringSlice = SliceBase[string, StringConfig, stringValue]
type StringSliceFlag = FlagBase[[]string, StringConfig, StringSlice]

var NewStringSlice = NewSliceBase[string, NoConfig, stringValue]
var NewStringSlice = NewSliceBase[string, StringConfig, stringValue]

// StringSlice looks up the value of a local StringSliceFlag, returns
// nil if not found
Expand Down
4 changes: 4 additions & 0 deletions flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ func TestFlagsFromEnv(t *testing.T) {
{"foobar", 0, &Uint64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, `could not parse "foobar" as uint64 value from environment variable "SECONDS" for flag seconds: .*`},

{"foo=bar,empty=", map[string]string{"foo": "bar", "empty": ""}, &StringMapFlag{Name: "names", EnvVars: []string{"NAMES"}}, ""},

{" foo", "foo", &StringFlag{Name: "names", EnvVars: []string{"NAMES"}, Config: StringConfig{TrimSpace: true}}, ""},
{"foo , bar ", []string{"foo", "bar"}, &StringSliceFlag{Name: "names", EnvVars: []string{"NAMES"}, Config: StringConfig{TrimSpace: true}}, ""},
{"foo= bar ", map[string]string{"foo": "bar"}, &StringMapFlag{Name: "names", EnvVars: []string{"NAMES"}, Config: StringConfig{TrimSpace: true}}, ""},
}

for i, test := range flagTests {
Expand Down
20 changes: 13 additions & 7 deletions godoc-current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionN
var NewFloat64Slice = NewSliceBase[float64, NoConfig, float64Value]
var NewInt64Slice = NewSliceBase[int64, IntegerConfig, int64Value]
var NewIntSlice = NewSliceBase[int, IntegerConfig, intValue]
var NewStringMap = NewMapBase[string, NoConfig, stringValue]
var NewStringSlice = NewSliceBase[string, NoConfig, stringValue]
var NewStringMap = NewMapBase[string, StringConfig, stringValue]
var NewStringSlice = NewSliceBase[string, StringConfig, stringValue]
var NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uint64Value]
var NewUintSlice = NewSliceBase[uint, IntegerConfig, uintValue]
var OsExiter = os.Exit
Expand Down Expand Up @@ -1028,15 +1028,21 @@ func (i SliceBase[T, C, VC]) ToString(t []T) string
func (i *SliceBase[T, C, VC]) Value() []T
Value returns the slice of values set by this flag

type StringFlag = FlagBase[string, NoConfig, stringValue]
type StringConfig struct {
// Whether to trim whitespace of parsed value
TrimSpace bool
}
StringConfig defines the configuration for string flags

type StringFlag = FlagBase[string, StringConfig, stringValue]

type StringMap = MapBase[string, NoConfig, stringValue]
type StringMap = MapBase[string, StringConfig, stringValue]

type StringMapFlag = FlagBase[map[string]string, NoConfig, StringMap]
type StringMapFlag = FlagBase[map[string]string, StringConfig, StringMap]

type StringSlice = SliceBase[string, NoConfig, stringValue]
type StringSlice = SliceBase[string, StringConfig, stringValue]

type StringSliceFlag = FlagBase[[]string, NoConfig, StringSlice]
type StringSliceFlag = FlagBase[[]string, StringConfig, StringSlice]

type SuggestCommandFunc func(commands []*Command, provided string) string

Expand Down
20 changes: 13 additions & 7 deletions testdata/godoc-v3.x.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionN
var NewFloat64Slice = NewSliceBase[float64, NoConfig, float64Value]
var NewInt64Slice = NewSliceBase[int64, IntegerConfig, int64Value]
var NewIntSlice = NewSliceBase[int, IntegerConfig, intValue]
var NewStringMap = NewMapBase[string, NoConfig, stringValue]
var NewStringSlice = NewSliceBase[string, NoConfig, stringValue]
var NewStringMap = NewMapBase[string, StringConfig, stringValue]
var NewStringSlice = NewSliceBase[string, StringConfig, stringValue]
var NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uint64Value]
var NewUintSlice = NewSliceBase[uint, IntegerConfig, uintValue]
var OsExiter = os.Exit
Expand Down Expand Up @@ -1028,15 +1028,21 @@ func (i SliceBase[T, C, VC]) ToString(t []T) string
func (i *SliceBase[T, C, VC]) Value() []T
Value returns the slice of values set by this flag

type StringFlag = FlagBase[string, NoConfig, stringValue]
type StringConfig struct {
// Whether to trim whitespace of parsed value
TrimSpace bool
}
StringConfig defines the configuration for string flags

type StringFlag = FlagBase[string, StringConfig, stringValue]

type StringMap = MapBase[string, NoConfig, stringValue]
type StringMap = MapBase[string, StringConfig, stringValue]

type StringMapFlag = FlagBase[map[string]string, NoConfig, StringMap]
type StringMapFlag = FlagBase[map[string]string, StringConfig, StringMap]

type StringSlice = SliceBase[string, NoConfig, stringValue]
type StringSlice = SliceBase[string, StringConfig, stringValue]

type StringSliceFlag = FlagBase[[]string, NoConfig, StringSlice]
type StringSliceFlag = FlagBase[[]string, StringConfig, StringSlice]

type SuggestCommandFunc func(commands []*Command, provided string) string

Expand Down

0 comments on commit 5dd5dd0

Please sign in to comment.