diff --git a/src/config/load.rs b/src/config/load.rs index 1393a88..3ac5ca1 100644 --- a/src/config/load.rs +++ b/src/config/load.rs @@ -32,22 +32,27 @@ pub fn load_config_from_path(specific_path: Option<&str>) -> Result = Vec::new(); - - // User-specific path - if let Some(home_dir) = dirs::home_dir() { - let user_config_path = home_dir.join(".config/superfreq/config.toml"); - config_paths.push(user_config_path); - } else { + // Check for SUPERFREQ_CONFIG environment variable + if let Ok(env_path) = std::env::var("SUPERFREQ_CONFIG") { + let env_path = Path::new(&env_path); + if env_path.exists() { + println!( + "Loading config from SUPERFREQ_CONFIG: {}", + env_path.display() + ); + return load_and_parse_config(env_path); + } eprintln!( - "Warning: Could not determine home directory. User-specific config will not be loaded." + "Warning: Config file specified by SUPERFREQ_CONFIG not found: {}", + env_path.display() ); } // System-wide paths - config_paths.push(PathBuf::from("/etc/xdg/superfreq/config.toml")); - config_paths.push(PathBuf::from("/etc/superfreq.toml")); + let config_paths = vec![ + PathBuf::from("/etc/xdg/superfreq/config.toml"), + PathBuf::from("/etc/superfreq.toml"), + ]; for path in config_paths { if path.exists() { diff --git a/src/config/types.rs b/src/config/types.rs index 10e0a9c..6446e3e 100644 --- a/src/config/types.rs +++ b/src/config/types.rs @@ -87,8 +87,6 @@ pub struct AppConfig { pub enum ConfigError { IoError(std::io::Error), TomlError(toml::de::Error), - NoValidConfigFound, - HomeDirNotFound, ValidationError(String), } @@ -109,8 +107,6 @@ impl std::fmt::Display for ConfigError { match self { Self::IoError(e) => write!(f, "I/O error: {e}"), Self::TomlError(e) => write!(f, "TOML parsing error: {e}"), - Self::NoValidConfigFound => write!(f, "No valid configuration file found."), - Self::HomeDirNotFound => write!(f, "Could not determine user home directory."), Self::ValidationError(s) => write!(f, "Configuration validation error: {s}"), } } diff --git a/src/config/watcher.rs b/src/config/watcher.rs index 8998281..c362e0d 100644 --- a/src/config/watcher.rs +++ b/src/config/watcher.rs @@ -1,3 +1,4 @@ +use log::{debug, error, warn}; use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; use std::error::Error; use std::path::Path; @@ -26,6 +27,8 @@ impl ConfigWatcher { // Start watching the config file watcher.watch(Path::new(config_path), RecursiveMode::NonRecursive)?; + debug!("Started watching config file: {config_path}"); + Ok(Self { rx, _watcher: watcher, @@ -46,15 +49,34 @@ impl ConfigWatcher { loop { match self.rx.try_recv() { Ok(Ok(event)) => { - // Only process write/modify events - if matches!(event.kind, EventKind::Modify(_)) { - should_reload = true; + // Process various file events that might indicate configuration changes + match event.kind { + EventKind::Modify(_) => { + debug!("Detected modification to config file: {}", self.config_path); + should_reload = true; + } + EventKind::Create(_) => { + debug!("Detected recreation of config file: {}", self.config_path); + should_reload = true; + } + EventKind::Remove(_) => { + // Some editors delete then recreate the file when saving + // Just log this event and wait for the create event + debug!( + "Detected removal of config file: {} - waiting for recreation", + self.config_path + ); + } + _ => {} // Ignore other event types + } + + if should_reload { self.last_event_time = std::time::Instant::now(); } } Ok(Err(e)) => { // File watcher error, log but continue - eprintln!("Error watching config file: {e}"); + warn!("Error watching config file: {e}"); } Err(TryRecvError::Empty) => { // No more events @@ -62,7 +84,7 @@ impl ConfigWatcher { } Err(TryRecvError::Disconnected) => { // Channel disconnected, watcher is dead - eprintln!("Config watcher channel disconnected"); + error!("Config watcher channel disconnected"); return None; } } @@ -78,18 +100,31 @@ impl ConfigWatcher { thread::sleep(debounce_time - time_since_last_event); } + // Ensure the file exists before attempting to reload + let config_path = Path::new(&self.config_path); + if !config_path.exists() { + warn!( + "Config file does not exist after change events: {}", + self.config_path + ); + return None; + } + + debug!("Reloading configuration from {}", self.config_path); + // Attempt to reload the config from the specific path being watched match load_config_from_path(Some(&self.config_path)) { - Ok(config) => Some(Ok(config)), - Err(e) => Some(Err(Box::new(e))), + Ok(config) => { + debug!("Successfully reloaded configuration"); + Some(Ok(config)) + } + Err(e) => { + error!("Failed to reload configuration: {e}"); + Some(Err(Box::new(e))) + } } } else { None } } - - /// Get the path of the config file being watched - pub const fn config_path(&self) -> &String { - &self.config_path - } } diff --git a/src/main.rs b/src/main.rs index 5398444..133af98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -100,7 +100,7 @@ fn main() { Ok(cfg) => cfg, Err(e) => { error!("Error loading configuration: {e}. Using default values."); - // Proceed with default config if loading fails, as per previous steps + // Proceed with default config if loading fails AppConfig::default() } };