use std::collections::BTreeMap;
use std::path::PathBuf;
use anyhow::Result;
pub struct Config {
path: PathBuf,
values: BTreeMap<String, String>,
}
impl Config {
pub fn load() -> Result<Self> {
let path = config_path();
let values = if path.exists() {
let content = std::fs::read_to_string(&path)?;
let table: toml::Table = content.parse().unwrap_or_default();
table
.into_iter()
.filter_map(|(k, v)| v.as_str().map(|s| (k, s.to_string())))
.collect()
} else {
BTreeMap::new()
};
Ok(Self { path, values })
}
pub fn get(&self, key: &str) -> Option<&str> {
self.values.get(key).map(String::as_str)
}
pub fn set(&mut self, key: &str, value: &str) -> Result<()> {
self.values.insert(key.to_string(), value.to_string());
Ok(())
}
pub fn entries(&self) -> impl Iterator<Item = (&str, &str)> {
self.values.iter().map(|(k, v)| (k.as_str(), v.as_str()))
}
pub fn save(&self) -> Result<()> {
if let Some(parent) = self.path.parent() {
std::fs::create_dir_all(parent)?;
}
let mut table = toml::Table::new();
for (k, v) in &self.values {
table.insert(k.clone(), toml::Value::String(v.clone()));
}
let content = toml::to_string_pretty(&table)?;
std::fs::write(&self.path, content)?;
Ok(())
}
}
fn config_path() -> PathBuf {
dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("genome-sh")
.join("config.toml")
}