1use std::path::PathBuf;
6
7fn xdg(var: &str, default: &str) -> Option<PathBuf> {
8 std::env::var_os(var)
9 .filter(|v| !v.is_empty())
10 .map(PathBuf::from)
11 .or_else(|| dirs::home_dir().map(|h| h.join(default)))
12}
13
14pub fn config_dir() -> Option<PathBuf> {
16 xdg("XDG_CONFIG_HOME", ".config")
17}
18
19pub fn cache_dir() -> Option<PathBuf> {
21 xdg("XDG_CACHE_HOME", ".cache")
22}
23
24pub fn state_dir() -> Option<PathBuf> {
26 xdg("XDG_STATE_HOME", ".local/state")
27}
28
29pub fn data_dir() -> Option<PathBuf> {
31 xdg("XDG_DATA_HOME", ".local/share")
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
39 fn unset_vars_fall_back_to_xdg_defaults() {
40 for (var, default) in [
43 ("XDG_CONFIG_HOME", ".config"),
44 ("XDG_CACHE_HOME", ".cache"),
45 ("XDG_STATE_HOME", ".local/state"),
46 ("XDG_DATA_HOME", ".local/share"),
47 ] {
48 assert!(
49 std::env::var_os(var).is_none(),
50 "{var} must not leak into tests"
51 );
52 let home = dirs::home_dir().unwrap();
53 assert_eq!(xdg(var, default), Some(home.join(default)));
54 }
55 }
56}