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 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 pub struct Icon;
102
103 impl Icon {
104 pub const EMPTY: &'static str = "⭕";
105 pub const ENTRY: &'static str = "🗃️ ";
107 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 pub const H2: &'static str = "📚";
114 pub const FILE2: &'static str = "📄";
115 pub const FILE2_HIDDEN: &'static str = "⚙️ ";
116 pub const FOLDER2: &'static str = "📁";
118 pub const FOLDER2_HIDDEN: &'static str = "🗃️";
119 pub const LANG_RUST: &'static str = "🦀";
120 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 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 pub const ENTRY_TERMINAL: &'static str = " └───";
155 pub const ITEM: &'static str = " •";
157 pub const ITEM_BETWEEN: &'static str = " ├──•";
159 pub const ITEM_FIRST: &'static str = " ┌──•";
161 pub const ITEM_LAST: &'static str = " └──•";
163 pub const ITEM_ONEFOLD: &'static str = " ──•";
165
166 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 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 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 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()?; 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 fn clean_file(file_path: &Path) -> std::io::Result<bool> {
251 let content = fs::read_to_string(file_path)?;
252
253 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 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}