Add support for negated boolean flags
Will automatically set a boolean Struct field to false if the flag starts with `--no-`, even when the default is `true`.
For example:
```
type Cmd struct {
Output bool `default:"true"`
}
```
Calling
```
command
```
Will set `Output` to `true`, but
```
command --no-output
```
Will set `Output` to `false`.
This commit is contained in:
+8
-1
@@ -579,6 +579,9 @@ func (c *Context) getValue(value *Value) reflect.Value {
|
|||||||
}
|
}
|
||||||
c.values[value] = v
|
c.values[value] = v
|
||||||
}
|
}
|
||||||
|
if value.Flag != nil && value.Flag.Negated {
|
||||||
|
v.SetBool(false)
|
||||||
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,15 +642,19 @@ func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
|
|||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
long := "--" + flag.Name
|
long := "--" + flag.Name
|
||||||
short := "-" + string(flag.Short)
|
short := "-" + string(flag.Short)
|
||||||
|
neg := "--no-" + flag.Name
|
||||||
candidates = append(candidates, long)
|
candidates = append(candidates, long)
|
||||||
if flag.Short != 0 {
|
if flag.Short != 0 {
|
||||||
candidates = append(candidates, short)
|
candidates = append(candidates, short)
|
||||||
}
|
}
|
||||||
if short != match && long != match {
|
if short != match && long != match && neg != match {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Found a matching flag.
|
// Found a matching flag.
|
||||||
c.scan.Pop()
|
c.scan.Pop()
|
||||||
|
if flag.Value.IsBool() && match == neg {
|
||||||
|
flag.Negated = true
|
||||||
|
}
|
||||||
err := flag.Parse(c.scan, c.getValue(flag.Value))
|
err := flag.Parse(c.scan, c.getValue(flag.Value))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if e, ok := errors.Cause(err).(*expectedError); ok && e.token.InferredType().IsAny(FlagToken, ShortFlagToken) {
|
if e, ok := errors.Cause(err).(*expectedError); ok && e.token.InferredType().IsAny(FlagToken, ShortFlagToken) {
|
||||||
|
|||||||
@@ -356,6 +356,19 @@ func TestTraceErrorPartiallySucceeds(t *testing.T) {
|
|||||||
require.Equal(t, "one", ctx.Command())
|
require.Equal(t, "one", ctx.Command())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNegatedBooleanFlag(t *testing.T) {
|
||||||
|
var cli struct {
|
||||||
|
Cmd struct {
|
||||||
|
Flag bool `kong:"default='true'"`
|
||||||
|
} `kong:"cmd"`
|
||||||
|
}
|
||||||
|
|
||||||
|
p := mustNew(t, &cli)
|
||||||
|
_, err := p.Parse([]string{"cmd", "--no-flag"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, false, cli.Cmd.Flag)
|
||||||
|
}
|
||||||
|
|
||||||
type hookContext struct {
|
type hookContext struct {
|
||||||
cmd bool
|
cmd bool
|
||||||
values []string
|
values []string
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ type Value struct {
|
|||||||
Tag *Tag
|
Tag *Tag
|
||||||
Target reflect.Value
|
Target reflect.Value
|
||||||
Required bool
|
Required bool
|
||||||
|
Negated bool
|
||||||
Set bool // Set to true when this value is set through some mechanism.
|
Set bool // Set to true when this value is set through some mechanism.
|
||||||
Format string // Formatting directive, if applicable.
|
Format string // Formatting directive, if applicable.
|
||||||
Position int // Position (for positional arguments).
|
Position int // Position (for positional arguments).
|
||||||
|
|||||||
Reference in New Issue
Block a user