2018-02-17 16:12:41 -02:00
|
|
|
package templater
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2023-08-29 21:04:01 +00:00
|
|
|
"maps"
|
2020-05-16 15:45:41 -03:00
|
|
|
"strings"
|
2018-02-17 16:12:41 -02:00
|
|
|
"text/template"
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
"github.com/go-task/task/v3/taskfile/ast"
|
2018-02-17 16:12:41 -02:00
|
|
|
)
|
|
|
|
|
|
|
|
// Templater is a help struct that allow us to call "replaceX" funcs multiple
|
|
|
|
// times, without having to check for error each time. The first error that
|
|
|
|
// happen will be assigned to r.err, and consecutive calls to funcs will just
|
|
|
|
// return the zero value.
|
|
|
|
type Templater struct {
|
2023-12-29 20:32:03 +00:00
|
|
|
Vars *ast.Vars
|
2018-02-17 16:12:41 -02:00
|
|
|
|
2023-03-30 20:03:59 +00:00
|
|
|
cacheMap map[string]any
|
2019-08-25 13:16:59 -07:00
|
|
|
err error
|
2018-02-17 16:12:41 -02:00
|
|
|
}
|
|
|
|
|
2019-09-14 17:54:41 -03:00
|
|
|
func (r *Templater) ResetCache() {
|
2019-08-25 13:16:59 -07:00
|
|
|
r.cacheMap = r.Vars.ToCacheMap()
|
2019-08-25 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2018-02-17 16:12:41 -02:00
|
|
|
func (r *Templater) Replace(str string) string {
|
2023-06-15 15:04:03 +00:00
|
|
|
return r.replace(str, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Templater) ReplaceWithExtra(str string, extra map[string]any) string {
|
|
|
|
return r.replace(str, extra)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Templater) replace(str string, extra map[string]any) string {
|
2018-02-17 16:12:41 -02:00
|
|
|
if r.err != nil || str == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
templ, err := template.New("").Funcs(templateFuncs).Parse(str)
|
|
|
|
if err != nil {
|
|
|
|
r.err = err
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2019-08-25 13:16:59 -07:00
|
|
|
if r.cacheMap == nil {
|
|
|
|
r.cacheMap = r.Vars.ToCacheMap()
|
2018-02-17 16:12:41 -02:00
|
|
|
}
|
|
|
|
|
|
|
|
var b bytes.Buffer
|
2023-06-15 15:04:03 +00:00
|
|
|
if extra == nil {
|
|
|
|
err = templ.Execute(&b, r.cacheMap)
|
|
|
|
} else {
|
|
|
|
// Copy the map to avoid modifying the cached map
|
|
|
|
m := maps.Clone(r.cacheMap)
|
|
|
|
maps.Copy(m, extra)
|
|
|
|
err = templ.Execute(&b, m)
|
|
|
|
}
|
|
|
|
if err != nil {
|
2018-02-17 16:12:41 -02:00
|
|
|
r.err = err
|
|
|
|
return ""
|
|
|
|
}
|
2023-12-29 20:26:02 +00:00
|
|
|
return strings.ReplaceAll(b.String(), "<no value>", "")
|
2018-02-17 16:12:41 -02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Templater) ReplaceSlice(strs []string) []string {
|
|
|
|
if r.err != nil || len(strs) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
new := make([]string, len(strs))
|
|
|
|
for i, str := range strs {
|
|
|
|
new[i] = r.Replace(str)
|
|
|
|
}
|
|
|
|
return new
|
|
|
|
}
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
func (r *Templater) ReplaceGlobs(globs []*ast.Glob) []*ast.Glob {
|
2023-11-29 19:38:12 -06:00
|
|
|
if r.err != nil || len(globs) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
new := make([]*ast.Glob, len(globs))
|
2023-11-29 19:38:12 -06:00
|
|
|
for i, g := range globs {
|
2023-12-29 20:32:03 +00:00
|
|
|
new[i] = &ast.Glob{
|
2023-11-29 19:38:12 -06:00
|
|
|
Glob: r.Replace(g.Glob),
|
|
|
|
Negate: g.Negate,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new
|
|
|
|
}
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
func (r *Templater) ReplaceVars(vars *ast.Vars) *ast.Vars {
|
2023-06-15 15:04:03 +00:00
|
|
|
return r.replaceVars(vars, nil)
|
|
|
|
}
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
func (r *Templater) ReplaceVarsWithExtra(vars *ast.Vars, extra map[string]any) *ast.Vars {
|
2023-06-15 15:04:03 +00:00
|
|
|
return r.replaceVars(vars, extra)
|
|
|
|
}
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
func (r *Templater) replaceVars(vars *ast.Vars, extra map[string]any) *ast.Vars {
|
2021-03-20 11:56:19 -03:00
|
|
|
if r.err != nil || vars.Len() == 0 {
|
2018-02-17 16:12:41 -02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-12-29 20:32:03 +00:00
|
|
|
var newVars ast.Vars
|
|
|
|
_ = vars.Range(func(k string, v ast.Var) error {
|
|
|
|
var newVar ast.Var
|
2023-11-29 16:21:21 +00:00
|
|
|
switch value := v.Value.(type) {
|
|
|
|
case string:
|
|
|
|
newVar.Value = r.ReplaceWithExtra(value, extra)
|
|
|
|
}
|
|
|
|
newVar.Live = v.Live
|
|
|
|
newVar.Sh = r.ReplaceWithExtra(v.Sh, extra)
|
2023-12-29 03:49:12 +00:00
|
|
|
newVar.Ref = v.Ref
|
|
|
|
newVar.Json = r.ReplaceWithExtra(v.Json, extra)
|
|
|
|
newVar.Yaml = r.ReplaceWithExtra(v.Yaml, extra)
|
2023-11-29 16:21:21 +00:00
|
|
|
newVars.Set(k, newVar)
|
2020-03-29 16:54:59 -03:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
2023-11-29 16:21:21 +00:00
|
|
|
return &newVars
|
2018-02-17 16:12:41 -02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Templater) Err() error {
|
|
|
|
return r.err
|
|
|
|
}
|