Skip to main content

plot/lib/mapping/
middleware_translate_to_job_raw_from_cli.rs

1use crate::lib::{
2	core::{default_for_item, default_run_modes, default_string_strategy},
3	schema::{
4		RawCliJob,
5		RawTomlJob,
6		RawTomlJobAttributes,
7		RawTomlJobAttributesOptions,
8		RawTomlJobExplorer,
9		RawTomlJobExport,
10		RawTomlJobPileMode,
11		RawTomlJobSortNum,
12		RawTomlJobSortTex,
13		RawTomlJobStringStrategy,
14		RawTomlJobTuples,
15		RawTomlJobTuplesPile,
16		RawTomlJobTuplesSort,
17		SharedJobOptForAttrItem,
18		SharedJobOptForAttrSize,
19		SharedJobPart,
20		SharedJobRunMode,
21		SharedJobStringMode,
22	},
23};
24
25/// MIDDLEWARE: Nakłada flagi z CLI na pusty obiekt RawTomlJob
26pub fn translate(mut raw: RawTomlJob, cli: &RawCliJob) -> RawTomlJob {
27	// 1. RUN MODES (Wstrzykujemy flagi jako nadpisanie modów uruchomieniowych)
28	let mut modes = raw.run_mode.clone().unwrap_or_else(default_run_modes);
29	if cli.dry_run.unwrap_or(false) {
30		modes.push(SharedJobRunMode::DryRun);
31	}
32	if cli.export_nothing.unwrap_or(false) {
33		modes.retain(|m| *m != SharedJobRunMode::Save && *m != SharedJobRunMode::SaveWithInspection);
34	}
35	if cli.print_nothing.unwrap_or(false) {
36		modes.push(SharedJobRunMode::PrintNothing);
37	}
38	if cli.print_warnings.unwrap_or(false) {
39		modes.push(SharedJobRunMode::PrintOnlyWarning);
40	}
41	if cli.inspection_in_export.unwrap_or(false) {
42		modes.retain(|m| *m != SharedJobRunMode::Save);
43		modes.push(SharedJobRunMode::SaveWithInspection);
44	}
45	if cli.inspection_in_print.unwrap_or(false) {
46		modes.push(SharedJobRunMode::PrintWithInspection);
47	}
48	if cli.show_colors.unwrap_or(false) {
49		modes.push(SharedJobRunMode::PrintColor);
50	}
51	raw.run_mode = Some(modes);
52
53	// 2. EXPLORER (Wstrzykujemy ścieżki i wzorce)
54	let mut exp = raw.explorer.unwrap_or_else(|| RawTomlJobExplorer {
55		workspace_dir: None,
56		ignore_case: None,
57		patterns: None,
58		parts: None,
59	});
60	exp.workspace_dir = Some(cli.dir_to_scan.clone());
61	if !cli.patterns.is_empty() {
62		exp.patterns = Some(cli.patterns.clone());
63	}
64	if !cli.query_parts.is_empty() {
65		let mut parts = Vec::new();
66		for cp in &cli.query_parts {
67			match cp.to_lowercase().as_str() {
68				"md" | "matched-dirs" => parts.push(SharedJobPart::MD),
69				"mf" | "matched-files" => parts.push(SharedJobPart::MF),
70				"xd" | "mismatched-dirs" => parts.push(SharedJobPart::XD),
71				"xf" | "mismatched-files" => parts.push(SharedJobPart::XF),
72				_ => {}
73			}
74		}
75		if !parts.is_empty() {
76			exp.parts = Some(parts);
77		}
78	}
79	if let Some(ic) = cli.ignore_case {
80		exp.ignore_case = Some(ic);
81	}
82	raw.explorer = Some(exp);
83
84	// 3. EXPORT (Wstrzykujemy informacje wyjściowe)
85	let mut export = raw.export.unwrap_or_else(|| RawTomlJobExport {
86		out_dir: None,
87		title: None,
88		name: None,
89		name_is_first: None,
90		save_separately: None,
91	});
92	export.out_dir = Some(cli.out_dir.clone());
93	if let Some(t) = &cli.title {
94		export.title = Some(t.clone());
95	}
96	if let Some(n) = &cli.name {
97		export.name = Some(n.clone());
98	}
99	if let Some(nif) = cli.name_is_first {
100		export.name_is_first = Some(nif);
101	}
102	if let Some(ss) = cli.save_separately {
103		export.save_separately = Some(ss);
104	}
105	raw.export = Some(export);
106
107	// 4. ATTRIBUTES (Wstrzykujemy opcje formatowania tabeli)
108	let mut attr = raw.attributes.unwrap_or_else(|| RawTomlJobAttributes { select: None, option: None });
109	if let Some(sel) = &cli.attributes {
110		attr.select = Some(sel.clone());
111	}
112
113	let mut opt = attr.option.unwrap_or_else(|| RawTomlJobAttributesOptions {
114		for_item: None,
115		for_date: None,
116		for_time: None,
117		for_size: None,
118	});
119	let mut for_item = opt.for_item.unwrap_or_else(default_for_item);
120
121	if cli.tree_hide.unwrap_or(false) {
122		for_item.retain(|i| *i != SharedJobOptForAttrItem::ListTree);
123		if !for_item.contains(&SharedJobOptForAttrItem::ListFlat) {
124			for_item.push(SharedJobOptForAttrItem::ListFlat);
125		}
126	}
127	if cli.icon_hide.unwrap_or(false) {
128		for_item.retain(|i| *i != SharedJobOptForAttrItem::IconsLite && *i != SharedJobOptForAttrItem::IconsMore);
129		for_item.push(SharedJobOptForAttrItem::IconsHide);
130	} else if cli.icon_more.unwrap_or(false) {
131		for_item.retain(|i| *i != SharedJobOptForAttrItem::IconsLite);
132		for_item.push(SharedJobOptForAttrItem::IconsMore);
133	}
134	if cli.name_hide.unwrap_or(false) {
135		for_item.push(SharedJobOptForAttrItem::NameHide);
136	}
137	if cli.align_hide.unwrap_or(false) {
138		for_item.push(SharedJobOptForAttrItem::AlignHide);
139	}
140	if cli.num_before.unwrap_or(false) {
141		for_item.retain(|i| *i != SharedJobOptForAttrItem::NumListAft);
142		for_item.push(SharedJobOptForAttrItem::NumListBef);
143	}
144	opt.for_item = Some(for_item);
145
146	if let Some(fd) = &cli.fmt_date {
147		opt.for_date = Some(fd.clone());
148	}
149	if let Some(ft) = &cli.fmt_time {
150		opt.for_time = Some(ft.clone());
151	}
152	if cli.size_binary.unwrap_or(false) {
153		opt.for_size = Some(SharedJobOptForAttrSize::Binary);
154	}
155
156	attr.option = Some(opt);
157	raw.attributes = Some(attr);
158
159	// 5. TUPLES (Wstrzykujemy sortowanie i grupowanie)
160	if cli.pile.is_some() || cli.sort.is_some() {
161		let mut tuples = raw.tuples.unwrap_or_else(|| RawTomlJobTuples { pile: None, sort: None });
162
163		if let Some(pile_type) = &cli.pile {
164			let pile_mode = RawTomlJobPileMode {
165				dir_first: cli.dir_first.unwrap_or(false),
166				same_name_dirs_and_files_nearby: cli.name_nearby.unwrap_or(false),
167			};
168			match pile_type.as_str() {
169				"name" => tuples.pile = Some(RawTomlJobTuplesPile::Name(pile_mode)),
170				"exte" => tuples.pile = Some(RawTomlJobTuplesPile::Exte(pile_mode)),
171				_ => {}
172			}
173		}
174
175		if let Some(sort_type) = &cli.sort {
176			let rev = cli.reverse.unwrap_or(false);
177			let mir = cli.mirror.unwrap_or(false);
178			let strat = cli.strategy.as_deref().map(map_string_strategy).unwrap_or_else(default_string_strategy);
179			let strat_arr = RawTomlJobStringStrategy([strat[0], strat[1], strat[2]]);
180
181			match sort_type.as_str() {
182				"date" => tuples.sort = Some(RawTomlJobTuplesSort::Date(RawTomlJobSortNum { reverse: rev })),
183				"size" => tuples.sort = Some(RawTomlJobTuplesSort::Size(RawTomlJobSortNum { reverse: rev })),
184				"path" => {
185					tuples.sort = Some(RawTomlJobTuplesSort::Path(RawTomlJobSortTex {
186						reverse: rev,
187						mirror: mir,
188						string_strategy: strat_arr.clone(),
189					}))
190				}
191				"name" => {
192					tuples.sort = Some(RawTomlJobTuplesSort::Name(RawTomlJobSortTex {
193						reverse: rev,
194						mirror: mir,
195						string_strategy: strat_arr,
196					}))
197				}
198				_ => {}
199			}
200		}
201		raw.tuples = Some(tuples);
202	}
203
204	raw
205}
206
207fn map_string_strategy(s: &str) -> Vec<SharedJobStringMode> {
208	let mut vec: Vec<_> = s
209		.split(',')
210		.filter_map(|part| match part.trim() {
211			"Spec" => Some(SharedJobStringMode::Spec),
212			"Num" => Some(SharedJobStringMode::Num),
213			"AaZz" => Some(SharedJobStringMode::AaZz),
214			"aAzZ" => Some(SharedJobStringMode::aAzZ),
215			"AZaz" => Some(SharedJobStringMode::AZaz),
216			"azAZ" => Some(SharedJobStringMode::azAZ),
217			_ => None,
218		})
219		.collect();
220
221	// Gwarantujemy, że zwrócimy dokładnie 3 elementy, aby uniknąć paniki przy konwersji do tablicy [T; 3]
222	while vec.len() < 3 {
223		vec.push(SharedJobStringMode::Spec);
224	}
225	vec
226}