diff --git a/templateutil/defaults.go b/templateutil/defaults.go new file mode 100644 index 0000000..f2e31d3 --- /dev/null +++ b/templateutil/defaults.go @@ -0,0 +1,45 @@ +package templateutil + +import ( + "encoding/base64" + "text/template" + "unicode" + + "github.com/symflower/pretty" + "github.com/zimmski/osutil/bytesutil" +) + +// DefaultFuncMap holds common template functions. +var DefaultFuncMap = template.FuncMap{ + "base64": func(in string) string { + return base64.StdEncoding.EncodeToString([]byte(in)) + }, + "prefixContinuationLinesWith": bytesutil.PrefixContinuationLinesWith, + "lowerFirst": func(s string) string { + return string(unicode.ToLower(rune(s[0]))) + s[1:] + }, + "pretty": func(data any) string { + return pretty.Sprintf("%# v", data) + }, + "prettyLazy": func(data any) string { + return pretty.LazySprintf("%# v", data) + }, + "quote": func(data any) string { + return pretty.Sprintf("%q", data) + }, +} + +// MergeFuncMaps returns all functions of "a" and all functions of "b" in a new function mapping. +// For entries that are defined in both maps the entry defined in b is chosen. +func MergeFuncMaps(a template.FuncMap, b template.FuncMap) template.FuncMap { + c := template.FuncMap{} + + for n, f := range a { + c[n] = f + } + for n, f := range b { + c[n] = f + } + + return c +} diff --git a/templateutil/file.go b/templateutil/file.go new file mode 100644 index 0000000..c9af39e --- /dev/null +++ b/templateutil/file.go @@ -0,0 +1,53 @@ +package templateutil + +import ( + "bytes" + "errors" + "os" + "path/filepath" + "text/template" + + pkgerrors "github.com/pkg/errors" + "github.com/symflower/pretty" +) + +// WriteTemplateToFile executes a template with the given data and saves the result into a file. +func WriteTemplateToFile(filePath string, tmpl *template.Template, data any) error { + var driver bytes.Buffer + + err := tmpl.Execute(&driver, data) + if err != nil { + return pkgerrors.Wrap(err, pretty.LazySprintf("%# v", data)) + } + + err = os.WriteFile(filePath, driver.Bytes(), 0640) + if err != nil { + return pkgerrors.Wrap(err, filePath) + } + + return nil +} + +// RewriteFileAsTemplate read in a file, execute it as a template with the given data and save the result into the same file. +func RewriteFileAsTemplate(filePath string, funcMap template.FuncMap, data any) (err error) { + tmpl, err := template.New(filepath.Base(filePath)).Funcs(funcMap).ParseFiles(filePath) // REMARK Use the file name as template identifier because otherwise `template.ParseFiles` fails. + if err != nil { + return pkgerrors.Wrap(err, filePath) + } + + f, err := os.Create(filePath) + if err != nil { + return pkgerrors.Wrap(err, filePath) + } + defer func() { + if e := f.Close(); e != nil { + err = errors.Join(err, e) + } + }() + + if err := tmpl.Execute(f, data); err != nil { + return pkgerrors.Wrap(err, filePath) + } + + return nil +}