#![allow(dead_code)] use std::fs; use std::path::PathBuf; use std::sync::OnceLock; use anyhow::Result; const APP_NAME: &str = env!("CARGO_PKG_NAME"); const APP_ORG: &str = "valeth"; static CONFIG: OnceLock = OnceLock::new(); static DATA: OnceLock = OnceLock::new(); static CACHE: OnceLock = OnceLock::new(); static STATE: OnceLock = OnceLock::new(); static SELECTED_PROJECT_FILE: OnceLock = OnceLock::new(); pub fn config_path() -> &'static PathBuf { CONFIG.get_or_init(|| init("XDG_CONFIG_HOME", ".config").unwrap()) } pub fn data_path() -> &'static PathBuf { DATA.get_or_init(|| init("XDG_DATA_HOME", ".local/share").unwrap()) } pub fn cache_path() -> &'static PathBuf { CACHE.get_or_init(|| init("XDG_CACHE_HOME", ".cache").unwrap()) } pub fn state_path() -> &'static PathBuf { STATE.get_or_init(|| init("XDG_STATE_HOME", ".local/state").unwrap()) } pub fn selected_project_file() -> &'static PathBuf { SELECTED_PROJECT_FILE.get_or_init(|| state_path().join("selected-project")) } fn init(xdg_var: &str, fallback_home_path: &str) -> Result { let path = xdg_path_with_fallback(xdg_var, fallback_home_path)?; if !path.exists() { fs::create_dir_all(&path)?; } Ok(path) } fn xdg_path_with_fallback(xdg_var: &str, fallback_home_path: &str) -> Result { use std::env; let user_home = env::var("HOME").expect("HOME variable is not set"); let user_home = PathBuf::from(user_home); let apply_fallback = |e| match e { env::VarError::NotPresent => Ok(user_home.join(fallback_home_path)), _ => Err(e.into()), }; env::var(xdg_var) .map(PathBuf::from) .or_else(apply_fallback) .map(|path| path.join(APP_ORG).join(APP_NAME)) }