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