pda/cmd/config_fields.go

55 lines
1.4 KiB
Go

package cmd
import "reflect"
// ConfigField represents a single leaf field in the Config struct,
// mapped to its dotted TOML key path.
type ConfigField struct {
Key string // dotted key, e.g. "git.auto_commit"
Value any // current value
Default any // value from defaultConfig()
IsDefault bool // Value == Default
Field reflect.Value // settable reflect.Value (from cfg pointer)
Kind reflect.Kind // field type kind
}
// configFields walks cfg and defaults in parallel, returning a ConfigField
// for every leaf field. Keys are built from TOML struct tags.
func configFields(cfg, defaults *Config) []ConfigField {
var fields []ConfigField
walk(reflect.ValueOf(cfg).Elem(), reflect.ValueOf(defaults).Elem(), "", &fields)
return fields
}
func walk(cv, dv reflect.Value, prefix string, out *[]ConfigField) {
ct := cv.Type()
for i := 0; i < ct.NumField(); i++ {
sf := ct.Field(i)
tag := sf.Tag.Get("toml")
if tag == "" || tag == "-" {
continue
}
key := tag
if prefix != "" {
key = prefix + "." + tag
}
cfv := cv.Field(i)
dfv := dv.Field(i)
if sf.Type.Kind() == reflect.Struct {
walk(cfv, dfv, key, out)
continue
}
*out = append(*out, ConfigField{
Key: key,
Value: cfv.Interface(),
Default: dfv.Interface(),
IsDefault: reflect.DeepEqual(cfv.Interface(), dfv.Interface()),
Field: cfv,
Kind: sf.Type.Kind(),
})
}
}