Skip to content

Commit

Permalink
Merge pull request #3343 from JoeKar/fix/volatile-after-reinit
Browse files Browse the repository at this point in the history
Rework `filetype` change, `reload` command and `autosave`
  • Loading branch information
JoeKar authored Aug 19, 2024
2 parents fd3a002 + b80ea93 commit 7dc78b7
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 128 deletions.
8 changes: 6 additions & 2 deletions cmd/micro/micro.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,10 @@ func main() {
screen.TermMessage(err)
continue
}
if err = config.OptionIsValid(k, nativeValue); err != nil {
screen.TermMessage(err)
continue
}
config.GlobalSettings[k] = nativeValue
config.VolatileSettings[k] = true
}
Expand Down Expand Up @@ -352,9 +356,9 @@ func main() {
log.Println(clipErr, " or change 'clipboard' option")
}

config.StartAutoSave()
if a := config.GetGlobalOption("autosave").(float64); a > 0 {
config.SetAutoTime(int(a))
config.StartAutoSave()
config.SetAutoTime(a)
}

screen.Events = make(chan tcell.Event)
Expand Down
75 changes: 50 additions & 25 deletions internal/action/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"os/exec"
"path/filepath"
"reflect"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -357,10 +358,24 @@ func reloadRuntime(reloadPlugins bool) {
err := config.ReadSettings()
if err != nil {
screen.TermMessage(err)
}
err = config.InitGlobalSettings()
if err != nil {
screen.TermMessage(err)
} else {
parsedSettings := config.ParsedSettings()
defaultSettings := config.DefaultAllSettings()
for k := range defaultSettings {
if _, ok := config.VolatileSettings[k]; ok {
// reload should not override volatile settings
continue
}

if _, ok := parsedSettings[k]; ok {
err = doSetGlobalOptionNative(k, parsedSettings[k])
} else {
err = doSetGlobalOptionNative(k, defaultSettings[k])
}
if err != nil {
screen.TermMessage(err)
}
}
}

if reloadPlugins {
Expand Down Expand Up @@ -393,7 +408,7 @@ func reloadRuntime(reloadPlugins bool) {
screen.TermMessage(err)
}
for _, b := range buffer.OpenBuffers {
b.UpdateRules()
b.ReloadSettings(true)
}
}

Expand Down Expand Up @@ -512,16 +527,11 @@ func (h *BufPane) NewTabCmd(args []string) {
}
}

