You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.9 KiB
105 lines
2.9 KiB
2 years ago
|
package core
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"os"
|
||
|
"sync"
|
||
|
"text/template"
|
||
|
|
||
|
"github.com/mgutz/ansi"
|
||
|
)
|
||
|
|
||
|
// DisableColor can be used to make testing reliable
|
||
|
var DisableColor = false
|
||
|
|
||
|
var TemplateFuncsWithColor = map[string]interface{}{
|
||
|
// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
|
||
|
"color": ansi.ColorCode,
|
||
|
}
|
||
|
|
||
|
var TemplateFuncsNoColor = map[string]interface{}{
|
||
|
// Templates without Color formatting. For layout/ testing.
|
||
|
"color": func(color string) string {
|
||
|
return ""
|
||
|
},
|
||
|
}
|
||
|
|
||
|
// envColorDisabled returns if output colors are forbid by environment variables
|
||
|
func envColorDisabled() bool {
|
||
|
return os.Getenv("NO_COLOR") != "" || os.Getenv("CLICOLOR") == "0"
|
||
|
}
|
||
|
|
||
|
// envColorForced returns if output colors are forced from environment variables
|
||
|
func envColorForced() bool {
|
||
|
val, ok := os.LookupEnv("CLICOLOR_FORCE")
|
||
|
return ok && val != "0"
|
||
|
}
|
||
|
|
||
|
// RunTemplate returns two formatted strings given a template and
|
||
|
// the data it requires. The first string returned is generated for
|
||
|
// user-facing output and may or may not contain ANSI escape codes
|
||
|
// for colored output. The second string does not contain escape codes
|
||
|
// and can be used by the renderer for layout purposes.
|
||
|
func RunTemplate(tmpl string, data interface{}) (string, string, error) {
|
||
|
tPair, err := GetTemplatePair(tmpl)
|
||
|
if err != nil {
|
||
|
return "", "", err
|
||
|
}
|
||
|
userBuf := bytes.NewBufferString("")
|
||
|
err = tPair[0].Execute(userBuf, data)
|
||
|
if err != nil {
|
||
|
return "", "", err
|
||
|
}
|
||
|
layoutBuf := bytes.NewBufferString("")
|
||
|
err = tPair[1].Execute(layoutBuf, data)
|
||
|
if err != nil {
|
||
|
return userBuf.String(), "", err
|
||
|
}
|
||
|
return userBuf.String(), layoutBuf.String(), err
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
memoizedGetTemplate = map[string][2]*template.Template{}
|
||
|
|
||
|
memoMutex = &sync.RWMutex{}
|
||
|
)
|
||
|
|
||
|
// GetTemplatePair returns a pair of compiled templates where the
|
||
|
// first template is generated for user-facing output and the
|
||
|
// second is generated for use by the renderer. The second
|
||
|
// template does not contain any color escape codes, whereas
|
||
|
// the first template may or may not depending on DisableColor.
|
||
|
func GetTemplatePair(tmpl string) ([2]*template.Template, error) {
|
||
|
memoMutex.RLock()
|
||
|
if t, ok := memoizedGetTemplate[tmpl]; ok {
|
||
|
memoMutex.RUnlock()
|
||
|
return t, nil
|
||
|
}
|
||
|
memoMutex.RUnlock()
|
||
|
|
||
|
templatePair := [2]*template.Template{nil, nil}
|
||
|
|
||
|
templateNoColor, err := template.New("prompt").Funcs(TemplateFuncsNoColor).Parse(tmpl)
|
||
|
if err != nil {
|
||
|
return [2]*template.Template{}, err
|
||
|
}
|
||
|
|
||
|
templatePair[1] = templateNoColor
|
||
|
|
||
|
envColorHide := envColorDisabled() && !envColorForced()
|
||
|
if DisableColor || envColorHide {
|
||
|
templatePair[0] = templatePair[1]
|
||
|
} else {
|
||
|
templateWithColor, err := template.New("prompt").Funcs(TemplateFuncsWithColor).Parse(tmpl)
|
||
|
templatePair[0] = templateWithColor
|
||
|
if err != nil {
|
||
|
return [2]*template.Template{}, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memoMutex.Lock()
|
||
|
memoizedGetTemplate[tmpl] = templatePair
|
||
|
memoMutex.Unlock()
|
||
|
return templatePair, nil
|
||
|
}
|