Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support listing enums in specified order #274

Merged
merged 2 commits into from Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 5 additions & 6 deletions context.go
Expand Up @@ -891,16 +891,15 @@ func checkEnum(value *Value, target reflect.Value) error {
return errors.Errorf("enum can only be applied to a slice or value")

default:
enumMap := value.EnumMap()
enumSlice := value.EnumSlice()
v := fmt.Sprintf("%v", target)
if enumMap[v] {
return nil
}
enums := []string{}
for enum := range enumMap {
for _, enum := range enumSlice {
if enum == v {
return nil
}
enums = append(enums, fmt.Sprintf("%q", enum))
}
sort.Strings(enums)
return fmt.Errorf("%s must be one of %s but got %q", value.ShortSummary(), strings.Join(enums, ","), target.Interface())
}
}
Expand Down
9 changes: 9 additions & 0 deletions kong_test.go
Expand Up @@ -663,6 +663,7 @@ func TestInterpolationIntoModel(t *testing.T) {
require.Equal(t, "Some default value.", flag.Default)
require.Equal(t, "Help, I need chickens!", flag.Help)
require.Equal(t, map[string]bool{"a": true, "b": true, "c": true, "d": true}, flag.EnumMap())
require.Equal(t, []string{"a", "b", "c", "d"}, flag.EnumSlice())
require.Equal(t, "One of a,b", flag2.Help)
require.Equal(t, "SAVE_THE_QUEEN", flag3.Env)
require.Equal(t, "God SAVE_THE_QUEEN", flag3.Help)
Expand Down Expand Up @@ -787,6 +788,14 @@ func TestEnum(t *testing.T) {
require.EqualError(t, err, "--flag must be one of \"a\",\"b\",\"c\" but got \"d\"")
}

func TestEnumMeaningfulOrder(t *testing.T) {
var cli struct {
Flag string `enum:"first,second,third,fourth,fifth" required:""`
}
_, err := mustNew(t, &cli).Parse([]string{"--flag", "sixth"})
require.EqualError(t, err, "--flag must be one of \"first\",\"second\",\"third\",\"fourth\",\"fifth\" but got \"sixth\"")
}

type commandWithHook struct {
value string
}
Expand Down
10 changes: 10 additions & 0 deletions model.go
Expand Up @@ -257,6 +257,16 @@ func (v *Value) EnumMap() map[string]bool {
return out
}

// EnumSlice returns a slice of the enums in this value.
func (v *Value) EnumSlice() []string {
parts := strings.Split(v.Enum, ",")
out := make([]string, len(parts))
for i, part := range parts {
out[i] = strings.TrimSpace(part)
}
return out
}

// ShortSummary returns a human-readable summary of the value, not including any placeholders/defaults.
func (v *Value) ShortSummary() string {
if v.Flag != nil {
Expand Down