diff --git a/README.md b/README.md index 44a7a5d..bb791e5 100644 --- a/README.md +++ b/README.md @@ -414,6 +414,7 @@ Tag | Description `group:"X"` | Logical group for a flag or command. `prefix:"X"` | Prefix for all sub-flags. `set:"K=V"` | Set a variable for expansion by child elements. Multiples can occur. +`embed` | If present, this field's children will be embedded in the parent. Useful for composition. ## Variable interpolation diff --git a/build.go b/build.go index ae1ccf7..0616785 100644 --- a/build.go +++ b/build.go @@ -52,7 +52,7 @@ func flattenedFields(v reflect.Value) (out []flattenedField) { if tag.Ignored { continue } - if ft.Anonymous { + if ft.Anonymous || tag.Embed { if fv.Kind() == reflect.Interface { fv = fv.Elem() } diff --git a/kong_test.go b/kong_test.go index 2bd8a7b..450f711 100644 --- a/kong_test.go +++ b/kong_test.go @@ -626,3 +626,19 @@ func TestExcludedField(t *testing.T) { _, err = p.Parse([]string{"--excluded=foo"}) require.Error(t, err) } + +func TestUnnamedFieldEmbeds(t *testing.T) { + type Embed struct { + Flag string + } + var cli struct { + One Embed `prefix:"one-" embed:""` + Two Embed `prefix:"two-" embed:""` + } + buf := &strings.Builder{} + p := mustNew(t, &cli, kong.Writers(buf, buf), kong.Exit(func(int) {})) + _, err := p.Parse([]string{"--help"}) + require.NoError(t, err) + require.Contains(t, buf.String(), `--one-flag=STRING`) + require.Contains(t, buf.String(), `--two-flag=STRING`) +} diff --git a/tag.go b/tag.go index 7167a9e..a5d7030 100644 --- a/tag.go +++ b/tag.go @@ -29,6 +29,7 @@ type Tag struct { Group string Vars Vars Prefix string // Optional prefix on anonymous structs. All sub-flags will have this prefix. + Embed bool // Storage for all tag keys for arbitrary lookups. items map[string][]string @@ -151,6 +152,7 @@ func parseTag(fv reflect.Value, ft reflect.StructField) *Tag { t.Sep, _ = t.GetRune("sep") t.Group = t.Get("group") t.Prefix = t.Get("prefix") + t.Embed = t.Has("embed") if t.Sep == 0 { if t.Get("sep") == "none" { t.Sep = -1 diff --git a/tag_test.go b/tag_test.go index 5276788..5f155a2 100644 --- a/tag_test.go +++ b/tag_test.go @@ -138,3 +138,14 @@ func TestTagSetOnCommand(t *testing.T) { require.NoError(t, err) require.Contains(t, buf.String(), `A key from somewhere.`) } + +func TestTagSetOnFlag(t *testing.T) { + var cli struct { + Flag string `set:"where=somewhere" help:"A key from ${where}."` + } + buf := &strings.Builder{} + p := mustNew(t, &cli, kong.Writers(buf, buf), kong.Exit(func(int) {})) + _, err := p.Parse([]string{"--help"}) + require.NoError(t, err) + require.Contains(t, buf.String(), `A key from somewhere.`) +}