Added theme customization via config.toml #17 ``` [theme] border = "#665C54" accent = "#FABD2F" muted = "#928374" text = "#EBDBB2" text_sel = "#FBF1C7" match = "#FE8019" desc = "#A89984" desc_sel = "#EBDBB2" sel_bg = "#504945" scroll_info = "#83A598" ghost_text = "#7C6F64" hist= "#fe8019" hist_sel = "#d65d0e" sys = "#fb4934" sys_sel = "#cc241d" alias = "#b8bb26" alias_sel = "#98971a" ``` --------- Co-authored-by: verse91 <versedev.store@proton.me> Co-authored-by: VERSE <sunnyone0901@gmail.com>
105 lines
2.4 KiB
Go
105 lines
2.4 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"reflect"
|
|
"sync"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
)
|
|
|
|
var defaultTheme = ThemeStyles{
|
|
Border: "#a277ff",
|
|
Accent: "#61ffca",
|
|
Muted: "#6d6a7f",
|
|
Text: "#edecee",
|
|
TextSel: "#ffffff",
|
|
Key: "#a277ff",
|
|
Match: "#61ffca",
|
|
Desc: "#9692a8",
|
|
DescSel: "#edecee",
|
|
SelBg: "#3d375e",
|
|
SelText: "#110f18",
|
|
ScrollInfo: "#a277ff",
|
|
GhostText: "#4B4A4C",
|
|
History: "#1a2d36",
|
|
HistorySel: "#61ffca",
|
|
Sys: "#1e1d28",
|
|
SysSel: "#a277ff",
|
|
Alias: "#2a2342",
|
|
AliasSel: "#a277ff",
|
|
}
|
|
|
|
var (
|
|
themeMu sync.RWMutex
|
|
themeStyles = defaultTheme
|
|
)
|
|
|
|
func Theme() ThemeStyles {
|
|
themeMu.RLock()
|
|
defer themeMu.RUnlock()
|
|
return themeStyles
|
|
}
|
|
|
|
type ThemeStyles struct {
|
|
Border string `toml:"border"`
|
|
Accent string `toml:"accent"`
|
|
Muted string `toml:"muted"`
|
|
Text string `toml:"text"`
|
|
TextSel string `toml:"text_sel"`
|
|
Key string `toml:"key"`
|
|
Match string `toml:"match"`
|
|
Desc string `toml:"desc"`
|
|
DescSel string `toml:"desc_sel"`
|
|
SelBg string `toml:"sel_bg"`
|
|
SelText string `toml:"sel_text"`
|
|
ScrollInfo string `toml:"scroll_info"`
|
|
GhostText string `toml:"ghost_text"`
|
|
Sys string `toml:"sys"`
|
|
SysSel string `toml:"sys_sel"`
|
|
History string `toml:"hist"`
|
|
HistorySel string `toml:"hist_sel"`
|
|
Alias string `toml:"alias"`
|
|
AliasSel string `toml:"alias_sel"`
|
|
}
|
|
|
|
// LoadTheme reads theme.toml at filePath
|
|
// Missing file - use defaults silently
|
|
// Missing/empty fields - fall back to the default value for that field
|
|
func LoadTheme(filePath string) {
|
|
themeMu.Lock()
|
|
defer themeMu.Unlock()
|
|
|
|
themeStyles = defaultTheme
|
|
|
|
data, err := os.ReadFile(filePath)
|
|
if err != nil {
|
|
// missing or unreadable file: use defaults
|
|
return
|
|
}
|
|
|
|
var t ThemeStyles
|
|
if _, err := toml.Decode(string(data), &t); err != nil {
|
|
return
|
|
}
|
|
|
|
applyThemeWithFallback(&themeStyles, t, defaultTheme)
|
|
}
|
|
|
|
// applyThemeWithFallback copies non-empty string fields from src into dst,
|
|
// using def for any field that is empty in src
|
|
func applyThemeWithFallback(dst *ThemeStyles, src, def ThemeStyles) {
|
|
dv := reflect.ValueOf(dst).Elem()
|
|
sv := reflect.ValueOf(src)
|
|
dv2 := reflect.ValueOf(def)
|
|
|
|
for i := range dv.NumField() {
|
|
sf := sv.Field(i).String()
|
|
if sf != "" {
|
|
dv.Field(i).SetString(sf)
|
|
} else {
|
|
dv.Field(i).SetString(dv2.Field(i).String())
|
|
}
|
|
}
|
|
}
|