-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathconfig.go
302 lines (272 loc) · 7.33 KB
/
config.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
package rrh
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/tamada/rrh/decorator"
)
/*
VERSION shows the version of RRH.
*/
const VERSION = "2.0.0"
/*
The environment variable names.
*/
const (
AliasPath = "RRH_ALIAS_PATH"
AutoDeleteGroup = "RRH_AUTO_DELETE_GROUP"
AutoCreateGroup = "RRH_AUTO_CREATE_GROUP"
CloneDestination = "RRH_CLONE_DESTINATION"
ColorSetting = "RRH_COLOR"
ConfigPath = "RRH_CONFIG_PATH"
DatabasePath = "RRH_DATABASE_PATH"
DefaultGroupName = "RRH_DEFAULT_GROUP_NAME"
EnableColorized = "RRH_ENABLE_COLORIZED"
Home = "RRH_HOME"
SortOnUpdating = "RRH_SORT_ON_UPDATING"
TimeFormat = "RRH_TIME_FORMAT"
)
/*
AvailableLabels represents the labels availables in the config.
*/
var AvailableLabels = []string{
AliasPath, AutoCreateGroup, AutoDeleteGroup, CloneDestination,
ColorSetting, ConfigPath, DatabasePath, DefaultGroupName,
EnableColorized, Home, SortOnUpdating, TimeFormat,
}
var boolLabels = []string{
AutoCreateGroup, AutoDeleteGroup, EnableColorized,
SortOnUpdating,
}
/*
The the 2nd return value of GetString method (ReadFrom).
*/
const (
Default = "default"
ConfigFile = "config_file"
Env = "environment"
NotFound = "not found"
)
/*
Relative shows the default value of RrhTimeFormat.
*/
const Relative = "relative"
const (
trueString = "true"
falseString = "false"
)
/*
The values of RrhOnError.
*/
const (
Fail = "FAIL"
FailImmediately = "FAIL_IMMEDIATELY"
Warn = "WARN"
Ignore = "IGNORE"
)
/*
Config shows the values of configuration variables.
*/
type Config struct {
values map[string]string
Decorator decorator.Decorator
Color *Color
}
/*
ReadFrom shows the value of config load from.
The available values are default, config_file, environment, and not found.
*/
type ReadFrom string
var defaultValues = Config{
values: map[string]string{
AliasPath: "${RRH_HOME}/alias.json",
AutoCreateGroup: "false",
AutoDeleteGroup: "false",
CloneDestination: ".",
ColorSetting: "repository:fg=red+group:fg=magenta+label:op=bold+configValue:fg=green",
ConfigPath: "${RRH_HOME}/config.json",
DatabasePath: "${RRH_HOME}/database.json",
DefaultGroupName: "no-group",
EnableColorized: "false",
Home: "${HOME}/.config/rrh",
SortOnUpdating: "false",
TimeFormat: Relative,
},
Color: &Color{},
}
func trueOrFalse(value string) (string, error) {
if strings.ToLower(value) == trueString {
return trueString, nil
} else if strings.ToLower(value) == falseString {
return falseString, nil
}
return "", fmt.Errorf("%s: not true nor false", value)
}
func normalizeValueOfOnError(value string) (string, error) {
var newvalue = strings.ToUpper(value)
if newvalue == Fail || newvalue == FailImmediately || newvalue == Warn || newvalue == Ignore {
return newvalue, nil
}
return "", fmt.Errorf("%s: Unknown value of RRH_ON_ERROR (must be %s, %s, %s, or %s)", value, Fail, FailImmediately, Warn, Ignore)
}
func contains(slice []string, label string) bool {
for _, item := range slice {
if label == item {
return true
}
}
return false
}
/*
Unset method deletes the specified config value.
*/
func (config *Config) Unset(label string) error {
if !contains(AvailableLabels, label) {
return fmt.Errorf("%s: unknown variable name", label)
}
delete(config.values, label)
return nil
}
func validateArgumentsOnUpdate(label string, value string) error {
if !contains(AvailableLabels, label) {
return fmt.Errorf("%s: unknown variable name", label)
}
if label == ConfigPath {
return fmt.Errorf("%s: cannot set in config file", ConfigPath)
}
return nil
}
func (config *Config) updateBoolValue(label string, value string) error {
var flag, err = trueOrFalse(value)
if err == nil {
config.values[label] = string(flag)
}
return err
}
/*
Update method updates the config value with the given `value`.
*/
func (config *Config) Update(label string, value string) error {
if err := validateArgumentsOnUpdate(label, value); err != nil {
return err
}
if contains(boolLabels, label) {
return config.updateBoolValue(label, value)
}
config.values[label] = value
return nil
}
/*
IsSet returns the bool value of the given label.
If the label is not RrhAutoCreateGroup, RrhAutoDeleteGroup, and RrhSortOnUpdating, this method always returns false.
*/
func (config *Config) IsSet(label string) bool {
if contains(boolLabels, label) {
return strings.ToLower(config.values[label]) == trueString
}
return false
}
func (config *Config) replaceHome(value string) string {
if strings.Contains(value, "${HOME}") {
var home, _ = os.UserHomeDir()
value = strings.Replace(value, "${HOME}", home, 1)
}
if strings.Contains(value, "${RRH_HOME}") {
var rrhHome = config.GetValue(Home)
value = strings.Replace(value, "${RRH_HOME}", strings.TrimRight(rrhHome, "/"), -1)
}
return value
}
/*
GetValue returns the value of the given variable name.
*/
func (config *Config) GetValue(label string) string {
var value, _ = config.GetString(label)
return config.replaceHome(value)
}
/*
GetString returns the value of the given variable name and the definition part of the value.
*/
func (config *Config) GetString(label string) (string, ReadFrom) {
if !contains(AvailableLabels, label) {
return "", NotFound
}
var value, ok = config.values[label]
if !ok {
return config.getStringFromEnv(label)
}
return config.replaceHome(value), ConfigFile
}
/*
GetDefaultValue returns the default value of the given variable name.
*/
func (config *Config) GetDefaultValue(label string) string {
var value, _ = config.findDefaultValue(label)
return value
}
func (config *Config) getStringFromEnv(label string) (string, ReadFrom) {
var valueFromEnv = os.Getenv(label)
if valueFromEnv != "" {
valueFromEnv = config.replaceHome(valueFromEnv)
return valueFromEnv, Env
}
return config.findDefaultValue(label)
}
func (config *Config) findDefaultValue(label string) (string, ReadFrom) {
if !contains(AvailableLabels, label) {
return "", NotFound
}
var value = defaultValues.values[label]
value = config.replaceHome(value)
return value, Default
}
/*
StoreConfig saves the store.
*/
func (config *Config) StoreConfig() error {
var configPath = config.GetValue(ConfigPath)
var err1 = CreateParentDir(configPath)
if err1 != nil {
return err1
}
var bytes, err2 = json.Marshal(config.values)
if err2 != nil {
return err2
}
return ioutil.WriteFile(configPath, bytes, 0644)
}
/*
NewConfig generates the new Config instance.
*/
func NewConfig() *Config {
return &Config{values: map[string]string{}, Color: &Color{colorSettings{}, colorFuncs{}}}
}
/*
OpenConfig reads the config file and returns it.
The load path is based on `RrhConfigPath` of the environment variables.
*/
func OpenConfig() *Config {
var config = NewConfig()
var configPath, _ = config.getStringFromEnv(ConfigPath)
bytes, err := ioutil.ReadFile(configPath)
if err != nil {
return config
}
var values = map[string]string{}
if err := json.Unmarshal(bytes, &values); err != nil {
return nil
}
config.values = values
config.Decorator = initDecorator(config)
return config
}
func initDecorator(config *Config) decorator.Decorator {
var settingString = config.GetValue(ColorSetting)
if config.IsSet(EnableColorized) && settingString != "" {
decorator, _ := decorator.New(settingString)
return decorator
}
return decorator.NewNoDecorator()
}