import (
"encoding/json"
"errors"
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/zyedidia/glob"
"github.com/zyedidia/json5"
- "github.com/zyedidia/micro/internal/util"
+ "github.com/zyedidia/micro/v2/internal/util"
"golang.org/x/text/encoding/htmlindex"
)
// This is the raw parsed json
parsedSettings map[string]interface{}
+
+ // ModifiedSettings is a map of settings which should be written to disk
+ // because they have been modified by the user in this session
+ ModifiedSettings map[string]bool
)
func init() {
+ ModifiedSettings = make(map[string]bool)
parsedSettings = make(map[string]interface{})
}
return nil
}
+func verifySetting(option string, value reflect.Type, def reflect.Type) bool {
+ var interfaceArr []interface{}
+ switch option {
+ case "pluginrepos", "pluginchannels":
+ return value.AssignableTo(reflect.TypeOf(interfaceArr))
+ default:
+ return def.AssignableTo(value)
+ }
+}
+
// InitGlobalSettings initializes the options map and sets all options to their default values
// Must be called after ReadSettings
-func InitGlobalSettings() {
+func InitGlobalSettings() error {
+ var err error
GlobalSettings = DefaultGlobalSettings()
for k, v := range parsedSettings {
if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
+ if _, ok := GlobalSettings[k]; ok && !verifySetting(k, reflect.TypeOf(v), reflect.TypeOf(GlobalSettings[k])) {
+ err = errors.New(fmt.Sprintf("Global Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v), GlobalSettings[k], reflect.TypeOf(GlobalSettings[k])))
+ continue
+ }
+
GlobalSettings[k] = v
}
}
+ return err
}
// InitLocalSettings scans the json in settings.json and sets the options locally based
if strings.HasPrefix(k, "ft:") {
if settings["filetype"].(string) == k[3:] {
for k1, v1 := range v.(map[string]interface{}) {
+ if _, ok := settings[k1]; ok && !verifySetting(k1, reflect.TypeOf(v1), reflect.TypeOf(settings[k1])) {
+ parseError = errors.New(fmt.Sprintf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v1), settings[k1], reflect.TypeOf(settings[k1])))
+ continue
+ }
settings[k1] = v1
}
}
if g.MatchString(path) {
for k1, v1 := range v.(map[string]interface{}) {
+ if _, ok := settings[k1]; ok && !verifySetting(k1, reflect.TypeOf(v1), reflect.TypeOf(settings[k1])) {
+ parseError = errors.New(fmt.Sprintf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v1), settings[k1], reflect.TypeOf(settings[k1])))
+ continue
+ }
settings[k1] = v1
}
}
func WriteSettings(filename string) error {
var err error
if _, e := os.Stat(ConfigDir); e == nil {
+ defaults := DefaultGlobalSettings()
+
+ // remove any options froms parsedSettings that have since been marked as default
+ for k, v := range parsedSettings {
+ if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
+ cur, okcur := GlobalSettings[k]
+ if def, ok := defaults[k]; ok && okcur && reflect.DeepEqual(cur, def) {
+ delete(parsedSettings, k)
+ }
+ }
+ }
+
+ // add any options to parsedSettings that have since been marked as non-default
for k, v := range GlobalSettings {
- parsedSettings[k] = v
+ if def, ok := defaults[k]; !ok || !reflect.DeepEqual(v, def) {
+ if _, wr := ModifiedSettings[k]; wr {
+ parsedSettings[k] = v
+ }
+ }
}
txt, _ := json.MarshalIndent(parsedSettings, "", " ")
return err
}
+// OverwriteSettings writes the current settings to settings.json and
+// resets any user configuration of local settings present in settings.json
func OverwriteSettings(filename string) error {
+ settings := make(map[string]interface{})
+
var err error
if _, e := os.Stat(ConfigDir); e == nil {
- txt, _ := json.MarshalIndent(GlobalSettings, "", " ")
+ defaults := DefaultGlobalSettings()
+ for k, v := range GlobalSettings {
+ if def, ok := defaults[k]; !ok || !reflect.DeepEqual(v, def) {
+ if _, wr := ModifiedSettings[k]; wr {
+ settings[k] = v
+ }
+ }
+ }
+
+ txt, _ := json.MarshalIndent(settings, "", " ")
err = ioutil.WriteFile(filename, append(txt, '\n'), 0644)
}
return err
if v, ok := GlobalSettings[name]; !ok {
defaultCommonSettings[name] = defaultvalue
GlobalSettings[name] = defaultvalue
- err := WriteSettings(filepath.Join(ConfigDir, "/settings.json"))
+ err := WriteSettings(filepath.Join(ConfigDir, "settings.json"))
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
}
// RegisterGlobalOption creates a new global-only option
func RegisterGlobalOption(name string, defaultvalue interface{}) error {
if v, ok := GlobalSettings[name]; !ok {
- defaultGlobalSettings[name] = defaultvalue
+ DefaultGlobalOnlySettings[name] = defaultvalue
GlobalSettings[name] = defaultvalue
err := WriteSettings(filepath.Join(ConfigDir, "settings.json"))
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
}
} else {
- defaultGlobalSettings[name] = v
+ DefaultGlobalOnlySettings[name] = v
}
return nil
}
var defaultCommonSettings = map[string]interface{}{
"autoindent": true,
+ "autosu": false,
"backup": true,
"basename": false,
"colorcolumn": float64(0),
"cursorline": true,
+ "diffgutter": false,
"encoding": "utf-8",
- "eofnewline": false,
- "fastdirty": true,
+ "eofnewline": true,
+ "fastdirty": false,
"fileformat": "unix",
"filetype": "unknown",
"ignorecase": false,
"readonly": false,
"rmtrailingws": false,
"ruler": true,
+ "relativeruler": false,
"savecursor": false,
"saveundo": false,
"scrollbar": false,
// a list of settings that should only be globally modified and their
// default values
-var defaultGlobalSettings = map[string]interface{}{
+var DefaultGlobalOnlySettings = map[string]interface{}{
"autosave": float64(0),
"colorscheme": "default",
+ "divchars": "|-",
+ "divreverse": true,
"infobar": true,
"keymenu": false,
"mouse": true,
+ "parsecursor": false,
"paste": false,
"savehistory": true,
"sucmd": "sudo",
"pluginchannels": []string{"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json"},
"pluginrepos": []string{},
+ "xterm": false,
}
// a list of settings that should never be globally modified
for k, v := range defaultCommonSettings {
globalsettings[k] = v
}
- for k, v := range defaultGlobalSettings {
+ for k, v := range DefaultGlobalOnlySettings {
globalsettings[k] = v
}
return globalsettings
for k, v := range defaultCommonSettings {
allsettings[k] = v
}
- for k, v := range defaultGlobalSettings {
+ for k, v := range DefaultGlobalOnlySettings {
allsettings[k] = v
}
return allsettings