pub mod ai_types;
mod types;
pub use types::{ClipboardBackend, Config};
#[allow(unused_imports)]
pub use types::AutocompleteConfig;
#[allow(unused_imports)]
pub use ai_types::{AiConfig, AiProviderType, AnthropicConfig};
#[allow(unused_imports)]
pub use types::TooltipConfig;
use std::fs;
use std::path::PathBuf;
pub struct ConfigResult {
pub config: Config,
pub warning: Option<String>,
}
pub fn load_config() -> ConfigResult {
let config_path = get_config_path();
log::debug!("Config path: {:?}", config_path);
if !config_path.exists() {
log::debug!("No config file found, using defaults");
return ConfigResult {
config: Config::default(),
warning: None,
};
}
let contents = match fs::read_to_string(&config_path) {
Ok(contents) => contents,
Err(e) => {
log::error!("Failed to read config file {:?}: {}", config_path, e);
return ConfigResult {
config: Config::default(),
warning: Some(format!("Failed to read config: {}", e)),
};
}
};
match toml::from_str::<Config>(&contents) {
Ok(mut config) => {
config.autocomplete.array_sample_size =
config.autocomplete.array_sample_size.clamp(1, 1000);
log::debug!(
"Config: clipboard={:?}, ai.enabled={}, ai.provider={:?}, array_sample_size={}",
config.clipboard.backend,
config.ai.enabled,
config.ai.provider,
config.autocomplete.array_sample_size
);
ConfigResult {
config,
warning: None,
}
}
Err(e) => {
log::error!("Failed to parse config file {:?}: {}", config_path, e);
ConfigResult {
config: Config::default(),
warning: Some(format!("Invalid config: {}", e)),
}
}
}
}
fn get_config_path() -> PathBuf {
dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join(".config")
.join("jiq")
.join("config.toml")
}
#[cfg(test)]
#[path = "config_tests.rs"]
mod config_tests;