Skip to content

Commit 4663927

Browse files
committed
config: Refactor parsed option handling
Validate the parsed options directly after read and inform about errors.
1 parent 395d848 commit 4663927

File tree

4 files changed

+90
-39
lines changed

4 files changed

+90
-39
lines changed

cmd/micro/micro.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ func main() {
273273
screen.TermMessage(err)
274274
continue
275275
}
276+
if err = config.OptionIsValid(k, nativeValue); err != nil {
277+
screen.TermMessage(err)
278+
continue
279+
}
276280
config.GlobalSettings[k] = nativeValue
277281
config.VolatileSettings[k] = true
278282
}

internal/action/command.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,10 @@ func doSetGlobalOptionNative(option string, nativeValue interface{}) error {
592592
}
593593

594594
func SetGlobalOptionNative(option string, nativeValue interface{}) error {
595+
if err := config.OptionIsValid(option, nativeValue); err != nil {
596+
return err
597+
}
598+
595599
// check for local option first...
596600
for _, s := range config.LocalSettings {
597601
if s == option {

internal/buffer/settings.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import (
99
)
1010

1111
func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error {
12+
if err := config.OptionIsValid(option, nativeValue); err != nil {
13+
return err
14+
}
15+
1216
if reflect.DeepEqual(b.Settings[option], nativeValue) {
1317
return nil
1418
}

internal/config/settings.go

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,63 @@ func init() {
156156
VolatileSettings = make(map[string]bool)
157157
}
158158

159+
func validateParsedSettings() error {
160+
var err error
161+
defaults := DefaultAllSettings()
162+
for k, v := range parsedSettings {
163+
if strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
164+
if strings.HasPrefix(k, "ft:") {
165+
for k1, v1 := range v.(map[string]interface{}) {
166+
if _, ok := defaults[k1]; ok {
167+
if e := verifySetting(k1, v1, defaults[k1]); e != nil {
168+
err = e
169+
parsedSettings[k].(map[string]interface{})[k1] = defaults[k1]
170+
continue
171+
}
172+
}
173+
}
174+
} else {
175+
if _, e := glob.Compile(k); e != nil {
176+
err = errors.New("Error with glob setting " + k + ": " + e.Error())
177+
delete(parsedSettings, k)
178+
continue
179+
}
180+
for k1, v1 := range v.(map[string]interface{}) {
181+
if _, ok := defaults[k1]; ok {
182+
if e := verifySetting(k1, v1, defaults[k1]); e != nil {
183+
err = e
184+
parsedSettings[k].(map[string]interface{})[k1] = defaults[k1]
185+
continue
186+
}
187+
}
188+
}
189+
}
190+
continue
191+
}
192+
193+
if k == "autosave" {
194+
// if autosave is a boolean convert it to float
195+
s, ok := v.(bool)
196+
if ok {
197+
if s {
198+
parsedSettings["autosave"] = 8.0
199+
} else {
200+
parsedSettings["autosave"] = 0.0
201+
}
202+
}
203+
continue
204+
}
205+
if _, ok := defaults[k]; ok {
206+
if e := verifySetting(k, v, defaults[k]); e != nil {
207+
err = e
208+
parsedSettings[k] = defaults[k]
209+
continue
210+
}
211+
}
212+
}
213+
return err
214+
}
215+
159216
func ReadSettings() error {
160217
parsedSettings = make(map[string]interface{})
161218
filename := filepath.Join(ConfigDir, "settings.json")
@@ -172,17 +229,9 @@ func ReadSettings() error {
172229
settingsParseError = true
173230
return errors.New("Error reading settings.json: " + err.Error())
174231
}
175-
176-
// check if autosave is a boolean and convert it to float if so
177-
if v, ok := parsedSettings["autosave"]; ok {
178-
s, ok := v.(bool)
179-
if ok {
180-
if s {
181-
parsedSettings["autosave"] = 8.0
182-
} else {
183-
parsedSettings["autosave"] = 0.0
184-
}
185-
}
232+
err = validateParsedSettings()
233+
if err != nil {
234+
return err
186235
}
187236
}
188237
}
@@ -197,14 +246,27 @@ func ParsedSettings() map[string]interface{} {
197246
return s
198247
}
199248

200-
func verifySetting(option string, value reflect.Type, def reflect.Type) bool {
249+
func verifySetting(option string, value interface{}, def interface{}) error {
201250
var interfaceArr []interface{}
251+
valType := reflect.TypeOf(value)
252+
defType := reflect.TypeOf(def)
253+
assignable := false
254+
202255
switch option {
203256
case "pluginrepos", "pluginchannels":
204-
return value.AssignableTo(reflect.TypeOf(interfaceArr))
257+
assignable = valType.AssignableTo(reflect.TypeOf(interfaceArr))
205258
default:
206-
return def.AssignableTo(value)
259+
assignable = defType.AssignableTo(valType)
260+
}
261+
if !assignable {
262+
return fmt.Errorf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", option, valType, def, defType)
207263
}
264+
265+
if err := OptionIsValid(option, value); err != nil {
266+
return err
267+
}
268+
269+
return nil
208270
}
209271

210272
// InitGlobalSettings initializes the options map and sets all options to their default values
@@ -215,11 +277,6 @@ func InitGlobalSettings() error {
215277

216278
for k, v := range parsedSettings {
217279
if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
218-
if _, ok := GlobalSettings[k]; ok && !verifySetting(k, reflect.TypeOf(v), reflect.TypeOf(GlobalSettings[k])) {
219-
err = fmt.Errorf("Global Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v), GlobalSettings[k], reflect.TypeOf(GlobalSettings[k]))
220-
continue
221-
}
222-
223280
GlobalSettings[k] = v
224281
}
225282
}
@@ -229,40 +286,25 @@ func InitGlobalSettings() error {
229286
// InitLocalSettings scans the json in settings.json and sets the options locally based
230287
// on whether the filetype or path matches ft or glob local settings
231288
// Must be called after ReadSettings
232-
func InitLocalSettings(settings map[string]interface{}, path string) error {
233-
var parseError error
289+
func InitLocalSettings(settings map[string]interface{}, path string) {
234290
for k, v := range parsedSettings {
235291
if strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
236292
if strings.HasPrefix(k, "ft:") {
237293
if settings["filetype"].(string) == k[3:] {
238294
for k1, v1 := range v.(map[string]interface{}) {
239-
if _, ok := settings[k1]; ok && !verifySetting(k1, reflect.TypeOf(v1), reflect.TypeOf(settings[k1])) {
240-
parseError = fmt.Errorf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v1), settings[k1], reflect.TypeOf(settings[k1]))
241-
continue
242-
}
243295
settings[k1] = v1
244296
}
245297
}
246298
} else {
247-
g, err := glob.Compile(k)
248-
if err != nil {
249-
parseError = errors.New("Error with glob setting " + k + ": " + err.Error())
250-
continue
251-
}
252-
299+
g, _ := glob.Compile(k)
253300
if g.MatchString(path) {
254301
for k1, v1 := range v.(map[string]interface{}) {
255-
if _, ok := settings[k1]; ok && !verifySetting(k1, reflect.TypeOf(v1), reflect.TypeOf(settings[k1])) {
256-
parseError = fmt.Errorf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v1), settings[k1], reflect.TypeOf(settings[k1]))
257-
continue
258-
}
259302
settings[k1] = v1
260303
}
261304
}
262305
}
263306
}
264307
}
265-
return parseError
266308
}
267309

268310
// WriteSettings writes the settings to the specified filename as JSON
@@ -436,9 +478,6 @@ func GetNativeValue(option string, realValue interface{}, value string) (interfa
436478
return nil, ErrInvalidValue
437479
}
438480

439-
if err := OptionIsValid(option, native); err != nil {
440-
return nil, err
441-
}
442481
return native, nil
443482
}
444483

0 commit comments

Comments
 (0)