From 5e6362074e2c15221e3593e8cdad6905ef33c2ec Mon Sep 17 00:00:00 2001 From: EnumDev Date: Sun, 26 Apr 2026 22:24:52 +0300 Subject: [PATCH] Improve config locators for compatibility with Windows --- config/config.yml | 2 +- src/config.go | 42 +++++++++++++++++++++++++------------ src/keybindings.go | 44 ++++++++++++++++++++++++++------------- src/style.go | 52 ++++++++++++++++++++++++++-------------------- 4 files changed, 90 insertions(+), 50 deletions(-) diff --git a/config/config.yml b/config/config.yml index a5d0e11..4ffa822 100644 --- a/config/config.yml +++ b/config/config.yml @@ -7,4 +7,4 @@ show_top_menu: true show_line_index: true extend_line_index: false # Extend line index to the bottom of the screen buffer_info_message: "File: %f Cursor: (%x, %y, %p) Chars: %c" -tab_indentation: 4 # Length of tab characters \ No newline at end of file +tab_indentation: 4 # Length of tab characters diff --git a/src/config.go b/src/config.go index 66fe1c1..6cc9252 100644 --- a/src/config.go +++ b/src/config.go @@ -1,10 +1,12 @@ package main import ( - "gopkg.in/yaml.v3" "log" "os" "path" + "runtime" + + "gopkg.in/yaml.v3" ) type TyperConfig struct { @@ -35,25 +37,39 @@ func readConfig() { log.Fatalf("Could not get home directory: %s", err) } - if _, err := os.Stat(path.Join(homeDir, ".config/typer/config.yml")); err == nil { - data, err := os.ReadFile(path.Join(homeDir, ".config/typer/config.yml")) + execPath, err := os.Executable() + if err != nil { + log.Fatalf("Could not get path to executable: %s", err) + } + + configPaths := make([]string, 0) + if runtime.GOOS == "windows" { + configPaths = append(configPaths, path.Join(homeDir, "AppData/Roaming/Typer/config.yml")) + configPaths = append(configPaths, path.Join(path.Dir(execPath), "etc/typer/config.yml")) + } else { + configPaths = append(configPaths, path.Join(homeDir, ".config/typer/config.yml")) + configPaths = append(configPaths, path.Join(sysconfdir, "typer/config.yml")) + } + + for _, configPath := range configPaths { + // Ensure config exists at path + if _, err := os.Stat(configPath); err != nil { + continue + } + + // Read config file + data, err := os.ReadFile(configPath) if err != nil { log.Fatalf("Could not read config.yml: %s", err) } + + // Unmarshal contents into struct err = yaml.Unmarshal(data, &Config) if err != nil { log.Fatalf("Could not unmarshal config.yml: %s", err) } - } else if _, err := os.Stat(path.Join(sysconfdir, "typer/config.yml")); err == nil { - reader, err := os.Open(path.Join(sysconfdir, "typer/config.yml")) - if err != nil { - log.Fatalf("Could not read config.yml: %s", err) - } - err = yaml.NewDecoder(reader).Decode(&Config) - if err != nil { - log.Fatalf("Could not read config.yml: %s", err) - } - reader.Close() + + break } // Validate config options diff --git a/src/keybindings.go b/src/keybindings.go index 132c96c..8653d00 100644 --- a/src/keybindings.go +++ b/src/keybindings.go @@ -1,12 +1,14 @@ package main import ( - "github.com/gdamore/tcell/v2" - "gopkg.in/yaml.v3" "log" "os" "path" + "runtime" "strings" + + "github.com/gdamore/tcell/v2" + "gopkg.in/yaml.v3" ) type TyperKeybindings struct { @@ -31,25 +33,39 @@ func readKeybindings() { log.Fatalf("Could not get home directory: %s", err) } - if _, err := os.Stat(path.Join(homeDir, ".config/typer/keybindings.yml")); err == nil { - data, err := os.ReadFile(path.Join(homeDir, ".config/typer/keybindings.yml")) + execPath, err := os.Executable() + if err != nil { + log.Fatalf("Could not get path to executable: %s", err) + } + + configPaths := make([]string, 0) + if runtime.GOOS == "windows" { + configPaths = append(configPaths, path.Join(homeDir, "AppData/Roaming/Typer/keybindings.yml")) + configPaths = append(configPaths, path.Join(path.Dir(execPath), "etc/typer/keybindings.yml")) + } else { + configPaths = append(configPaths, path.Join(homeDir, ".config/typer/keybindings.yml")) + configPaths = append(configPaths, path.Join(sysconfdir, "typer/keybindings.yml")) + } + + for _, configPath := range configPaths { + // Ensure config exists at path + if _, err := os.Stat(configPath); err != nil { + continue + } + + // Read config file + data, err := os.ReadFile(configPath) if err != nil { log.Fatalf("Could not read keybindings.yml: %s", err) } + + // Unmarshal contents into struct err = yaml.Unmarshal(data, &Keybindings) if err != nil { log.Fatalf("Could not unmarshal keybindings.yml: %s", err) } - } else if _, err := os.Stat(path.Join(sysconfdir, "typer/keybindings.yml")); err == nil { - reader, err := os.Open(path.Join(sysconfdir, "typer/keybindings.yml")) - if err != nil { - log.Fatalf("Could not read keybindings.yml: %s", err) - } - err = yaml.NewDecoder(reader).Decode(&Keybindings) - if err != nil { - log.Fatalf("Could not read keybindings.yml: %s", err) - } - reader.Close() + + break } } diff --git a/src/style.go b/src/style.go index e67e4a8..f5d4179 100644 --- a/src/style.go +++ b/src/style.go @@ -2,15 +2,17 @@ package main import ( "fmt" - "github.com/gdamore/tcell/v2" - "gopkg.in/yaml.v3" "log" "os" "path" "reflect" + "runtime" "slices" "strconv" "strings" + + "github.com/gdamore/tcell/v2" + "gopkg.in/yaml.v3" ) type TyperStyle struct { @@ -76,36 +78,42 @@ func readStyles() { log.Fatalf("Could not get home directory: %s", err) } - if stat, err := os.Stat(path.Join(homeDir, ".config/typer/styles/")); err == nil && stat.IsDir() { - entries, err := os.ReadDir(path.Join(homeDir, ".config/typer/styles/")) - if err != nil { - log.Fatalf("Could not read user style directory: %s", err) - } - - for _, entry := range entries { - entryPath := path.Join(homeDir, ".config/typer/styles/", entry.Name()) - style, err := readStyleYamlFile(entryPath) - if err != nil { - log.Fatalf("Could not read style file (%s): %s", entryPath, err) - } - - if _, ok := AvailableStyles[style.Name]; !ok { - AvailableStyles[style.Name] = style - } - } + execPath, err := os.Executable() + if err != nil { + log.Fatalf("Could not get path to executable: %s", err) } - if stat, err := os.Stat(path.Join(sysconfdir, "typer/styles/")); err == nil && stat.IsDir() { - entries, err := os.ReadDir(path.Join(sysconfdir, "typer/styles/")) + + stylesPaths := make([]string, 0) + if runtime.GOOS == "windows" { + stylesPaths = append(stylesPaths, path.Join(homeDir, "AppData/Roaming/Typer/styles")) + stylesPaths = append(stylesPaths, path.Join(path.Dir(execPath), "etc/typer/styles")) + } else { + stylesPaths = append(stylesPaths, path.Join(homeDir, ".config/typer/styles")) + stylesPaths = append(stylesPaths, path.Join(sysconfdir, "typer/styles")) + } + + for _, stylesPath := range stylesPaths { + // Ensure directory exists at path + if stat, err := os.Stat(stylesPath); err != nil || !stat.IsDir() { + fmt.Println(stylesPath) + continue + } + + // Get directory entries + entries, err := os.ReadDir(stylesPath) if err != nil { log.Fatalf("Could not read user style directory: %s", err) } + // Read entries in directory for _, entry := range entries { - entryPath := path.Join(path.Join(sysconfdir, "typer/styles/"), entry.Name()) + entryPath := path.Join(stylesPath, entry.Name()) + style, err := readStyleYamlFile(entryPath) if err != nil { log.Fatalf("Could not read style file (%s): %s", entryPath, err) } + if _, ok := AvailableStyles[style.Name]; !ok { AvailableStyles[style.Name] = style }