| 1 | extern crate dirs_sys; |
| 2 | |
| 3 | use std::env; |
| 4 | use std::path::PathBuf; |
| 5 | |
| 6 | use BaseDirs; |
| 7 | use UserDirs; |
| 8 | use ProjectDirs; |
| 9 | |
| 10 | pub 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 | |
| 40 | pub fn user_dirs() -> Option<UserDirs> { |
| 41 | if let Some(home_dir: PathBuf) = dirs_sys::home_dir() { |
| 42 | let data_dir: PathBuf = env::var_os(key:"XDG_DATA_HOME" ).and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(path:".local/share" )); |
| 43 | let font_dir: PathBuf = data_dir.join(path:"fonts" ); |
| 44 | let mut user_dirs_map: HashMap = dirs_sys::user_dirs(&home_dir); |
| 45 | |
| 46 | let user_dirs: UserDirs = 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 | |
| 64 | pub 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 | |
| 92 | pub fn project_dirs_from(_qualifier: &str, _organization: &str, application: &str) -> Option<ProjectDirs> { |
| 93 | ProjectDirs::from_path(project_path:PathBuf::from(&trim_and_lowercase_then_replace_spaces(name:application, replacement:"" ))) |
| 94 | } |
| 95 | |
| 96 | fn trim_and_lowercase_then_replace_spaces(name: &str, replacement: &str) -> String { |
| 97 | let mut buf: String = String::with_capacity(name.len()); |
| 98 | let mut parts: SplitWhitespace<'_> = name.split_whitespace(); |
| 99 | let mut current_part: Option<&str> = parts.next(); |
| 100 | let replace: bool = !replacement.is_empty(); |
| 101 | while current_part.is_some() { |
| 102 | let value: String = 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(string:replacement); |
| 107 | } |
| 108 | } |
| 109 | buf |
| 110 | } |
| 111 | |
| 112 | #[cfg (test)] |
| 113 | mod 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 | } |
| 146 | |