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
47pub fn prepare(raw: RawTomlJob) -> ReadyJob {
50 let id = raw.id;
51 let description = raw.description.unwrap_or_default();
52
53 let raw_modes = raw.run_mode.unwrap_or_else(default_run_modes);
55 let run_modes = resolve_run_modes(raw_modes);
56
57 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 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 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 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 ReadyJob::new(id, description, run_modes, explorer, export, attributes, tuples)
153}
154
155fn 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