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"` // 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") } // getConfigPath returns the config file path within the depository func getConfigPath(depoPath string) string { return filepath.Join(depoPath, ".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() // Determine depository path (from flag, env var, or default) actualDepoPath := depoPath if actualDepoPath == "" { actualDepoPath = viper.GetString("depo_path") if actualDepoPath == "" { actualDepoPath = getDefaultDepoPath() } } // Set defaults viper.SetDefault("depo_path", actualDepoPath) viper.SetDefault("tag_prefix", "+") // Ensure depository and .jade directory exist jadeDir := filepath.Join(actualDepoPath, ".jade") if err := os.MkdirAll(jadeDir, 0755); err != nil { return nil, fmt.Errorf("failed to create .jade directory: %w", err) } // Determine config file location configFilePath := cfgPath if configFilePath == "" { configFilePath = getConfigPath(actualDepoPath) } // Set up config file viper.SetConfigFile(configFilePath) // Try to read existing config file if err := viper.ReadInConfig(); err != nil { // Check if file doesn't exist (handles both viper.ConfigFileNotFoundError and os.IsNotExist) if _, ok := err.(viper.ConfigFileNotFoundError); ok || os.IsNotExist(err) { // Config file not found, create it with defaults 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) } // 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 }