Skip to main content

lib/
fn_plotfiles.rs

1// Zaktualizowany Plik-021: src/lib/fn_plotfiles.rs
2use crate::fn_filestree::FileNode;
3use colored::*;
4
5/// Zestaw znaków używanych do rysowania gałęzi drzewa.
6#[derive(Debug, Clone)]
7pub struct TreeStyle {
8    // Foldery (d)
9    pub dir_last_with_children: String, // └──┬
10    pub dir_last_no_children: String,   // └───
11    pub dir_mid_with_children: String,  // ├──┬
12    pub dir_mid_no_children: String,    // ├───
13
14    // Pliki (f)
15    pub file_last: String, // └──
16    pub file_mid: String,  // ├──
17
18    // Wcięcia dla kolejnych poziomów (i)
19    pub indent_last: String, // "   " (3 spacje)
20    pub indent_mid: String,  // "│  " (kreska + 2 spacje)
21}
22
23impl Default for TreeStyle {
24    fn default() -> Self {
25        Self {
26            dir_last_with_children: "└──┬".to_string(),
27            dir_last_no_children: "└───".to_string(),
28            dir_mid_with_children: "├──┬".to_string(),
29            dir_mid_no_children: "├───".to_string(),
30
31            file_last: "└──•".to_string(),
32            file_mid: "├──•".to_string(),
33
34            indent_last: "   ".to_string(),
35            indent_mid: "│  ".to_string(),
36        }
37    }
38}
39
40/// Prywatna funkcja pomocnicza, która odwala całą powtarzalną robotę.
41fn plot(nodes: &[FileNode], indent: &str, s: &TreeStyle, use_color: bool) -> String {
42    let mut result = String::new();
43
44    for (i, node) in nodes.iter().enumerate() {
45        let is_last = i == nodes.len() - 1;
46        let has_children = !node.children.is_empty();
47
48        // 1. Wybór odpowiedniego znaku gałęzi
49        let branch = if node.is_dir {
50            match (is_last, has_children) {
51                (true, true) => &s.dir_last_with_children,
52                (false, true) => &s.dir_mid_with_children,
53                (true, false) => &s.dir_last_no_children,
54                (false, false) => &s.dir_mid_no_children,
55            }
56        } else if is_last {
57            &s.file_last
58        } else {
59            &s.file_mid
60        };
61
62        // KROK NOWY: Przygotowanie kolorowanej (lub nie) ramki z wagą
63        let weight_prefix = if node.weight_str.is_empty() {
64            String::new()
65        } else if use_color {
66            // W CLI waga będzie szara, by nie odciągać uwagi od struktury plików
67            node.weight_str.truecolor(120, 120, 120).to_string()
68        } else {
69            node.weight_str.clone()
70        };
71
72        // 2. Formatowanie konkretnej linii (z kolorami lub bez)
73        let line = if use_color {
74            if node.is_dir {
75                format!(
76                    "{}{}{} {}{}/\n",
77                    weight_prefix, // ZMIANA TUTAJ
78                    indent.green(),
79                    branch.green(),
80                    node.icon,
81                    node.name.truecolor(200, 200, 50)
82                )
83            } else {
84                format!(
85                    "{}{}{} {}{}\n",
86                    weight_prefix, // ZMIANA TUTAJ
87                    indent.green(),
88                    branch.green(),
89                    node.icon,
90                    node.name.white()
91                )
92            }
93        } else {
94            // ZMIANA TUTAJ: Doklejenie prefixu dla zwykłego tekstu
95            format!(
96                "{}{}{} {} {}\n",
97                weight_prefix, indent, branch, node.icon, node.name
98            )
99        };
100
101        result.push_str(&line);
102
103        // 3. Rekurencja dla dzieci z wyliczonym nowym wcięciem
104        if has_children {
105            let new_indent = if is_last {
106                format!("{}{}", indent, s.indent_last)
107            } else {
108                format!("{}{}", indent, s.indent_mid)
109            };
110            result.push_str(&plot(&node.children, &new_indent, s, use_color));
111        }
112    }
113
114    result
115}
116
117/// GENEROWANIE PLAIN TEXT / MARKDOWN
118pub fn plotfiles_txt(nodes: &[FileNode], indent: &str, style: Option<&TreeStyle>) -> String {
119    let default_style = TreeStyle::default();
120    let s = style.unwrap_or(&default_style);
121
122    plot(nodes, indent, s, false)
123}
124
125/// GENEROWANIE KOLOROWANEGO ASCII DO CLI
126pub fn plotfiles_cli(nodes: &[FileNode], indent: &str, style: Option<&TreeStyle>) -> String {
127    let default_style = TreeStyle::default();
128    let s = style.unwrap_or(&default_style);
129
130    plot(nodes, indent, s, true)
131}