package engine import ( "fmt" "os" "path/filepath" "github.com/spf13/viper" ) type Config struct { // DepoPath is the path to the jade depository. Default ~/jade-depository DepoPath string `mapstructure:"depo_path"` // ConfigPath is the path to the config directory. Default ~/.config/jade/config.yml ConfigPath string `mapstructure:"config_path"` // TagPrefix is the prefix used for tags in notes. Default "+" TagPrefix string `mapstructure:"tag_prefix"` } // getDefaultDepoPath returns the default depository path func getDefaultDepoPath() string { home, err := os.UserHomeDir() if err != nil { return "./jade-depository" } return filepath.Join(home, "jade-depository") } // getDefaultConfigPath returns the default config directory path func getDefaultConfigPath() string { home, err := os.UserHomeDir() if err != nil { return "./.config/jade/config.yml" } return filepath.Join(home, ".config", "jade", "config.yml") } // initConfig initializes the configuration using Viper // Precedence order: flags > environment variables > config file > defaults func initConfig(cfgPath, depoPath string) (*Config, error) { // Set up environment variable support viper.SetEnvPrefix("JADE") viper.AutomaticEnv() // Set defaults viper.SetDefault("depo_path", getDefaultDepoPath()) viper.SetDefault("config_path", getDefaultConfigPath()) viper.SetDefault("tag_prefix", "+") // Determine config file location configDir := cfgPath if configDir == "" { configDir = getDefaultConfigPath() } // Ensure config directory exists if err := os.MkdirAll(configDir, 0755); err != nil { return nil, fmt.Errorf("failed to create config directory: %w", err) } // Set up config file viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(configDir) // Try to read existing config file if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { // Config file not found, create it with defaults configFilePath := filepath.Join(configDir, "config.yaml") if err := viper.SafeWriteConfigAs(configFilePath); err != nil { return nil, fmt.Errorf("failed to create config file: %w", err) } } else { // Config file was found but another error occurred return nil, fmt.Errorf("error reading config file: %w", err) } } // Override with flags if provided (highest precedence) if depoPath != "" { viper.Set("depo_path", depoPath) } if cfgPath != "" { viper.Set("config_path", cfgPath) } // Unmarshal config into struct cfg := &Config{} if err := viper.Unmarshal(cfg); err != nil { return nil, fmt.Errorf("failed to unmarshal config: %w", err) } // Write config back to persist any changes (e.g., from flags or env vars) if err := viper.WriteConfig(); err != nil { return nil, fmt.Errorf("failed to write config: %w", err) } return cfg, nil }