Make negatable flag name customisable (#439)
* fix: Check if negatable duplicates another flag
Add a check for flags with the `negatable` option if the negative flag
conflicts with another tag, such as:
Flag bool `negatable:""`
NoFlag bool
The flag `--no-flag` is ambiguous in this scenario.
* feat: Make negatable flag name customisable
Allow a value on the `negatable` tag to specify a flag name to use for
negation instead of using `--no-<flag-name>` as the flag.
e.g.
Approve bool `default:"true",negatable:"deny"`
This example will allow `--deny` to set the `Approve` field to false.
This commit is contained in:
+71
-22
@@ -357,8 +357,9 @@ func TestTraceErrorPartiallySucceeds(t *testing.T) {
|
||||
}
|
||||
|
||||
type commandWithNegatableFlag struct {
|
||||
Flag bool `kong:"default='true',negatable"`
|
||||
ran bool
|
||||
Flag bool `kong:"default='true',negatable"`
|
||||
Custom bool `kong:"default='true',negatable='standard'"`
|
||||
ran bool
|
||||
}
|
||||
|
||||
func (c *commandWithNegatableFlag) Run() error {
|
||||
@@ -368,34 +369,64 @@ func (c *commandWithNegatableFlag) Run() error {
|
||||
|
||||
func TestNegatableFlag(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
expected bool
|
||||
name string
|
||||
args []string
|
||||
expectedFlag bool
|
||||
expectedCustom bool
|
||||
}{
|
||||
{
|
||||
name: "no flag",
|
||||
args: []string{"cmd"},
|
||||
expected: true,
|
||||
name: "no flag",
|
||||
args: []string{"cmd"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: true,
|
||||
},
|
||||
{
|
||||
name: "boolean flag",
|
||||
args: []string{"cmd", "--flag"},
|
||||
expected: true,
|
||||
name: "boolean flag",
|
||||
args: []string{"cmd", "--flag"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: true,
|
||||
},
|
||||
{
|
||||
name: "inverted boolean flag",
|
||||
args: []string{"cmd", "--flag=false"},
|
||||
expected: false,
|
||||
name: "custom boolean flag",
|
||||
args: []string{"cmd", "--custom"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: true,
|
||||
},
|
||||
{
|
||||
name: "negated boolean flag",
|
||||
args: []string{"cmd", "--no-flag"},
|
||||
expected: false,
|
||||
name: "inverted boolean flag",
|
||||
args: []string{"cmd", "--flag=false"},
|
||||
expectedFlag: false,
|
||||
expectedCustom: true,
|
||||
},
|
||||
{
|
||||
name: "inverted negated boolean flag",
|
||||
args: []string{"cmd", "--no-flag=false"},
|
||||
expected: true,
|
||||
name: "custom inverted boolean flag",
|
||||
args: []string{"cmd", "--custom=false"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: false,
|
||||
},
|
||||
{
|
||||
name: "negated boolean flag",
|
||||
args: []string{"cmd", "--no-flag"},
|
||||
expectedFlag: false,
|
||||
expectedCustom: true,
|
||||
},
|
||||
{
|
||||
name: "custom negated boolean flag",
|
||||
args: []string{"cmd", "--standard"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: false,
|
||||
},
|
||||
{
|
||||
name: "inverted negated boolean flag",
|
||||
args: []string{"cmd", "--no-flag=false"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: true,
|
||||
},
|
||||
{
|
||||
name: "inverted custom negated boolean flag",
|
||||
args: []string{"cmd", "--standard=false"},
|
||||
expectedFlag: true,
|
||||
expectedCustom: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -408,16 +439,34 @@ func TestNegatableFlag(t *testing.T) {
|
||||
p := mustNew(t, &cli)
|
||||
kctx, err := p.Parse(tt.args)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, cli.Cmd.Flag)
|
||||
assert.Equal(t, tt.expectedFlag, cli.Cmd.Flag)
|
||||
assert.Equal(t, tt.expectedCustom, cli.Cmd.Custom)
|
||||
|
||||
err = kctx.Run()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, cli.Cmd.Flag)
|
||||
assert.Equal(t, tt.expectedFlag, cli.Cmd.Flag)
|
||||
assert.Equal(t, tt.expectedCustom, cli.Cmd.Custom)
|
||||
assert.True(t, cli.Cmd.ran)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateNegatableLong(t *testing.T) {
|
||||
cli2 := struct {
|
||||
NoFlag bool
|
||||
Flag bool `negatable:""` // negation duplicates NoFlag
|
||||
}{}
|
||||
_, err := kong.New(&cli2)
|
||||
assert.EqualError(t, err, "<anonymous struct>.Flag: duplicate negation flag --no-flag")
|
||||
|
||||
cli3 := struct {
|
||||
One bool
|
||||
Two bool `negatable:"one"` // negation duplicates Flag2
|
||||
}{}
|
||||
_, err = kong.New(&cli3)
|
||||
assert.EqualError(t, err, "<anonymous struct>.Two: duplicate negation flag --one")
|
||||
}
|
||||
|
||||
func TestExistingNoFlag(t *testing.T) {
|
||||
var cli struct {
|
||||
Cmd struct {
|
||||
|
||||
Reference in New Issue
Block a user