use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CliConfig {
pub log_level: String,
pub default_port: u16,
pub cache: CacheConfig,
pub server: ServerConfig,
pub compiler: CompilerConfig,
}
impl Default for CliConfig {
fn default() -> Self {
Self {
log_level: "info".to_string(),
default_port: 3000,
cache: CacheConfig::default(),
server: ServerConfig::default(),
compiler: CompilerConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheConfig {
pub enabled: bool,
pub directory: PathBuf,
pub max_size_mb: usize,
pub ttl_hours: u64,
}
impl Default for CacheConfig {
fn default() -> Self {
Self {
enabled: true,
directory: get_cache_dir(),
max_size_mb: 100,
ttl_hours: 24,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
pub host: String,
pub port: u16,
pub timeout_seconds: u64,
pub max_connections: usize,
pub cors_enabled: bool,
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
host: "127.0.0.1".to_string(),
port: 3000,
timeout_seconds: 30,
max_connections: 100,
cors_enabled: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompilerConfig {
pub optimization_level: u8,
pub include_debug_info: bool,
pub generate_source_maps: bool,
pub target_arch: String,
}
impl Default for CompilerConfig {
fn default() -> Self {
Self {
optimization_level: 0,
include_debug_info: true,
generate_source_maps: true,
target_arch: std::env::consts::ARCH.to_string(),
}
}
}
pub struct ConfigManager {
config: CliConfig,
config_path: PathBuf,
}
impl ConfigManager {
pub fn new() -> Result<Self, Box<dyn std::error::Error>> {
let config_dir = get_config_dir();
std::fs::create_dir_all(&config_dir)?;
let config_path = config_dir.join("cli.toml");
let config = if config_path.exists() {
Self::load_config(&config_path)?
} else {
CliConfig::default()
};
Ok(Self {
config,
config_path,
})
}
fn load_config(path: &Path) -> Result<CliConfig, Box<dyn std::error::Error>> {
let content = std::fs::read_to_string(path)?;
let config: CliConfig = toml::from_str(&content)?;
Ok(config)
}
pub fn save_config(&self) -> Result<(), Box<dyn std::error::Error>> {
let content = toml::to_string_pretty(&self.config)?;
std::fs::write(&self.config_path, content)?;
Ok(())
}
pub fn get_config(&self) -> &CliConfig {
&self.config
}
pub fn update_config<F>(&mut self, updater: F)
where
F: FnOnce(&mut CliConfig),
{
updater(&mut self.config);
}
pub fn reset_config(&mut self) -> Result<(), Box<dyn std::error::Error>> {
self.config = CliConfig::default();
self.save_config()
}
}
fn get_config_dir() -> PathBuf {
dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("kotoba")
}
fn get_cache_dir() -> PathBuf {
dirs::cache_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("kotoba")
}