From c6b26b8b9fd5c3becf46e4ee74f5727d995a31e0 Mon Sep 17 00:00:00 2001 From: jokemanfire Date: Mon, 13 Jan 2025 15:15:59 +0800 Subject: [PATCH] Add hashmap type show. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If flag is StringMapFlag ,it will print `--property string=string [--property string=string]…` Signed-off-by: jokemanfire --- flag.go | 6 +++--- flag_impl.go | 15 +++++++++++---- flag_test.go | 14 +++++++------- godoc-current.txt | 8 ++++---- testdata/godoc-v3.x.txt | 6 +++--- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/flag.go b/flag.go index c3a96b3018..063f9c4175 100644 --- a/flag.go +++ b/flag.go @@ -182,7 +182,7 @@ type LocalFlag interface { // FlagType is an interface to detect if a flag is a string, bool, etc. type FlagType interface { - GetFlagType() string + TypeName() string } func newFlagSet(name string, flags []Flag) (*flag.FlagSet, error) { @@ -312,8 +312,8 @@ func stringifyFlag(f Flag) string { // if needsPlaceholder is true, placeholder is empty if needsPlaceholder && placeholder == "" { // try to get type from flag - if v1, ok := f.(FlagType); ok && v1.GetFlagType() != "" { - placeholder = v1.GetFlagType() + if ft, ok := f.(FlagType); ok && ft.TypeName() != "" { + placeholder = ft.TypeName() } else { placeholder = defaultPlaceholder } diff --git a/flag_impl.go b/flag_impl.go index bf294b00c9..6e3323b9d9 100644 --- a/flag_impl.go +++ b/flag_impl.go @@ -98,18 +98,25 @@ func (f *FlagBase[T, C, V]) GetValue() string { return fmt.Sprintf("%v", f.Value) } -// GetFlagType returns the type of the flag. -func (f *FlagBase[T, C, V]) GetFlagType() string { +// TypeName returns the type of the flag. +func (f *FlagBase[T, C, V]) TypeName() string { ty := reflect.TypeOf(f.Value) if ty == nil { return "" } + switch ty.Kind() { // if it is a Slice, then return the slice's inner type. Will nested slices be used in the future? - if ty.Kind() == reflect.Slice { + case reflect.Slice: elemType := ty.Elem() return elemType.Name() + // if it is a Map, then return the map's key and value types. + case reflect.Map: + keyType := ty.Key() + valueType := ty.Elem() + return fmt.Sprintf("%s=%s", keyType.Name(), valueType.Name()) + default: + return ty.Name() } - return ty.Name() } // Apply populates the flag given the flag set and environment diff --git a/flag_test.go b/flag_test.go index 0414e4e154..c020185cde 100644 --- a/flag_test.go +++ b/flag_test.go @@ -2706,7 +2706,7 @@ func TestFlagDefaultValue(t *testing.T) { name: "stringMap", flag: &StringMapFlag{Name: "flag", Value: map[string]string{"default1": "default2"}}, toParse: []string{"--flag", "parsed="}, - expect: `--flag value [ --flag value ] (default: default1="default2")`, + expect: `--flag string=string [ --flag string=string ] (default: default1="default2")`, }, } for _, v := range cases { @@ -2845,7 +2845,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { name: "stringMap", flag: &StringMapFlag{Name: "flag", Value: map[string]string{"default1": "default2"}, Sources: EnvVars("ssflag")}, toParse: []string{"--flag", "parsed="}, - expect: `--flag value [ --flag value ] (default: default1="default2")` + withEnvHint([]string{"ssflag"}, ""), + expect: `--flag string=string [ --flag string=string ] (default: default1="default2")` + withEnvHint([]string{"ssflag"}, ""), environ: map[string]string{ "ssflag": "some-other-env_value=", }, @@ -3007,11 +3007,11 @@ var stringMapFlagTests = []struct { value map[string]string expected string }{ - {"foo", nil, nil, "--foo value [ --foo value ]\t"}, - {"f", nil, nil, "-f value [ -f value ]\t"}, - {"f", nil, map[string]string{"Lipstick": ""}, "-f value [ -f value ]\t(default: Lipstick=)"}, - {"test", nil, map[string]string{"Something": ""}, "--test value [ --test value ]\t(default: Something=)"}, - {"dee", []string{"d"}, map[string]string{"Inka": "Dinka", "dooo": ""}, "--dee value, -d value [ --dee value, -d value ]\t(default: Inka=\"Dinka\", dooo=)"}, + {"foo", nil, nil, "--foo string=string [ --foo string=string ]\t"}, + {"f", nil, nil, "-f string=string [ -f string=string ]\t"}, + {"f", nil, map[string]string{"Lipstick": ""}, "-f string=string [ -f string=string ]\t(default: Lipstick=)"}, + {"test", nil, map[string]string{"Something": ""}, "--test string=string [ --test string=string ]\t(default: Something=)"}, + {"dee", []string{"d"}, map[string]string{"Inka": "Dinka", "dooo": ""}, "--dee string=string, -d string=string [ --dee string=string, -d string=string ]\t(default: Inka=\"Dinka\", dooo=)"}, } func TestStringMapFlagHelpOutput(t *testing.T) { diff --git a/godoc-current.txt b/godoc-current.txt index d6ed0ddca6..d4743f5ba6 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -705,9 +705,6 @@ func (f *FlagBase[T, C, V]) GetDefaultText() string func (f *FlagBase[T, C, V]) GetEnvVars() []string GetEnvVars returns the env vars for this flag -func (f *FlagBase[T, C, V]) GetFlagType() string - GetFlagType returns the type of the flag. - func (f *FlagBase[T, C, V]) GetUsage() string GetUsage returns the usage string for the flag @@ -748,6 +745,9 @@ func (f *FlagBase[T, C, V]) String() string func (f *FlagBase[T, C, V]) TakesValue() bool TakesValue returns true if the flag takes a value, otherwise false +func (f *FlagBase[T, C, V]) TypeName() string + TypeName returns the type of the flag. + type FlagCategories interface { // AddFlags adds a flag to a category, creating a new category if necessary. AddFlag(category string, fl Flag) @@ -789,7 +789,7 @@ var FlagStringer FlagStringFunc = stringifyFlag display a flag. type FlagType interface { - GetFlagType() string + TypeName() string } FlagType is an interface to detect if a flag is a string, bool, etc. diff --git a/testdata/godoc-v3.x.txt b/testdata/godoc-v3.x.txt index d6ed0ddca6..ec7cc438fc 100644 --- a/testdata/godoc-v3.x.txt +++ b/testdata/godoc-v3.x.txt @@ -705,8 +705,8 @@ func (f *FlagBase[T, C, V]) GetDefaultText() string func (f *FlagBase[T, C, V]) GetEnvVars() []string GetEnvVars returns the env vars for this flag -func (f *FlagBase[T, C, V]) GetFlagType() string - GetFlagType returns the type of the flag. +func (f *FlagBase[T, C, V]) TypeName() string + TypeName returns the type of the flag. func (f *FlagBase[T, C, V]) GetUsage() string GetUsage returns the usage string for the flag @@ -789,7 +789,7 @@ var FlagStringer FlagStringFunc = stringifyFlag display a flag. type FlagType interface { - GetFlagType() string + TypeName() string } FlagType is an interface to detect if a flag is a string, bool, etc.