diff options
| author | Paul Buetow <paul@buetow.org> | 2025-08-17 23:03:24 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-08-17 23:03:24 +0300 |
| commit | d72f95ae4e6cd4e7a0beca2b9764511c10de8655 (patch) | |
| tree | d5b034abce358cc26f271c3fc492d97da6e5734c /internal/appconfig | |
| parent | 8dfbbbb6de0f0c67413ee157e976fc3eaee4f914 (diff) | |
refactor(ordering): types/constants first; exported before private; ensure consistent receiver semantics per file
Diffstat (limited to 'internal/appconfig')
| -rw-r--r-- | internal/appconfig/config.go | 167 |
1 files changed, 84 insertions, 83 deletions
diff --git a/internal/appconfig/config.go b/internal/appconfig/config.go index c5166a0..1f7e9d8 100644 --- a/internal/appconfig/config.go +++ b/internal/appconfig/config.go @@ -31,86 +31,13 @@ type App struct { CopilotModel string `json:"copilot_model"` } -func newDefaultConfig() App { - return App{ - MaxTokens: 4000, - ContextMode: "always-full", - ContextWindowLines: 120, - MaxContextTokens: 4000, - LogPreviewLimit: 100, - } -} - -func loadFromFile(path string, logger *log.Logger) (*App, error) { - f, err := os.Open(path) - if err != nil { - if !os.IsNotExist(err) && logger != nil { - logger.Printf("cannot open config file %s: %v", path, err) - } - return nil, err - } - defer f.Close() - - dec := json.NewDecoder(f) - var fileCfg App - if err := dec.Decode(&fileCfg); err != nil { - if logger != nil { - logger.Printf("invalid config file %s: %v", path, err) - } - return nil, err - } - return &fileCfg, nil -} - -func (a *App) mergeWith(other *App) { - if other.MaxTokens > 0 { - a.MaxTokens = other.MaxTokens - } - if strings.TrimSpace(other.ContextMode) != "" { - a.ContextMode = other.ContextMode - } - if other.ContextWindowLines > 0 { - a.ContextWindowLines = other.ContextWindowLines - } - if other.MaxContextTokens > 0 { - a.MaxContextTokens = other.MaxContextTokens - } - if other.LogPreviewLimit >= 0 { - a.LogPreviewLimit = other.LogPreviewLimit - } - if len(other.TriggerCharacters) > 0 { - a.TriggerCharacters = slices.Clone(other.TriggerCharacters) - } - if strings.TrimSpace(other.Provider) != "" { - a.Provider = other.Provider - } - if strings.TrimSpace(other.OpenAIBaseURL) != "" { - a.OpenAIBaseURL = other.OpenAIBaseURL - } - if strings.TrimSpace(other.OpenAIModel) != "" { - a.OpenAIModel = other.OpenAIModel - } - if strings.TrimSpace(other.OllamaBaseURL) != "" { - a.OllamaBaseURL = other.OllamaBaseURL - } - if strings.TrimSpace(other.OllamaModel) != "" { - a.OllamaModel = other.OllamaModel - } - if strings.TrimSpace(other.CopilotBaseURL) != "" { - a.CopilotBaseURL = other.CopilotBaseURL - } - if strings.TrimSpace(other.CopilotModel) != "" { - a.CopilotModel = other.CopilotModel - } -} - // Load reads configuration from a file and merges with defaults. // It respects the XDG Base Directory Specification. func Load(logger *log.Logger) App { - cfg := newDefaultConfig() - if logger == nil { - return cfg // Return defaults if no logger is provided (e.g. in tests) - } + cfg := newDefaultConfig() + if logger == nil { + return cfg // Return defaults if no logger is provided (e.g. in tests) + } configPath, err := getConfigPath() if err != nil { @@ -123,15 +50,89 @@ func Load(logger *log.Logger) App { return cfg } - cfg.mergeWith(fileCfg) - return cfg + cfg.mergeWith(fileCfg) + return cfg +} + +// Private helpers +func newDefaultConfig() App { + return App{ + MaxTokens: 4000, + ContextMode: "always-full", + ContextWindowLines: 120, + MaxContextTokens: 4000, + LogPreviewLimit: 100, + } +} + +func loadFromFile(path string, logger *log.Logger) (*App, error) { + f, err := os.Open(path) + if err != nil { + if !os.IsNotExist(err) && logger != nil { + logger.Printf("cannot open config file %s: %v", path, err) + } + return nil, err + } + defer f.Close() + + dec := json.NewDecoder(f) + var fileCfg App + if err := dec.Decode(&fileCfg); err != nil { + if logger != nil { + logger.Printf("invalid config file %s: %v", path, err) + } + return nil, err + } + return &fileCfg, nil +} + +func (a *App) mergeWith(other *App) { + if other.MaxTokens > 0 { + a.MaxTokens = other.MaxTokens + } + if strings.TrimSpace(other.ContextMode) != "" { + a.ContextMode = other.ContextMode + } + if other.ContextWindowLines > 0 { + a.ContextWindowLines = other.ContextWindowLines + } + if other.MaxContextTokens > 0 { + a.MaxContextTokens = other.MaxContextTokens + } + if other.LogPreviewLimit >= 0 { + a.LogPreviewLimit = other.LogPreviewLimit + } + if len(other.TriggerCharacters) > 0 { + a.TriggerCharacters = slices.Clone(other.TriggerCharacters) + } + if strings.TrimSpace(other.Provider) != "" { + a.Provider = other.Provider + } + if strings.TrimSpace(other.OpenAIBaseURL) != "" { + a.OpenAIBaseURL = other.OpenAIBaseURL + } + if strings.TrimSpace(other.OpenAIModel) != "" { + a.OpenAIModel = other.OpenAIModel + } + if strings.TrimSpace(other.OllamaBaseURL) != "" { + a.OllamaBaseURL = other.OllamaBaseURL + } + if strings.TrimSpace(other.OllamaModel) != "" { + a.OllamaModel = other.OllamaModel + } + if strings.TrimSpace(other.CopilotBaseURL) != "" { + a.CopilotBaseURL = other.CopilotBaseURL + } + if strings.TrimSpace(other.CopilotModel) != "" { + a.CopilotModel = other.CopilotModel + } } func getConfigPath() (string, error) { - var configPath string - if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" { - configPath = filepath.Join(xdgConfigHome, "hexai", "config.json") - } else { + var configPath string + if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" { + configPath = filepath.Join(xdgConfigHome, "hexai", "config.json") + } else { home, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("cannot find user home directory: %v", err) |
