diff --git a/flag_bool_with_inverse.go b/flag_bool_with_inverse.go index d885bbda93..e17b0b41f1 100644 --- a/flag_bool_with_inverse.go +++ b/flag_bool_with_inverse.go @@ -146,7 +146,7 @@ func (bif *BoolWithInverseFlag) Set(name, val string) error { if slices.Contains(append([]string{bif.Name}, bif.Aliases...), name) { if bif.nset { - return fmt.Errorf("cannot set both flags `--%s` and `--%s`", bif.Name, bif.inversePrefix()+bif.Name) + return bif.errBothSet() } if err := bif.value.Set(val); err != nil { return err @@ -154,7 +154,7 @@ func (bif *BoolWithInverseFlag) Set(name, val string) error { bif.pset = true } else { if bif.pset { - return fmt.Errorf("cannot set both flags `--%s` and `--%s`", bif.Name, bif.inversePrefix()+bif.Name) + return bif.errBothSet() } if err := bif.value.Set("false"); err != nil { return err @@ -169,6 +169,13 @@ func (bif *BoolWithInverseFlag) Set(name, val string) error { return nil } +// errBothSet reports that both the flag and its inverse were set, with the +// same `-` or `--` prefix the help output uses. +func (bif *BoolWithInverseFlag) errBothSet() error { + inverse := bif.inversePrefix() + bif.Name + return fmt.Errorf("cannot set both flags `%s%s` and `%s%s`", prefixFor(bif.Name), bif.Name, prefixFor(inverse), inverse) +} + func (bif *BoolWithInverseFlag) Names() []string { names := append([]string{bif.Name}, bif.Aliases...) @@ -203,12 +210,8 @@ func (bif *BoolWithInverseFlag) String() string { i := strings.Index(out, "\t") - prefix := "--" - // single character flags are prefixed with `-` instead of `--` - if len(bif.Name) == 1 { - prefix = "-" - } + prefix := prefixFor(bif.Name) // Guard against a FlagStringer that returns a string without a tab (e.g. // a custom stringer or the default stringer when the flag does not @@ -220,11 +223,7 @@ func (bif *BoolWithInverseFlag) String() string { var aliasParts []string for _, alias := range bif.Aliases { - aPrefix := "--" - if len(alias) == 1 { - aPrefix = "-" - } - aliasParts = append(aliasParts, aPrefix+alias) + aliasParts = append(aliasParts, prefixFor(alias)+alias) } names := fmt.Sprintf("%s[%s]%s", prefix, bif.inversePrefix(), bif.Name) diff --git a/flag_bool_with_inverse_test.go b/flag_bool_with_inverse_test.go index 895c33d7ec..8d262ca40e 100644 --- a/flag_bool_with_inverse_test.go +++ b/flag_bool_with_inverse_test.go @@ -292,6 +292,34 @@ func TestBoolWithInverseWithPrefix(t *testing.T) { } } +func TestBoolWithInverseSingleCharName(t *testing.T) { + for _, name := range []string{"e", "ü"} { + flagMethod := func() *BoolWithInverseFlag { + return &BoolWithInverseFlag{ + Name: name, + } + } + + errBothSet := fmt.Errorf("cannot set both flags `-%s` and `--no-%s`", name, name) + testCases := []*boolWithInverseTestCase{ + { + args: []string{"-" + name, "--no-" + name}, + err: errBothSet, + }, + { + args: []string{"--no-" + name, "-" + name}, + err: errBothSet, + }, + } + + err := runBoolWithInverseFlagTests(t, flagMethod, testCases) + if err != nil { + t.Error(err) + return + } + } +} + func TestBoolWithInverseRequired(t *testing.T) { flagMethod := func() *BoolWithInverseFlag { return &BoolWithInverseFlag{ @@ -367,6 +395,12 @@ func TestBoolWithInverseString(t *testing.T) { required: true, expected: "-[no-]e\t", }, + { + testName: "single-char multibyte flag name", + flagName: "ü", + required: true, + expected: "-[no-]ü\t", + }, { testName: "multi-char flag name", flagName: "env", @@ -412,6 +446,13 @@ func TestBoolWithInverseString(t *testing.T) { aliases: []string{"c"}, expected: "--[no-]color, -c\t(default: false)", }, + { + testName: "short multibyte alias", + flagName: "color", + required: false, + aliases: []string{"ü"}, + expected: "--[no-]color, -ü\t(default: false)", + }, { testName: "long alias", flagName: "color",