@@ -446,7 +446,7 @@ Tag | Description
|
|||||||
`mapsep:"X"` | Separator for maps (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.
|
`enum:"X,Y,..."` | Set of valid values allowed for this flag.
|
||||||
`group:"X"` | Logical group for a flag or command.
|
`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.
|
`xor:"X,Y,..."` | Exclusive OR groups for flags. Only one flag in the group can be used which is restricted within the same command.
|
||||||
`prefix:"X"` | Prefix for all sub-flags.
|
`prefix:"X"` | Prefix for all sub-flags.
|
||||||
`set:"K=V"` | Set a variable for expansion by child elements. Multiples can occur.
|
`set:"K=V"` | Set a variable for expansion by child elements. Multiples can occur.
|
||||||
`embed:""` | If present, this field's children will be embedded in the parent. Useful for composition.
|
`embed:""` | If present, this field's children will be embedded in the parent. Useful for composition.
|
||||||
|
|||||||
+5
-6
@@ -871,13 +871,12 @@ func checkXorDuplicates(paths []*Path) error {
|
|||||||
if !flag.Set {
|
if !flag.Set {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if flag.Xor == "" {
|
for _, xor := range flag.Xor {
|
||||||
continue
|
if seen[xor] != nil {
|
||||||
|
return fmt.Errorf("--%s and --%s can't be used together", seen[xor].Name, flag.Name)
|
||||||
|
}
|
||||||
|
seen[xor] = flag
|
||||||
}
|
}
|
||||||
if seen[flag.Xor] != nil {
|
|
||||||
return fmt.Errorf("--%s and --%s can't be used together", seen[flag.Xor].Name, flag.Name)
|
|
||||||
}
|
|
||||||
seen[flag.Xor] = flag
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -868,6 +868,22 @@ func TestXorChild(t *testing.T) {
|
|||||||
require.Error(t, err, "--two and --three can't be used together")
|
require.Error(t, err, "--two and --three can't be used together")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMultiXor(t *testing.T) {
|
||||||
|
var cli struct {
|
||||||
|
Hello bool `xor:"one,two"`
|
||||||
|
One bool `xor:"one"`
|
||||||
|
Two string `xor:"two"`
|
||||||
|
}
|
||||||
|
|
||||||
|
p := mustNew(t, &cli)
|
||||||
|
_, err := p.Parse([]string{"--hello", "--one"})
|
||||||
|
require.EqualError(t, err, "--hello and --one can't be used together")
|
||||||
|
|
||||||
|
p = mustNew(t, &cli)
|
||||||
|
_, err = p.Parse([]string{"--hello", "--two=foo"})
|
||||||
|
require.EqualError(t, err, "--hello and --two can't be used together")
|
||||||
|
}
|
||||||
|
|
||||||
func TestEnumSequence(t *testing.T) {
|
func TestEnumSequence(t *testing.T) {
|
||||||
var cli struct {
|
var cli struct {
|
||||||
State []string `enum:"a,b,c" default:"a"`
|
State []string `enum:"a,b,c" default:"a"`
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ type Positional = Value
|
|||||||
type Flag struct {
|
type Flag struct {
|
||||||
*Value
|
*Value
|
||||||
Group *Group // Logical grouping when displaying. May also be used by configuration loaders to group options logically.
|
Group *Group // Logical grouping when displaying. May also be used by configuration loaders to group options logically.
|
||||||
Xor string
|
Xor []string
|
||||||
PlaceHolder string
|
PlaceHolder string
|
||||||
Env string
|
Env string
|
||||||
Short rune
|
Short rune
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type Tag struct {
|
|||||||
MapSep rune
|
MapSep rune
|
||||||
Enum string
|
Enum string
|
||||||
Group string
|
Group string
|
||||||
Xor string
|
Xor []string
|
||||||
Vars Vars
|
Vars Vars
|
||||||
Prefix string // Optional prefix on anonymous structs. All sub-flags will have this prefix.
|
Prefix string // Optional prefix on anonymous structs. All sub-flags will have this prefix.
|
||||||
Embed bool
|
Embed bool
|
||||||
@@ -125,6 +125,10 @@ func newEmptyTag() *Tag {
|
|||||||
return &Tag{items: map[string][]string{}}
|
return &Tag{items: map[string][]string{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tagSplitFn(r rune) bool {
|
||||||
|
return r == ',' || r == ' '
|
||||||
|
}
|
||||||
|
|
||||||
func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
|
func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
|
||||||
if ft.Tag.Get("kong") == "-" {
|
if ft.Tag.Get("kong") == "-" {
|
||||||
t := newEmptyTag()
|
t := newEmptyTag()
|
||||||
@@ -164,7 +168,9 @@ func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
|
|||||||
t.Sep, _ = t.GetSep("sep", ',')
|
t.Sep, _ = t.GetSep("sep", ',')
|
||||||
t.MapSep, _ = t.GetSep("mapsep", ';')
|
t.MapSep, _ = t.GetSep("mapsep", ';')
|
||||||
t.Group = t.Get("group")
|
t.Group = t.Get("group")
|
||||||
t.Xor = t.Get("xor")
|
for _, xor := range t.GetAll("xor") {
|
||||||
|
t.Xor = append(t.Xor, strings.FieldsFunc(xor, tagSplitFn)...)
|
||||||
|
}
|
||||||
t.Prefix = t.Get("prefix")
|
t.Prefix = t.Get("prefix")
|
||||||
t.Embed = t.Has("embed")
|
t.Embed = t.Has("embed")
|
||||||
negatable := t.Has("negatable")
|
negatable := t.Has("negatable")
|
||||||
@@ -172,12 +178,9 @@ func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
|
|||||||
fail("negatable can only be set on booleans")
|
fail("negatable can only be set on booleans")
|
||||||
}
|
}
|
||||||
t.Negatable = negatable
|
t.Negatable = negatable
|
||||||
splitFn := func(r rune) bool {
|
|
||||||
return r == ',' || r == ' '
|
|
||||||
}
|
|
||||||
aliases := t.Get("aliases")
|
aliases := t.Get("aliases")
|
||||||
if len(aliases) > 0 {
|
if len(aliases) > 0 {
|
||||||
t.Aliases = append(t.Aliases, strings.FieldsFunc(aliases, splitFn)...)
|
t.Aliases = append(t.Aliases, strings.FieldsFunc(aliases, tagSplitFn)...)
|
||||||
}
|
}
|
||||||
t.Vars = Vars{}
|
t.Vars = Vars{}
|
||||||
for _, set := range t.GetAll("set") {
|
for _, set := range t.GetAll("set") {
|
||||||
|
|||||||
Reference in New Issue
Block a user