1use crate::lib::logic::{
2 AnchoredPathsDatum,
3 DocMarkdown,
4 PartitioningResult,
5 PatternsToApply,
6 ScanSpec,
7 ScannedToApply,
8 TabSpec,
9 TableOutput,
10 TagTime,
11 tag_time,
12};
13
14#[derive(Clone, Copy)]
15pub enum MX {
16 M,
17 X,
18 Matched,
19 Mismatched,
20}
21
22#[derive(Clone, Copy)]
23pub struct RenderFlags {
24 pub hide_stats: bool,
25 pub hide_promo: bool,
26 pub mode: MX,
27}
28
29pub struct DocEngine {
31 pub path: AnchoredPathsDatum,
32 pub tagtime: TagTime,
33 pub result: PartitioningResult,
34 pub last_render: Option<RenderFlags>,
35}
36
37impl DocEngine {
38 pub fn new(scan: ScanSpec) -> Self {
39 let anchored_paths_datum = AnchoredPathsDatum::new(&scan.work_path).unwrap_or_else(|x| {
40 eprintln!("❌ {}", x);
41 std::process::exit(1);
42 });
43
44 let scanned_to_apply = ScannedToApply::scan(&anchored_paths_datum);
45 let ref_patterns: Vec<&str> = scan.patterns.iter().map(|s| s.as_str()).collect();
46 let patterns_to_apply = PatternsToApply::new(ref_patterns, scan.ignore_case);
47
48 let partitioning_result = PartitioningResult::new(scanned_to_apply, patterns_to_apply);
53
54 Self { path: anchored_paths_datum, tagtime: tag_time(), result: partitioning_result, last_render: None }
55 }
56
57 pub fn spec(mut self, spec: TabSpec) -> Self {
58 self.result.spec = spec;
59 self
60 }
61
62 fn section_header(&self, border: String) -> String {
67 let pats = format!("{:?}", self.result.patterns.patterns.0);
68 let m_len = self.result.m.paths.len();
69 let x_len = self.result.x.paths.len();
70
71 let stat = &self.result.scanner.stat;
72 let dir_path = format!("\"{}\"", stat.relation.select_dir.buf.display());
73
74 let mut header = String::new();
75 header.push_str(&format!("{}\n", border));
76 header.push_str(&format!(
77 "📊 | 📝 {} | 📂 {} | ⭕ {} | ✔️ {} | ✖️ {} |\n",
78 stat.count_files, stat.count_folder, stat.count_empty, m_len, x_len
79 ));
80 header.push_str(&format!("🔎 {}\n", pats));
81 header.push_str(&format!("🗃️ {}\n", dir_path));
82 header.push_str(&border);
83 header
84 }
85
86 fn section_footer(&self, border: String) -> String {
87 let mut footer = String::new();
88 footer.push_str("📚 | [Crates.io](https://crates.io/crates/cargo-plot) |\n");
89 footer.push_str("📚 | [GitHub](https://github.com/j-Cis/cargo-plot/releases) |\n");
90 footer.push_str(&border);
92 footer
93 }
94
95 fn build_structure_of_the_content(&self, flags: &RenderFlags) -> String {
97 let tab_out = match flags.mode {
98 MX::M | MX::Matched => self.result.build_matched(),
99 MX::X | MX::Mismatched => self.result.build_mismatched(),
100 };
101
102 let mut parts = Vec::with_capacity(3);
103
104 if !flags.hide_stats {
105 parts.push(self.section_header("░".repeat(80)));
106 parts.push(format!("{}", tab_out));
107 parts.push("░".repeat(80));
108 } else {
109 parts.push(format!("{}", tab_out));
110 }
111
112 if !flags.hide_promo {
113 parts.push(self.section_footer("░".repeat(80)));
114 }
115
116 parts.join("\n") + "\n"
118 }
119
120 #[inline]
125 fn finalize_view_structure_of_the_content(&mut self, flags: RenderFlags) {
126 self.last_render = Some(flags);
127 print!("{}", self.build_structure_of_the_content(&flags));
128 }
129
130 pub fn view(mut self, tab_mode: MX, hide_stats: bool, hide_promo: bool) -> Self {
132 self.finalize_view_structure_of_the_content(RenderFlags { hide_stats, hide_promo, mode: tab_mode });
133 self
134 }
135
136 pub fn view_trimmed(
138 mut self,
139 tab_mode: MX,
140 hide_stats: bool,
141 hide_promo: bool,
142 size: usize,
143 page: Option<usize>, ) -> Self {
145 self.result.spec = self.result.spec.trim(size, page);
146 self.finalize_view_structure_of_the_content(RenderFlags { hide_stats, hide_promo, mode: tab_mode });
147 self
148 }
149
150 fn current_flags(&self) -> RenderFlags {
156 self.last_render.unwrap_or(RenderFlags { hide_stats: false, hide_promo: false, mode: MX::M })
157 }
158
159 fn generate_table(&self, mode: MX) -> TableOutput {
161 match mode {
162 MX::M | MX::Matched => self.result.build_matched(),
163 MX::X | MX::Mismatched => self.result.build_mismatched(),
164 }
165 }
166
167 fn init_markdown(&self, content: String, table: TableOutput) -> DocMarkdown {
170 DocMarkdown::new(
171 content,
172 table,
173 self.path.execut_dir.clone(),
174 self.path.select_dir.clone(),
175 self.tagtime.clone(),
176 )
177 }
178
179 pub fn save_structure_of_the_content(self, rel_path: &str, title: Option<&str>) -> Self {
184 let flags = self.current_flags();
185 let table_output = self.generate_table(flags.mode);
186 let raw_out_str = self.build_structure_of_the_content(&flags);
187 let md = self.init_markdown(raw_out_str, table_output);
188
189 if let Err(e) = md.structure_of_the_content_save_as(rel_path, title) {
190 eprintln!("❌ Błąd zapisu SOTC (Struktura Zawartości): {}", e);
191 }
192 self
193 }
194
195 pub fn save_content_of_the_structure(self, rel_path: &str, title: Option<&str>) -> Self {
196 let flags = self.current_flags();
197 let table_output = self.generate_table(flags.mode);
198 let raw_out_str = self.build_structure_of_the_content(&flags);
199 let md = self.init_markdown(raw_out_str, table_output);
200
201 if let Err(e) = md.content_of_the_structure_save_as(rel_path, title) {
202 eprintln!("❌ Błąd zapisu COTS (Zawartość Struktury): {}", e);
203 }
204 self
205 }
206}