1use std::{
2 io,
3 path::{Path, PathBuf},
4};
5
6fn absolute(path: Option<PathBuf>) -> Option<PathBuf> {
7 path.filter(|path| path.is_absolute())
8}
9
10pub fn home_dir() -> PathBuf {
13 absolute(dirs::home_dir())
14 .or_else(|| std::env::current_dir().ok())
15 .unwrap_or_else(|| PathBuf::from(std::path::MAIN_SEPARATOR_STR))
16}
17
18pub fn home_path<P: AsRef<Path>>(path: P) -> PathBuf {
19 home_dir().join(path)
20}
21
22pub fn path_entry_exists(path: &Path) -> io::Result<bool> {
25 match std::fs::symlink_metadata(path) {
26 Ok(_) => Ok(true),
27 Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
28 Err(error) => Err(error),
29 }
30}
31
32fn xdg_directory(value: Option<PathBuf>, home: Option<PathBuf>, suffix: &str) -> Option<PathBuf> {
33 absolute(value).or_else(|| absolute(home).map(|home| home.join(suffix)))
34}
35
36pub fn config_dir() -> Option<PathBuf> {
38 xdg_directory(
39 std::env::var_os("XDG_CONFIG_HOME").map(PathBuf::from),
40 dirs::home_dir(),
41 ".config",
42 )
43}
44
45pub fn state_dir() -> Option<PathBuf> {
47 xdg_directory(
48 std::env::var_os("XDG_STATE_HOME").map(PathBuf::from),
49 dirs::home_dir(),
50 ".local/state",
51 )
52}
53
54#[cfg(test)]
55#[path = "tests/paths/mod.rs"]
56mod tests;