Skip to content

Commit 82b1afc

Browse files
authored
Merge pull request #1849 from dearchap/issue_1842
Fix:(issue_1842) Make value source chain more user friendly
2 parents 2f492f5 + 9b457f3 commit 82b1afc

File tree

6 files changed

+72
-26
lines changed

6 files changed

+72
-26
lines changed

flag_bool_with_inverse.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func (parent *BoolWithInverseFlag) initialize() {
9090
parent.negativeFlag = &BoolFlag{
9191
Category: child.Category,
9292
DefaultText: child.DefaultText,
93-
Sources: ValueSourceChain{Chain: append([]ValueSource{}, child.Sources.Chain...)},
93+
Sources: NewValueSourceChain(child.Sources.Chain...),
9494
Usage: child.Usage,
9595
Required: child.Required,
9696
Hidden: child.Hidden,
@@ -109,12 +109,13 @@ func (parent *BoolWithInverseFlag) initialize() {
109109
parent.negativeFlag.Name = parent.inverseName()
110110
parent.negativeFlag.Aliases = parent.inverseAliases()
111111

112-
if len(child.Sources.Chain) > 0 {
113-
parent.negativeFlag.Sources = ValueSourceChain{Chain: make([]ValueSource, len(child.Sources.Chain))}
112+
if len(child.Sources.EnvKeys()) > 0 {
113+
sources := []ValueSource{}
114114

115-
for idx, envVar := range child.GetEnvVars() {
116-
parent.negativeFlag.Sources.Chain[idx] = &envVarValueSource{Key: strings.ToUpper(parent.InversePrefix) + envVar}
115+
for _, envVar := range child.GetEnvVars() {
116+
sources = append(sources, &envVarValueSource{Key: strings.ToUpper(parent.InversePrefix) + envVar})
117117
}
118+
parent.negativeFlag.Sources = NewValueSourceChain(sources...)
118119
}
119120
}
120121

flag_impl.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -238,15 +238,7 @@ func (f *FlagBase[T, C, V]) GetUsage() string {
238238

239239
// GetEnvVars returns the env vars for this flag
240240
func (f *FlagBase[T, C, V]) GetEnvVars() []string {
241-
vals := []string{}
242-
243-
for _, src := range f.Sources.Chain {
244-
if v, ok := src.(*envVarValueSource); ok {
245-
vals = append(vals, v.Key)
246-
}
247-
}
248-
249-
return vals
241+
return f.Sources.EnvKeys()
250242
}
251243

252244
// TakesValue returns true if the flag takes a value, otherwise false

godoc-current.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,8 @@ type ValueSource interface {
967967
ValueSource is a source which can be used to look up a value, typically for
968968
use with a cli.Flag
969969

970+
func EnvVar(key string) ValueSource
971+
970972
type ValueSourceChain struct {
971973
Chain []ValueSource
972974
}
@@ -981,6 +983,12 @@ func Files(paths ...string) ValueSourceChain
981983
Files is a helper function to encapsulate a number of fileValueSource
982984
together as a ValueSourceChain
983985

986+
func NewValueSourceChain(src ...ValueSource) ValueSourceChain
987+
988+
func (vsc *ValueSourceChain) Append(other ValueSourceChain)
989+
990+
func (vsc *ValueSourceChain) EnvKeys() []string
991+
984992
func (vsc *ValueSourceChain) GoString() string
985993

986994
func (vsc *ValueSourceChain) Lookup() (string, bool)

testdata/godoc-v3.x.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,8 @@ type ValueSource interface {
967967
ValueSource is a source which can be used to look up a value, typically for
968968
use with a cli.Flag
969969

970+
func EnvVar(key string) ValueSource
971+
970972
type ValueSourceChain struct {
971973
Chain []ValueSource
972974
}
@@ -981,6 +983,12 @@ func Files(paths ...string) ValueSourceChain
981983
Files is a helper function to encapsulate a number of fileValueSource
982984
together as a ValueSourceChain
983985

986+
func NewValueSourceChain(src ...ValueSource) ValueSourceChain
987+
988+
func (vsc *ValueSourceChain) Append(other ValueSourceChain)
989+
990+
func (vsc *ValueSourceChain) EnvKeys() []string
991+
984992
func (vsc *ValueSourceChain) GoString() string
985993

986994
func (vsc *ValueSourceChain) Lookup() (string, bool)

value_source.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,28 @@ type ValueSourceChain struct {
2424
Chain []ValueSource
2525
}
2626

27+
func NewValueSourceChain(src ...ValueSource) ValueSourceChain {
28+
return ValueSourceChain{
29+
Chain: src,
30+
}
31+
}
32+
33+
func (vsc *ValueSourceChain) Append(other ValueSourceChain) {
34+
vsc.Chain = append(vsc.Chain, other.Chain...)
35+
}
36+
37+
func (vsc *ValueSourceChain) EnvKeys() []string {
38+
vals := []string{}
39+
40+
for _, src := range vsc.Chain {
41+
if v, ok := src.(*envVarValueSource); ok {
42+
vals = append(vals, v.Key)
43+
}
44+
}
45+
46+
return vals
47+
}
48+
2749
func (vsc *ValueSourceChain) String() string {
2850
s := []string{}
2951

@@ -73,6 +95,12 @@ func (e *envVarValueSource) GoString() string {
7395
return fmt.Sprintf("&envVarValueSource{Key:%[1]q}", e.Key)
7496
}
7597

98+
func EnvVar(key string) ValueSource {
99+
return &envVarValueSource{
100+
Key: key,
101+
}
102+
}
103+
76104
// EnvVars is a helper function to encapsulate a number of
77105
// envVarValueSource together as a ValueSourceChain
78106
func EnvVars(keys ...string) ValueSourceChain {

value_source_test.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import (
1212

1313
func TestEnvVarValueSource(t *testing.T) {
1414
t.Run("implements ValueSource", func(t *testing.T) {
15-
src := &envVarValueSource{Key: "foo"}
15+
src := EnvVar("foo")
1616
require.Implements(t, (*ValueSource)(nil), src)
1717

1818
t.Run("not found", func(t *testing.T) {
1919
t.Setenv("foo", "bar")
2020

21-
src := &envVarValueSource{Key: "foo_1"}
21+
src := EnvVar("foo_1")
2222
_, ok := src.Lookup()
2323
require.False(t, ok)
2424
})
@@ -27,7 +27,7 @@ func TestEnvVarValueSource(t *testing.T) {
2727
t.Setenv("foo", "bar")
2828

2929
r := require.New(t)
30-
src := &envVarValueSource{Key: "foo"}
30+
src := EnvVar("foo")
3131

3232
str, ok := src.Lookup()
3333
r.True(ok)
@@ -37,15 +37,15 @@ func TestEnvVarValueSource(t *testing.T) {
3737
})
3838

3939
t.Run("implements fmt.Stringer", func(t *testing.T) {
40-
src := &envVarValueSource{Key: "foo"}
40+
src := EnvVar("foo")
4141
r := require.New(t)
4242

4343
r.Implements((*fmt.Stringer)(nil), src)
4444
r.Equal("environment variable \"foo\"", src.String())
4545
})
4646

4747
t.Run("implements fmt.GoStringer", func(t *testing.T) {
48-
src := &envVarValueSource{Key: "foo"}
48+
src := EnvVar("foo")
4949
r := require.New(t)
5050

5151
r.Implements((*fmt.GoStringer)(nil), src)
@@ -122,6 +122,16 @@ func TestFilePaths(t *testing.T) {
122122
r.Contains(src.String(), fmt.Sprintf("%[1]q", fileName))
123123
}
124124

125+
func TestValueSourceChainEnvKeys(t *testing.T) {
126+
chain := NewValueSourceChain(
127+
&staticValueSource{"hello"},
128+
)
129+
chain.Append(EnvVars("foo", "bar"))
130+
131+
r := require.New(t)
132+
r.Equal([]string{"foo", "bar"}, chain.EnvKeys())
133+
}
134+
125135
func TestValueSourceChain(t *testing.T) {
126136
t.Run("implements ValueSource", func(t *testing.T) {
127137
vsc := &ValueSourceChain{}
@@ -140,11 +150,10 @@ func TestValueSourceChain(t *testing.T) {
140150
r.Implements((*fmt.GoStringer)(nil), vsc)
141151
r.Equal("&ValueSourceChain{Chain:{}}", vsc.GoString())
142152

143-
vsc.Chain = []ValueSource{
144-
&staticValueSource{v: "yahtzee"},
153+
vsc1 := NewValueSourceChain(&staticValueSource{v: "yahtzee"},
145154
&staticValueSource{v: "matzoh"},
146-
}
147-
r.Equal("&ValueSourceChain{Chain:{&staticValueSource{v:\"yahtzee\"},&staticValueSource{v:\"matzoh\"}}}", vsc.GoString())
155+
)
156+
r.Equal("&ValueSourceChain{Chain:{&staticValueSource{v:\"yahtzee\"},&staticValueSource{v:\"matzoh\"}}}", vsc1.GoString())
148157
})
149158

150159
t.Run("implements fmt.Stringer", func(t *testing.T) {
@@ -154,12 +163,12 @@ func TestValueSourceChain(t *testing.T) {
154163
r.Implements((*fmt.Stringer)(nil), vsc)
155164
r.Equal("", vsc.String())
156165

157-
vsc.Chain = []ValueSource{
166+
vsc1 := NewValueSourceChain(
158167
&staticValueSource{v: "soup"},
159168
&staticValueSource{v: "salad"},
160169
&staticValueSource{v: "pumpkins"},
161-
}
162-
r.Equal("soup,salad,pumpkins", vsc.String())
170+
)
171+
r.Equal("soup,salad,pumpkins", vsc1.String())
163172
})
164173
}
165174

0 commit comments

Comments
 (0)