Skip to main content

plot/lib/mapping/
prepare_job_raw_toml_to_ready.rs

1use std::path::PathBuf;
2
3use crate::lib::{
4	core::{
5		DEFAULT_DIR_FIRST,
6		DEFAULT_FOR_DATE,
7		DEFAULT_FOR_SIZE,
8		DEFAULT_FOR_TIME,
9		DEFAULT_IGNORE_CASE,
10		DEFAULT_MIRROR,
11		DEFAULT_NAME,
12		DEFAULT_NAME_IS_FIRST,
13		DEFAULT_REVERSE,
14		DEFAULT_SAME_NAME_DIRS_AND_FILES_NEARBY,
15		DEFAULT_SAVE_SEPARATELY,
16		DEFAULT_TITLE,
17		default_attributes_select,
18		default_explorer_parts,
19		default_explorer_patterns,
20		default_for_item,
21		default_out_dir,
22		default_run_modes,
23		default_string_strategy,
24		default_workspace_dir,
25	},
26	schema::{
27		RawTomlJob,
28		RawTomlJobSortTex,
29		RawTomlJobTuplesPile,
30		RawTomlJobTuplesSort,
31		ReadyJob,
32		ReadyJobAttributes,
33		ReadyJobExplorer,
34		ReadyJobExport,
35		ReadyJobPileMode,
36		ReadyJobSortNum,
37		ReadyJobSortTex,
38		ReadyJobTuples,
39		ReadyJobTuplesPile,
40		ReadyJobTuplesSort,
41		SharedJobOptForAttrItem,
42		SharedJobRunMode,
43		SharedJobStringMode,
44	},
45};
46
47/// Przygotowuje zadanie: pobiera surowy obiekt TOML, aplikuje domyślne ustawienia
48/// dla brakujących pól i rozwiązuje ewentualne konflikty logiczne.
49pub fn prepare(raw: RawTomlJob) -> ReadyJob {
50	let id = raw.id;
51	let description = raw.description.unwrap_or_default();
52
53	// ░░░░░░░░░░ 1. RUN MODES ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
54	let raw_modes = raw.run_mode.unwrap_or_else(default_run_modes);
55	let run_modes = resolve_run_modes(raw_modes);
56
57	// ░░░░░░░░░░ 2. EXPLORER ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
58	let explorer = match raw.explorer {
59		Some(ex) => ReadyJobExplorer::new(
60			ex.workspace_dir.map(PathBuf::from).unwrap_or_else(default_workspace_dir),
61			ex.ignore_case.unwrap_or(DEFAULT_IGNORE_CASE),
62			ex.patterns.unwrap_or_else(default_explorer_patterns),
63			ex.parts.unwrap_or_else(default_explorer_parts),
64		),
65		None => ReadyJobExplorer::new(
66			default_workspace_dir(),
67			DEFAULT_IGNORE_CASE,
68			default_explorer_patterns(),
69			default_explorer_parts(),
70		),
71	};
72
73	// ░░░░░░░░░░ 3. EXPORT ░░░░░░░░░░
74	let export = match raw.export {
75		Some(ex) => ReadyJobExport::new(
76			ex.out_dir.map(PathBuf::from).unwrap_or_else(default_out_dir),
77			ex.title.unwrap_or_else(|| DEFAULT_TITLE.to_string()),
78			ex.name.unwrap_or_else(|| DEFAULT_NAME.to_string()),
79			ex.name_is_first.unwrap_or(DEFAULT_NAME_IS_FIRST),
80			ex.save_separately.unwrap_or(DEFAULT_SAVE_SEPARATELY),
81		),
82		None => ReadyJobExport::new(
83			default_out_dir(),
84			DEFAULT_TITLE.to_string(),
85			DEFAULT_NAME.to_string(),
86			DEFAULT_NAME_IS_FIRST,
87			DEFAULT_SAVE_SEPARATELY,
88		),
89	};
90
91	// ░░░░░░░░░░ 4. ATTRIBUTES ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
92	let attributes = match raw.attributes {
93		Some(attr) => {
94			let select = attr.select.unwrap_or_else(default_attributes_select);
95			let (for_item, for_date, for_time, for_size) = match attr.option {
96				Some(opt) => (
97					resolve_attr_items(opt.for_item.unwrap_or_else(default_for_item)),
98					opt.for_date.unwrap_or_else(|| DEFAULT_FOR_DATE.to_string()),
99					opt.for_time.unwrap_or_else(|| DEFAULT_FOR_TIME.to_string()),
100					opt.for_size.unwrap_or(DEFAULT_FOR_SIZE),
101				),
102				None => {
103					(default_for_item(), DEFAULT_FOR_DATE.to_string(), DEFAULT_FOR_TIME.to_string(), DEFAULT_FOR_SIZE)
104				}
105			};
106			ReadyJobAttributes::new(select, for_item, for_date, for_time, for_size)
107		}
108		None => ReadyJobAttributes::new(
109			default_attributes_select(),
110			default_for_item(),
111			DEFAULT_FOR_DATE.to_string(),
112			DEFAULT_FOR_TIME.to_string(),
113			DEFAULT_FOR_SIZE,
114		),
115	};
116
117	// ░░░░░░░░░░ 5. TUPLES ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
118	let tuples = match raw.tuples {
119		Some(t) => {
120			let pile = match t.pile {
121				Some(RawTomlJobTuplesPile::Name(p)) => {
122					ReadyJobTuplesPile::Name(ReadyJobPileMode::new(p.dir_first, p.same_name_dirs_and_files_nearby))
123				}
124				Some(RawTomlJobTuplesPile::Exte(p)) => {
125					ReadyJobTuplesPile::Exte(ReadyJobPileMode::new(p.dir_first, p.same_name_dirs_and_files_nearby))
126				}
127				None => ReadyJobTuplesPile::Name(ReadyJobPileMode::new(
128					DEFAULT_DIR_FIRST,
129					DEFAULT_SAME_NAME_DIRS_AND_FILES_NEARBY,
130				)),
131			};
132			let sort = match t.sort {
133				Some(RawTomlJobTuplesSort::Path(s)) => ReadyJobTuplesSort::Path(resolve_sort_tex(s)),
134				Some(RawTomlJobTuplesSort::Name(s)) => ReadyJobTuplesSort::Name(resolve_sort_tex(s)),
135				Some(RawTomlJobTuplesSort::Date(s)) => ReadyJobTuplesSort::Date(ReadyJobSortNum::new(s.reverse)),
136				Some(RawTomlJobTuplesSort::Size(s)) => ReadyJobTuplesSort::Size(ReadyJobSortNum::new(s.reverse)),
137				None => ReadyJobTuplesSort::Name(ReadyJobSortTex::new(
138					DEFAULT_REVERSE,
139					DEFAULT_MIRROR,
140					default_string_strategy(),
141				)),
142			};
143			ReadyJobTuples::new(pile, sort)
144		}
145		None => ReadyJobTuples::new(
146			ReadyJobTuplesPile::Name(ReadyJobPileMode::new(DEFAULT_DIR_FIRST, DEFAULT_SAME_NAME_DIRS_AND_FILES_NEARBY)),
147			ReadyJobTuplesSort::Name(ReadyJobSortTex::new(DEFAULT_REVERSE, DEFAULT_MIRROR, default_string_strategy())),
148		),
149	};
150
151	// Finał: Wrzucamy wszystko do bezpiecznego konstruktora
152	ReadyJob::new(id, description, run_modes, explorer, export, attributes, tuples)
153}
154
155// ░░░░░░░░░░░░░░░░░░░░ REGUŁY BIZNESOWE (Korekta konfliktów) ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
156
157fn resolve_run_modes(modes: Vec<SharedJobRunMode>) -> Vec<SharedJobRunMode> {
158	let mut resolved = Vec::new();
159	for mode in &modes {
160		let keep = match mode {
161			SharedJobRunMode::Save | SharedJobRunMode::SaveWithInspection => !modes.contains(&SharedJobRunMode::DryRun),
162			SharedJobRunMode::PrintOnlyWarning | SharedJobRunMode::PrintColor => {
163				!modes.contains(&SharedJobRunMode::PrintNothing)
164			}
165			SharedJobRunMode::PrintWithInspection => {
166				!modes.contains(&SharedJobRunMode::PrintNothing) && !modes.contains(&SharedJobRunMode::PrintOnlyWarning)
167			}
168			_ => true,
169		};
170		if keep && !resolved.contains(mode) {
171			resolved.push(*mode);
172		}
173	}
174	resolved
175}
176
177fn resolve_attr_items(items: Vec<SharedJobOptForAttrItem>) -> Vec<SharedJobOptForAttrItem> {
178	let mut resolved = Vec::new();
179	for item in &items {
180		let keep = match item {
181			SharedJobOptForAttrItem::ListFlat => !items.contains(&SharedJobOptForAttrItem::ListTree),
182			SharedJobOptForAttrItem::IconsMore => !items.contains(&SharedJobOptForAttrItem::IconsLite),
183			SharedJobOptForAttrItem::NumListAft => !items.contains(&SharedJobOptForAttrItem::NumListBef),
184			SharedJobOptForAttrItem::IconsHide => {
185				!items.contains(&SharedJobOptForAttrItem::IconsLite)
186					&& !items.contains(&SharedJobOptForAttrItem::IconsMore)
187			}
188			_ => true,
189		};
190		if keep && !resolved.contains(item) {
191			resolved.push(*item);
192		}
193	}
194	resolved
195}
196
197fn resolve_sort_tex(tex: RawTomlJobSortTex) -> ReadyJobSortTex {
198	let mut strat = Vec::new();
199	let raw = tex.string_strategy.0;
200	for s in &raw {
201		let keep = match s {
202			SharedJobStringMode::aAzZ => !raw.contains(&SharedJobStringMode::AaZz),
203			SharedJobStringMode::AZaz => {
204				!raw.contains(&SharedJobStringMode::AaZz) && !raw.contains(&SharedJobStringMode::aAzZ)
205			}
206			SharedJobStringMode::azAZ => {
207				!raw.contains(&SharedJobStringMode::AaZz)
208					&& !raw.contains(&SharedJobStringMode::aAzZ)
209					&& !raw.contains(&SharedJobStringMode::AZaz)
210			}
211			_ => true,
212		};
213		if keep && !strat.contains(s) {
214			strat.push(*s);
215		}
216	}
217	ReadyJobSortTex::new(tex.reverse, tex.mirror, strat)
218}
219
220// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
221// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
222// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░