/
variables.go
138 lines (120 loc) · 3.1 KB
/
variables.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package conf
import (
"fmt"
"sort"
"github.com/Depado/projectmpl/utils"
"github.com/fatih/color"
survey "gopkg.in/AlecAivazis/survey.v1"
)
// Variables represents a map of variable
type Variables map[string]*Variable
// Prompt will prompt the variables
func (vv Variables) Prompt() {
// Order the variables alphabetically to keep the same order
var ordered []*Variable
for k, v := range vv {
if v == nil { // Unconfigured values do have a key but no value
v = &Variable{Name: k}
} else {
v.Name = k
}
ordered = append(ordered, v)
}
sort.Slice(ordered, func(i, j int) bool {
return ordered[i].Name < ordered[j].Name
})
for _, variable := range ordered {
variable.Prompt()
}
}
// Ctx generates the context from the variables
func (vv Variables) Ctx() map[string]interface{} {
ctx := make(map[string]interface{})
for k, v := range vv {
if v != nil {
if v.Confirm != nil {
ctx[k] = *v.Confirm
} else {
ctx[k] = v.Result
}
}
if v.Variables != nil {
v.Variables.AddToCtx(k, ctx)
}
}
return ctx
}
// AddToCtx will add the variable results to a sub-key
func (vv Variables) AddToCtx(key string, ctx map[string]interface{}) {
for k, v := range vv.Ctx() {
ctx[key+"_"+k] = v
}
}
// Variable represents a single variable
type Variable struct {
// Default value to display to the user for input prompts
Default string `yaml:"default"`
// Prompt allows to override the standard prompt and display more info
CustomPrompt string `yaml:"prompt"`
// List of possible values for the user to answer
Values []string `yaml:"values"`
// If this field isn't empty, then an help message can be shown to the user
Help string `yaml:"help"`
// Flags a variable as required, preventing the user from entering empty
// values
Required bool `yaml:"required"`
// Confirm is used both for default variable and to store the result.
// If this field isn't nil, then a confirmation survey is used.
Confirm *bool `yaml:"confirm,omitempty"`
Variables Variables `yaml:"variables,omitempty"`
Result string
Name string
}
// True returns if the variable has been filled
func (v *Variable) True() bool {
return v.Result != "" || v.Confirm != nil && *v.Confirm
}
// Prompt prompts for the variable
func (v *Variable) Prompt() {
var prompt survey.Prompt
var validator survey.Validator
msg := fmt.Sprintf("Choose a value for %s:", color.YellowString(v.Name))
if v.CustomPrompt != "" {
msg = v.CustomPrompt
}
if len(v.Values) != 0 {
prompt = &survey.Select{
Message: msg,
Options: v.Values,
Default: v.Default,
Help: v.Help,
}
} else if v.Confirm != nil {
prompt = &survey.Confirm{
Message: msg,
Default: *v.Confirm,
Help: v.Help,
}
} else {
prompt = &survey.Input{
Message: msg,
Default: v.Default,
Help: v.Help,
}
}
if v.Required {
validator = survey.Required
}
var out interface{}
if v.Confirm != nil {
out = v.Confirm
} else {
out = &v.Result
}
if err := survey.AskOne(prompt, out, validator); err != nil {
utils.FatalPrintln("Couldn't get an answer:", err)
}
if v.True() && v.Variables != nil {
v.Variables.Prompt()
}
}