add support to make map separator configurable

This commit is contained in:
Rene Zbinden
2020-02-14 10:47:58 +01:00
committed by Alec Thomas
parent ca3a30c5f1
commit 529703d8d1
4 changed files with 23 additions and 2 deletions
+2 -1
View File
@@ -370,7 +370,7 @@ var CLI struct {
}
```
For flags, multiple key+value pairs should be separated by `;` eg. `--set="key1=value1;key2=value2"`.
For flags, multiple key+value pairs should be separated by `mapsep:"rune"` tag (defaults to `;`) eg. `--set="key1=value1;key2=value2"`.
<a id="markdown-custom-named-decoders" name="custom-named-decoders"></a>
## Custom named decoders
@@ -428,6 +428,7 @@ Tag | Description
`hidden` | If present, command or flag is hidden.
`format:"X"` | Format for parsing input, if supported.
`sep:"X"` | Separator for sequences (defaults to ","). May be `none` to disable splitting.
`mapsep:"X"` | Separator for maps (defaults to ";"). May be `none` to disable splitting.
`enum:"X,Y,..."` | Set of valid values allowed for this flag.
`group:"X"` | Logical group for a flag or command.
`xor:"X"` | Exclusive OR group for flags. Only one flag in the group can be used which is restricted within the same command.
+2 -1
View File
@@ -408,6 +408,7 @@ func mapDecoder(r *Registry) MapperFunc {
target.Set(reflect.MakeMap(target.Type()))
}
el := target.Type()
sep := ctx.Value.Tag.MapSep
var childScanner *Scanner
if ctx.Value.Flag != nil {
t := ctx.Scan.Pop()
@@ -417,7 +418,7 @@ func mapDecoder(r *Registry) MapperFunc {
}
switch v := t.Value.(type) {
case string:
childScanner = Scan(SplitEscaped(v, ';')...)
childScanner = Scan(SplitEscaped(v, sep)...)
case []map[string]interface{}:
for _, m := range v {
+10
View File
@@ -161,6 +161,16 @@ func TestMapWithMultipleValues(t *testing.T) {
require.Equal(t, map[string]string{"a": "b", "c": "d"}, cli.Value)
}
func TestMapWithDifferentSeparator(t *testing.T) {
var cli struct {
Value map[string]string `mapsep:","`
}
k := mustNew(t, &cli)
_, err := k.Parse([]string{"--value=a=b,c=d"})
require.NoError(t, err)
require.Equal(t, map[string]string{"a": "b", "c": "d"}, cli.Value)
}
func TestURLMapper(t *testing.T) {
var cli struct {
URL *url.URL `arg:""`
+9
View File
@@ -25,6 +25,7 @@ type Tag struct {
Short rune
Hidden bool
Sep rune
MapSep rune
Enum string
Group string
Xor string
@@ -151,6 +152,7 @@ func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
t.Hidden = t.Has("hidden")
t.Format = t.Get("format")
t.Sep, _ = t.GetRune("sep")
t.MapSep, _ = t.GetRune("mapsep")
t.Group = t.Get("group")
t.Xor = t.Get("xor")
t.Prefix = t.Get("prefix")
@@ -162,6 +164,13 @@ func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
t.Sep = ','
}
}
if t.MapSep == 0 {
if t.Get("mapsep") == "none" {
t.MapSep = -1
} else {
t.MapSep = ';'
}
}
t.Vars = Vars{}
for _, set := range t.GetAll("set") {
parts := strings.SplitN(set, "=", 2)