1use super::enums::DirType;
2use dirs::home_dir;
3use serde::{Deserialize, Serialize};
4use std::iter::FromIterator;
5use std::iter::IntoIterator;
6use std::path::PathBuf;
7
8#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, PartialOrd)]
9pub struct Dir {
10 pub path: PathBuf,
11 pub cd_count: u32,
12 pub dirtype: DirType,
13}
14
15impl Default for Dir {
16 fn default() -> Self {
17 Self {
18 path: home_dir().unwrap(),
19 cd_count: 0,
20 dirtype: DirType::NotSure,
21 }
22 }
23}
24
25impl Dir {
26 pub fn invalid() -> Self {
27 Self {
28 path: PathBuf::from(""),
29 cd_count: 0,
30 dirtype: DirType::Invalid,
31 }
32 }
33
34 pub fn path(mut self, path: PathBuf) -> Self {
35 self.path = path;
36 self
37 }
38
39 pub fn dirtype(mut self, dir_type: DirType) -> Self {
40 self.dirtype = dir_type;
41 self
42 }
43
44 pub fn new(path: PathBuf, cd_count: u32, dirtype: DirType) -> Dir {
45 Dir {
46 path,
47 cd_count,
48 dirtype,
49 }
50 }
51
52 pub fn new_visited(dir: PathBuf) -> Self {
53 Self {
54 path: dir,
55 cd_count: 1,
56 dirtype: DirType::VisitedDir,
57 }
58 }
59
60 pub fn add_cd_count(&mut self) {
61 self.cd_count += 1;
62 }
63
64 pub fn as_dirtype(&mut self, dirtype: DirType) {
65 self.dirtype = dirtype
66 }
67}
68
69#[derive(PartialEq, PartialOrd, Debug, Serialize, Deserialize, Clone, Default)]
70pub struct DirVec {
71 pub map: Vec<Dir>,
72}
73
74impl FromIterator<Dir> for DirVec {
75 fn from_iter<I: IntoIterator<Item = Dir>>(iter: I) -> Self {
76 let mut dirvec = DirVec::new();
77
78 for i in iter {
79 dirvec.map.push(i);
80 }
81 dirvec
82 }
83}
84
85impl DirVec {
86 pub fn new() -> DirVec {
87 DirVec { map: Vec::new() }
88 }
89 pub fn push(&mut self, elm: Dir) {
90 self.map.push(elm)
91 }
92 pub fn append(&mut self, mut v: DirVec) {
93 self.map.append(&mut v.map)
94 }
95
96 pub fn all_path_to_str(&self) -> String {
97 let s: String = self
98 .map
99 .iter()
100 .map(|elm| {
101 format!(
102 "{}\n",
103 elm.path
104 .to_str()
105 .unwrap_or("DirVec::all_path_to_string error")
106 )
107 })
108 .collect();
109 s
110 }
111
112 pub fn sort(&mut self) {
113 let _ = &self.map.sort_by(|a, b| {
114 a.dirtype
115 .order()
116 .cmp(&b.dirtype.order())
117 .then(a.cd_count.cmp(&b.cd_count).reverse())
118 });
119 }
120}
121
122#[cfg(test)]
123mod tests_for_dir {
124 use super::*;
125
126 #[test]
127 fn add_cd_count() {
128 let path = PathBuf::from("/a/dir");
129 let mut dir = Dir::new(path, 0, DirType::VisitedDir);
130 assert_eq!(dir.cd_count, 0);
131 dir.add_cd_count();
132 assert_eq!(dir.cd_count, 1);
133 }
134
135 #[test]
136 fn as_dirtype() {
137 let path = PathBuf::from("/a/dir");
138 let mut dir = Dir::new(path, 0, DirType::VisitedDir);
139 dir.as_dirtype(DirType::ParentDir);
140 assert_eq!(dir.dirtype, DirType::ParentDir);
141 }
142
143 #[test]
144 fn push() {
145 let mut dir_vec = DirVec::new();
146 let path = PathBuf::from("/a/dir");
147 let dir = Dir::new(path, 0, DirType::VisitedDir);
148 dir_vec.push(dir);
149
150 let path = PathBuf::from("/a/dir");
151 let dir = Dir::new(path, 0, DirType::VisitedDir);
152 assert_eq!(dir_vec.map[0], dir);
153 }
154}
155
156#[cfg(test)]
157mod tests_for_dirvec {
158 use super::*;
159
160 #[test]
161 fn all_path_to_string() {
162 let mut dirvec = DirVec::new();
163 dirvec.push(Dir::new(PathBuf::from("/a/dir/1"), 0, DirType::VisitedDir));
164 dirvec.push(Dir::new(PathBuf::from("/a/dir/2"), 0, DirType::VisitedDir));
165 assert_eq!(dirvec.all_path_to_str(), "/a/dir/1\n/a/dir/2\n");
166 }
167
168 #[test]
169 fn sort_fun_sorts_dirtypes() {
170 let mut dirvec = DirVec::new();
171 dirvec.push(Dir::new(PathBuf::from("/a/dir/1"), 0, DirType::NotSure));
172 dirvec.push(Dir::new(PathBuf::from("/a/dir/2"), 0, DirType::ParentDir));
173 dirvec.push(Dir::new(PathBuf::from("/a/dir/3"), 0, DirType::CurrentDir));
174 dirvec.push(Dir::new(PathBuf::from("/a/dir/4"), 0, DirType::ChildDir));
175 dirvec.push(Dir::new(PathBuf::from("/a/dir/5"), 0, DirType::VisitedDir));
176
177 let mut sorted_result = DirVec::new();
178 sorted_result.push(Dir::new(PathBuf::from("/a/dir/3"), 0, DirType::CurrentDir));
179 sorted_result.push(Dir::new(PathBuf::from("/a/dir/5"), 0, DirType::VisitedDir));
180 sorted_result.push(Dir::new(PathBuf::from("/a/dir/2"), 0, DirType::ParentDir));
181 sorted_result.push(Dir::new(PathBuf::from("/a/dir/4"), 0, DirType::ChildDir));
182 sorted_result.push(Dir::new(PathBuf::from("/a/dir/1"), 0, DirType::NotSure));
183
184 dirvec.sort();
185
186 assert_eq!(dirvec, sorted_result);
187 }
188
189 #[test]
190 fn sort_fun_sorts_dirtypes_by_cdcount() {
191 let mut dirvec = DirVec::new();
192 dirvec.push(Dir::new(PathBuf::from("/a/dir/5"), 0, DirType::VisitedDir));
193 dirvec.push(Dir::new(PathBuf::from("/a/dir/5"), 2, DirType::VisitedDir));
194 dirvec.push(Dir::new(PathBuf::from("/a/dir/5"), 3, DirType::VisitedDir));
195
196 let mut sorted_result = DirVec::new();
197 sorted_result.push(Dir::new(PathBuf::from("/a/dir/5"), 3, DirType::VisitedDir));
198 sorted_result.push(Dir::new(PathBuf::from("/a/dir/5"), 2, DirType::VisitedDir));
199 sorted_result.push(Dir::new(PathBuf::from("/a/dir/5"), 0, DirType::VisitedDir));
200
201 dirvec.sort();
202
203 assert_eq!(dirvec, sorted_result);
204 }
205}