oh-my-posh/src/template/text.go

88 lines
2.2 KiB
Go
Raw Normal View History

2022-01-26 06:54:36 -08:00
package template
2021-02-07 01:54:36 -08:00
import (
"bytes"
2021-04-11 06:24:03 -07:00
"errors"
"fmt"
"oh-my-posh/environment"
"oh-my-posh/regex"
"strings"
2021-02-07 01:54:36 -08:00
"text/template"
)
const (
// Errors to show when the template handling fails
2022-01-26 06:54:36 -08:00
InvalidTemplate = "invalid template text"
IncorrectTemplate = "unable to create text based on template"
2021-02-07 01:54:36 -08:00
)
2022-01-26 06:54:36 -08:00
type Text struct {
2021-02-07 01:54:36 -08:00
Template string
Context interface{}
Env environment.Environment
2021-02-07 01:54:36 -08:00
}
type Data interface{}
type Context struct {
environment.TemplateCache
2022-01-18 00:48:47 -08:00
// Simple container to hold ANY object
Data
}
2022-01-26 06:54:36 -08:00
func (c *Context) init(t *Text) {
c.Data = t.Context
if cache := t.Env.TemplateCache(); cache != nil {
c.TemplateCache = *cache
return
2021-06-15 12:23:08 -07:00
}
}
2022-01-26 06:54:36 -08:00
func (t *Text) Render() (string, error) {
t.cleanTemplate()
2021-12-11 08:31:58 -08:00
tmpl, err := template.New("title").Funcs(funcMap()).Parse(t.Template)
2021-02-07 01:54:36 -08:00
if err != nil {
2022-01-26 06:54:36 -08:00
return "", errors.New(InvalidTemplate)
2021-02-07 01:54:36 -08:00
}
context := &Context{}
context.init(t)
2021-02-07 01:54:36 -08:00
buffer := new(bytes.Buffer)
defer buffer.Reset()
err = tmpl.Execute(buffer, context)
2021-02-07 01:54:36 -08:00
if err != nil {
2022-01-26 06:54:36 -08:00
return "", errors.New(IncorrectTemplate)
2021-02-07 01:54:36 -08:00
}
text := buffer.String()
// issue with missingkey=zero ignored for map[string]interface{}
// https://github.com/golang/go/issues/24963
text = strings.ReplaceAll(text, "<no value>", "")
return text, nil
}
2022-01-26 06:54:36 -08:00
func (t *Text) cleanTemplate() {
unknownVariable := func(variable string, knownVariables *[]string) (string, bool) {
variable = strings.TrimPrefix(variable, ".")
splitted := strings.Split(variable, ".")
if len(splitted) == 0 {
return "", false
}
for _, b := range *knownVariables {
if b == splitted[0] {
return "", false
}
}
*knownVariables = append(*knownVariables, splitted[0])
return splitted[0], true
}
knownVariables := []string{"Root", "PWD", "Folder", "Shell", "ShellVersion", "UserName", "HostName", "Env", "Data", "Code", "OS", "WSL"}
matches := regex.FindAllNamedRegexMatch(`(?: |{|\()(?P<var>(\.[a-zA-Z_][a-zA-Z0-9]*)+)`, t.Template)
for _, match := range matches {
if variable, OK := unknownVariable(match["var"], &knownVariables); OK {
pattern := fmt.Sprintf(`\.%s\b`, variable)
dataVar := fmt.Sprintf(".Data.%s", variable)
t.Template = regex.ReplaceAllString(pattern, t.Template, dataVar)
}
}
2021-02-07 01:54:36 -08:00
}