1 use std::env;
2 use std::path::PathBuf;
3 
4 use crate::BaseDirs;
5 use crate::UserDirs;
6 use crate::ProjectDirs;
7 
base_dirs() -> Option<BaseDirs>8 pub 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 
user_dirs() -> Option<UserDirs>34 pub 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 
project_dirs_from_path(project_path: PathBuf) -> Option<ProjectDirs>58 pub 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 
project_dirs_from(_qualifier: &str, _organization: &str, application: &str) -> Option<ProjectDirs>80 pub 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 
trim_and_lowercase_then_replace_spaces(name: &str, replacement: &str) -> String84 fn 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)]
101 mod tests {
102     use crate::lin::trim_and_lowercase_then_replace_spaces;
103 
104     #[test]
test_trim_and_lowercase_then_replace_spaces()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]
test_file_user_dirs_exists()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 }
134