diff --git a/README.md b/README.md index fa90ad5..f0f519b 100644 --- a/README.md +++ b/README.md @@ -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"`. ## 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. diff --git a/mapper.go b/mapper.go index 1482f1b..a1d9058 100644 --- a/mapper.go +++ b/mapper.go @@ -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 { diff --git a/mapper_test.go b/mapper_test.go index e67cfc2..1ec9441 100644 --- a/mapper_test.go +++ b/mapper_test.go @@ -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:""` diff --git a/tag.go b/tag.go index a642e99..88380fe 100644 --- a/tag.go +++ b/tag.go @@ -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)