From bb8c8533025de28144adf2197448d6a1df0c0271 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Wed, 25 Jun 2025 18:21:06 -0700 Subject: [PATCH] add finders for windows/unix/local --- cspell.json | 40 +++++++++++++++++++++++- internal/config/config.go | 64 ++++++++++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 12 deletions(-) diff --git a/cspell.json b/cspell.json index 5e62368ec8ffecaaebb2fdc1c4ef23bc42cc0e0f..2595963182b8e2aa6fe575bbe9ca6a5da0f70a9b 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1,39 @@ -{"flagWords":[],"words":["crush","charmbracelet","lipgloss","bubbletea","textinput","Focusable","lsps","Sourcegraph","filepicker","imageorient","rasterx","oksvg","termenv","trashhalo","lucasb","nfnt","srwiley","Lanczos","fsext","GROQ","alecthomas","Preproc","Emph","charmtone","Charple","Guac","diffview","Strikethrough","Unticked","uniseg","rivo"],"version":"0.2","language":"en"} \ No newline at end of file +{ + "flagWords": [], + "words": [ + "afero", + "alecthomas", + "bubbletea", + "charmbracelet", + "charmtone", + "Charple", + "crush", + "diffview", + "Emph", + "filepicker", + "Focusable", + "fsext", + "GROQ", + "Guac", + "imageorient", + "Lanczos", + "lipgloss", + "lsps", + "lucasb", + "nfnt", + "oksvg", + "Preproc", + "rasterx", + "rivo", + "Sourcegraph", + "srwiley", + "Strikethrough", + "termenv", + "textinput", + "trashhalo", + "uniseg", + "Unticked" + ], + "version": "0.2", + "language": "en" +} diff --git a/internal/config/config.go b/internal/config/config.go index 3f932221c5b5ecdd21164a3efe8ed85f60cc1cce..376cfb78f5dc81a67e4c4a3df96772e9a937ecd3 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,6 +11,7 @@ import ( "github.com/charmbracelet/crush/internal/llm/models" "github.com/charmbracelet/crush/internal/logging" + "github.com/spf13/afero" "github.com/spf13/viper" ) @@ -199,21 +200,62 @@ func Load(workingDir string, debug bool) (*Config, error) { return cfg, nil } +type configFinder struct { + appName string + dotPrefix bool + paths []string +} + +func (f configFinder) Find(fsys afero.Fs) ([]string, error) { + var configFiles []string + configName := fmt.Sprintf("%s.json", f.appName) + if f.dotPrefix { + configName = fmt.Sprintf(".%s.json", f.appName) + } + paths := []string{} + for _, p := range f.paths { + if p == "" { + continue + } + paths = append(paths, os.ExpandEnv(p)) + } + + for _, path := range paths { + if path == "" { + continue + } + + configPath := filepath.Join(path, configName) + if exists, err := afero.Exists(fsys, configPath); err == nil && exists { + configFiles = append(configFiles, configPath) + } + } + return configFiles, nil +} + // configureViper sets up viper's configuration paths and environment variables. func configureViper() { - viper.SetConfigName(fmt.Sprintf(".%s", appName)) viper.SetConfigType("json") - // Unix-style paths - viper.AddConfigPath("$HOME") - viper.AddConfigPath(fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName)) - viper.AddConfigPath(fmt.Sprintf("$HOME/.config/%s", appName)) - - // Windows-style paths - viper.AddConfigPath(fmt.Sprintf("$USERPROFILE")) - viper.AddConfigPath(fmt.Sprintf("$APPDATA/%s", appName)) - viper.AddConfigPath(fmt.Sprintf("$LOCALAPPDATA/%s", appName)) - + // Create the three finders + windowsFinder := configFinder{appName: appName, dotPrefix: false, paths: []string{ + "$USERPROFILE", + fmt.Sprintf("$APPDATA/%s", appName), + fmt.Sprintf("$LOCALAPPDATA/%s", appName), + }} + + unixFinder := configFinder{appName: appName, dotPrefix: false, paths: []string{ + "$HOME", + fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName), + fmt.Sprintf("$HOME/.config/%s", appName), + }} + + localFinder := configFinder{appName: appName, dotPrefix: true, paths: []string{ + ".", + }} + + // Use all finders with viper + viper.SetOptions(viper.WithFinder(viper.Finders(windowsFinder, unixFinder, localFinder))) viper.SetEnvPrefix(strings.ToUpper(appName)) viper.AutomaticEnv() }