use std::path::PathBuf; use serde::{Deserialize, Serialize}; use crate::{Error, Result, args::ServArgs}; const STYLE: &str = include_str!("../examples/simple-gruvbox.css"); const BOOKMARKS: &str = include_str!("../examples/bookmarks.json"); const FAVICON: &str = include_str!("../examples/favicon.svg"); #[derive(Deserialize, Serialize, Clone)] pub struct Config { pub port: u16, pub style_file: PathBuf, pub bookmarks_file: PathBuf, pub favicon_file: PathBuf, } impl Config { pub fn new(args: ServArgs) -> Result { let config_home = Config::get_config_home()?; let config_path = &config_home.join("config.toml"); let mut config = if config_path.exists() { Config::load_config(config_path)? } else { tracing::info!( "Couldn't load configuration from {}, generating defaults", config_path.display() ); Config::generate_defaults(config_home)? }; config.override_with_serv_args(args)?; Ok(config) } pub fn load_config(config: &PathBuf) -> Result { let config = std::fs::read_to_string(&config)?; let config: Config = toml::from_str(&config)?; Ok(config) } pub fn generate_defaults(config_home: PathBuf) -> Result { std::fs::create_dir_all(&config_home)?; let style_file = config_home.join("style.css"); let bookmarks_file = config_home.join("bookmarks.json"); let favicon_file = config_home.join("favicon.svg"); let config_file = config_home.join("config.toml"); std::fs::write(&style_file, &STYLE)?; std::fs::write(&bookmarks_file, &BOOKMARKS)?; std::fs::write(&favicon_file, &FAVICON)?; let config = Config { port: 8080, style_file, bookmarks_file, favicon_file, }; let config_file_content = toml::to_string(&config)?; std::fs::write(config_file, config_file_content)?; Ok(config) } pub fn override_with_serv_args(&mut self, args: ServArgs) -> Result<()> { if let Some(port) = &args.port { self.port = port.parse::()?; } if let Some(style_file) = &args.style_file { if PathBuf::from(style_file).exists() { self.style_file = PathBuf::from(style_file) } } if let Some(bookmarks_file) = &args.bookmarks_file { if PathBuf::from(bookmarks_file).exists() { self.bookmarks_file = PathBuf::from(bookmarks_file) } } if let Some(favicon_file) = &args.favicon_file { if PathBuf::from(favicon_file).exists() { self.favicon_file = PathBuf::from(favicon_file) } } Ok(()) } fn get_config_home() -> Result { let config_home = if let Ok(xdg_config_home) = std::env::var("XDG_CONFIG_HOME") { PathBuf::from(xdg_config_home).join("sbm-rs") } else if let Ok(home) = std::env::var("HOME") { PathBuf::from(home).join(".config/sbm-rs") } else { return Err(Error::ConfigHomeNotFound); }; Ok(config_home) } }