use std::{ fs::read_to_string, io, path::{Path, PathBuf}, }; use lazy_static::lazy_static; use serde::Deserialize; use crate::{ console::warning, install::languages::{LanguageDb, LanguageDefs}, }; lazy_static! { static ref XDG: xdg::BaseDirectories = xdg::BaseDirectories::with_prefix("chrysopoeia").unwrap(); } #[derive(Debug, Default, Deserialize)] pub struct Settings { #[serde(default = "default_data_dir")] pub data_dir: PathBuf, #[serde(default)] pub install: InstallSettings, #[serde(rename = "languages")] pub user_language_defs: Option, } #[derive(Debug, Default, Deserialize)] pub struct InstallSettings { #[serde(alias = "cc")] pub compiler: Option, } fn default_data_dir() -> PathBuf { if cfg!(debug_assertions) { "share".into() } else { XDG.get_data_home() } } pub fn default_config() -> PathBuf { if cfg!(debug_assertions) { "chrysopoeia.toml".into() } else { XDG.get_config_file("config.toml") } } #[derive(Debug, thiserror::Error)] pub enum Error { #[error("unable to read config file: {0}")] Io(#[from] io::Error), #[error("{file:?}: {e}")] Toml { file: PathBuf, e: toml::de::Error }, } pub fn get_settings(path: &Path) -> Result { toml::from_str(&read_to_string(path)?).map_err(|e| Error::Toml { file: path.to_owned(), e, }) } impl Settings { pub fn parser_dir(&self) -> PathBuf { self.data_dir.join("parsers") } /// note: this method moves out of self.user_language_defs pub fn language_defs(&mut self) -> Result { let mut sources: Vec = self.user_language_defs.take().into_iter().collect(); let default_path = self.data_dir.join("languages.toml"); match read_to_string(&default_path) { Ok(default_defs) => { sources.push(toml::from_str(&default_defs).map_err(|e| Error::Toml { file: default_path, e, })?) } Err(e) => warning!("couldn't read language install info from {default_path:?}: {e}"), } Ok(LanguageDb::new(sources)) } }