Skip to content

Commit

Permalink
Merge pull request #1 from ConduitIO/add-support-to-struct
Browse files Browse the repository at this point in the history
feat: add support to nested structs
  • Loading branch information
raulb authored Dec 2, 2024
2 parents 1031f32 + 2b0b1c4 commit a81cef8
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ func (f Flags) SetDefault(long string, val any) bool {
return false
}

// BuildFlags creates a slice of Flags from a struct.
// It supports nested structs and will only generate flags if it finds a 'short' or 'long' tag.
func BuildFlags(obj any) Flags {
v := reflect.ValueOf(obj)
if v.Kind() != reflect.Ptr {
Expand All @@ -74,19 +76,39 @@ func BuildFlags(obj any) Flags {
if v.Kind() != reflect.Struct {
panic(fmt.Errorf("expected a struct, got %s", v.Kind()))
}

return buildFlagsRecursive(v)
}

func buildFlagsRecursive(v reflect.Value) Flags {
t := v.Type()
var flags Flags

var err error
flags := make([]Flag, t.NumField())
for i := 0; i < t.NumField(); i++ {
flags[i], err = buildFlag(v.Field(i), t.Field(i))
if err != nil {
panic(err)
field := t.Field(i)
fieldValue := v.Field(i)

// Only process fields with a 'short' or 'long' tag
if hasTag(field.Tag, "short") || hasTag(field.Tag, "long") {
flag, err := buildFlag(fieldValue, field)
if err != nil {
panic(err)
}
flags = append(flags, flag)
} else if fieldValue.Kind() == reflect.Struct {
// If the field is a struct, recurse into it
embeddedFlags := buildFlagsRecursive(fieldValue)
flags = append(flags, embeddedFlags...)
}
}
return flags
}

func hasTag(tag reflect.StructTag, key string) bool {
_, ok := tag.Lookup(key)
return ok
}

func buildFlag(val reflect.Value, sf reflect.StructField) (Flag, error) {
const (
tagNameLong = "long"
Expand Down

0 comments on commit a81cef8

Please sign in to comment.