core/config/loader.go

123 lines
2.5 KiB
Go
Raw Permalink Normal View History

2023-11-02 22:04:28 +00:00
package config
import (
"os"
"reflect"
"regexp"
"strings"
"gitea.meta-tech.academy/go/core/style"
2023-11-02 22:04:28 +00:00
"gopkg.in/yaml.v3"
)
type Cfg interface {
GetVar() []VarConfig
GetStylesDef() []string
SetStyles(*style.Styles)
2023-11-02 22:04:28 +00:00
}
type VarConfig struct {
Name string `yaml:"name"`
Value string `yaml:"value"`
}
type ConfigLoader struct {
Var []VarConfig
Config interface{}
varDef *VarPattern
refstr []*reflect.Value
}
func LoadConfig(path string, out Cfg, varPattern *VarPattern) {
cl := &ConfigLoader{varDef: varPattern, refstr: []*reflect.Value{}}
data, err := os.ReadFile(path)
if err != nil {
panic(err)
}
if err = yaml.Unmarshal(data, out); err != nil {
panic(err)
}
cl.Var = out.GetVar()
cl.Config = out
cl.parse()
cl.refstr = []*reflect.Value{}
cl.buildStyles(out)
}
func (cl *ConfigLoader) buildStyles(out Cfg) {
styles := style.NewStyles()
for _, def := range out.GetStylesDef() {
s := style.NewStyleByDef(def)
styles.List[s.Name] = s
}
out.SetStyles(styles)
2023-11-02 22:04:28 +00:00
}
func (cl *ConfigLoader) findVarName(match string) string {
re := regexp.MustCompile(cl.varDef.getPatternCaptureName())
parts := re.FindStringSubmatch(match)
if len(parts) > 0 {
match = parts[1]
}
return match
}
func (cl *ConfigLoader) findVarValue(v string) string {
names := strings.SplitN(v, ".", 2)
if names[0] == "var" {
for _, varConfig := range cl.Var {
if varConfig.Name == names[1] {
v = varConfig.Value
}
}
}
return v
}
func (cl *ConfigLoader) findStringRef(ref reflect.Value) {
switch ref.Kind() {
case reflect.Ptr, reflect.Interface:
cl.findStringRef(ref.Elem())
case reflect.Struct:
for i := 0; i < ref.NumField(); i++ {
refc := ref.Field(i)
cl.findStringRef(refc)
}
case reflect.Slice:
if !ref.IsNil() {
for i := 0; i < ref.Len(); i++ {
refc := ref.Index(i)
cl.findStringRef(refc)
}
}
case reflect.String:
if ref.Len() > 0 {
cl.refstr = append(cl.refstr, &ref)
}
}
}
func (cl *ConfigLoader) parse() {
var name string
var tmp string
var parts []string
var re2 *regexp.Regexp
cl.findStringRef(reflect.ValueOf(&cl))
re := regexp.MustCompile(cl.varDef.getPatternVar())
for _, ref := range cl.refstr {
tmp = ref.String()
parts = re.FindStringSubmatch(tmp)
if len(parts) > 0 {
s := strings.SplitAfter(parts[1], cl.varDef.Close)
for _, part := range s {
name = cl.findVarName(part)
re2 = regexp.MustCompile(cl.varDef.getPatternVarName(name))
tmp = re2.ReplaceAllString(tmp, cl.findVarValue(name))
}
ref.SetString(tmp)
}
}
}