diff --git a/context.go b/context.go index d01abfd..d132b7d 100644 --- a/context.go +++ b/context.go @@ -635,12 +635,7 @@ func (c *Context) Apply() (string, error) { panic("unsupported path ?!") } if value != nil { - v := c.getValue(value) - if value.Flag != nil && value.Flag.Negated { - v.SetBool(!v.Bool()) - } - - value.Apply(v) + value.Apply(c.getValue(value)) } } @@ -673,6 +668,11 @@ func (c *Context) parseFlag(flags []*Flag, match string) (err error) { } return err } + if flag.Negated { + value := c.getValue(flag.Value) + value.SetBool(!value.Bool()) + flag.Value.Apply(value) + } c.Path = append(c.Path, &Path{Flag: flag}) return nil } diff --git a/kong_test.go b/kong_test.go index 2f333b7..6dec560 100644 --- a/kong_test.go +++ b/kong_test.go @@ -356,30 +356,66 @@ 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',negatable"` - } `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 commandWithNegatableFlag struct { + Flag bool `kong:"default='true',negatable"` + ran bool } -func TestInvertedNegatedBooleanFlag(t *testing.T) { - var cli struct { - Cmd struct { - Flag bool `kong:"default='true',negatable"` - } `kong:"cmd"` - } +func (c *commandWithNegatableFlag) Run() error { + c.ran = true + return nil +} - p := mustNew(t, &cli) - _, err := p.Parse([]string{"cmd", "--no-flag=false"}) - require.NoError(t, err) - require.Equal(t, true, cli.Cmd.Flag) +func TestNegatableFlag(t *testing.T) { + tests := []struct { + name string + args []string + expected bool + }{ + { + name: "no flag", + args: []string{"cmd"}, + expected: true, + }, + { + name: "boolean flag", + args: []string{"cmd", "--flag"}, + expected: true, + }, + { + name: "inverted boolean flag", + args: []string{"cmd", "--flag=false"}, + expected: false, + }, + { + name: "negated boolean flag", + args: []string{"cmd", "--no-flag"}, + expected: false, + }, + { + name: "inverted negated boolean flag", + args: []string{"cmd", "--no-flag=false"}, + expected: true, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + var cli struct { + Cmd commandWithNegatableFlag `kong:"cmd"` + } + + p := mustNew(t, &cli) + kctx, err := p.Parse(tt.args) + require.NoError(t, err) + require.Equal(t, tt.expected, cli.Cmd.Flag) + + err = kctx.Run() + require.NoError(t, err) + require.Equal(t, tt.expected, cli.Cmd.Flag) + require.True(t, cli.Cmd.ran) + }) + } } func TestExistingNoFlag(t *testing.T) {