dot_over/
utils.rs

1use dirs::home_dir;
2
3// Change the alias to `Box<error::Error>`.
4pub type Expect<T> = std::result::Result<T, Box<dyn std::error::Error>>;
5
6// Shorten a path as string
7pub fn short_path(path: &str) -> String {
8    let binding = home_dir().unwrap();
9    let home = binding.to_str().unwrap();
10    if path.starts_with(home) {
11        path.replace(home, "~")
12    } else {
13        path.to_string()
14    }
15}
16
17// Find the longuest common suffix between two strings
18// Returns an empty string if no common suffix is found
19pub fn longuest_common_suffix<'a>(a: &'a str, b: &'a str) -> String {
20    let reversed = a.chars().rev()
21        .zip(b.chars().rev())
22        .take_while(|(a, b)| a == b)
23        .map(|(a, _)| a)
24        .collect::<String>();
25    reversed.chars().rev().collect::<String>()
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use rstest::*;
32
33    fn home() -> String {
34        let h = home_dir().unwrap();
35        h.to_str().unwrap().to_string()
36    }
37
38    #[rstest]
39    #[case::home_dir(&home(), "~")]
40    #[case::home_dir_with_path(&format!("{}/.config", home()), "~/.config")]
41    #[case::outside_home("/tmp", "/tmp")]
42    fn test_short_path(#[case] path: &str, #[case] expected: &str) {
43        assert_eq!(short_path(path), expected.to_string());
44    }
45
46    #[rstest]
47    #[case::empty("", "", "")]
48    #[case::no_common_suffix("hello", "world", "")]
49    #[case::common_suffix("~/.dotfiles/path/to/overlay", "somewhere/path/to/overlay", "/path/to/overlay")]
50    #[case::common_unicode_suffix("~/.dötfiles/päth/tö/ovërlay", "sömewhere/päth/tö/ovërlay", "/päth/tö/ovërlay")]
51    fn test_longuest_common_suffix(#[case] a: &str, #[case] b: &str, #[case] expected: &str) {
52        assert_eq!(longuest_common_suffix(a, b), expected);
53    }
54}