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:
Joe Schmitt
2021-02-18 02:49:07 -05:00
committed by Alec Thomas
parent 541ee3302f
commit 2a0d7af9c5
3 changed files with 22 additions and 1 deletions
+8 -1
View File
@@ -579,6 +579,9 @@ func (c *Context) getValue(value *Value) reflect.Value {
}
c.values[value] = v
}
if value.Flag != nil && value.Flag.Negated {
v.SetBool(false)
}
return v
}
@@ -639,15 +642,19 @@ func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
for _, flag := range flags {
long := "--" + flag.Name
short := "-" + string(flag.Short)
neg := "--no-" + flag.Name
candidates = append(candidates, long)
if flag.Short != 0 {
candidates = append(candidates, short)
}
if short != match && long != match {
if short != match && long != match && neg != match {
continue
}
// Found a matching flag.
c.scan.Pop()
if flag.Value.IsBool() && match == neg {
flag.Negated = true
}
err := flag.Parse(c.scan, c.getValue(flag.Value))
if err != nil {
if e, ok := errors.Cause(err).(*expectedError); ok && e.token.InferredType().IsAny(FlagToken, ShortFlagToken) {
+13
View File
@@ -356,6 +356,19 @@ func TestTraceErrorPartiallySucceeds(t *testing.T) {
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 {
cmd bool
values []string
+1
View File
@@ -227,6 +227,7 @@ type Value struct {
Tag *Tag
Target reflect.Value
Required bool
Negated bool
Set bool // Set to true when this value is set through some mechanism.
Format string // Formatting directive, if applicable.
Position int // Position (for positional arguments).