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  }