use std::{env, path::PathBuf};
pub fn home_dir() -> Result<PathBuf, HomeDirError> {
home::home_dir().ok_or(HomeDirError)
}
pub mod os {
use std::{env, path::PathBuf};
use crate::{home_dir, HomeDirError};
pub fn data_dir() -> Result<PathBuf, HomeDirError> {
let home = home_dir()?;
Ok(match env::consts::OS {
"macos" => home.join("Library").join("Application Support"),
"windows" => env::var("APPDATA")
.map_or_else(|_| home.join("AppData").join("Roaming"), PathBuf::from),
_ => home.join(".local").join("share"),
})
}
pub fn config_dir() -> Result<PathBuf, HomeDirError> {
let home = home_dir()?;
Ok(match env::consts::OS {
"macos" => home.join("Library").join("Preferences"),
"windows" => env::var("APPDATA")
.map_or_else(|_| home.join("AppData").join("Roaming"), PathBuf::from),
_ => home.join(".config"),
})
}
pub fn cache_dir() -> Result<PathBuf, HomeDirError> {
let home = home_dir()?;
Ok(match env::consts::OS {
"macos" => home.join("Library").join("Caches"),
"windows" => env::var("LOCALAPPDATA")
.map_or_else(|_| home.join("AppData").join("Local"), PathBuf::from),
_ => home.join(".cache"),
})
}
pub fn state_dir() -> Result<Option<PathBuf>, HomeDirError> {
let home = home_dir()?;
Ok(Some(match env::consts::OS {
"macos" | "windows" => return Ok(None), _ => home.join(".local").join("state"),
}))
}
}
pub fn data_dir() -> Result<PathBuf, HomeDirError> {
let dir = if let Ok(xdg_data) = env::var("XDG_DATA_HOME") {
PathBuf::from(xdg_data)
} else {
crate::os::data_dir()?
};
Ok(dir)
}
pub fn config_dir() -> Result<PathBuf, HomeDirError> {
let dir = if let Ok(xdg_config) = env::var("XDG_CONFIG_HOME") {
PathBuf::from(xdg_config)
} else {
crate::os::config_dir()?
};
Ok(dir)
}
pub fn cache_dir() -> Result<PathBuf, HomeDirError> {
let dir = if let Ok(xdg_cache) = env::var("XDG_CACHE_HOME") {
PathBuf::from(xdg_cache)
} else {
crate::os::cache_dir()?
};
Ok(dir)
}
pub fn state_dir() -> Result<Option<PathBuf>, HomeDirError> {
let dir = if let Ok(xdg_state) = env::var("XDG_STATE_HOME") {
Some(PathBuf::from(xdg_state))
} else {
crate::os::state_dir()?
};
Ok(dir)
}
pub fn runtime_dir() -> Option<PathBuf> {
if let Ok(xdg_runtime) = env::var("XDG_RUNTIME_DIR") {
return Some(PathBuf::from(xdg_runtime));
}
None
}
#[derive(Debug)]
pub struct HomeDirError;
impl std::fmt::Display for HomeDirError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "could not locate home directory")
}
}
impl std::error::Error for HomeDirError {}