1use crate::fn_filestree::FileNode;
2use colored::*;
3
4#[derive(Debug, Clone)]
6pub struct TreeStyle {
7 pub dir_last_with_children: String, pub dir_last_no_children: String, pub dir_mid_with_children: String, pub dir_mid_no_children: String, pub file_last: String, pub file_mid: String, pub indent_last: String, pub indent_mid: String, }
21
22impl Default for TreeStyle {
23 fn default() -> Self {
24 Self {
25 dir_last_with_children: "└──┬".to_string(),
26 dir_last_no_children: "└───".to_string(),
27 dir_mid_with_children: "├──┬".to_string(),
28 dir_mid_no_children: "├───".to_string(),
29
30 file_last: "└──•".to_string(),
31 file_mid: "├──•".to_string(),
32
33 indent_last: " ".to_string(),
34 indent_mid: "│ ".to_string(),
35 }
36 }
37}
38
39fn plot(nodes: &[FileNode], indent: &str, s: &TreeStyle, use_color: bool) -> String {
41 let mut result = String::new();
42
43 for (i, node) in nodes.iter().enumerate() {
44 let is_last = i == nodes.len() - 1;
45 let has_children = !node.children.is_empty();
46
47 let branch = if node.is_dir {
49 match (is_last, has_children) {
50 (true, true) => &s.dir_last_with_children,
51 (false, true) => &s.dir_mid_with_children,
52 (true, false) => &s.dir_last_no_children,
53 (false, false) => &s.dir_mid_no_children,
54 }
55 } else if is_last {
56 &s.file_last
57 } else {
58 &s.file_mid
59 };
60
61 let line = if use_color {
63 if node.is_dir {
64 format!(
65 "{}{} {}{}/\n",
66 indent.green(),
67 branch.green(),
68 node.icon,
69 node.name.truecolor(200, 200, 50)
70 )
71 } else {
72 format!(
73 "{}{} {}{}\n",
74 indent.green(),
75 branch.green(),
76 node.icon,
77 node.name.white()
78 )
79 }
80 } else {
81 format!("{}{} {} {}\n", indent, branch, node.icon, node.name)
82 };
83
84 result.push_str(&line);
85
86 if has_children {
88 let new_indent = if is_last {
89 format!("{}{}", indent, s.indent_last)
90 } else {
91 format!("{}{}", indent, s.indent_mid)
92 };
93 result.push_str(&plot(&node.children, &new_indent, s, use_color));
94 }
95 }
96
97 result
98}
99
100pub fn plotfiles_txt(nodes: &[FileNode], indent: &str, style: Option<&TreeStyle>) -> String {
102 let default_style = TreeStyle::default();
103 let s = style.unwrap_or(&default_style);
104
105 plot(nodes, indent, s, false)
106}
107
108pub fn plotfiles_cli(nodes: &[FileNode], indent: &str, style: Option<&TreeStyle>) -> String {
110 let default_style = TreeStyle::default();
111 let s = style.unwrap_or(&default_style);
112
113 plot(nodes, indent, s, true)
114}