directories/
lin.rs

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