Skip to main content

plot/
api.rs

1pub mod lib {
2	pub mod logic {
3		pub mod path {
4			pub mod path_canonical_ctx;
5			pub use path_canonical_ctx::{AnchoredPathsDatum, PathNode};
6			pub mod path_scan;
7			pub use path_scan::{ScanPathStat, ScannedToApply};
8			pub mod path_context;
9			pub use path_context::PathContext;
10			pub mod paths_patterns;
11			pub use paths_patterns::{PattEnvIndex, PattExp, PattRaw, PatternsToApply};
12			pub mod paths_table;
13			pub use paths_table::{FileKind, TableData, TableOutput, TableRow};
14			pub mod paths_result;
15			pub use paths_result::{MatchLabel, Matched, Mismatched, Partition, PartitioningResult};
16		}
17		pub use path::{
18			AnchoredPathsDatum,
19			FileKind,
20			MatchLabel,
21			Matched,
22			Mismatched,
23			Partition,
24			PartitioningResult,
25			PathContext,
26			PathNode,
27			PattEnvIndex,
28			PattExp,
29			PattRaw,
30			PatternsToApply,
31			ScanPathStat,
32			ScannedToApply,
33			TableData,
34			TableOutput,
35			TableRow,
36		};
37
38		pub mod specification;
39		pub use specification::{
40			JobMode,
41			JobSpec,
42			ScanSpec,
43			TabColumn,
44			TabPathStructure,
45			TabSortBy,
46			TabSortOrder,
47			TabSpec,
48		};
49		pub mod tag_time;
50		pub use tag_time::{TagTime, tag_time};
51		pub mod mapper_lang_type;
52		pub use mapper_lang_type::LangMapper;
53		pub mod file_markdown_docs;
54		pub use file_markdown_docs::DocMarkdown;
55		pub mod engine;
56		pub use engine::{DocEngine, MX, RenderFlags};
57		pub mod engine_multiple;
58		pub use engine_multiple::DocEngineMultiple;
59		pub mod config_model;
60		pub use config_model::{
61			ConfigExport,
62			ConfigJob,
63			ConfigLayout,
64			ConfigManifest,
65			ConfigPattern,
66			ConfigSpec,
67			ConfigTrimming,
68		};
69		pub mod file_toml_config;
70		pub use file_toml_config::IoConfig;
71	}
72	// pub mod command {
73	// 	pub mod args;
74	// 	pub mod help;
75	// }
76	pub mod display {
77
78		pub mod config;
79		pub mod path_canonical_ctx;
80		pub mod path_scan;
81		pub mod paths_patterns;
82		pub mod paths_result;
83		pub mod table_data;
84
85		use colored::*;
86
87		pub struct Color;
88		impl Color {
89			pub fn tree(s: &str) -> ColoredString { s.truecolor(41, 211, 152) }
90			pub fn num(s: &str) -> ColoredString { s.bright_magenta() }
91			pub fn size(s: &str) -> ColoredString { s.cyan() }
92			pub fn date(s: &str) -> ColoredString { s.truecolor(140, 120, 100) }
93			pub fn time(s: &str) -> ColoredString { s.truecolor(100, 70, 100) }
94			pub fn folder(s: &str) -> ColoredString { s.truecolor(200, 200, 50).bold() }
95			pub fn file(s: &str) -> ColoredString { s.bright_white() }
96			pub fn binary(s: &str) -> ColoredString { s.bright_red() }
97			pub fn border(s: &str) -> ColoredString { s.truecolor(20, 20, 20).dimmed() }
98		}
99
100		/// [POL]: Scentralizowane symbole formatowania dla projektu.
101		pub struct Icon;
102
103		impl Icon {
104			pub const EMPTY: &'static str = "⭕";
105			// --- Symbole zasobów ---
106			pub const ENTRY: &'static str = "🗃️ ";
107			// --- Symbole dla Entry (Twój styl z obrazka) ---
108			pub const EXPAND: &'static str = "🔀";
109			pub const BOOL_FALSE: &'static str = "✖️ ";
110			pub const FILE: &'static str = "📝";
111			pub const FOLDER: &'static str = "📂";
112			// --- Symbole sekcji ---
113			pub const H2: &'static str = "📚";
114			pub const FILE2: &'static str = "📄";
115			pub const FILE2_HIDDEN: &'static str = "⚙️ ";
116			// ⚡ --- Symbole zasobów (Rozszerzone - z wersji OLD) ---
117			pub const FOLDER2: &'static str = "📁";
118			pub const FOLDER2_HIDDEN: &'static str = "🗃️";
119			pub const LANG_RUST: &'static str = "🦀";
120			// --- Symbole logiczne (Bool) ---
121			pub const BOOL_TRUE: &'static str = "✔️ ";
122
123			#[inline]
124			pub fn bool(val: bool) -> &'static str { if val { Self::BOOL_TRUE } else { Self::BOOL_FALSE } }
125		}
126
127		/// [POL]: Rozszerzenie dla bool, aby pisać `val.as_symbol()`.
128		pub trait BoolExt {
129			fn as_symbol(&self) -> &'static str;
130		}
131
132		impl BoolExt for bool {
133			fn as_symbol(&self) -> &'static str { Icon::bool(*self) }
134		}
135		pub struct TreeLast;
136		impl TreeLast {
137			pub const DIR_NO_CHILDREN: &'static str = "└───";
138			pub const DIR_WITH_CHILDREN: &'static str = "└──┬";
139			pub const FILE: &'static str = "└──•";
140			pub const INDENT: &'static str = "   ";
141		}
142		pub struct TreeMid;
143		impl TreeMid {
144			pub const DIR_NO_CHILDREN: &'static str = "├───";
145			pub const DIR_WITH_CHILDREN: &'static str = "├──┬";
146			pub const FILE: &'static str = "├──•";
147			pub const INDENT: &'static str = "│  ";
148		}
149
150		pub struct DrawTree;
151		impl DrawTree {
152			pub const ENTRY_BRANCH: &'static str = "  ├───";
153			// view::fs::entry
154			pub const ENTRY_TERMINAL: &'static str = "  └───";
155			// view::fs::entry
156			pub const ITEM: &'static str = "     •";
157			// view::path::pattern
158			pub const ITEM_BETWEEN: &'static str = "  ├──•";
159			// self
160			pub const ITEM_FIRST: &'static str = "  ┌──•";
161			// view::fs::filter
162			pub const ITEM_LAST: &'static str = "  └──•";
163			// self
164			pub const ITEM_ONEFOLD: &'static str = "   ──•";
165
166			// self
167
168			/// Automatycznie dobiera symbol gałęzi na podstawie indeksu i
169			/// rozmiaru listy.
170			pub fn list(index: usize, total: usize) -> &'static str {
171				if total == 1 {
172					Self::ITEM_ONEFOLD
173				} else if index == 0 {
174					Self::ITEM_FIRST
175				} else if index == total - 1 {
176					Self::ITEM_LAST
177				} else {
178					Self::ITEM_BETWEEN
179				}
180			}
181
182			/// Zwraca krotkę: (symbol_gałęzi_dla_siebie, wcięcie_dla_dzieci)
183			pub fn tree(is_dir: bool, is_last: bool, has_children: bool) -> (&'static str, &'static str) {
184				let branch = if is_dir {
185					match (is_last, has_children) {
186						(true, true) => TreeLast::DIR_WITH_CHILDREN,
187						(false, true) => TreeMid::DIR_WITH_CHILDREN,
188						(true, false) => TreeLast::DIR_NO_CHILDREN,
189						(false, false) => TreeMid::DIR_NO_CHILDREN,
190					}
191				} else if is_last {
192					TreeLast::FILE
193				} else {
194					TreeMid::FILE
195				};
196
197				let next_indent = if is_last { TreeLast::INDENT } else { TreeMid::INDENT };
198
199				(branch, next_indent)
200			}
201		}
202	}
203	pub mod util {
204		use std::{fs, path::Path, process::Command};
205
206		use walkdir::WalkDir;
207
208		pub struct WhitespaceCleaner;
209
210		impl WhitespaceCleaner {
211			/// Skanuje i czyści białe znaki (istniejąca metoda)
212			pub fn clean_project<P: AsRef<Path>>(dir: P) -> std::io::Result<()> {
213				let mut cleaned_files = 0;
214
215				for entry in WalkDir::new(dir).into_iter().filter_map(|e| e.ok()) {
216					let path = entry.path();
217
218					// Interesują nas tylko pliki Rustowe
219					if path.is_file() && path.extension().is_some_and(|ext| ext == "rs") && Self::clean_file(path)? {
220						cleaned_files += 1;
221					}
222				}
223
224				if cleaned_files > 0 {
225					println!("🧹 Pomyślnie wyczyszczono białe znaki w {} plikach.", cleaned_files);
226				} else {
227					println!("✨ Twój kod jest czysty. Żadne pliki nie wymagały czyszczenia.");
228				}
229
230				Ok(())
231			}
232
233			pub fn run_cargo_fmt() -> std::io::Result<()> {
234				println!("formatting...");
235
236				let status = Command::new("cargo")
237					.args(["+nightly", "fmt", "--", "--config-path", "./.rustfmt.toml"])
238					.status()?; // Czekamy na zakończenie procesu
239
240				if status.success() {
241					println!("✅ formatowanie zakończone pomyślnie.");
242				} else {
243					eprintln!("❌ formatowanie zwróciło błąd (prawdopodobnie błędy składni w kodzie).");
244				}
245
246				Ok(())
247			}
248
249			/// Pomocnicza funkcja clean_file (zostaje bez zmian)
250			fn clean_file(file_path: &Path) -> std::io::Result<bool> {
251				let content = fs::read_to_string(file_path)?;
252
253				// Szacujemy pojemność, by uniknąć reallokacji (z reguły plik po czyszczeniu
254				// będzie nieco mniejszy)
255				let mut cleaned = String::with_capacity(content.len());
256				let mut is_modified = false;
257
258				for line in content.lines() {
259					let trimmed = line.trim_end();
260					if trimmed.len() != line.len() {
261						is_modified = true;
262					}
263					cleaned.push_str(trimmed);
264					cleaned.push('\n');
265				}
266
267				// Zapisujemy tylko, jeśli faktycznie dokonano zmian (chroni to czasy
268				// modyfikacji mtime)
269				if is_modified {
270					fs::write(file_path, cleaned)?;
271					println!("   -> Wyczyszczono: {}", file_path.display());
272					Ok(true)
273				} else {
274					Ok(false)
275				}
276			}
277		}
278	}
279}