1use std::path::Path;
2
3use crate::common::UtfWidth;
4
5pub struct PathShortener {
8 size: usize,
9 path_str: String,
10}
11
12impl PathShortener {
13 const MAX_PATH_ELEM_SIZE: usize = 80;
14
15 pub fn path(path: &Path) -> Option<Self> {
16 Some(Self {
17 path_str: path.to_str()?.to_owned(),
18 size: Self::MAX_PATH_ELEM_SIZE,
19 })
20 }
21
22 pub fn with_size(mut self, size: usize) -> Self {
23 self.size = size;
24 self
25 }
26
27 pub fn shorten(self) -> String {
28 if self.path_str.utf_width() < self.size {
29 return self.path_str;
30 }
31 self.shorten_long_path()
32 }
33
34 fn shorten_long_path(self) -> String {
35 let splitted_path: Vec<_> = self.path_str.split('/').collect();
36 let size_per_elem = std::cmp::max(1, self.size / (splitted_path.len() + 1)) + 1;
37 Self::elems(splitted_path, size_per_elem).join("/")
38 }
39
40 fn elems(splitted_path: Vec<&str>, size_per_elem: usize) -> Vec<&str> {
41 splitted_path
42 .iter()
43 .filter_map(|p| Self::slice_long(p, size_per_elem))
44 .collect()
45 }
46
47 fn slice_long(p: &str, size_per_elem: usize) -> Option<&str> {
48 if p.len() <= size_per_elem {
49 Some(p)
50 } else {
51 p.get(0..size_per_elem)
52 }
53 }
54}