on main help sign in
add finders for windows/unix/local
commitbb8c8533025de28144adf2197448d6a1df0c0271 authorTai Groot <tai@taigrr.com> dateWed 25 Jun 2025, 18:21 (1 year ago) parent41f97bc
2 files changed+92−12
cspell.json+39−1 internal/config/config.go+53−11
cspell.json+39−1
@@ -1 +1,39 @@
1−{"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"}
1+{
2+ "flagWords": [],
3+ "words": [
4+ "afero",
5+ "alecthomas",
6+ "bubbletea",
7+ "charmbracelet",
8+ "charmtone",
9+ "Charple",
10+ "crush",
11+ "diffview",
12+ "Emph",
13+ "filepicker",
14+ "Focusable",
15+ "fsext",
16+ "GROQ",
17+ "Guac",
18+ "imageorient",
19+ "Lanczos",
20+ "lipgloss",
21+ "lsps",
22+ "lucasb",
23+ "nfnt",
24+ "oksvg",
25+ "Preproc",
26+ "rasterx",
27+ "rivo",
28+ "Sourcegraph",
29+ "srwiley",
30+ "Strikethrough",
31+ "termenv",
32+ "textinput",
33+ "trashhalo",
34+ "uniseg",
35+ "Unticked"
36+ ],
37+ "version": "0.2",
38+ "language": "en"
39+}
internal/config/config.go+53−11
@@ -11,6 +11,7 @@ import (
1111
1212 "github.com/charmbracelet/crush/internal/llm/models"
1313 "github.com/charmbracelet/crush/internal/logging"
14+ "github.com/spf13/afero"
1415 "github.com/spf13/viper"
1516)
1617
@@ -199,21 +200,62 @@ func Load(workingDir string, debug bool) (*Config, error) {
199200 return cfg, nil
200201}
201202
203+type configFinder struct {
204+ appName string
205+ dotPrefix bool
206+ paths []string
207+}
208+
209+func (f configFinder) Find(fsys afero.Fs) ([]string, error) {
210+ var configFiles []string
211+ configName := fmt.Sprintf("%s.json", f.appName)
212+ if f.dotPrefix {
213+ configName = fmt.Sprintf(".%s.json", f.appName)
214+ }
215+ paths := []string{}
216+ for _, p := range f.paths {
217+ if p == "" {
218+ continue
219+ }
220+ paths = append(paths, os.ExpandEnv(p))
221+ }
222+
223+ for _, path := range paths {
224+ if path == "" {
225+ continue
226+ }
227+
228+ configPath := filepath.Join(path, configName)
229+ if exists, err := afero.Exists(fsys, configPath); err == nil && exists {
230+ configFiles = append(configFiles, configPath)
231+ }
232+ }
233+ return configFiles, nil
234+}
235+
202236// configureViper sets up viper's configuration paths and environment variables.
203237func configureViper() {
204− viper.SetConfigName(fmt.Sprintf(".%s", appName))
205238 viper.SetConfigType("json")
206239
207− // Unix-style paths
208− viper.AddConfigPath("$HOME")
209− viper.AddConfigPath(fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName))
210− viper.AddConfigPath(fmt.Sprintf("$HOME/.config/%s", appName))
211−
212− // Windows-style paths
213− viper.AddConfigPath(fmt.Sprintf("$USERPROFILE"))
214− viper.AddConfigPath(fmt.Sprintf("$APPDATA/%s", appName))
215− viper.AddConfigPath(fmt.Sprintf("$LOCALAPPDATA/%s", appName))
216−
240+ // Create the three finders
241+ windowsFinder := configFinder{appName: appName, dotPrefix: false, paths: []string{
242+ "$USERPROFILE",
243+ fmt.Sprintf("$APPDATA/%s", appName),
244+ fmt.Sprintf("$LOCALAPPDATA/%s", appName),
245+ }}
246+
247+ unixFinder := configFinder{appName: appName, dotPrefix: false, paths: []string{
248+ "$HOME",
249+ fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName),
250+ fmt.Sprintf("$HOME/.config/%s", appName),
251+ }}
252+
253+ localFinder := configFinder{appName: appName, dotPrefix: true, paths: []string{
254+ ".",
255+ }}
256+
257+ // Use all finders with viper
258+ viper.SetOptions(viper.WithFinder(viper.Finders(windowsFinder, unixFinder, localFinder)))
217259 viper.SetEnvPrefix(strings.ToUpper(appName))
218260 viper.AutomaticEnv()
219261}