use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct Config {
pub editor: EditorConfig,
pub theme: ThemeConfig,
pub cache: CacheConfig,
pub provider: ProviderConfig,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct ProviderConfig {
pub kind: String,
pub command: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct EditorConfig {
pub program: Option<String>,
pub args: Vec<String>,
pub read_only: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct CacheConfig {
pub max_mb: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct ThemeConfig {
pub name: String,
pub path: Option<PathBuf>,
}
impl Default for Config {
fn default() -> Self {
Config {
editor: EditorConfig {
program: None,
args: Vec::new(),
read_only: true,
},
theme: ThemeConfig {
name: "catppuccin-mocha".into(),
path: None,
},
cache: CacheConfig { max_mb: 512 },
provider: ProviderConfig::default(),
}
}
}
impl Default for ProviderConfig {
fn default() -> Self {
ProviderConfig {
kind: "github".into(),
command: Vec::new(),
}
}
}
impl Default for EditorConfig {
fn default() -> Self {
Config::default().editor
}
}
impl Default for ThemeConfig {
fn default() -> Self {
Config::default().theme
}
}
impl Default for CacheConfig {
fn default() -> Self {
Config::default().cache
}
}
impl Config {
pub fn path() -> Option<PathBuf> {
dirs::config_dir().map(|d| d.join("rootle").join("config.toml"))
}
pub fn load() -> Self {
let Some(path) = Self::path() else {
return Self::default();
};
Self::load_from(&path)
}
pub fn save(&self) -> std::io::Result<()> {
let Some(path) = Self::path() else {
return Ok(()); };
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
let text = toml::to_string_pretty(self).map_err(std::io::Error::other)?;
std::fs::write(path.with_extension("toml.tmp"), text)?;
std::fs::rename(path.with_extension("toml.tmp"), path)
}
pub fn load_from(path: &std::path::Path) -> Self {
let Ok(text) = std::fs::read_to_string(path) else {
return Self::default();
};
toml::from_str(&text).unwrap_or_default()
}
}