1package core
2
3import (
4	"bytes"
5	"sync"
6	"text/template"
7
8	"github.com/mgutz/ansi"
9)
10
11var DisableColor = false
12
13var (
14	// HelpInputRune is the rune which the user should enter to trigger
15	// more detailed question help
16	HelpInputRune = '?'
17
18	// ErrorIcon will be be shown before an error
19	ErrorIcon = "X"
20
21	// HelpIcon will be shown before more detailed question help
22	HelpIcon = "?"
23	// QuestionIcon will be shown before a question Message
24	QuestionIcon = "?"
25
26	// MarkedOptionIcon will be prepended before a selected multiselect option
27	MarkedOptionIcon = "[x]"
28	// UnmarkedOptionIcon will be prepended before an unselected multiselect option
29	UnmarkedOptionIcon = "[ ]"
30
31	// SelectFocusIcon is prepended to an option to signify the user is
32	// currently focusing that option
33	SelectFocusIcon = ">"
34)
35
36/*
37  SetFancyIcons changes the err, help, marked, and focus input icons to their
38  fancier forms. These forms may not be compatible with most terminals.
39  This function will not touch the QuestionIcon as its fancy and non fancy form
40  are the same.
41*/
42func SetFancyIcons() {
43	ErrorIcon = "✘"
44	HelpIcon = "ⓘ"
45	// QuestionIcon fancy and non-fancy form are the same
46
47	MarkedOptionIcon = "◉"
48	UnmarkedOptionIcon = "◯"
49
50	SelectFocusIcon = "❯"
51}
52
53var TemplateFuncs = map[string]interface{}{
54	// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
55	"color": func(color string) string {
56		if DisableColor {
57			return ""
58		}
59		return ansi.ColorCode(color)
60	},
61	"HelpInputRune": func() string {
62		return string(HelpInputRune)
63	},
64	"ErrorIcon": func() string {
65		return ErrorIcon
66	},
67	"HelpIcon": func() string {
68		return HelpIcon
69	},
70	"QuestionIcon": func() string {
71		return QuestionIcon
72	},
73	"MarkedOptionIcon": func() string {
74		return MarkedOptionIcon
75	},
76	"UnmarkedOptionIcon": func() string {
77		return UnmarkedOptionIcon
78	},
79	"SelectFocusIcon": func() string {
80		return SelectFocusIcon
81	},
82}
83
84var (
85	memoizedGetTemplate = map[string]*template.Template{}
86
87	memoMutex = &sync.RWMutex{}
88)
89
90func getTemplate(tmpl string) (*template.Template, error) {
91	memoMutex.RLock()
92	if t, ok := memoizedGetTemplate[tmpl]; ok {
93		memoMutex.RUnlock()
94		return t, nil
95	}
96	memoMutex.RUnlock()
97
98	t, err := template.New("prompt").Funcs(TemplateFuncs).Parse(tmpl)
99	if err != nil {
100		return nil, err
101	}
102
103	memoMutex.Lock()
104	memoizedGetTemplate[tmpl] = t
105	memoMutex.Unlock()
106	return t, nil
107}
108
109func RunTemplate(tmpl string, data interface{}) (string, error) {
110	t, err := getTemplate(tmpl)
111	if err != nil {
112		return "", err
113	}
114	buf := bytes.NewBufferString("")
115	err = t.Execute(buf, data)
116	if err != nil {
117		return "", err
118	}
119	return buf.String(), err
120}
121