Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buffer: Fix ReloadSettings(true) for volatile filetype #3662

Merged
merged 6 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions internal/action/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1794,24 +1794,24 @@ 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
}

// 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
Expand Down
21 changes: 5 additions & 16 deletions internal/buffer/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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":
Expand Down Expand Up @@ -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)
Expand Down
38 changes: 26 additions & 12 deletions internal/buffer/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
}
}
35 changes: 22 additions & 13 deletions internal/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down