directories_next/
lin.rs

1use std::env;
2use std::path::PathBuf;
3
4use crate::BaseDirs;
5use crate::UserDirs;
6use crate::ProjectDirs;
7
8pub fn base_dirs() -> Option<BaseDirs> {
9    if let Some(home_dir)  = dirs_sys_next::home_dir() {
10        let cache_dir      = env::var_os("XDG_CACHE_HOME") .and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".cache"));
11        let config_dir     = env::var_os("XDG_CONFIG_HOME").and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".config"));
12        let data_dir       = env::var_os("XDG_DATA_HOME")  .and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share"));
13        let data_local_dir = data_dir.clone();
14        let runtime_dir    = env::var_os("XDG_RUNTIME_DIR").and_then(dirs_sys_next::is_absolute_path);
15        let executable_dir = 
16            env::var_os("XDG_BIN_HOME").and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| {
17                let mut new_dir = data_dir.clone(); new_dir.pop(); new_dir.push("bin"); new_dir });
18
19        let base_dirs = BaseDirs {
20            home_dir:       home_dir,
21            cache_dir:      cache_dir,
22            config_dir:     config_dir,
23            data_dir:       data_dir,
24            data_local_dir: data_local_dir,
25            executable_dir: Some(executable_dir),
26            runtime_dir:    runtime_dir
27        };
28        Some(base_dirs)
29    } else {
30        None
31    }
32}
33
34pub fn user_dirs() -> Option<UserDirs> {
35    if let Some(home_dir) = dirs_sys_next::home_dir() {
36        let data_dir  = env::var_os("XDG_DATA_HOME").and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share"));
37        let font_dir  = data_dir.join("fonts");
38        let mut user_dirs_map = dirs_sys_next::user_dirs(&home_dir);
39
40        let user_dirs = UserDirs {
41            home_dir:     home_dir,
42            audio_dir:    user_dirs_map.remove("MUSIC"),
43            desktop_dir:  user_dirs_map.remove("DESKTOP"),
44            document_dir: user_dirs_map.remove("DOCUMENTS"),
45            download_dir: user_dirs_map.remove("DOWNLOAD"),
46            font_dir:     Some(font_dir),
47            picture_dir:  user_dirs_map.remove("PICTURES"),
48            public_dir:   user_dirs_map.remove("PUBLICSHARE"),
49            template_dir: user_dirs_map.remove("TEMPLATES"),
50            video_dir:    user_dirs_map.remove("VIDEOS")
51        };
52        Some(user_dirs)
53    } else {
54        None
55    }
56}
57
58pub fn project_dirs_from_path(project_path: PathBuf) -> Option<ProjectDirs> {
59    if let Some(home_dir)  = dirs_sys_next::home_dir() {
60        let cache_dir      = env::var_os("XDG_CACHE_HOME") .and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".cache")).join(&project_path);
61        let config_dir     = env::var_os("XDG_CONFIG_HOME").and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".config")).join(&project_path);
62        let data_dir       = env::var_os("XDG_DATA_HOME")  .and_then(dirs_sys_next::is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share")).join(&project_path);
63        let data_local_dir = data_dir.clone();
64        let runtime_dir    = env::var_os("XDG_RUNTIME_DIR").and_then(dirs_sys_next::is_absolute_path).map(|o| o.join(&project_path));
65
66        let project_dirs = ProjectDirs {
67            project_path:   project_path,
68            cache_dir:      cache_dir,
69            config_dir:     config_dir,
70            data_dir:       data_dir,
71            data_local_dir: data_local_dir,
72            runtime_dir:    runtime_dir
73        };
74        Some(project_dirs)
75    } else {
76        None
77    }
78}
79
80pub fn project_dirs_from(_qualifier: &str, _organization: &str, application: &str) -> Option<ProjectDirs> {
81    ProjectDirs::from_path(PathBuf::from(&trim_and_lowercase_then_replace_spaces(application, "")))
82}
83
84fn trim_and_lowercase_then_replace_spaces(name: &str, replacement: &str) -> String {
85    let mut buf = String::with_capacity(name.len());
86    let mut parts = name.split_whitespace();
87    let mut current_part = parts.next();
88    let replace = !replacement.is_empty();
89    while current_part.is_some() {
90        let value = current_part.unwrap().to_lowercase();
91        buf.push_str(&value);
92        current_part = parts.next();
93        if replace && current_part.is_some() {
94            buf.push_str(replacement);
95        }
96    }
97    buf
98}
99
100#[cfg(test)]
101mod tests {
102    use crate::lin::trim_and_lowercase_then_replace_spaces;
103
104    #[test]
105    fn test_trim_and_lowercase_then_replace_spaces() {
106        let input1    = "Bar App";
107        let actual1   = trim_and_lowercase_then_replace_spaces(input1, "-");
108        let expected1 = "bar-app";
109        assert_eq!(expected1, actual1);
110
111        let input2    = "BarApp-Foo";
112        let actual2   = trim_and_lowercase_then_replace_spaces(input2, "-");
113        let expected2 = "barapp-foo";
114        assert_eq!(expected2, actual2);
115
116        let input3    = " Bar App ";
117        let actual3   = trim_and_lowercase_then_replace_spaces(input3, "-");
118        let expected3 = "bar-app";
119        assert_eq!(expected3, actual3);
120
121        let input4    = "  Bar  App  ";
122        let actual4   = trim_and_lowercase_then_replace_spaces(input4, "-");
123        let expected4 = "bar-app";
124        assert_eq!(expected4, actual4);
125    }
126
127    #[test]
128    fn test_file_user_dirs_exists() {
129        let base_dirs      = crate::BaseDirs::new();
130        let user_dirs_file = base_dirs.unwrap().config_dir().join("user-dirs.dirs");
131        println!("{:?} exists: {:?}", user_dirs_file, user_dirs_file.exists());
132    }
133}