Skip to main content

fm/modes/display/
tree.rs

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/// An element of a tree.
16/// It's a file/directory, some optional children.
17/// A Node knows if it's folded or selected.
18#[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    /// Creates a new Node from a path and its children.
32    /// By default it's not selected nor folded.
33    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    /// Is the node selected ?
63    pub fn selected(&self) -> bool {
64        self.selected
65    }
66
67    /// The index of the node in displayed tree
68    pub fn index(&self) -> usize {
69        self.index
70    }
71
72    /// Path of this node
73    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
83/// Describe a movement in a navigable structure
84pub trait Go {
85    fn go(&mut self, to: To);
86}
87
88/// Describes a direction for the next selected tree element.
89pub 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    /// Select another element from a tree.
102    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
119/// Trait allowing to measure the depth of something.
120trait Depth {
121    fn depth(&self) -> usize;
122}
123
124impl Depth for Arc<Path> {
125    /// Measure the number of components of a [`std::path::Path`].
126    /// For absolute paths, it's the number of folders plus one for / and one for the file itself.
127    #[inline]
128    fn depth(&self) -> usize {
129        self.components().collect::<Vec<_>>().len()
130    }
131}
132
133/// Used to build trees.
134///
135/// It's configured with the builder pattern.
136pub 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
207/// A builder of [`Tree`] nodes.
208pub 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, &current_path) {
252                self.create_children(&mut stack, &current_path)
253            } else {
254                None
255            };
256            let current_node = Node::new(&current_path, children, &last_path, index);
257            self.set_next_for_last(&mut nodes, &current_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    /// Create a displayable content from the tree.
379    /// Returns 2 informations :
380    /// - the index of the selected node into this content.
381    ///   It's usefull to know where the user clicked
382    /// - a vector of `TreeLineMaker` which holds every information
383    ///   needed to display the tree.
384    ///   We try to keep as much reference as possible and generate
385    ///   the information lazyly, avoiding as much useless calcuations
386    ///   as possible.
387    ///   The metadata information (permissions, modified time etc.) must be
388    ///   calculated immediatly, therefore for every node, since it requires
389    ///   an access to the user list.
390    ///   The prefix (straight lines displaying targets) must also be calcuated immediatly.
391    ///   Name format is calculated on the fly.
392    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) = &current_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/// A vector of displayable lines used to draw a tree content.
436/// We use the index to follow the user movements in the tree.
437#[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    /// Index of the currently selected file.
453    pub fn index(&self) -> usize {
454        self.index
455    }
456
457    /// A reference to the displayable lines.
458    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/// Holds a few references used to display a tree line
487/// Only the metadata info is hold.
488#[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    /// Uses references to fileinfo, prefix, node & path to create an instance.
498    fn new(prefix: &str, node: &Node, path: &Path) -> Self {
499        // required for some edge cases when opening the tree while "." is the selected file
500        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    /// Formated filename
514    pub fn filename(&self, with_icon: bool) -> String {
515        filename_format(&self.path, self.folded, with_icon)
516    }
517
518    /// Vertical bar displayed before the filename to show
519    /// the adress of the file
520    pub fn prefix(&self) -> &str {
521        self.prefix.borrow()
522    }
523
524    /// Path of the file
525    pub fn path(&self) -> &Path {
526        self.path.borrow()
527    }
528
529    /// Change the current effect to Empty, displaying
530    /// the file as not selected
531    pub fn unselect(&mut self) {
532        self.is_selected = false;
533    }
534
535    /// Change the current effect to `REVERSED`, displaying
536    /// the file as selected.
537    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/// A FileSystem tree of nodes.
549/// Internally it's a wrapper around an `std::collections::HashMap<PathBuf, Node>`
550/// It also holds informations about the required height of the tree.
551#[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    /// Root path of the tree.
572    pub fn root_path(&self) -> &Path {
573        self.root_path.borrow()
574    }
575
576    /// Selected path
577    pub fn selected_path(&self) -> &Path {
578        self.selected.borrow()
579    }
580
581    /// Returns an _existing_ path which is either the selected path or its
582    /// first existing parent.
583    ///
584    /// # Errors
585    /// Will fail if the selected node doesn't exists or has no parent.
586    /// It should never be the case since we can't rename or delete the root `/`.
587    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    /// Selected node
607    pub fn selected_node(&self) -> Option<&Node> {
608        self.nodes.get(&self.selected)
609    }
610
611    /// The folder containing the selected node.
612    /// Itself if selected is a directory.
613    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    /// Relative path of selected from rootpath.
622    pub fn selected_path_relative_to_root(&self) -> Result<&Path> {
623        Ok(self.selected.strip_prefix(&self.root_path)?)
624    }
625
626    /// Number of nodes
627    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    /// True if there's no node.
636    pub fn is_empty(&self) -> bool {
637        self.nodes.is_empty()
638    }
639
640    /// True if selected is root.
641    pub fn is_on_root(&self) -> bool {
642        self.selected == self.root_path
643    }
644
645    /// True if selected is the last file
646    fn is_on_last(&self) -> bool {
647        self.find_next_path() == self.root_path
648    }
649
650    /// True if the node has a parent which is in `self.nodes` and is folded.
651    /// This hacky and inefficient solution is necessary to know if we can select
652    /// this node in `select_prev` `select_next`.
653    /// It will construct all parent path from `/` to `node.path` except for the last one.
654    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    /// Select next sibling or the next sibling of the parent
672    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(&current_path) {
682                let next_path = &current_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    /// Select previous sibling or the parent
695    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(&current_path) {
704                let prev_path = &current_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    /// Fold selected node
810    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    /// Fold all node from root to end
848    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    /// Unfold all node from root to end
857    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    /// Vector of `Path` of nodes.
873    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    /// True if any directory (not symlink to a directory)
884    /// has been modified less than 10 seconds ago.
885    #[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    /// Iterate over line from current index to bottom then from top to current index.
923    ///
924    /// Useful when going to next match in search results
925    fn index_to_index(&self) -> Chain<Skip<Iter<'_, TLine>>, Take<Iter<'_, TLine>>> {
926        self.displayable().index_to_index()
927    }
928}