func SetGlobalOptionNative(option string, nativeValue interface{}) error {
// check for local option first...
for _, s := range config.LocalSettings {
if s == option {
MainTab().CurPane().Buf.SetOptionNative(option, nativeValue)
return nil
}
func doSetGlobalOptionNative(option string, nativeValue interface{}) error {
if reflect.DeepEqual(config.GlobalSettings[option], nativeValue) {
return nil
}

// ...if it's not local continue with the globals
config.GlobalSettings[option] = nativeValue
config.ModifiedSettings[option] = true
delete(config.VolatileSettings, option)
Expand All @@ -542,8 +552,7 @@ func SetGlobalOptionNative(option string, nativeValue interface{}) error {
}
} else if option == "autosave" {
if nativeValue.(float64) > 0 {
config.SetAutoTime(int(nativeValue.(float64)))
config.StartAutoSave()
config.SetAutoTime(nativeValue.(float64))
} else {
config.SetAutoTime(0)
}
Expand Down Expand Up @@ -574,8 +583,30 @@ func SetGlobalOptionNative(option string, nativeValue interface{}) error {
}
}

return nil
}

func SetGlobalOptionNative(option string, nativeValue interface{}) error {
if err := config.OptionIsValid(option, nativeValue); err != nil {
return err
}

// check for local option first...
for _, s := range config.LocalSettings {
if s == option {
return MainTab().CurPane().Buf.SetOptionNative(option, nativeValue)
}
}

// ...if it's not local continue with the globals...
if err := doSetGlobalOptionNative(option, nativeValue); err != nil {
return err
}

// ...at last check the buffer locals
for _, b := range buffer.OpenBuffers {
b.SetOptionNative(option, nativeValue)
b.DoSetOptionNative(option, nativeValue)
delete(b.LocalSettings, option)
}

return config.WriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
Expand All @@ -602,16 +633,10 @@ func (h *BufPane) ResetCmd(args []string) {
}

option := args[0]
defaults := config.DefaultAllSettings()

defaultGlobals := config.DefaultGlobalSettings()
defaultLocals := config.DefaultCommonSettings()

if _, ok := defaultGlobals[option]; ok {
SetGlobalOptionNative(option, defaultGlobals[option])
return
}
if _, ok := defaultLocals[option]; ok {
h.Buf.SetOptionNative(option, defaultLocals[option])
if _, ok := defaults[option]; ok {
SetGlobalOptionNative(option, defaults[option])
return
}
InfoBar.Error(config.ErrInvalidOption)
Expand Down
6 changes: 6 additions & 0 deletions internal/buffer/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ type SharedBuffer struct {

// Settings customized by the user
Settings map[string]interface{}
// LocalSettings customized by the user for this buffer only
LocalSettings map[string]bool

Suggestions []string
Completions []string
Expand Down Expand Up @@ -326,6 +328,7 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT
// 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
Expand Down Expand Up @@ -364,6 +367,9 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT
case "dos":
ff = FFDos
}
} else {
// in case of autodetection treat as locally set
b.LocalSettings["fileformat"] = true
}

b.LineArray = NewLineArray(uint64(size), ff, reader)
Expand Down
65 changes: 53 additions & 12 deletions internal/buffer/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,54 @@ package buffer

import (
"crypto/md5"
"reflect"

"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/screen"
)

func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error {
func (b *Buffer) ReloadSettings(reloadFiletype bool) {
settings := config.ParsedSettings()

if _, ok := b.LocalSettings["filetype"]; !ok && reloadFiletype {
// need to update filetype before updating other settings based on it
b.Settings["filetype"] = "unknown"
if v, ok := settings["filetype"]; ok {
b.Settings["filetype"] = v
}
}

// update syntax rules, which will also update filetype if needed
b.UpdateRules()
settings["filetype"] = b.Settings["filetype"]

config.InitLocalSettings(settings, b.Path)
for k, v := range config.DefaultCommonSettings() {
if k == "filetype" {
// prevent recursion
continue
}
if _, ok := config.VolatileSettings[k]; ok {
// reload should not override volatile settings
continue
}
if _, ok := b.LocalSettings[k]; ok {
// reload should not override local settings
continue
}
if _, ok := settings[k]; ok {
b.DoSetOptionNative(k, settings[k])
} else {
b.DoSetOptionNative(k, v)
}
}
}

func (b *Buffer) DoSetOptionNative(option string, nativeValue interface{}) {
if reflect.DeepEqual(b.Settings[option], nativeValue) {
return
}

b.Settings[option] = nativeValue

if option == "fastdirty" {
Expand All @@ -26,17 +68,7 @@ func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error {
} else if option == "statusline" {
screen.Redraw()
} else if option == "filetype" {
config.InitRuntimeFiles(true)
err := config.ReadSettings()
if err != nil {
screen.TermMessage(err)
}
err = config.InitGlobalSettings()
if err != nil {
screen.TermMessage(err)
}
config.InitLocalSettings(b.Settings, b.Path)
b.UpdateRules()
b.ReloadSettings(false)
} else if option == "fileformat" {
switch b.Settings["fileformat"].(string) {
case "unix":
Expand Down Expand Up @@ -85,6 +117,15 @@ func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error {
if b.OptionCallback != nil {
b.OptionCallback(option, nativeValue)
}
}

func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error {
if err := config.OptionIsValid(option, nativeValue); err != nil {
return err
}

b.DoSetOptionNative(option, nativeValue)
b.LocalSettings[option] = true

return nil
}
Expand Down
51 changes: 28 additions & 23 deletions internal/config/autosave.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
package config

import (
"sync"
"time"
)

var Autosave chan bool
var autotime int

// lock for autosave
var autolock sync.Mutex
var autotime chan float64

func init() {
Autosave = make(chan bool)
autotime = make(chan float64)
}

func SetAutoTime(a int) {
autolock.Lock()
autotime = a
autolock.Unlock()
}

func GetAutoTime() int {
autolock.Lock()
a := autotime
autolock.Unlock()
return a
func SetAutoTime(a float64) {
autotime <- a
}

func StartAutoSave() {
go func() {
var a float64
var t *time.Timer
var elapsed <-chan time.Time
for {
autolock.Lock()
a := autotime
autolock.Unlock()
if a < 1 {
break
select {
case a = <-autotime:
if t != nil {
t.Stop()
for len(elapsed) > 0 {
<-elapsed
}
}
if a > 0 {
if t != nil {
t.Reset(time.Duration(a * float64(time.Second)))
} else {
t = time.NewTimer(time.Duration(a * float64(time.Second)))
elapsed = t.C
}
}
case <-elapsed:
if a > 0 {
t.Reset(time.Duration(a * float64(time.Second)))
Autosave <- true
}
}
time.Sleep(time.Duration(a) * time.Second)
Autosave <- true
}
}()
}
Loading

0 comments on commit 7dc78b7

Please sign in to comment.