diff --git a/build.go b/build.go index bd46907..4a487b9 100644 --- a/build.go +++ b/build.go @@ -47,6 +47,9 @@ func flattenedFields(v reflect.Value) (out []flattenedField) { ft := v.Type().Field(i) fv := v.Field(i) tag := parseTag(fv, ft) + if tag.Ignored { + continue + } if ft.Anonymous { if fv.Kind() == reflect.Interface { fv = fv.Elem() @@ -68,7 +71,7 @@ func flattenedFields(v reflect.Value) (out []flattenedField) { } out = append(out, flattenedField{field: ft, value: fv, tag: tag}) } - return + return out } func buildNode(k *Kong, v reflect.Value, typ NodeType, seenFlags map[string]bool) *Node { diff --git a/kong_test.go b/kong_test.go index 3863c9e..2bd8a7b 100644 --- a/kong_test.go +++ b/kong_test.go @@ -613,3 +613,16 @@ func TestEmbedInterface(t *testing.T) { require.Equal(t, "foo", cli.SomeFlag) require.Equal(t, "yes", cli.TestInterface.(*TestImpl).Flag) } + +func TestExcludedField(t *testing.T) { + var cli struct { + Flag string + Excluded string `kong:"-"` + } + + p := mustNew(t, &cli) + _, err := p.Parse([]string{"--flag=foo"}) + require.NoError(t, err) + _, err = p.Parse([]string{"--excluded=foo"}) + require.Error(t, err) +} diff --git a/tag.go b/tag.go index 6669194..5ade2f1 100644 --- a/tag.go +++ b/tag.go @@ -10,6 +10,7 @@ import ( // Tag represents the parsed state of Kong tags in a struct field tag. type Tag struct { + Ignored bool // Field is ignored by Kong. ie. kong:"-" Cmd bool Arg bool Required bool @@ -39,7 +40,7 @@ type tagChars struct { var kongChars = tagChars{sep: ',', quote: '\'', assign: '='} var bareChars = tagChars{sep: ' ', quote: '"', assign: ':'} -func parseTagItems(s string, chr tagChars) map[string]string { +func parseTagItems(tagString string, chr tagChars) map[string]string { d := map[string]string{} key := []rune{} value := []rune{} @@ -53,7 +54,7 @@ func parseTagItems(s string, chr tagChars) map[string]string { inKey = true } - runes := []rune(s) + runes := []rune(tagString) for idx := 0; idx < len(runes); idx++ { r := runes[idx] next := rune(0) @@ -82,7 +83,7 @@ func parseTagItems(s string, chr tagChars) map[string]string { if next == chr.sep || eof { continue } - fail("%v has an unexpected char at pos %v", s, idx) + fail("%v has an unexpected char at pos %v", tagString, idx) } else { quotes = true continue @@ -95,7 +96,7 @@ func parseTagItems(s string, chr tagChars) map[string]string { } } if quotes { - fail("%v is not quoted properly", s) + fail("%v is not quoted properly", tagString) } add() @@ -113,6 +114,9 @@ func getTagInfo(ft reflect.StructField) (string, tagChars) { } func parseTag(fv reflect.Value, ft reflect.StructField) *Tag { + if ft.Tag.Get("kong") == "-" { + return &Tag{Ignored: true, items: map[string]string{}} + } s, chars := getTagInfo(ft) t := &Tag{ items: parseTagItems(s, chars),