alecthomas / kong

Kong is a command-line parser for Go
MIT License
2.16k stars 140 forks source link

xor isn't supported with enum flags #215

Open shueybubbles opened 3 years ago

shueybubbles commented 3 years ago

I'd like to be able to xor two flags, where one flag is a string with lots of options and another flag is a bool. If the user uses the bool the enum flag should get assigned its default value.

IE this test should pass:


func TestXorEnum(t *testing.T) {
    var cli struct {
        One string `xor:"a" default:"None" enum:"A,B,C,None"`
        Two bool   `xor:"a"`
    }
    p := mustNew(t, &cli)
    _, err := p.Parse([]string{"--two"})
    require.NoError(t, err)
        require.Equal(t, "None", cli.One)
}

Today it fails

--- FAIL: TestXorEnum (0.00s)
    kong_test.go:846:
                Error Trace:    kong_test.go:846
                Error:          Received unexpected error:
                                --one and --two can't be used together
                Test:           TestXorEnum
shueybubbles commented 3 years ago

PS when is your next release tag planned? I would like an official tag with the fix for multiple xor groups, please.

alecthomas commented 3 years ago

Huhh, interesting bug, thanks for the report.

Re. release you can use @master without having to wait for a release.

alecthomas commented 3 years ago

On reflection does this make sense? --one will always be set, defeating the purpose of xor

shueybubbles commented 3 years ago

I thought the purpose of xor is to block the user from setting two flags, not from the underlying structure having a value. What I really want is this semantic for my sqlcmd replacement:

-E : Ignore environment variables and use Windows authentication -G [ActiveDirectoryInteractive | ActiveDirectoryManagedInstance | ActiveDirectoryDefault] Force Azure Active Directory Authentication

E and G are mutually exclusive. I would like the field that backs G to be assigned an empty value if not chosen but you now require some non-empty value for default. I'd prefer not to expose the default value as a user choice since it makes no sense to pass -G None

Maybe the "ideal" interface is to have a single switch which combines all the possible authentication types into one list but I have backwards compatibility requirements to abide by.

alecthomas commented 3 years ago

I more meant that there's no way to differentiate between -G None and not having passed a flag at all, but now that you've reminded me about enums requiring a default it makes sense.

That said, it's not clear to me what the right solution here is :\

Murat343434 commented 2 years ago

@shueybubbles