1use std::borrow::Borrow;
2use std::cmp::min;
3use std::collections::HashMap;
4use std::path::{Path, PathBuf};
5use std::sync::Arc;
6
7use anyhow::{bail, Context, Result};
8
9use crate::common::{filename_from_path, has_last_modification_happened_less_than};
10use crate::impl_index_to_index;
11use crate::modes::{
12 files_collection, ContentWindow, FileInfo, FilterKind, Flagged, Icon, SortKind, ToPath, Users,
13};
14
15#[derive(Debug, Clone)]
19pub struct Node {
20 path: Arc<Path>,
21 prev: Arc<Path>,
22 next: Arc<Path>,
23 index: usize,
24 children: Option<Vec<Arc<Path>>>,
25 folded: bool,
26 selected: bool,
27 reachable: bool,
28}
29
30impl Node {
31 fn new(path: &Path, children: Option<Vec<Arc<Path>>>, prev: &Path, index: usize) -> Self {
34 Self {
35 path: Arc::from(path),
36 prev: Arc::from(prev),
37 next: Arc::from(Path::new("")),
38 index,
39 children,
40 folded: false,
41 selected: false,
42 reachable: true,
43 }
44 }
45
46 fn fold(&mut self) {
47 self.folded = true
48 }
49
50 fn unfold(&mut self) {
51 self.folded = false
52 }
53
54 fn select(&mut self) {
55 self.selected = true
56 }
57
58 fn unselect(&mut self) {
59 self.selected = false
60 }
61
62 pub fn selected(&self) -> bool {
64 self.selected
65 }
66
67 pub fn index(&self) -> usize {
69 self.index
70 }
71
72 pub fn path(&self) -> &Path {
74 &self.path
75 }
76
77 #[inline]
78 fn have_children(self: &Node) -> bool {
79 !self.folded && self.children.is_some()
80 }
81}
82
83pub trait Go {
85 fn go(&mut self, to: To);
86}
87
88pub enum To<'a> {
90 Next,
91 Prev,
92 Root,
93 Last,
94 Parent,
95 NextSibling,
96 PreviousSibling,
97 Path(&'a Path),
98}
99
100impl Go for Tree {
101 fn go(&mut self, to: To) {
103 if self.is_empty() {
104 return;
105 }
106 match to {
107 To::Next => self.select_next(),
108 To::Prev => self.select_prev(),
109 To::Root => self.select_root(),
110 To::Last => self.select_last(),
111 To::Parent => self.select_parent(),
112 To::NextSibling => self.select_next_sibling(),
113 To::PreviousSibling => self.select_previous_sibling(),
114 To::Path(path) => self.select_path(path),
115 }
116 }
117}
118
119trait Depth {
121 fn depth(&self) -> usize;
122}
123
124impl Depth for Arc<Path> {
125 #[inline]
128 fn depth(&self) -> usize {
129 self.components().collect::<Vec<_>>().len()
130 }
131}
132
133pub struct TreeBuilder<'a> {
137 root_path: Arc<Path>,
138 users: &'a Users,
139 filter_kind: &'a FilterKind,
140 max_depth: usize,
141 show_hidden: bool,
142 sort_kind: SortKind,
143}
144
145impl<'a> TreeBuilder<'a> {
146 const DEFAULT_DEPTH: usize = 5;
147 const DEFAULT_FILTER: FilterKind = FilterKind::All;
148 const DEFAULT_HIDDEN: bool = false;
149 const DEFAULT_SORT: SortKind = SortKind::tree_default();
150
151 pub fn new(root_path: Arc<Path>, users: &'a Users) -> Self {
152 let filter_kind = &Self::DEFAULT_FILTER;
153 let max_depth = Self::DEFAULT_DEPTH;
154 let show_hidden = Self::DEFAULT_HIDDEN;
155 let sort_kind = Self::DEFAULT_SORT;
156 Self {
157 root_path,
158 users,
159 filter_kind,
160 max_depth,
161 show_hidden,
162 sort_kind,
163 }
164 }
165
166 pub fn with_filter_kind(mut self, filter_kind: &'a FilterKind) -> Self {
167 self.filter_kind = filter_kind;
168 self
169 }
170
171 pub fn with_max_depth(mut self, max_depth: usize) -> Self {
172 self.max_depth = max_depth;
173 self
174 }
175
176 pub fn with_hidden(mut self, show_hidden: bool) -> Self {
177 self.show_hidden = show_hidden;
178 self
179 }
180
181 pub fn with_sort_kind(mut self, sort_kind: SortKind) -> Self {
182 self.sort_kind = sort_kind;
183 self
184 }
185
186 pub fn build(self) -> Tree {
187 let nodes = NodesBuilder::new(
188 &self.root_path,
189 self.max_depth,
190 self.sort_kind,
191 self.users,
192 self.show_hidden,
193 self.filter_kind,
194 )
195 .build();
196 let displayable_lines = TreeLinesBuilder::new(&nodes, &self.root_path).build();
197
198 Tree {
199 selected: self.root_path.clone(),
200 root_path: self.root_path,
201 nodes,
202 displayable_lines,
203 }
204 }
205}
206
207pub struct NodesBuilder<'a> {
209 root_path: &'a Arc<Path>,
210 max_depth: usize,
211 sort_kind: SortKind,
212 users: &'a Users,
213 show_hidden: bool,
214 filter_kind: &'a FilterKind,
215 root_depth: usize,
216}
217
218impl<'a> NodesBuilder<'a> {
219 fn new(
220 root_path: &'a Arc<Path>,
221 max_depth: usize,
222 sort_kind: SortKind,
223 users: &'a Users,
224 show_hidden: bool,
225 filter_kind: &'a FilterKind,
226 ) -> Self {
227 let root_depth = root_path.depth();
228 Self {
229 root_path,
230 max_depth,
231 sort_kind,
232 users,
233 show_hidden,
234 filter_kind,
235 root_depth,
236 }
237 }
238
239 #[inline]
240 fn build(self) -> HashMap<Arc<Path>, Node> {
241 let mut stack = vec![self.root_path.to_owned()];
242 let mut nodes = HashMap::new();
243 let mut last_path = self.root_path.to_owned();
244 let mut index = 0;
245
246 while let Some(current_path) = stack.pop() {
247 let current_depth = current_path.depth();
248 if self.current_is_too_deep(current_depth) {
249 continue;
250 }
251 let children = if self.node_may_have_children(current_depth, ¤t_path) {
252 self.create_children(&mut stack, ¤t_path)
253 } else {
254 None
255 };
256 let current_node = Node::new(¤t_path, children, &last_path, index);
257 self.set_next_for_last(&mut nodes, ¤t_path, &last_path);
258 last_path = current_path.clone();
259 nodes.insert(current_path.clone(), current_node);
260 index += 1;
261 }
262 self.set_prev_for_root(&mut nodes, last_path);
263 nodes
264 }
265
266 fn current_is_too_deep(&self, current_depth: usize) -> bool {
267 current_depth >= self.max_depth + self.root_depth
268 }
269
270 fn node_may_have_children(&self, current_depth: usize, current_path: &Path) -> bool {
271 self.is_not_too_deep_for_children(current_depth)
272 && current_path.is_dir()
273 && !current_path.is_symlink()
274 }
275
276 fn is_not_too_deep_for_children(&self, current_depth: usize) -> bool {
277 self.root_depth + self.max_depth > 1 + current_depth
278 }
279
280 #[inline]
281 fn set_prev_for_root(&self, nodes: &mut HashMap<Arc<Path>, Node>, last_path: Arc<Path>) {
282 let Some(root_node) = nodes.get_mut(self.root_path) else {
283 unreachable!("root_path should be in nodes");
284 };
285 root_node.prev = last_path;
286 root_node.select();
287 }
288
289 #[inline]
290 fn set_next_for_last(
291 &self,
292 nodes: &mut HashMap<Arc<Path>, Node>,
293 current_path: &Path,
294 last_path: &Path,
295 ) {
296 if let Some(last_node) = nodes.get_mut(last_path) {
297 last_node.next = Arc::from(current_path);
298 };
299 }
300
301 #[inline]
302 fn create_children(
303 &self,
304 stack: &mut Vec<Arc<Path>>,
305 current_path: &Path,
306 ) -> Option<Vec<Arc<Path>>> {
307 if let Some(mut files) = files_collection(
308 current_path,
309 self.users,
310 self.show_hidden,
311 self.filter_kind,
312 true,
313 ) {
314 self.sort_kind.sort(&mut files);
315 let children = Self::make_children_and_stack_them(stack, &files);
316 if !children.is_empty() {
317 return Some(children);
318 }
319 }
320 None
321 }
322
323 #[inline]
324 fn make_children_and_stack_them(
325 stack: &mut Vec<Arc<Path>>,
326 files: &[FileInfo],
327 ) -> Vec<Arc<Path>> {
328 files
329 .iter()
330 .map(|fileinfo| fileinfo.path.clone())
331 .inspect(|path| stack.push(path.clone()))
332 .collect()
333 }
334}
335
336#[inline]
337fn first_prefix(prefix: &str) -> String {
338 let mut prefix = prefix.to_string();
339 prefix.push(' ');
340 prefix = prefix.replace("└──", " ");
341 prefix = prefix.replace("├──", "│ ");
342 prefix.push_str("└──");
343 prefix
344}
345
346#[inline]
347fn other_prefix(prefix: &str) -> String {
348 let mut prefix = prefix.to_string();
349 prefix.push(' ');
350 prefix = prefix.replace("└──", " ");
351 prefix = prefix.replace("├──", "│ ");
352 prefix.push_str("├──");
353 prefix
354}
355
356#[inline]
357fn filename_format(current_path: &Path, folded: bool, with_icon: bool) -> String {
358 let icon = if with_icon { current_path.icon() } else { "" };
359 let filename = filename_from_path(current_path).unwrap_or_default();
360 if current_path.is_dir() && !current_path.is_symlink() {
361 let fold_symbol = if folded { "▸" } else { "▾" };
362 format!("{fold_symbol} {icon}{filename}")
363 } else {
364 format!("{icon}{filename}")
365 }
366}
367
368struct TreeLinesBuilder<'a> {
369 nodes: &'a HashMap<Arc<Path>, Node>,
370 root_path: &'a Arc<Path>,
371}
372
373impl<'a> TreeLinesBuilder<'a> {
374 fn new(nodes: &'a HashMap<Arc<Path>, Node>, root_path: &'a Arc<Path>) -> Self {
375 Self { nodes, root_path }
376 }
377
378 fn build(self) -> TreeLines {
393 let mut stack = vec![("".to_owned(), self.root_path.clone())];
394 let mut lines = vec![];
395 let mut index = 0;
396
397 while let Some((prefix, path)) = stack.pop() {
398 let Some(node) = self.nodes.get(&path) else {
399 continue;
400 };
401
402 if node.selected {
403 index = lines.len();
404 }
405
406 lines.push(TLine::new(&prefix, node, &path));
407
408 if node.have_children() {
409 Self::stack_children(&mut stack, prefix, node);
410 }
411 }
412 TreeLines::new(lines, index)
413 }
414
415 #[inline]
416 fn stack_children(stack: &mut Vec<(String, Arc<Path>)>, prefix: String, current_node: &Node) {
417 let first_prefix = first_prefix(&prefix);
418 let other_prefix = other_prefix(&prefix);
419
420 let Some(children) = ¤t_node.children else {
421 return;
422 };
423 let mut children = children.iter();
424 let Some(first_leaf) = children.next() else {
425 return;
426 };
427 stack.push((first_prefix, first_leaf.clone()));
428
429 for leaf in children {
430 stack.push((other_prefix.clone(), leaf.clone()));
431 }
432 }
433}
434
435#[derive(Clone, Debug, Default)]
438pub struct TreeLines {
439 pub content: Vec<TLine>,
440 index: usize,
441}
442
443impl TreeLines {
444 fn new(content: Vec<TLine>, index: usize) -> Self {
445 Self { content, index }
446 }
447
448 pub fn content(&self) -> &Vec<TLine> {
449 &self.content
450 }
451
452 pub fn index(&self) -> usize {
454 self.index
455 }
456
457 pub fn lines(&self) -> &Vec<TLine> {
459 &self.content
460 }
461
462 fn find_by_path(&self, path: &Path) -> Option<usize> {
463 self.content.iter().position(|tlm| tlm.path() == path)
464 }
465
466 fn unselect(&mut self) {
467 if !self.content.is_empty() {
468 self.content[self.index].unselect()
469 }
470 }
471
472 fn select(&mut self, index: usize) {
473 if !self.content.is_empty() {
474 self.index = index;
475 self.content[self.index].select()
476 }
477 }
478
479 fn selected_is_last(&self) -> bool {
480 self.index + 1 == self.content.len()
481 }
482}
483
484impl_index_to_index!(TLine, TreeLines);
485
486#[derive(Clone, Debug)]
489pub struct TLine {
490 folded: bool,
491 prefix: Arc<str>,
492 pub path: Arc<Path>,
493 pub is_selected: bool,
494}
495
496impl TLine {
497 fn new(prefix: &str, node: &Node, path: &Path) -> Self {
499 let is_selected = node.selected();
501 let prefix = Arc::from(prefix);
502 let path = Arc::from(path);
503 let folded = node.folded;
504
505 Self {
506 folded,
507 prefix,
508 path,
509 is_selected,
510 }
511 }
512
513 pub fn filename(&self, with_icon: bool) -> String {
515 filename_format(&self.path, self.folded, with_icon)
516 }
517
518 pub fn prefix(&self) -> &str {
521 self.prefix.borrow()
522 }
523
524 pub fn path(&self) -> &Path {
526 self.path.borrow()
527 }
528
529 pub fn unselect(&mut self) {
532 self.is_selected = false;
533 }
534
535 pub fn select(&mut self) {
538 self.is_selected = true;
539 }
540}
541
542impl ToPath for TLine {
543 fn to_path(&self) -> &Path {
544 &self.path
545 }
546}
547
548#[derive(Debug, Clone)]
552pub struct Tree {
553 root_path: Arc<Path>,
554 selected: Arc<Path>,
555 nodes: HashMap<Arc<Path>, Node>,
556 displayable_lines: TreeLines,
557}
558
559impl Default for Tree {
560 fn default() -> Self {
561 Self {
562 root_path: Arc::from(Path::new("")),
563 selected: Arc::from(Path::new("")),
564 nodes: HashMap::new(),
565 displayable_lines: TreeLines::default(),
566 }
567 }
568}
569
570impl Tree {
571 pub fn root_path(&self) -> &Path {
573 self.root_path.borrow()
574 }
575
576 pub fn selected_path(&self) -> &Path {
578 self.selected.borrow()
579 }
580
581 pub fn selected_path_or_parent(&self) -> Result<PathBuf> {
588 if self.selected.exists() {
589 return Ok(self.selected.to_path_buf());
590 }
591 let absolute_root_depth = self.root_path.components().count();
592 let mut current_depth = self.selected.components().count();
593 let current = self.selected_path();
594 while current_depth >= absolute_root_depth {
595 let Some(current) = current.parent() else {
596 bail!("No parent, are we deleting root / ?");
597 };
598 if current.exists() {
599 return Ok(current.to_owned());
600 }
601 current_depth -= 1;
602 }
603 Ok(self.root_path().to_owned())
604 }
605
606 pub fn selected_node(&self) -> Option<&Node> {
608 self.nodes.get(&self.selected)
609 }
610
611 pub fn directory_of_selected(&self) -> Option<&Path> {
614 if self.selected.is_dir() && !self.selected.is_symlink() {
615 Some(self.selected.borrow())
616 } else {
617 self.selected.parent()
618 }
619 }
620
621 pub fn selected_path_relative_to_root(&self) -> Result<&Path> {
623 Ok(self.selected.strip_prefix(&self.root_path)?)
624 }
625
626 pub fn len(&self) -> usize {
628 self.nodes.len()
629 }
630
631 pub fn display_len(&self) -> usize {
632 self.displayable().lines().len()
633 }
634
635 pub fn is_empty(&self) -> bool {
637 self.nodes.is_empty()
638 }
639
640 pub fn is_on_root(&self) -> bool {
642 self.selected == self.root_path
643 }
644
645 fn is_on_last(&self) -> bool {
647 self.find_next_path() == self.root_path
648 }
649
650 fn node_has_parent_folded(&self, node: &Node) -> bool {
655 let node_path = node.path();
656 let mut current_path = PathBuf::from("/");
657 for part in node_path.components() {
658 current_path = current_path.join(part.as_os_str());
659 if current_path == node_path {
660 continue;
661 }
662 if let Some(current_node) = self.nodes.get(current_path.as_path()) {
663 if current_node.folded {
664 return true;
665 }
666 }
667 }
668 false
669 }
670
671 fn select_next(&mut self) {
673 let next_path = self.find_next_path();
674 self.select_path(&next_path);
675 drop(next_path);
676 }
677
678 fn find_next_path(&self) -> Arc<Path> {
679 let mut current_path: Arc<Path> = self.selected.clone();
680 loop {
681 if let Some(current_node) = self.nodes.get(¤t_path) {
682 let next_path = ¤t_node.next;
683 let Some(next_node) = self.nodes.get(next_path) else {
684 return self.root_path.clone();
685 };
686 if next_node.reachable && !self.node_has_parent_folded(next_node) {
687 return next_path.to_owned();
688 }
689 current_path = next_path.clone();
690 }
691 }
692 }
693
694 fn select_prev(&mut self) {
696 let previous_path = self.find_prev_path();
697 self.select_path(&previous_path);
698 }
699
700 fn find_prev_path(&self) -> Arc<Path> {
701 let mut current_path = self.selected.to_owned();
702 loop {
703 if let Some(current_node) = self.nodes.get(¤t_path) {
704 let prev_path = ¤t_node.prev;
705 let Some(prev_node) = self.nodes.get(prev_path) else {
706 unreachable!("");
707 };
708 if prev_node.reachable && !self.node_has_parent_folded(prev_node) {
709 return prev_path.to_owned();
710 }
711 current_path = prev_path.to_owned();
712 }
713 }
714 }
715
716 pub fn page_up(&mut self) {
717 for _ in 1..10 {
718 if self.is_on_root() {
719 break;
720 }
721 self.go(To::Prev);
722 }
723 }
724
725 pub fn page_down(&mut self) {
726 for _ in 1..10 {
727 if self.is_on_last() {
728 break;
729 }
730 self.go(To::Next);
731 }
732 }
733
734 fn select_root(&mut self) {
735 let root_path = self.root_path.to_owned();
736 self.select_path(&root_path);
737 }
738
739 fn select_last(&mut self) {
740 self.select_root();
741 self.select_prev();
742 }
743
744 fn select_parent(&mut self) {
745 if let Some(parent_path) = self.selected.parent() {
746 self.select_path(parent_path.to_owned().as_path());
747 }
748 }
749
750 fn find_siblings(&self) -> &Option<Vec<Arc<Path>>> {
751 let Some(parent_path) = self.selected.parent() else {
752 return &None;
753 };
754 let Some(parent_node) = self.nodes.get(parent_path) else {
755 return &None;
756 };
757 &parent_node.children
758 }
759
760 fn select_next_sibling(&mut self) {
761 let Some(children) = self.find_siblings() else {
762 self.select_next();
763 return;
764 };
765 let Some(curr_index) = children.iter().position(|p| p == &self.selected) else {
766 return;
767 };
768 let next_index = if curr_index > 0 {
769 curr_index - 1
770 } else {
771 children.len().checked_sub(1).unwrap_or_default()
772 };
773 let sibling_path = children[next_index].clone();
774 self.select_path(&sibling_path);
775 }
776
777 fn select_previous_sibling(&mut self) {
778 let Some(children) = self.find_siblings() else {
779 self.select_prev();
780 return;
781 };
782 let Some(curr_index) = children.iter().position(|p| p == &self.selected) else {
783 return;
784 };
785 let next_index = (curr_index + 1) % children.len();
786 let sibling_path = children[next_index].clone();
787 self.select_path(&sibling_path);
788 }
789
790 fn select_path(&mut self, dest_path: &Path) {
791 if Arc::from(dest_path) == self.selected {
792 return;
793 }
794 let Some(dest_node) = self.nodes.get_mut(dest_path) else {
795 return;
796 };
797 dest_node.select();
798 let Some(selected_node) = self.nodes.get_mut(&self.selected) else {
799 unreachable!("current_node should be in nodes");
800 };
801 selected_node.unselect();
802 self.selected = Arc::from(dest_path);
803 self.displayable_lines.unselect();
804 if let Some(index) = self.displayable_lines.find_by_path(dest_path) {
805 self.displayable_lines.select(index);
806 }
807 }
808
809 pub fn toggle_fold(&mut self) {
811 if let Some(node) = self.nodes.get_mut(&self.selected) {
812 if node.folded {
813 node.unfold();
814 self.make_children_reachable()
815 } else {
816 node.fold();
817 self.make_children_unreachable()
818 }
819 }
820 self.remake_displayable();
821 }
822
823 fn children_of_selected(&self) -> Option<&Vec<Arc<Path>>> {
824 self.nodes.get(&self.selected)?.children.as_ref()
825 }
826
827 fn make_children_reachable(&mut self) {
828 self.set_children_reachable(true)
829 }
830
831 fn make_children_unreachable(&mut self) {
832 self.set_children_reachable(false)
833 }
834
835 fn set_children_reachable(&mut self, reachable: bool) {
836 let Some(children) = self.children_of_selected() else {
837 return;
838 };
839 for child_path in children.to_owned().iter() {
840 let Some(child_node) = self.nodes.get_mut(child_path) else {
841 continue;
842 };
843 child_node.reachable = reachable;
844 }
845 }
846
847 pub fn fold_all(&mut self) {
849 for (_, node) in self.nodes.iter_mut() {
850 node.fold()
851 }
852 self.select_root();
853 self.remake_displayable();
854 }
855
856 pub fn unfold_all(&mut self) {
858 for (_, node) in self.nodes.iter_mut() {
859 node.unfold()
860 }
861 self.remake_displayable();
862 }
863
864 fn remake_displayable(&mut self) {
865 self.displayable_lines = TreeLinesBuilder::new(&self.nodes, &self.root_path).build();
866 }
867
868 pub fn displayable(&self) -> &TreeLines {
869 &self.displayable_lines
870 }
871
872 pub fn paths(&self) -> Vec<&Path> {
874 self.nodes.keys().map(|p| p.borrow()).collect()
875 }
876
877 pub fn flag_all(&self, flagged: &mut Flagged) {
878 self.nodes
879 .keys()
880 .for_each(|p| flagged.push(p.to_path_buf()))
881 }
882
883 #[inline]
886 pub fn has_modified_dirs(&self) -> bool {
887 self.nodes
888 .keys()
889 .filter(|path| path.is_dir() && !path.is_symlink())
890 .any(|path| has_last_modification_happened_less_than(path, 10).unwrap_or(false))
891 }
892
893 pub fn selected_is_last(&self) -> bool {
894 self.displayable_lines.selected_is_last()
895 }
896
897 pub fn path_from_index(&self, index: usize) -> Result<PathBuf> {
898 let displayable = self.displayable();
899 Ok(displayable
900 .lines()
901 .get(index)
902 .context("tree: no selected file")?
903 .path()
904 .to_owned())
905 }
906
907 pub fn lines_enum_skip_take(
908 &self,
909 window: &ContentWindow,
910 ) -> Take<Skip<Enumerate<Iter<'_, TLine>>>> {
911 let lines = self.displayable().lines();
912 let length = lines.len();
913 lines
914 .iter()
915 .enumerate()
916 .skip(window.top)
917 .take(min(length, window.bottom + 1))
918 }
919}
920
921impl IndexToIndex<TLine> for Tree {
922 fn index_to_index(&self) -> Chain<Skip<Iter<'_, TLine>>, Take<Iter<'_, TLine>>> {
926 self.displayable().index_to_index()
927 }
928}