github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/vars/vars.go (about) 1 package vars 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 ) 8 9 type GenFn func() interface{} 10 11 type MapGenValue struct { 12 GenMap map[string]func(params string) GenFn 13 Map map[string]GenFn 14 MissedVars map[string]bool 15 Vars map[string]interface{} 16 } 17 18 func NewMapGenValue(m map[string]func(params string) GenFn) *MapGenValue { 19 return &MapGenValue{ 20 GenMap: m, 21 Map: make(map[string]GenFn), 22 Vars: make(map[string]interface{}), 23 MissedVars: make(map[string]bool), 24 } 25 } 26 27 func (m *MapGenValue) Value(name, params, expr string) interface{} { 28 return m.GetValue(name, params, expr) 29 } 30 31 func (m *MapGenValue) GetValue(name, params, expr string) interface{} { 32 if fn, ok := m.Map[name]; ok { 33 return fn() 34 } 35 36 var f GenFn 37 38 if fn, ok := m.GenMap[name]; ok { 39 ff := fn(params) 40 f = func() interface{} { 41 v := ff() 42 m.Vars[name] = v 43 return v 44 } 45 } else { 46 f = func() interface{} { return expr } 47 m.MissedVars[name] = true 48 } 49 50 m.Map[name] = f 51 return f() 52 } 53 54 type VarValue interface { 55 GetValue(name, params, expr string) interface{} 56 } 57 58 type VarValueHandler func(name, params, expr string) interface{} 59 60 func (v VarValueHandler) GetValue(name, params, expr string) interface{} { 61 return v(name, params, expr) 62 } 63 64 func EvalSubstitute(s string, varValue VarValue) string { 65 return ParseSubstitute(s).Eval(varValue) 66 } 67 68 type Part interface { 69 Eval(varValue VarValue) string 70 } 71 72 type Var struct { 73 Name string 74 Expr string 75 } 76 77 type Literal struct{ V string } 78 79 func (l Literal) Eval(VarValue) string { return l.V } 80 func (l Var) Eval(varValue VarValue) string { 81 return fmt.Sprintf("%s", varValue.GetValue(l.Name, "", l.Expr)) 82 } 83 84 func (l Parts) Eval(varValue VarValue) string { 85 sb := strings.Builder{} 86 for _, p := range l { 87 sb.WriteString(p.Eval(varValue)) 88 } 89 return sb.String() 90 } 91 92 type Parts []Part 93 94 var varRe = regexp.MustCompile(`\$?\{[^{}]+?\}|\{\{[^{}]+?\}\}`) 95 96 func ParseSubstitute(s string) (parts Parts) { 97 locs := varRe.FindAllStringSubmatchIndex(s, -1) 98 start := 0 99 100 for _, loc := range locs { 101 parts = append(parts, &Literal{V: s[start:loc[0]]}) 102 sub := s[loc[0]+1 : loc[1]-1] 103 sub = strings.TrimPrefix(sub, "{") 104 sub = strings.TrimSuffix(sub, "}") 105 start = loc[1] 106 107 vn := strings.TrimSpace(sub) 108 109 parts = append(parts, &Var{Name: vn, Expr: sub}) 110 } 111 112 if start < len(s) { 113 parts = append(parts, &Literal{V: s[start:]}) 114 } 115 116 return parts 117 }