1use crate::*;
4use func_man::*;
5use std::path::PathBuf;
6
7mod bools;
8mod bytes;
9mod exec;
10mod folder;
11mod format;
12mod free_file;
13mod lists;
14mod maps;
15pub mod math;
16mod path;
17mod random;
18mod strings;
19mod svg;
20mod table;
21mod write;
22
23pub trait WithFuncs: Sized {
24 fn with_f<K: Into<String>>(self, k: K, f: Box<TFunc>, d: &'static str) -> Self;
25 fn with_fn<K: Into<String>>(self, k: K, f: TFn, d: &'static str) -> Self {
26 self.with_f(k, Box::new(f), d)
27 }
28
29 fn with_defaults(self) -> Self {
30 self.with_bools()
31 .with_strings()
32 .with_math()
33 .with_path()
34 .with_lists()
35 .with_maps()
36 .with_format()
37 .with_rand()
38 .with_bytes()
39 .with_svg()
40 }
41
42 fn with_bytes(self) -> Self {
43 self.with_fn(
44 "as_base64",
45 bytes::as_base64,
46 "(int)->string: Convert a number to base 64",
47 )
48 .with_fn(
49 "from_base64",
50 bytes::from_base64,
51 "(string)->int:Convert a to a number from base 64 string ",
52 )
53 }
54
55 fn with_rand(self) -> Self {
56 self.with_fn(
57 "rand",
58 random::get_rand,
59 "(?min,max)->int|(list)->value : Get a random number or item from list",
60 )
61 }
62 fn with_svg(self) -> Self {
63 self.with_fn(
64 "xy",
65 svg::xy,
66 "(x,y,?units)->string : set svg x and y values",
67 )
68 .with_fn(
69 "xywh",
70 svg::xywh,
71 "(x,y,w,h,?units)->string : set svg x,y,width and hight values",
72 )
73 .with_fn(
74 "cxyrr",
75 svg::cxyrr,
76 "(cx,cy,rx,ry,?units)->string : set svg ellipse values",
77 )
78 .with_fn(
79 "xy12",
80 svg::xy12,
81 "(x,y,x2,y2,?units)->string : set svg x,y,x2 and y2 values",
82 )
83 .with_fn(
84 "fl_stk",
85 svg::fl_stk,
86 "(fill_color,stroke_color,stroke_width)->string : set svg fill and stroke values",
87 )
88 .with_fn(
89 "xml_esc",
90 svg::xml_esc,
91 "(string)->string : escape an xml string",
92 )
93 .with_fn(
94 "font",
95 svg::font,
96 "(size,?name,?units)->string : set svg font",
97 )
98 }
99 fn with_maps(self) -> Self {
100 self.with_fn(
101 "map",
102 maps::map,
103 "(key,value,key,value, ...)->map : build map from list of key value pairs",
104 )
105 }
106
107 fn with_format(self) -> Self {
108 self.with_fn(
109 "r_json",
110 format::r_json,
111 "(string)->value : read json data to value, normally a map",
112 )
113 .with_fn(
114 "r_card",
115 format::r_card,
116 "(string)->map : read card_format data to list of values",
117 )
118 .with_fn(
119 "w_json",
120 format::w_json,
121 "(value)->string : json output of data",
122 )
123 }
124
125 fn with_lists(self) -> Self {
126 self.with_fn(
127 "list",
128 lists::list,
129 "(arg ...)->list<arg> : convert args to a single list",
130 )
131 .with_fn(
132 "sort",
133 lists::sort,
134 "(list ...)->list : combine lists and sort final list on simple value",
135 )
136 .with_fn(
137 "append",
138 lists::append,
139 "(list ...)->list : join all list args to single list",
140 )
141 .with_fn(
142 "sort_on",
143 lists::sort_on,
144 "(list, criteria...)->list : sort list by *criteria*",
145 )
146 .with_fn(
147 "bin_search",
148 lists::bin_search,
149 "(list, criteria)->index : search sorted list for comparator must match sort *criteria*",
150 )
151 .with_fn(
152 "bin_get",
153 lists::bin_get,
154 "(list, criteria)->value : search sorted list for comparator must match sort *criteria*",
155 )
156 .with_fn(
157 "index_of",
158 lists::index_of,
159 "(item,list)->uint/null : if item in list, returns index, else returns null"
160 )
161 .with_fn(
162 "get",
163 lists::get,
164 "(list,index)->value : get item from list by index (list,index)->value",
165 )
166 .with_fn(
167 "filter",
168 lists::filter,
169 "filter list by criteria (list,criteria)->list",
170 )
171 .with_fn("len", lists::len, "(list)->int : Length of the list")
172 .with_fn(
173 "slice",
174 lists::slice,
175 "(list|string, start,?end)->list|string : take a section of a list",
176 )
177 .with_fn(
178 "groups",
179 lists::groups,
180 "(int,list)->list<list> : break a list into groups of the given size",
181 )
182 }
183
184 fn with_strings(self) -> Self {
185 self.with_fn(
186 "cat",
187 strings::cat,
188 "(string...)->string : Concatenate strings",
189 )
190 .with_fn(
191 "md",
192 strings::md,
193 "(string)->string process a string as markdown",
194 )
195 .with_fn(
196 "table",
197 strings::table,
198 "use *table notation* to create an html table",
199 )
200 .with_fn(
201 "split",
202 strings::split,
203 "(string,splitter)->list<string> : split string on splitter",
204 )
205 .with_fn(
206 "string_from_ints",
207 strings::string_from_ints,
208 "(int...)->string : convert the ints to char and combine as a string",
209 )
210 .with_fn(
211 "str_contains",
212 strings::contains,
213 "(haystack,needle...)->bool, does the haystack contain any of the needles",
214 )
215 .with_fn(
216 "str_replace",
217 strings::replace,
218 "(string,needle,replacement)->string : Replace all copies of needle with replacement",
219 )
220 .with_fn("str_replace_n", strings::replace_n,"(string, needle,replacement,?n)->string : Replace n or 1 copies of needle with replacement")
221 .with_fn("html_esc", strings::html_esc,"(string)->string : sanitize input against html security")
222 .with_fn("regex", strings::regex,"(string,regex)->bool : Does the string match the regex")
223 .with_fn("word_wrap", strings::word_wrap,"(string,width)->[]string : Make new string with words wrapped. \\n is auto break, otherwise wrap on width")
224 .with_fn("debug", strings::debug,"(value ...)->() : print something to the log")
225 }
226
227 fn with_math(self) -> Self {
228 self.with_fn(
229 "add",
230 math::add,
231 "(number...)->number : Sum all the numbers",
232 )
233 .with_fn(
234 "sub",
235 math::sub,
236 "(up,down...)->number : Subtract all downs from up",
237 )
238 .with_fn(
239 "mul",
240 math::mul,
241 "(number...)->number : Multiply all the numbers",
242 )
243 .with_fn("div", math::div,"(top,bottom)->number : Divide the top by the bottom, if both are integers then result will be an integer")
244 .with_fn("mod", math::modulo,"(top,bottom...)->int : Top Modulo Bottom")
245 .with_fn("min", math::min,"(number...)->number : The lowest of the numbers")
246 .with_fn("max", math::max,"(number...)->number : The highest of the numbers")
247 }
248
249 fn with_bools(self) -> Self {
250 self.with_fn("eq", bools::eq, "(A,B...)->bool : Does A equal all the B's")
251 .with_fn(
252 "neq",
253 bools::neq,
254 "(A,B...)->bool : Is A different to all the B's",
255 )
256 .with_fn(
257 "eq_any",
258 bools::eq_any,
259 "(A,B...)->bool : Does A equal any of the B's",
260 )
261 .with_fn(
262 "gt",
263 bools::gt,
264 "(A,B...)->bool : Is A greater than all the B's",
265 )
266 .with_fn(
267 "gte",
268 bools::gte,
269 "(A,B...)->bool : Is A greater than or equal to all the B's",
270 )
271 .with_fn(
272 "lt",
273 bools::lt,
274 "(A,B...)->bool : Is a Less than all the B's",
275 )
276 .with_fn(
277 "lte",
278 bools::lte,
279 "(A,B...)->bool : Is a Less than or equal to all the B's",
280 )
281 .with_fn("and", bools::and, "(A...)->bool : Are all the values true")
282 .with_fn(
283 "nand",
284 bools::nand,
285 "(A...)->bool : False if all values are true, with one are, equivilent to not",
286 )
287 .with_fn(
288 "or",
289 bools::or,
290 "(A...)->bool : True if any values are true",
291 )
292 .with_fn(
293 "nor",
294 bools::nor,
295 "(A...)->bool : False if any values are true",
296 )
297 .with_fn(
298 "type_of",
299 bools::type_of,
300 "(value)->string : The type of the value",
301 )
302 .with_fn(
303 "is_null",
304 bools::is_null,
305 "(value)->bool : Is the value null",
306 )
307 .with_fn(
308 "is_num",
309 bools::is_num,
310 "(value)->bool : Is the value a number",
311 )
312 }
313
314 fn with_path(self) -> Self {
315 self.with_fn("parent", path::parent, "(path)->path : The parent path")
316 .with_fn("join", path::join, "(path...)->path : Join paths")
317 .with_fn(
318 "bread_crumbs",
319 path::bread_crumbs,
320 "(path)->list<path> : A list of paths for each parent of this path",
321 )
322 .with_fn(
323 "base_name",
324 path::base_name,
325 "(path)->string : Return file name within the folder Panics on empty",
326 )
327 .with_fn(
328 "base_name_sure",
329 path::base_name_sure,
330 "(path)->string : Return file name within the folder empty string on empty",
331 )
332 .with_fn(
333 "join_with",
334 path::join_with,
335 "(string,[]string)->string: Join the list into a string using the first param as a separator)",
336 )
337 .with_fn(
338 "with_ext",
339 path::with_ext,
340 "(path,ext)->path : replaces the current exstension an extension to a path,ext should not have a dot ",
341 )
342 .with_fn("stem", path::stem,"(path)->string : basename without extension")
343 .with_fn("full_stem", path::full_stem,"(path)->path : file path without extension")
344 }
345
346 fn with_folder_lock<P: Into<PathBuf>>(self, pb: P) -> Self {
347 let pb: PathBuf = pb.into();
348 self.with_f(
349 "dir",
350 folder::dir(pb.clone()),
351 "(path)->list<string> : Locked to folder : List files in folder",
352 )
353 .with_f(
354 "file",
355 folder::file(pb.clone()),
356 "(path)->string : Locked to folder : return a files string",
357 )
358 .with_f(
359 "file_bytes",
360 folder::file_bytes(pb.clone()),
361 "(path)->bytes : Locked to folder : read file as bytes",
362 )
363 .with_f(
364 "is_file",
365 folder::is_file(pb.clone()),
366 "(path)->bool : Locked to folder : Does path point to file",
367 )
368 .with_f(
369 "is_dir",
370 folder::is_dir(pb.clone()),
371 "(path)->bool : Locked to folder : Does path point to directory",
372 )
373 .with_f(
374 "scan_dir",
375 folder::scan_dir(pb.clone()),
376 "(path)->list<map> : Locked to folder :recursively scan directory",
377 )
378 .with_f(
379 "file_img_dimensions",
380 folder::file_img_dimensions(pb.clone()),
381 "(path)->map<x,y> : Locked to folder : Read img file dimensions without reading whole file"
382
383 ,
384 )
385 }
386
387 fn with_free_files(self) -> Self {
388 self.with_fn(
389 "dir",
390 free_file::dir,
391 "(path)->list : List the contents of a directory",
392 )
393 .with_fn(
394 "file",
395 free_file::file,
396 "(path)->string : The contents of a text file",
397 )
398 .with_fn(
399 "file_bytes",
400 free_file::file_bytes,
401 "(path)->bytes : The byte contents of a file",
402 )
403 .with_fn(
404 "is_file",
405 free_file::is_file,
406 "(path)->bool : Dows the path point to a file",
407 )
408 .with_fn(
409 "is_dir",
410 free_file::is_dir,
411 "(path)->bool : Does the path point to a Directory",
412 )
413 .with_fn(
414 "scan_dir",
415 free_file::scan_dir,
416 "(path)->list : recursive list of folder ",
417 )
418 .with_fn(
419 "file_img_dimensions",
420 free_file::file_img_dimensions,
421 "(path)->map<w,h> : get width and height of an image file without reading the whole file",
422 )
423 .with_fn("write", free_file::write ,"(path,contents ...)->bool : Write the contents to the file",)
424 }
425
426 fn with_exec(self) -> Self {
427 self.with_fn(
428 "exec",
429 exec::exec,
430 "(command,arg...)->string : Run the command and return the string result",
431 )
432 .with_fn(
433 "exec_stdin",
434 exec::exec_stdin,
435 "(command,stdin,arg...)->string : Run the command with stdin piped to it's std in",
436 )
437 .with_fn(
438 "env",
439 exec::env,
440 "(var_name,default)->string : read environment variable, if not found, use default",
441 )
442 }
443
444 fn with_write_lock<P: Into<PathBuf>>(self, pb: P) -> Self {
445 let pb: PathBuf = pb.into();
446 self.with_f(
447 "write",
448 write::write(pb.clone()),
449 "(rel_path,contents)->() : write locked within specific folder",
450 )
451 }
452}
453
454impl<FA: FuncAdder> WithFuncs for FA {
455 fn with_f<K: Into<String>>(self, k: K, f: Box<TFunc>, d: &'static str) -> Self {
456 self.with_func(k, f, d)
457 }
458}