Skip to main content

doing_config/
paths.rs

1use std::path::{Path, PathBuf};
2
3/// Expands a leading `~` in a path to the user's home directory.
4///
5/// Returns the path unchanged if it does not start with `~`.
6pub fn expand_tilde(path: &Path) -> PathBuf {
7  let s = path.to_string_lossy();
8  if let Some(rest) = s.strip_prefix("~/") {
9    let home = dir_spec::home().expect("failed to resolve user's home directory");
10    home.join(rest)
11  } else if s == "~" {
12    dir_spec::home().expect("failed to resolve user's home directory")
13  } else {
14    path.to_path_buf()
15  }
16}
17
18#[cfg(test)]
19mod test {
20  use super::*;
21
22  mod expand_tilde {
23    use super::*;
24
25    #[test]
26    fn it_expands_bare_tilde() {
27      let result = expand_tilde(Path::new("~"));
28
29      assert!(result.is_absolute());
30      assert!(!result.to_string_lossy().contains('~'));
31    }
32
33    #[test]
34    fn it_expands_tilde_prefix() {
35      let result = expand_tilde(Path::new("~/Documents/file.txt"));
36
37      assert!(result.is_absolute());
38      assert!(result.ends_with("Documents/file.txt"));
39    }
40
41    #[test]
42    fn it_leaves_absolute_paths_unchanged() {
43      let path = Path::new("/usr/local/bin");
44      let result = expand_tilde(path);
45
46      assert_eq!(result, path);
47    }
48
49    #[test]
50    fn it_leaves_relative_paths_unchanged() {
51      let path = Path::new("relative/path");
52      let result = expand_tilde(path);
53
54      assert_eq!(result, path);
55    }
56  }
57}