package main
import (
+ "crypto/md5"
+ "encoding/json"
"errors"
"io/ioutil"
"os"
"strconv"
"strings"
+ "github.com/flynn/json5"
"github.com/zyedidia/glob"
- "github.com/zyedidia/json5/encoding/json5"
)
type optionValidator func(string, interface{}) error
// The options that the user can set
var globalSettings map[string]interface{}
+var invalidSettings bool
+
// Options with validators
var optionValidators = map[string]optionValidator{
"tabsize": validatePositiveValue,
"scrollspeed": validateNonNegativeValue,
"colorscheme": validateColorscheme,
"colorcolumn": validateNonNegativeValue,
+ "fileformat": validateLineEnding,
}
// InitGlobalSettings initializes the options map and sets all options to their default values
func InitGlobalSettings() {
+ invalidSettings = false
defaults := DefaultGlobalSettings()
var parsed map[string]interface{}
if !strings.HasPrefix(string(input), "null") {
if err != nil {
TermMessage("Error reading settings.json file: " + err.Error())
+ invalidSettings = true
return
}
err = json5.Unmarshal(input, &parsed)
if err != nil {
TermMessage("Error reading settings.json:", err.Error())
+ invalidSettings = true
}
} else {
writeSettings = true
// InitLocalSettings scans the json in settings.json and sets the options locally based
// on whether the buffer matches the glob
func InitLocalSettings(buf *Buffer) {
+ invalidSettings = false
var parsed map[string]interface{}
filename := configDir + "/settings.json"
input, err := ioutil.ReadFile(filename)
if err != nil {
TermMessage("Error reading settings.json file: " + err.Error())
+ invalidSettings = true
return
}
err = json5.Unmarshal(input, &parsed)
if err != nil {
TermMessage("Error reading settings.json:", err.Error())
+ invalidSettings = true
}
}
// WriteSettings writes the settings to the specified filename as JSON
func WriteSettings(filename string) error {
+ if invalidSettings {
+ // Do not write the settings if there was an error when reading them
+ return nil
+ }
+
var err error
if _, e := os.Stat(configDir); e == nil {
parsed := make(map[string]interface{})
err = json5.Unmarshal(input, &parsed)
if err != nil {
TermMessage("Error reading settings.json:", err.Error())
+ invalidSettings = true
}
for k, v := range parsed {
}
}
- txt, _ := json5.MarshalIndent(parsed, "", " ")
+ txt, _ := json.MarshalIndent(parsed, "", " ")
err = ioutil.WriteFile(filename, append(txt, '\n'), 0644)
}
return err
"colorscheme": "default",
"cursorline": true,
"eofnewline": false,
- "rmtrailingws": false,
+ "fastdirty": true,
+ "fileformat": "unix",
"ignorecase": false,
"indentchar": " ",
"infobar": true,
+ "keymenu": false,
+ "mouse": true,
+ "rmtrailingws": false,
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollspeed": float64(2),
"scrollmargin": float64(3),
"softwrap": false,
- "splitRight": true,
- "splitBottom": true,
+ "splitright": true,
+ "splitbottom": true,
"statusline": true,
+ "sucmd": "sudo",
"syntax": true,
+ "tabmovement": false,
"tabsize": float64(4),
"tabstospaces": false,
+ "termtitle": false,
"pluginchannels": []string{
"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json",
},
"colorcolumn": float64(0),
"cursorline": true,
"eofnewline": false,
- "rmtrailingws": false,
+ "fastdirty": true,
+ "fileformat": "unix",
"filetype": "Unknown",
"ignorecase": false,
"indentchar": " ",
+ "rmtrailingws": false,
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollspeed": float64(2),
"scrollmargin": float64(3),
"softwrap": false,
- "splitRight": true,
- "splitBottom": true,
+ "splitright": true,
+ "splitbottom": true,
"statusline": true,
"syntax": true,
+ "tabmovement": false,
"tabsize": float64(4),
"tabstospaces": false,
"useprimary": true,
globalSettings[option] = nativeValue
if option == "colorscheme" {
- LoadSyntaxFiles()
+ // LoadSyntaxFiles()
+ InitColorscheme()
for _, tab := range tabs {
for _, view := range tab.views {
view.Buf.UpdateRules()
}
}
- if option == "infobar" {
+ if option == "infobar" || option == "keymenu" {
for _, tab := range tabs {
tab.Resize()
}
}
+ if option == "mouse" {
+ if !nativeValue.(bool) {
+ screen.DisableMouse()
+ } else {
+ screen.EnableMouse()
+ }
+ }
+
if _, ok := CurView().Buf.Settings[option]; ok {
for _, tab := range tabs {
for _, view := range tab.views {
return err
}
+ if option == "fastdirty" {
+ // If it is being turned off, we have to hash every open buffer
+ var empty [16]byte
+ for _, tab := range tabs {
+ for _, v := range tab.views {
+ if !nativeValue.(bool) {
+ if v.Buf.origHash == empty {
+ data, err := ioutil.ReadFile(v.Buf.AbsPath)
+ if err != nil {
+ data = []byte{}
+ }
+ v.Buf.origHash = md5.Sum(data)
+ }
+ } else {
+ v.Buf.IsModified = v.Buf.Modified()
+ }
+ }
+ }
+ }
+
buf.Settings[option] = nativeValue
if option == "statusline" {
}
if option == "filetype" {
- LoadSyntaxFiles()
+ // LoadSyntaxFiles()
+ InitColorscheme()
buf.UpdateRules()
}
+ if option == "fileformat" {
+ buf.IsModified = true
+ }
+
if option == "syntax" {
if !nativeValue.(bool) {
buf.ClearMatches()
return nil
}
+
+func validateLineEnding(option string, value interface{}) error {
+ endingType, ok := value.(string)
+
+ if !ok {
+ return errors.New("Expected string type for file format")
+ }
+
+ if endingType != "unix" && endingType != "dos" {
+ return errors.New("File format must be either 'unix' or 'dos'")
+ }
+
+ return nil
+}