Skip to content
Closed
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
45 changes: 45 additions & 0 deletions cmd/micro/micro.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,51 @@ func main() {
screen.TermMessage(err)
}

config.StartConfigWatcher([]config.WatchedFile{
// Reload the colorscheme when the active .micro file changes on disk.
{
Path: func() string {
name := "default"
if cs, ok := config.GlobalSettings["colorscheme"].(string); ok {
name = cs
}
return filepath.Join(config.ConfigDir, "colorschemes", name+".micro")
},
OnChange: func() {
timerChan <- func() {
if err := config.InitColorscheme(); err == nil {
screen.Redraw()
}
}
},
},
// Reload settings.json when it changes on disk.
{
Path: func() string {
return filepath.Join(config.ConfigDir, "settings.json")
},
OnChange: func() {
timerChan <- func() {
if err := config.ReadSettings(); err == nil {
config.InitGlobalSettings()
screen.Redraw()
}
}
},
},
// Reload bindings.json when it changes on disk.
{
Path: func() string {
return filepath.Join(config.ConfigDir, "bindings.json")
},
OnChange: func() {
timerChan <- func() {
action.InitBindings()
}
},
},
})

if clipErr != nil {
log.Println(clipErr, " or change 'clipboard' option")
}
Expand Down
59 changes: 59 additions & 0 deletions internal/config/watch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package config

import (
"os"
"time"
)

// WatchedFile describes a file to watch and the callback to invoke on modification.
type WatchedFile struct {
Path func() string // resolves to the current absolute path each tick
OnChange func() // called when modified; runs on a background goroutine
}

// StartConfigWatcher checks each WatchedFile once per second and calls its
// OnChange when the file is modified or the resolved path changes.
// OnChange runs on a background goroutine — post to a channel rather than
// mutating state directly.
// The returned function stops the watcher.
func StartConfigWatcher(files []WatchedFile) func() {
stop := make(chan struct{})

go func() {
type fileState struct {
path string
lastMod time.Time
}
states := make([]fileState, len(files))
for i, f := range files {
p := f.Path()
states[i].path = p
if fi, err := os.Stat(p); err == nil {
states[i].lastMod = fi.ModTime()
}
}

for {
time.Sleep(1 * time.Second)
select {
case <-stop:
return
default:
}
for i, f := range files {
newPath := f.Path()
fi, err := os.Stat(newPath)
if err != nil {
continue
}
if newPath != states[i].path || fi.ModTime().After(states[i].lastMod) {
states[i].path = newPath
states[i].lastMod = fi.ModTime()
f.OnChange()
}
}
}
}()

return func() { close(stop) }
}