diff --git a/internal/action/actions.go b/internal/action/actions.go index 84a5060b..e06b7815 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -1794,12 +1794,12 @@ func (h *BufPane) HalfPageDown() bool { // ToggleDiffGutter turns the diff gutter off and on func (h *BufPane) ToggleDiffGutter() bool { - if !h.Buf.Settings["diffgutter"].(bool) { - h.Buf.Settings["diffgutter"] = true + diffgutter := !h.Buf.Settings["diffgutter"].(bool) + h.Buf.SetOptionNative("diffgutter", diffgutter) + if diffgutter { h.Buf.UpdateDiff() InfoBar.Message("Enabled diff gutter") } else { - h.Buf.Settings["diffgutter"] = false InfoBar.Message("Disabled diff gutter") } return true @@ -1807,11 +1807,11 @@ func (h *BufPane) ToggleDiffGutter() bool { // ToggleRuler turns line numbers off and on func (h *BufPane) ToggleRuler() bool { - if !h.Buf.Settings["ruler"].(bool) { - h.Buf.Settings["ruler"] = true + ruler := !h.Buf.Settings["ruler"].(bool) + h.Buf.SetOptionNative("ruler", ruler) + if ruler { InfoBar.Message("Enabled ruler") } else { - h.Buf.Settings["ruler"] = false InfoBar.Message("Disabled ruler") } return true diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 1172dac8..092a5dcc 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -325,28 +325,17 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT b.AbsPath = absPath b.Path = path - // this is a little messy since we need to know some settings to read - // the file properly, but some settings depend on the filetype, which - // we don't know until reading the file. We first read the settings - // into a local variable and then use that to determine the encoding, - // readonly, and fileformat necessary for reading the file and - // assigning the filetype. - settings := config.DefaultCommonSettings() b.Settings = config.DefaultCommonSettings() b.LocalSettings = make(map[string]bool) for k, v := range config.GlobalSettings { if _, ok := config.DefaultGlobalOnlySettings[k]; !ok { // make sure setting is not global-only - settings[k] = v b.Settings[k] = v } } - config.InitLocalSettings(settings, absPath) - b.Settings["readonly"] = settings["readonly"] - b.Settings["filetype"] = settings["filetype"] - b.Settings["syntax"] = settings["syntax"] + config.UpdatePathGlobLocals(b.Settings, absPath) - enc, err := htmlindex.Get(settings["encoding"].(string)) + enc, err := htmlindex.Get(b.Settings["encoding"].(string)) if err != nil { enc = unicode.UTF8 b.Settings["encoding"] = "utf-8" @@ -366,7 +355,7 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT if size == 0 { // for empty files, use the fileformat setting instead of // autodetection - switch settings["fileformat"] { + switch b.Settings["fileformat"] { case "unix": ff = FFUnix case "dos": @@ -397,8 +386,8 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT } b.UpdateRules() - // init local settings again now that we know the filetype - config.InitLocalSettings(b.Settings, b.Path) + // we know the filetype now, so update per-filetype settings + config.UpdateFileTypeLocals(b.Settings, b.Settings["filetype"].(string)) if _, err := os.Stat(filepath.Join(config.ConfigDir, "buffers")); os.IsNotExist(err) { os.Mkdir(filepath.Join(config.ConfigDir, "buffers"), os.ModePerm) diff --git a/internal/buffer/settings.go b/internal/buffer/settings.go index 3bb3d0c0..3db35e97 100644 --- a/internal/buffer/settings.go +++ b/internal/buffer/settings.go @@ -12,8 +12,13 @@ import ( func (b *Buffer) ReloadSettings(reloadFiletype bool) { settings := config.ParsedSettings() + config.UpdatePathGlobLocals(settings, b.AbsPath) - if _, ok := b.LocalSettings["filetype"]; !ok && reloadFiletype { + oldFiletype := b.Settings["filetype"].(string) + + _, local := b.LocalSettings["filetype"] + _, volatile := config.VolatileSettings["filetype"] + if reloadFiletype && !local && !volatile { // need to update filetype before updating other settings based on it b.Settings["filetype"] = "unknown" if v, ok := settings["filetype"]; ok { @@ -23,9 +28,14 @@ func (b *Buffer) ReloadSettings(reloadFiletype bool) { // update syntax rules, which will also update filetype if needed b.UpdateRules() - settings["filetype"] = b.Settings["filetype"] - config.InitLocalSettings(settings, b.Path) + curFiletype := b.Settings["filetype"].(string) + if oldFiletype != curFiletype { + b.doCallbacks("filetype", oldFiletype, curFiletype) + } + + config.UpdateFileTypeLocals(settings, curFiletype) + for k, v := range config.DefaultCommonSettings() { if k == "filetype" { // prevent recursion @@ -117,15 +127,7 @@ func (b *Buffer) DoSetOptionNative(option string, nativeValue interface{}) { } } - if b.OptionCallback != nil { - b.OptionCallback(option, nativeValue) - } - - if err := config.RunPluginFn("onBufferOptionChanged", - luar.New(ulua.L, b), luar.New(ulua.L, option), - luar.New(ulua.L, oldValue), luar.New(ulua.L, nativeValue)); err != nil { - screen.TermMessage(err) - } + b.doCallbacks(option, oldValue, nativeValue) } func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error { @@ -152,3 +154,15 @@ func (b *Buffer) SetOption(option, value string) error { return b.SetOptionNative(option, nativeValue) } + +func (b *Buffer) doCallbacks(option string, oldValue interface{}, newValue interface{}) { + if b.OptionCallback != nil { + b.OptionCallback(option, newValue) + } + + if err := config.RunPluginFn("onBufferOptionChanged", + luar.New(ulua.L, b), luar.New(ulua.L, option), + luar.New(ulua.L, oldValue), luar.New(ulua.L, newValue)); err != nil { + screen.TermMessage(err) + } +} diff --git a/internal/config/settings.go b/internal/config/settings.go index a72f5025..7630915f 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -288,22 +288,31 @@ func InitGlobalSettings() error { return err } -// InitLocalSettings scans the json in settings.json and sets the options locally based -// on whether the filetype or path matches ft or glob local settings +// UpdatePathGlobLocals scans the already parsed settings and sets the options locally +// based on whether the path matches a glob // Must be called after ReadSettings -func InitLocalSettings(settings map[string]interface{}, path string) { +func UpdatePathGlobLocals(settings map[string]interface{}, path string) { for k, v := range parsedSettings { - if strings.HasPrefix(reflect.TypeOf(v).String(), "map") { - if strings.HasPrefix(k, "ft:") { - if settings["filetype"].(string) == k[3:] { - for k1, v1 := range v.(map[string]interface{}) { - settings[k1] = v1 - } + if strings.HasPrefix(reflect.TypeOf(v).String(), "map") && !strings.HasPrefix(k, "ft:") { + g, _ := glob.Compile(k) + if g.MatchString(path) { + for k1, v1 := range v.(map[string]interface{}) { + settings[k1] = v1 } - } else { - g, _ := glob.Compile(k) - if g.MatchString(path) { - for k1, v1 := range v.(map[string]interface{}) { + } + } + } +} + +// UpdateFileTypeLocals scans the already parsed settings and sets the options locally +// based on whether the filetype matches to "ft:" +// Must be called after ReadSettings +func UpdateFileTypeLocals(settings map[string]interface{}, filetype string) { + for k, v := range parsedSettings { + if strings.HasPrefix(reflect.TypeOf(v).String(), "map") && strings.HasPrefix(k, "ft:") { + if filetype == k[3:] { + for k1, v1 := range v.(map[string]interface{}) { + if k1 != "filetype" { settings[k1] = v1 } }