use std::path::PathBuf;
#[cfg(feature = "native")]
use directories::BaseDirs;
pub fn home_dir() -> PathBuf {
std::env::var("HOME")
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from("/tmp"))
}
pub fn xdg_data_home() -> PathBuf {
std::env::var("XDG_DATA_HOME")
.map(PathBuf::from)
.ok()
.or({
#[cfg(feature = "native")]
{ BaseDirs::new().map(|d| d.data_dir().to_path_buf()) }
#[cfg(not(feature = "native"))]
{ None }
})
.unwrap_or_else(|| home_dir().join(".local").join("share"))
}
pub fn xdg_config_home() -> PathBuf {
std::env::var("XDG_CONFIG_HOME")
.map(PathBuf::from)
.ok()
.or({
#[cfg(feature = "native")]
{ BaseDirs::new().map(|d| d.config_dir().to_path_buf()) }
#[cfg(not(feature = "native"))]
{ None }
})
.unwrap_or_else(|| home_dir().join(".config"))
}
pub fn xdg_cache_home() -> PathBuf {
std::env::var("XDG_CACHE_HOME")
.map(PathBuf::from)
.ok()
.or({
#[cfg(feature = "native")]
{ BaseDirs::new().map(|d| d.cache_dir().to_path_buf()) }
#[cfg(not(feature = "native"))]
{ None }
})
.unwrap_or_else(|| home_dir().join(".cache"))
}
pub fn xdg_runtime_dir() -> PathBuf {
std::env::var("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| std::env::temp_dir())
}
pub fn runtime_dir() -> PathBuf {
xdg_runtime_dir().join("kaish")
}
pub fn data_dir() -> PathBuf {
xdg_data_home().join("kaish")
}
pub fn config_dir() -> PathBuf {
xdg_config_home().join("kaish")
}
pub fn cache_dir() -> PathBuf {
xdg_cache_home().join("kaish")
}
pub fn kernels_dir() -> PathBuf {
data_dir().join("kernels")
}
pub fn spill_dir() -> PathBuf {
runtime_dir().join("spill")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn home_dir_is_absolute() {
let home = home_dir();
assert!(home.is_absolute());
}
#[test]
fn xdg_data_home_defaults_to_local_share() {
let data = xdg_data_home();
assert!(data.is_absolute());
let path_str = data.to_string_lossy();
assert!(
path_str.ends_with(".local/share") || std::env::var("XDG_DATA_HOME").is_ok(),
"Expected .local/share or XDG override, got: {}",
path_str
);
}
#[test]
fn xdg_config_home_defaults_to_config() {
let config = xdg_config_home();
assert!(config.is_absolute());
let path_str = config.to_string_lossy();
assert!(
path_str.ends_with(".config") || std::env::var("XDG_CONFIG_HOME").is_ok(),
"Expected .config or XDG override, got: {}",
path_str
);
}
#[test]
fn xdg_cache_home_defaults_to_cache() {
let cache = xdg_cache_home();
assert!(cache.is_absolute());
let path_str = cache.to_string_lossy();
assert!(
path_str.ends_with(".cache") || std::env::var("XDG_CACHE_HOME").is_ok(),
"Expected .cache or XDG override, got: {}",
path_str
);
}
#[test]
fn xdg_runtime_dir_is_absolute() {
let runtime = xdg_runtime_dir();
assert!(runtime.is_absolute());
}
#[test]
fn kaish_paths_are_under_kaish() {
assert!(runtime_dir().ends_with("kaish"));
assert!(data_dir().ends_with("kaish"));
assert!(config_dir().ends_with("kaish"));
assert!(cache_dir().ends_with("kaish"));
}
#[test]
fn kaish_paths_build_on_xdg_primitives() {
assert_eq!(data_dir(), xdg_data_home().join("kaish"));
assert_eq!(config_dir(), xdg_config_home().join("kaish"));
assert_eq!(cache_dir(), xdg_cache_home().join("kaish"));
assert_eq!(runtime_dir(), xdg_runtime_dir().join("kaish"));
}
#[test]
fn spill_dir_is_under_runtime() {
let spill = spill_dir();
assert!(spill.starts_with(&runtime_dir()));
assert!(spill.ends_with("spill"));
}
#[test]
fn kernels_dir_is_under_data() {
let kernels = kernels_dir();
let data = data_dir();
assert!(kernels.starts_with(&data));
assert!(kernels.ends_with("kernels"));
}
}