hyprshell_core_lib/
path.rs

1use std::env;
2use std::fs::DirEntry;
3use std::path::PathBuf;
4use tracing::{debug, trace, warn};
5
6pub fn get_default_config_path() -> PathBuf {
7    let mut path = get_config_home();
8    // use .ron as default (for generating)
9    path.push("hyprshell/config.ron");
10    if path.exists() {
11        trace!("Found config file at {path:?}");
12        return path;
13    }
14    path.set_extension("json");
15    if path.exists() {
16        trace!("Found config file at {path:?}");
17        return path;
18    }
19    #[cfg(feature = "toml_config")]
20    {
21        path.set_extension("toml");
22        if path.exists() {
23            trace!("Found config file at {path:?}");
24            return path;
25        }
26    }
27    path
28}
29
30pub fn get_default_css_path() -> PathBuf {
31    let mut path = get_config_home();
32    path.push("hyprshell/styles.css");
33    path
34}
35
36pub fn get_default_data_dir() -> PathBuf {
37    let mut path = get_data_home();
38    path.push("hyprshell");
39    path
40}
41
42pub fn get_data_home() -> PathBuf {
43    env::var_os("XDG_DATA_HOME")
44        .map(PathBuf::from)
45        .or_else(|| {
46            env::var_os("HOME")
47                .map(|home| PathBuf::from(format!("{}/.local/share", home.to_string_lossy())))
48        })
49        .expect("Failed to get config dir (XDG_DATA_HOME or HOME not set)")
50}
51
52pub fn get_config_home() -> PathBuf {
53    env::var_os("XDG_CONFIG_HOME")
54        .map(PathBuf::from)
55        .or_else(|| {
56            env::var_os("HOME")
57                .map(|home| PathBuf::from(format!("{}/.config", home.to_string_lossy())))
58        })
59        .expect("Failed to get config dir (XDG_CONFIG_HOME or HOME not set)")
60}
61
62pub fn get_config_dirs() -> Vec<PathBuf> {
63    env::var_os("XDG_CONFIG_DIRS")
64        .map(|val| env::split_paths(&val).collect())
65        .unwrap_or_else(|| vec![PathBuf::from("/etc/xdg/")])
66}
67
68pub fn get_data_dirs() -> Vec<PathBuf> {
69    let mut dirs = env::var_os("XDG_DATA_DIRS")
70        .map(|val| env::split_paths(&val).collect())
71        .unwrap_or_else(|| {
72            vec![
73                PathBuf::from("/usr/local/share"),
74                PathBuf::from("/usr/share"),
75            ]
76        });
77
78    if let Some(data_home) = env::var_os("XDG_DATA_HOME").map(PathBuf::from).map_or_else(
79        || {
80            env::var_os("HOME")
81                .map(|p| PathBuf::from(p).join(".local/share"))
82                .or_else(|| {
83                    warn!("No XDG_DATA_HOME and HOME environment variable found");
84                    None
85                })
86        },
87        Some,
88    ) {
89        dirs.push(data_home)
90    }
91
92    dirs.into_iter()
93        .map(|dir| dir.join("applications"))
94        .collect()
95}
96
97pub fn collect_desktop_files() -> Vec<DirEntry> {
98    let mut res = Vec::new();
99    for dir in get_data_dirs() {
100        if !dir.exists() {
101            continue;
102        }
103        match dir.read_dir() {
104            Ok(dir) => {
105                for entry in dir.flatten() {
106                    let path = entry.path();
107                    if path.is_file() && path.extension().is_some_and(|e| e == "desktop") {
108                        res.push(entry);
109                    }
110                }
111            }
112            Err(e) => {
113                warn!("Failed to read dir {dir:?}: {e}");
114                continue;
115            }
116        }
117    }
118    debug!("found {} desktop files", res.len());
119    res
120}