Skip to main content

ex_cli/
config.rs

1use crate::cli::cli::Cli;
2use crate::cli::file::FileKind;
3use crate::cli::hidden::HiddenKind;
4use crate::cli::order::OrderKind;
5use crate::cli::recent::{PeriodKind, RecentKind};
6use crate::error::MyResult;
7use crate::git::flags::GitFlags;
8use chrono::{DateTime, TimeZone, Utc};
9use clap_builder::{ColorChoice, Parser};
10use clap_complete::Shell;
11use std::collections::HashSet;
12
13#[derive(Debug, Default)]
14pub struct Config {
15    cli: Cli,
16    piped: bool,
17    curr_time: DateTime<Utc>,
18    sort_order: Vec<OrderKind>,
19    sort_name: bool,
20}
21
22impl Config {
23    pub fn new<G: Fn() -> DateTime<Utc>>(
24        args: Vec<String>,
25        piped: bool,
26        factory: G,
27    ) -> MyResult<Self> {
28        let mut cli = Cli::try_parse_from(args)?;
29        let piped = piped && !cli.terminal();
30        let curr_time = cli.curr_time(factory);
31        let (sort_order, sort_name) = cli.sort_order();
32        let config = Self { cli, piped, curr_time, sort_order, sort_name };
33        Ok(config)
34    }
35
36    pub fn curr_time(&self) -> &DateTime<Utc> {
37        &self.curr_time
38    }
39
40    pub fn min_depth(&self) -> Option<usize> {
41        self.cli.min_depth()
42    }
43
44    pub fn max_depth(&self) -> Option<usize> {
45        self.cli.max_depth()
46    }
47
48    pub fn show_indent(&self) -> bool {
49        self.cli.show_indent
50    }
51
52    pub fn show_hidden(&self) -> HiddenKind {
53        match self.cli.show_hidden {
54            0 => HiddenKind::None,
55            1 => HiddenKind::Files,
56            _ => HiddenKind::Recurse,
57        }
58    }
59
60    pub fn zip_expand(&self) -> bool {
61        self.cli.zip_expand
62    }
63
64    pub fn zip_password(&self) -> &Option<String> {
65        &self.cli.zip_password
66    }
67
68    pub fn case_sensitive(&self) -> Option<bool> {
69        if self.cli.case_sensitive {
70            Some(true)
71        } else if self.cli.case_insensitive {
72            Some(false)
73        } else {
74            None
75        }
76    }
77
78    pub fn sort_order(&self) -> &Vec<OrderKind> {
79        &self.sort_order
80    }
81
82    pub fn sort_name(&self) -> bool {
83        self.sort_name
84    }
85
86    pub fn filter_recent(&self) -> RecentKind<PeriodKind> {
87        self.cli.filter_recent.unwrap_or_default()
88    }
89
90    pub fn filter_types(&self) -> Option<&HashSet<FileKind>> {
91        self.cli.filter_types.as_ref().map(|x| &x.inner)
92    }
93
94    pub fn filter_git(&self) -> Option<&GitFlags> {
95        self.cli.filter_git.as_ref()
96    }
97
98    #[cfg(debug_assertions)]
99    pub fn show_debug(&self) -> bool {
100        self.cli.show_debug
101    }
102
103    pub fn show_precise(&self) -> bool {
104        self.cli.show_precise
105    }
106
107    pub fn show_utc(&self) -> bool {
108        self.cli.show_utc
109    }
110
111    pub fn show_total(&self) -> bool {
112        self.cli.show_total
113    }
114
115    #[cfg(unix)]
116    pub fn show_owner(&self) -> bool {
117        self.cli.show_owner
118    }
119
120    pub fn show_crc(&self) -> bool {
121        self.cli.show_crc
122    }
123
124    pub fn show_sig(&self) -> bool {
125        self.cli.show_sig
126    }
127
128    pub fn only_path(&self) -> bool {
129        if self.cli.null_path {
130            true
131        } else {
132            match self.cli.only_path {
133                0 => self.piped,
134                1 => true,
135                _ => false,
136            }
137        }
138    }
139
140    pub fn escape_path(&self) -> bool {
141        if self.cli.null_path {
142            false
143        } else {
144            match self.cli.only_path {
145                0 => self.piped,
146                1 => false,
147                _ => false,
148            }
149        }
150    }
151
152    pub fn null_path(&self) -> bool {
153        self.cli.null_path
154    }
155
156    pub fn abs_path(&self) -> bool {
157        self.cli.abs_path
158    }
159
160    #[cfg(windows)]
161    pub fn win_path(&self) -> bool {
162        self.cli.win_path
163    }
164
165    #[cfg(windows)]
166    pub fn win_ver(&self) -> bool {
167        self.cli.win_ver
168    }
169
170    pub fn color(&self) -> Option<ColorChoice> {
171        self.cli.color
172    }
173
174    pub fn quiet(&self) -> bool {
175        self.cli.quiet
176    }
177
178    pub fn completion(&self) -> Option<Shell> {
179        self.cli.completion
180    }
181
182    pub fn patterns(&self) -> &Vec<String> {
183        &self.cli.patterns
184    }
185
186    pub fn start_time<Tz: TimeZone>(&self, zone: &Tz) -> RecentKind<DateTime<Utc>> {
187        self.filter_recent().subtract_from(self.curr_time(), zone)
188    }
189
190    #[cfg(windows)]
191    pub fn want_decrypt(&self) -> bool {
192        self.show_sig() || self.win_ver()
193    }
194
195    #[cfg(not(windows))]
196    pub fn want_decrypt(&self) -> bool {
197        self.show_sig()
198    }
199}
200
201// noinspection DuplicatedCode
202#[cfg(test)]
203mod tests {
204    use crate::cli::file::{ExecKind, FileKind, FileSet};
205    use crate::cli::hidden::HiddenKind;
206    use crate::cli::order::DirKind;
207    use crate::cli::recent::{PeriodKind, RecentKind};
208    use crate::config::{Config, OrderKind};
209    use crate::error::MyResult;
210    use crate::git::flags::GitFlags;
211    use crate::util::matcher::tests::*;
212    use crate::util::time::tests::create_time;
213    use chrono::{DateTime, Utc};
214    use googletest::prelude::*;
215
216    #[gtest]
217    fn test_depth_is_handled() -> MyResult<()> {
218        let args = vec!["ex"];
219        let config = create_config(args)?;
220        expect_that!(config.min_depth(), some(eq(1)));
221        expect_that!(config.max_depth(), some(eq(1)));
222
223        let args = vec!["ex", "-d4"];
224        let config = create_config(args)?;
225        expect_that!(config.min_depth(), some(eq(1)));
226        expect_that!(config.max_depth(), some(eq(5)));
227
228        let args = vec!["ex", "-d-4"];
229        let config = create_config(args)?;
230        expect_that!(config.min_depth(), some(eq(1)));
231        expect_that!(config.max_depth(), some(eq(5)));
232
233        let args = vec!["ex", "-d2-4"];
234        let config = create_config(args)?;
235        expect_that!(config.min_depth(), some(eq(3)));
236        expect_that!(config.max_depth(), some(eq(5)));
237
238        let args = vec!["ex", "-d2-"];
239        let config = create_config(args)?;
240        expect_that!(config.min_depth(), some(eq(3)));
241        expect_that!(config.max_depth(), none());
242
243        let args = vec!["ex", "-s"];
244        let config = create_config(args)?;
245        expect_that!(config.min_depth(), some(eq(1)));
246        expect_that!(config.max_depth(), none());
247
248        let args = vec!["ex", "-s", "-d4"];
249        let config = create_config(args)?;
250        expect_that!(config.min_depth(), some(eq(1)));
251        expect_that!(config.max_depth(), none());
252
253        let args = vec!["ex", "--recurse"];
254        let config = create_config(args)?;
255        expect_that!(config.min_depth(), some(eq(1)));
256        expect_that!(config.max_depth(), none());
257
258        let args = vec!["ex", "--depth=4"];
259        let config = create_config(args)?;
260        expect_that!(config.min_depth(), some(eq(1)));
261        expect_that!(config.max_depth(), some(eq(5)));
262        Ok(())
263    }
264
265    #[gtest]
266    fn test_indent_is_handled() -> MyResult<()> {
267        let args = vec!["ex"];
268        let config = create_config(args)?;
269        expect_false!(config.show_indent());
270
271        let args = vec!["ex", "-i"];
272        let config = create_config(args)?;
273        expect_true!(config.show_indent());
274
275        let args = vec!["ex", "--indent"];
276        let config = create_config(args)?;
277        expect_true!(config.show_indent());
278        Ok(())
279    }
280
281    #[gtest]
282    fn test_all_files_is_handled() -> MyResult<()> {
283        let args = vec!["ex"];
284        let config = create_config(args)?;
285        expect_eq!(config.show_hidden(), HiddenKind::None);
286
287        let args = vec!["ex", "-a"];
288        let config = create_config(args)?;
289        expect_eq!(config.show_hidden(), HiddenKind::Files);
290
291        let args = vec!["ex", "-aa"];
292        let config = create_config(args)?;
293        expect_eq!(config.show_hidden(), HiddenKind::Recurse);
294
295        let args = vec!["ex", "-a", "-a"];
296        let config = create_config(args)?;
297        expect_eq!(config.show_hidden(), HiddenKind::Recurse);
298
299        let args = vec!["ex", "--all-files"];
300        let config = create_config(args)?;
301        expect_eq!(config.show_hidden(), HiddenKind::Files);
302        Ok(())
303    }
304
305    #[gtest]
306    fn test_zip_is_handled() -> MyResult<()> {
307        let args = vec!["ex"];
308        let config = create_config(args)?;
309        expect_false!(config.zip_expand());
310
311        let args = vec!["ex", "-z"];
312        let config = create_config(args)?;
313        expect_true!(config.zip_expand());
314
315        let args = vec!["ex", "--zip"];
316        let config = create_config(args)?;
317        expect_true!(config.zip_expand());
318        Ok(())
319    }
320
321    #[gtest]
322    fn test_password_is_handled() -> MyResult<()> {
323        let args = vec!["ex"];
324        let config = create_config(args)?;
325        expect_that!(config.zip_password(), none());
326
327        let args = vec!["ex", "--password", "secret"];
328        let config = create_config(args)?;
329        expect_that!(config.zip_password(), some(eq("secret")));
330        Ok(())
331    }
332
333    #[gtest]
334    fn test_case_is_handled() -> MyResult<()> {
335        let args = vec!["ex"];
336        let config = create_config(args)?;
337        expect_that!(config.case_sensitive(), none());
338
339        let args = vec!["ex", "--case"];
340        let config = create_config(args)?;
341        expect_that!(config.case_sensitive(), some(eq(true)));
342
343        let args = vec!["ex", "--case", "--no-case"];
344        let config = create_config(args)?;
345        expect_that!(config.case_sensitive(), some(eq(false)));
346
347        let args = vec!["ex", "--no-case"];
348        let config = create_config(args)?;
349        expect_that!(config.case_sensitive(), some(eq(false)));
350
351        let args = vec!["ex", "--no-case", "--case"];
352        let config = create_config(args)?;
353        expect_that!(config.case_sensitive(), some(eq(true)));
354        Ok(())
355    }
356
357    #[gtest]
358    fn test_order_is_handled() -> MyResult<()> {
359        let args = vec!["ex"];
360        let config = create_config(args)?;
361        expect_that!(config.sort_order(), elements_are![
362            &OrderKind::Group,
363            &OrderKind::Dir,
364            &OrderKind::Name,
365        ]);
366        expect_false!(config.sort_name());
367
368        let args = vec!["ex", "-od"];
369        let config = create_config(args)?;
370        expect_that!(config.sort_order(), elements_are![
371            &OrderKind::Dir,
372            &OrderKind::Name,
373        ]);
374        expect_false!(config.sort_name());
375
376        let args = vec!["ex", "-on"];
377        let config = create_config(args)?;
378        expect_that!(config.sort_order(), elements_are![
379            &OrderKind::Name,
380            &OrderKind::Dir,
381        ]);
382        expect_true!(config.sort_name());
383
384        let args = vec!["ex", "-oe"];
385        let config = create_config(args)?;
386        expect_that!(config.sort_order(), elements_are![
387            &OrderKind::Ext,
388            &OrderKind::Dir,
389            &OrderKind::Name,
390        ]);
391        expect_false!(config.sort_name());
392
393        let args = vec!["ex", "-os"];
394        let config = create_config(args)?;
395        expect_that!(config.sort_order(), elements_are![
396            &OrderKind::Size(DirKind::Asc),
397            &OrderKind::Dir,
398            &OrderKind::Name,
399        ]);
400        expect_false!(config.sort_name());
401
402        let args = vec!["ex", "-os+"];
403        let config = create_config(args)?;
404        expect_that!(config.sort_order(), elements_are![
405            &OrderKind::Size(DirKind::Asc),
406            &OrderKind::Dir,
407            &OrderKind::Name,
408        ]);
409        expect_false!(config.sort_name());
410
411        let args = vec!["ex", "-os-"];
412        let config = create_config(args)?;
413        expect_that!(config.sort_order(), elements_are![
414            &OrderKind::Size(DirKind::Desc),
415            &OrderKind::Dir,
416            &OrderKind::Name,
417        ]);
418        expect_false!(config.sort_name());
419
420        let args = vec!["ex", "-ot"];
421        let config = create_config(args)?;
422        expect_that!(config.sort_order(), elements_are![
423            &OrderKind::Time(DirKind::Asc),
424            &OrderKind::Dir,
425            &OrderKind::Name,
426        ]);
427        expect_false!(config.sort_name());
428
429        let args = vec!["ex", "-ot+"];
430        let config = create_config(args)?;
431        expect_that!(config.sort_order(), elements_are![
432            &OrderKind::Time(DirKind::Asc),
433            &OrderKind::Dir,
434            &OrderKind::Name,
435        ]);
436        expect_false!(config.sort_name());
437
438        let args = vec!["ex", "-ot-"];
439        let config = create_config(args)?;
440        expect_that!(config.sort_order(), elements_are![
441            &OrderKind::Time(DirKind::Desc),
442            &OrderKind::Dir,
443            &OrderKind::Name,
444        ]);
445        expect_false!(config.sort_name());
446
447        let args = vec!["ex", "--order=dest"];
448        let config = create_config(args)?;
449        expect_that!(config.sort_order(), elements_are![
450            &OrderKind::Dir,
451            &OrderKind::Ext,
452            &OrderKind::Size(DirKind::Asc),
453            &OrderKind::Time(DirKind::Asc),
454            &OrderKind::Name,
455        ]);
456        expect_false!(config.sort_name());
457
458        let args = vec!["ex", "--order=est"];
459        let config = create_config(args)?;
460        expect_that!(config.sort_order(), elements_are![
461            &OrderKind::Ext,
462            &OrderKind::Size(DirKind::Asc),
463            &OrderKind::Time(DirKind::Asc),
464            &OrderKind::Dir,
465            &OrderKind::Name,
466        ]);
467        expect_false!(config.sort_name());
468
469        let args = vec!["ex", "--order=e+s+t+"];
470        let config = create_config(args)?;
471        expect_that!(config.sort_order(), elements_are![
472            &OrderKind::Ext,
473            &OrderKind::Size(DirKind::Asc),
474            &OrderKind::Time(DirKind::Asc),
475            &OrderKind::Dir,
476            &OrderKind::Name,
477        ]);
478        expect_false!(config.sort_name());
479
480        let args = vec!["ex", "--order=e-s-t-"];
481        let config = create_config(args)?;
482        expect_that!(config.sort_order(), elements_are![
483            &OrderKind::Ext,
484            &OrderKind::Size(DirKind::Desc),
485            &OrderKind::Time(DirKind::Desc),
486            &OrderKind::Dir,
487            &OrderKind::Name,
488        ]);
489        expect_false!(config.sort_name());
490        Ok(())
491    }
492
493    #[gtest]
494    fn test_order_defaults_to_group_with_no_recursion() -> MyResult<()> {
495        let args = vec!["ex"];
496        let config = create_config(args)?;
497        expect_that!(config.sort_order(), elements_are![
498            &OrderKind::Group,
499            &OrderKind::Dir,
500            &OrderKind::Name,
501        ]);
502        expect_false!(config.sort_name());
503
504        let args = vec!["ex", "-d0"];
505        let config = create_config(args)?;
506        expect_that!(config.sort_order(), elements_are![
507            &OrderKind::Group,
508            &OrderKind::Dir,
509            &OrderKind::Name,
510        ]);
511        expect_false!(config.sort_name());
512
513        let args = vec!["ex", "-d1"];
514        let config = create_config(args)?;
515        expect_that!(config.sort_order(), elements_are![
516            &OrderKind::Dir,
517            &OrderKind::Name,
518        ]);
519        expect_false!(config.sort_name());
520
521        let args = vec!["ex", "-d2"];
522        let config = create_config(args)?;
523        expect_that!(config.sort_order(), elements_are![
524            &OrderKind::Dir,
525            &OrderKind::Name,
526        ]);
527        expect_false!(config.sort_name());
528
529        let args = vec!["ex", "-s"];
530        let config = create_config(args)?;
531        expect_that!(config.sort_order(), elements_are![
532            &OrderKind::Dir,
533            &OrderKind::Name,
534        ]);
535        expect_false!(config.sort_name());
536
537        let args = vec!["ex", "-oe"];
538        let config = create_config(args)?;
539        expect_that!(config.sort_order(), elements_are![
540            &OrderKind::Ext,
541            &OrderKind::Dir,
542            &OrderKind::Name,
543        ]);
544        expect_false!(config.sort_name());
545
546        let args = vec!["ex", "-oe", "-d0"];
547        let config = create_config(args)?;
548        expect_that!(config.sort_order(), elements_are![
549            &OrderKind::Ext,
550            &OrderKind::Dir,
551            &OrderKind::Name,
552        ]);
553        expect_false!(config.sort_name());
554
555        let args = vec!["ex", "-oe", "-d1"];
556        let config = create_config(args)?;
557        expect_that!(config.sort_order(), elements_are![
558            &OrderKind::Ext,
559            &OrderKind::Dir,
560            &OrderKind::Name,
561        ]);
562        expect_false!(config.sort_name());
563
564        let args = vec!["ex", "-oe", "-d2"];
565        let config = create_config(args)?;
566        expect_that!(config.sort_order(), elements_are![
567            &OrderKind::Ext,
568            &OrderKind::Dir,
569            &OrderKind::Name,
570        ]);
571        expect_false!(config.sort_name());
572
573        let args = vec!["ex", "-oe", "-s"];
574        let config = create_config(args)?;
575        expect_that!(config.sort_order(), elements_are![
576            &OrderKind::Ext,
577            &OrderKind::Dir,
578            &OrderKind::Name,
579        ]);
580        expect_false!(config.sort_name());
581        Ok(())
582    }
583
584    #[gtest]
585    fn test_order_defaults_to_directory_with_indent() -> MyResult<()> {
586        let args = vec!["ex", "-i"];
587        let config = create_config(args)?;
588        expect_that!(config.sort_order(), elements_are![
589            &OrderKind::Dir,
590            &OrderKind::Name,
591        ]);
592        expect_false!(config.sort_name());
593
594        let args = vec!["ex", "-i", "-d0"];
595        let config = create_config(args)?;
596        expect_that!(config.sort_order(), elements_are![
597            &OrderKind::Dir,
598            &OrderKind::Name,
599        ]);
600        expect_false!(config.sort_name());
601
602        let args = vec!["ex", "-i", "-d1"];
603        let config = create_config(args)?;
604        expect_that!(config.sort_order(), elements_are![
605            &OrderKind::Dir,
606            &OrderKind::Name,
607        ]);
608        expect_false!(config.sort_name());
609
610        let args = vec!["ex", "-i", "-d2"];
611        let config = create_config(args)?;
612        expect_that!(config.sort_order(), elements_are![
613            &OrderKind::Dir,
614            &OrderKind::Name,
615        ]);
616        expect_false!(config.sort_name());
617
618        let args = vec!["ex", "-i", "-s"];
619        let config = create_config(args)?;
620        expect_that!(config.sort_order(), elements_are![
621            &OrderKind::Dir,
622            &OrderKind::Name,
623        ]);
624        expect_false!(config.sort_name());
625
626        let args = vec!["ex", "-i", "-oe"];
627        let config = create_config(args)?;
628        expect_that!(config.sort_order(), elements_are![
629            &OrderKind::Dir,
630            &OrderKind::Ext,
631            &OrderKind::Name,
632        ]);
633        expect_false!(config.sort_name());
634
635        let args = vec!["ex", "-i", "-oe", "-d0"];
636        let config = create_config(args)?;
637        expect_that!(config.sort_order(), elements_are![
638            &OrderKind::Dir,
639            &OrderKind::Ext,
640            &OrderKind::Name,
641        ]);
642        expect_false!(config.sort_name());
643
644        let args = vec!["ex", "-i", "-oe", "-d1"];
645        let config = create_config(args)?;
646        expect_that!(config.sort_order(), elements_are![
647            &OrderKind::Dir,
648            &OrderKind::Ext,
649            &OrderKind::Name,
650        ]);
651        expect_false!(config.sort_name());
652
653        let args = vec!["ex", "-i", "-oe", "-d2"];
654        let config = create_config(args)?;
655        expect_that!(config.sort_order(), elements_are![
656            &OrderKind::Dir,
657            &OrderKind::Ext,
658            &OrderKind::Name,
659        ]);
660        expect_false!(config.sort_name());
661
662        let args = vec!["ex", "-i", "-oe", "-s"];
663        let config = create_config(args)?;
664        expect_that!(config.sort_order(), elements_are![
665            &OrderKind::Dir,
666            &OrderKind::Ext,
667            &OrderKind::Name,
668        ]);
669        expect_false!(config.sort_name());
670        Ok(())
671    }
672
673    #[gtest]
674    fn test_before_recent_is_handled() -> MyResult<()> {
675        let args = vec!["ex"];
676        let config = create_config(args)?;
677        expect_eq!(config.filter_recent(), RecentKind::None);
678
679        let args = vec!["ex", "-ry10-"];
680        let config = create_config(args)?;
681        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Year(10)));
682
683        let args = vec!["ex", "-rm6-"];
684        let config = create_config(args)?;
685        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Month(6)));
686
687        let args = vec!["ex", "-rw2-"];
688        let config = create_config(args)?;
689        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Week(2)));
690
691        let args = vec!["ex", "-rd-"];
692        let config = create_config(args)?;
693        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Day(1)));
694
695        let args = vec!["ex", "--recent=h-"];
696        let config = create_config(args)?;
697        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Hour(1)));
698
699        let args = vec!["ex", "--recent=H-"];
700        let config = create_config(args)?;
701        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Hour(1)));
702
703        let args = vec!["ex", "--recent=M5-"];
704        let config = create_config(args)?;
705        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Min(5)));
706
707        let args = vec!["ex", "--recent=S10-"];
708        let config = create_config(args)?;
709        expect_eq!(config.filter_recent(), RecentKind::Before(PeriodKind::Sec(10)));
710        Ok(())
711    }
712
713    #[gtest]
714    fn test_after_recent_is_handled() -> MyResult<()> {
715        let args = vec!["ex"];
716        let config = create_config(args)?;
717        expect_eq!(config.filter_recent(), RecentKind::None);
718
719        let args = vec!["ex", "-ry10"];
720        let config = create_config(args)?;
721        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Year(10)));
722
723        let args = vec!["ex", "-rm6"];
724        let config = create_config(args)?;
725        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Month(6)));
726
727        let args = vec!["ex", "-rw2+"];
728        let config = create_config(args)?;
729        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Week(2)));
730
731        let args = vec!["ex", "-rd+"];
732        let config = create_config(args)?;
733        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Day(1)));
734
735        let args = vec!["ex", "--recent=h"];
736        let config = create_config(args)?;
737        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Hour(1)));
738
739        let args = vec!["ex", "--recent=H"];
740        let config = create_config(args)?;
741        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Hour(1)));
742
743        let args = vec!["ex", "--recent=M5"];
744        let config = create_config(args)?;
745        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Min(5)));
746
747        let args = vec!["ex", "--recent=S10"];
748        let config = create_config(args)?;
749        expect_eq!(config.filter_recent(), RecentKind::After(PeriodKind::Sec(10)));
750        Ok(())
751    }
752
753    #[gtest]
754    fn test_none_is_subtracted_from_time() {
755        let now = create_time(2023, 7, 1, 0, 0, 0).unwrap();
756        expect_that!(RecentKind::None.subtract_from(&now, &Utc).to_option(), none());
757    }
758
759    #[gtest]
760    fn test_second_is_subtracted_from_time() {
761        let now = create_time(2023, 7, 1, 0, 0, 0).unwrap();
762        expect_that!(RecentKind::After(PeriodKind::Sec(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 7, 1, 0, 0, 0)));
763        expect_that!(RecentKind::After(PeriodKind::Sec(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 23, 59, 59)));
764        expect_that!(RecentKind::After(PeriodKind::Sec(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 23, 59, 58)));
765    }
766
767    #[gtest]
768    fn test_minute_is_subtracted_from_time() {
769        let now = create_time(2023, 7, 1, 0, 0, 0).unwrap();
770        expect_that!(RecentKind::After(PeriodKind::Min(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 7, 1, 0, 0, 0)));
771        expect_that!(RecentKind::After(PeriodKind::Min(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 23, 59, 0)));
772        expect_that!(RecentKind::After(PeriodKind::Min(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 23, 58, 0)));
773    }
774
775    #[gtest]
776    fn test_hour_is_subtracted_from_time() {
777        let now = create_time(2023, 7, 1, 0, 0, 0).unwrap();
778        expect_that!(RecentKind::After(PeriodKind::Hour(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 7, 1, 0, 0, 0)));
779        expect_that!(RecentKind::After(PeriodKind::Hour(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 23, 0, 0)));
780        expect_that!(RecentKind::After(PeriodKind::Hour(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 22, 0, 0)));
781    }
782
783    #[gtest]
784    fn test_day_is_subtracted_from_time() {
785        let now = create_time(2023, 7, 1, 0, 0, 0).unwrap();
786        expect_that!(RecentKind::After(PeriodKind::Day(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 7, 1, 0, 0, 0)));
787        expect_that!(RecentKind::After(PeriodKind::Day(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 30, 0, 0, 0)));
788        expect_that!(RecentKind::After(PeriodKind::Day(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 29, 0, 0, 0)));
789    }
790
791    #[gtest]
792    fn test_week_is_subtracted_from_time() {
793        let now = create_time(2023, 7, 1, 0, 0, 0).unwrap();
794        expect_that!(RecentKind::After(PeriodKind::Week(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 7, 1, 0, 0, 0)));
795        expect_that!(RecentKind::After(PeriodKind::Week(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 24, 0, 0, 0)));
796        expect_that!(RecentKind::After(PeriodKind::Week(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 6, 17, 0, 0, 0)));
797    }
798
799    #[gtest]
800    fn test_month_is_subtracted_from_time() {
801        let now = create_time(2023, 3, 31, 0, 0, 0).unwrap();
802        expect_that!(RecentKind::After(PeriodKind::Month(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 3, 31, 0, 0, 0)));
803        expect_that!(RecentKind::After(PeriodKind::Month(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 3, 1, 0, 0, 0)));
804        expect_that!(RecentKind::After(PeriodKind::Month(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 1, 31, 0, 0, 0)));
805        expect_that!(RecentKind::After(PeriodKind::Month(3)).subtract_from(&now, &Utc).to_option(), some(time_eq(2022, 12, 31, 0, 0, 0)));
806        expect_that!(RecentKind::After(PeriodKind::Month(4)).subtract_from(&now, &Utc).to_option(), some(time_eq(2022, 12, 1, 0, 0, 0)));
807        expect_that!(RecentKind::After(PeriodKind::Month(5)).subtract_from(&now, &Utc).to_option(), some(time_eq(2022, 10, 31, 0, 0, 0)));
808    }
809
810    #[gtest]
811    fn test_year_is_subtracted_from_time() {
812        let now = create_time(2024, 2, 29, 0, 0, 0).unwrap();
813        expect_that!(RecentKind::After(PeriodKind::Year(0)).subtract_from(&now, &Utc).to_option(), some(time_eq(2024, 2, 29, 0, 0, 0)));
814        expect_that!(RecentKind::After(PeriodKind::Year(1)).subtract_from(&now, &Utc).to_option(), some(time_eq(2023, 3, 1, 0, 0, 0)));
815        expect_that!(RecentKind::After(PeriodKind::Year(2)).subtract_from(&now, &Utc).to_option(), some(time_eq(2022, 3, 1, 0, 0, 0)));
816        expect_that!(RecentKind::After(PeriodKind::Year(3)).subtract_from(&now, &Utc).to_option(), some(time_eq(2021, 3, 1, 0, 0, 0)));
817        expect_that!(RecentKind::After(PeriodKind::Year(4)).subtract_from(&now, &Utc).to_option(), some(time_eq(2020, 2, 29, 0, 0, 0)));
818    }
819
820    #[gtest]
821    fn test_type_is_handled() -> MyResult<()> {
822        let args = vec!["ex"];
823        let config = create_config(args)?;
824        expect_that!(config.filter_types(), none());
825
826        let args = vec!["ex", "-tf"];
827        let config = create_config(args)?;
828        expect_that!(config.filter_types(), some(unordered_elements_are![
829            &FileKind::File(ExecKind::None),
830            &FileKind::File(ExecKind::User),
831            &FileKind::File(ExecKind::Other),
832        ]));
833
834        let args = vec!["ex", "-te"];
835        let config = create_config(args)?;
836        expect_that!(config.filter_types(), some(unordered_elements_are![
837            &FileKind::File(ExecKind::User),
838            &FileKind::File(ExecKind::Other),
839        ]));
840
841        let args = vec!["ex", "-td"];
842        let config = create_config(args)?;
843        expect_that!(config.filter_types(), some(unordered_elements_are![
844            &FileKind::Dir,
845        ]));
846
847        let args = vec!["ex", "-tfd"];
848        let config = create_config(args)?;
849        expect_that!(config.filter_types(), some(unordered_elements_are![
850            &FileKind::File(ExecKind::None),
851            &FileKind::File(ExecKind::User),
852            &FileKind::File(ExecKind::Other),
853            &FileKind::Dir,
854        ]));
855
856        let args = vec!["ex", "--type=l"];
857        let config = create_config(args)?;
858        expect_that!(config.filter_types(), some(unordered_elements_are![
859            &FileKind::Link(false),
860            &FileKind::Link(true),
861        ]));
862
863        let args = vec!["ex", "--type=bcps"];
864        let config = create_config(args)?;
865        expect_that!(config.filter_types(), some(unordered_elements_are![
866            &FileKind::Block,
867            &FileKind::Char,
868            &FileKind::Pipe,
869            &FileKind::Socket,
870        ]));
871        Ok(())
872    }
873
874    #[gtest]
875    fn test_git_is_handled() -> MyResult<()> {
876        let args = vec!["ex"];
877        let config = create_config(args)?;
878        expect_that!(config.filter_git(), none());
879
880        let args = vec!["ex", "-gx"];
881        let config = create_config(args)?;
882        expect_that!(config.filter_git(), some(pat!(&GitFlags {
883            everything: true,
884            cached: false,
885            added: false,
886            modified: false,
887            renamed: false,
888            untracked: false,
889            ignored: false,
890        })));
891
892        let args = vec!["ex", "-gc"];
893        let config = create_config(args)?;
894        expect_that!(config.filter_git(), some(pat!(&GitFlags {
895            everything: false,
896            cached: true,
897            added: false,
898            modified: false,
899            renamed: false,
900            untracked: false,
901            ignored: false,
902        })));
903
904        let args = vec!["ex", "-ga"];
905        let config = create_config(args)?;
906        expect_that!(config.filter_git(), some(pat!(&GitFlags {
907            everything: false,
908            cached: false,
909            added: true,
910            modified: false,
911            renamed: false,
912            untracked: false,
913            ignored: false,
914        })));
915
916        let args = vec!["ex", "-gm"];
917        let config = create_config(args)?;
918        expect_that!(config.filter_git(), some(pat!(&GitFlags {
919            everything: false,
920            cached: false,
921            added: false,
922            modified: true,
923            renamed: false,
924            untracked: false,
925            ignored: false,
926        })));
927
928        let args = vec!["ex", "-gr"];
929        let config = create_config(args)?;
930        expect_that!(config.filter_git(), some(pat!(&GitFlags {
931            everything: false,
932            cached: false,
933            added: false,
934            modified: false,
935            renamed: true,
936            untracked: false,
937            ignored: false,
938        })));
939
940        let args = vec!["ex", "-gu"];
941        let config = create_config(args)?;
942        expect_that!(config.filter_git(), some(pat!(&GitFlags {
943            everything: false,
944            cached: false,
945            added: false,
946            modified: false,
947            renamed: false,
948            untracked: true,
949            ignored: false,
950        })));
951
952        let args = vec!["ex", "-gi"];
953        let config = create_config(args)?;
954        expect_that!(config.filter_git(), some(pat!(&GitFlags {
955            everything: false,
956            cached: false,
957            added: false,
958            modified: false,
959            renamed: false,
960            untracked: false,
961            ignored: true,
962        })));
963
964        let args = vec!["ex", "--git=amr"];
965        let config = create_config(args)?;
966        expect_that!(config.filter_git(), some(pat!(&GitFlags {
967            everything: false,
968            cached: false,
969            added: true,
970            modified: true,
971            renamed: true,
972            untracked: false,
973            ignored: false,
974        })));
975        Ok(())
976    }
977
978    #[gtest]
979    fn test_precise_is_handled() -> MyResult<()> {
980        let args = vec!["ex"];
981        let config = create_config(args)?;
982        expect_false!(config.show_precise());
983
984        let args = vec!["ex", "-p"];
985        let config = create_config(args)?;
986        expect_true!(config.show_precise());
987
988        let args = vec!["ex", "--precise"];
989        let config = create_config(args)?;
990        expect_true!(config.show_precise());
991        Ok(())
992    }
993
994    #[gtest]
995    fn test_utc_is_handled() -> MyResult<()> {
996        let args = vec!["ex"];
997        let config = create_config(args)?;
998        expect_false!(config.show_utc());
999
1000        let args = vec!["ex", "-u"];
1001        let config = create_config(args)?;
1002        expect_true!(config.show_utc());
1003
1004        let args = vec!["ex", "--utc"];
1005        let config = create_config(args)?;
1006        expect_true!(config.show_utc());
1007        Ok(())
1008    }
1009
1010    #[gtest]
1011    fn test_total_is_handled() -> MyResult<()> {
1012        let args = vec!["ex"];
1013        let config = create_config(args)?;
1014        expect_false!(config.show_total());
1015
1016        let args = vec!["ex", "--total"];
1017        let config = create_config(args)?;
1018        expect_true!(config.show_total());
1019        Ok(())
1020    }
1021
1022    #[gtest]
1023    #[cfg(unix)]
1024    fn test_owner_is_handled() -> MyResult<()> {
1025        let args = vec!["ex"];
1026        let config = create_config(args)?;
1027        expect_false!(config.show_owner());
1028
1029        let args = vec!["ex", "--owner"];
1030        let config = create_config(args)?;
1031        expect_true!(config.show_owner());
1032        Ok(())
1033    }
1034
1035    #[gtest]
1036    fn test_data_is_handled() -> MyResult<()> {
1037        let args = vec!["ex"];
1038        let config = create_config(args)?;
1039        expect_false!(config.show_sig());
1040
1041        let args = vec!["ex", "--sig"];
1042        let config = create_config(args)?;
1043        expect_true!(config.show_sig());
1044        Ok(())
1045    }
1046
1047    #[gtest]
1048    fn test_only_path_is_handled_with_terminal() -> MyResult<()> {
1049        let args = vec!["ex"];
1050        let config = create_config_with_piped(args, false)?;
1051        expect_false!(config.only_path()); // (false if terminal)
1052        expect_false!(config.escape_path()); // (false if terminal)
1053        expect_false!(config.null_path());
1054
1055        let args = vec!["ex", "-x"];
1056        let config = create_config_with_piped(args, false)?;
1057        expect_true!(config.only_path());
1058        expect_false!(config.escape_path());
1059        expect_false!(config.null_path());
1060
1061        let args = vec!["ex", "-x", "-x"];
1062        let config = create_config_with_piped(args, false)?;
1063        expect_false!(config.only_path());
1064        expect_false!(config.escape_path());
1065        expect_false!(config.null_path());
1066
1067        let args = vec!["ex", "-xx"];
1068        let config = create_config_with_piped(args, false)?;
1069        expect_false!(config.only_path());
1070        expect_false!(config.escape_path());
1071        expect_false!(config.null_path());
1072
1073        let args = vec!["ex", "--only-path"];
1074        let config = create_config_with_piped(args, false)?;
1075        expect_true!(config.only_path());
1076        expect_false!(config.escape_path());
1077        expect_false!(config.null_path());
1078        Ok(())
1079    }
1080
1081    #[gtest]
1082    fn test_only_path_is_handled_with_piped() -> MyResult<()> {
1083        let args = vec!["ex"];
1084        let config = create_config_with_piped(args, true)?;
1085        expect_true!(config.only_path()); // (true if piped)
1086        expect_true!(config.escape_path()); // (true if piped)
1087        expect_false!(config.null_path());
1088
1089        let args = vec!["ex", "-x"];
1090        let config = create_config_with_piped(args, true)?;
1091        expect_true!(config.only_path());
1092        expect_false!(config.escape_path());
1093        expect_false!(config.null_path());
1094
1095        let args = vec!["ex", "-x", "-x"];
1096        let config = create_config_with_piped(args, true)?;
1097        expect_false!(config.only_path());
1098        expect_false!(config.escape_path());
1099        expect_false!(config.null_path());
1100
1101        let args = vec!["ex", "-xx"];
1102        let config = create_config_with_piped(args, true)?;
1103        expect_false!(config.only_path());
1104        expect_false!(config.escape_path());
1105        expect_false!(config.null_path());
1106
1107        let args = vec!["ex", "--only-path"];
1108        let config = create_config_with_piped(args, true)?;
1109        expect_true!(config.only_path());
1110        expect_false!(config.escape_path());
1111        expect_false!(config.null_path());
1112        Ok(())
1113    }
1114
1115    #[gtest]
1116    #[cfg(debug_assertions)]
1117    fn test_only_path_is_handled_with_override() -> MyResult<()> {
1118        let args = vec!["ex", "--terminal"];
1119        let config = create_config_with_piped(args, true)?;
1120        expect_false!(config.only_path()); // (false if terminal)
1121        expect_false!(config.escape_path()); // (false if terminal)
1122        expect_false!(config.null_path());
1123
1124        let args = vec!["ex", "--terminal", "-x"];
1125        let config = create_config_with_piped(args, true)?;
1126        expect_true!(config.only_path());
1127        expect_false!(config.escape_path());
1128        expect_false!(config.null_path());
1129
1130        let args = vec!["ex", "--terminal", "-x", "-x"];
1131        let config = create_config_with_piped(args, true)?;
1132        expect_false!(config.only_path());
1133        expect_false!(config.escape_path());
1134        expect_false!(config.null_path());
1135
1136        let args = vec!["ex", "--terminal", "-xx"];
1137        let config = create_config_with_piped(args, true)?;
1138        expect_false!(config.only_path());
1139        expect_false!(config.escape_path());
1140        expect_false!(config.null_path());
1141
1142        let args = vec!["ex", "--terminal", "--only-path"];
1143        let config = create_config_with_piped(args, true)?;
1144        expect_true!(config.only_path());
1145        expect_false!(config.escape_path());
1146        expect_false!(config.null_path());
1147        Ok(())
1148    }
1149
1150    #[gtest]
1151    fn test_null_path_is_handled() -> MyResult<()> {
1152        let args = vec!["ex"];
1153        let config = create_config_with_piped(args, false)?;
1154        expect_false!(config.only_path());
1155        expect_false!(config.escape_path());
1156        expect_false!(config.null_path());
1157
1158        let args = vec!["ex", "-z"]; // (reassigned "-z")
1159        let config = create_config_with_piped(args, false)?;
1160        expect_false!(config.only_path());
1161        expect_false!(config.escape_path());
1162        expect_false!(config.null_path());
1163
1164        let args = vec!["ex", "--null-path"];
1165        let config = create_config_with_piped(args, false)?;
1166        expect_true!(config.only_path());
1167        expect_false!(config.escape_path());
1168        expect_true!(config.null_path());
1169        Ok(())
1170    }
1171
1172    #[gtest]
1173    fn test_abs_path_is_handled() -> MyResult<()> {
1174        let args = vec!["ex"];
1175        let config = create_config(args)?;
1176        expect_false!(config.abs_path());
1177
1178        let args = vec!["ex", "-q"];
1179        let config = create_config(args)?;
1180        expect_true!(config.abs_path());
1181
1182        let args = vec!["ex", "--abs-path"];
1183        let config = create_config(args)?;
1184        expect_true!(config.abs_path());
1185        Ok(())
1186    }
1187
1188    #[gtest]
1189    #[cfg(windows)]
1190    fn test_win_path_is_handled() -> MyResult<()> {
1191        let args = vec!["ex"];
1192        let config = create_config(args)?;
1193        expect_false!(config.win_path());
1194
1195        let args = vec!["ex", "-w"];
1196        let config = create_config(args)?;
1197        expect_true!(config.win_path());
1198
1199        let args = vec!["ex", "--win-path"];
1200        let config = create_config(args)?;
1201        expect_true!(config.win_path());
1202        Ok(())
1203    }
1204
1205    #[gtest]
1206    #[cfg(windows)]
1207    fn test_win_ver_is_handled() -> MyResult<()> {
1208        let args = vec!["ex"];
1209        let config = create_config(args)?;
1210        expect_false!(config.win_ver());
1211
1212        let args = vec!["ex", "-v"];
1213        let config = create_config(args)?;
1214        expect_true!(config.win_ver());
1215
1216        let args = vec!["ex", "--win-ver"];
1217        let config = create_config(args)?;
1218        expect_true!(config.win_ver());
1219        Ok(())
1220    }
1221
1222    #[gtest]
1223    fn test_patterns_are_handled() -> MyResult<()> {
1224        let args = vec!["ex"];
1225        let config = create_config(args)?;
1226        expect_that!(config.patterns(), elements_are!["."]);
1227
1228        let args = vec!["ex", "file1"];
1229        let config = create_config(args)?;
1230        expect_that!(config.patterns(), elements_are!["file1"]);
1231
1232        let args = vec!["ex", "file1", "file2"];
1233        let config = create_config(args)?;
1234        expect_that!(config.patterns(), elements_are!["file1", "file2"]);
1235        Ok(())
1236    }
1237
1238    #[gtest]
1239    fn test_unexpected_depth_causes_error() {
1240        let args = vec!["ex", "-dfoo"];
1241        let result = create_config(args);
1242        expect_that!(result, err(displays_as(contains_substring("Invalid depth option: foo"))));
1243    }
1244
1245    #[gtest]
1246    fn test_unexpected_order_causes_error() {
1247        let args = vec!["ex", "-ofoo"];
1248        let result = create_config(args);
1249        expect_that!(result, err(displays_as(contains_substring("Invalid order option: foo"))));
1250    }
1251
1252    #[gtest]
1253    fn test_unexpected_recent_causes_error() {
1254        let args = vec!["ex", "-rfoo"];
1255        let result = create_config(args);
1256        expect_that!(result, err(displays_as(contains_substring("Invalid recent option: foo"))));
1257    }
1258
1259    #[gtest]
1260    fn test_unexpected_type_causes_error() {
1261        let args = vec!["ex", "-tfzd"];
1262        let result = create_config(args);
1263        expect_that!(result, err(displays_as(contains_substring("Invalid type option: z"))));
1264    }
1265
1266    #[gtest]
1267    fn test_unexpected_git_causes_error() {
1268        let args = vec!["ex", "-gazm"];
1269        let result = create_config(args);
1270        expect_that!(result, err(displays_as(contains_substring("Invalid git option: z"))));
1271    }
1272
1273    fn create_config(args: Vec<&str>) -> MyResult<Config> {
1274        create_config_with_piped(args, false)
1275    }
1276
1277    fn create_config_with_piped(args: Vec<&str>, piped: bool) -> MyResult<Config> {
1278        let args = args.into_iter().map(String::from).collect();
1279        Config::new(args, piped, DateTime::default)
1280    }
1281
1282    impl Config {
1283        pub fn with_curr_time(
1284            mut self,
1285            year: i32,
1286            month: u32,
1287            day: u32,
1288            hour: u32,
1289            minute: u32,
1290            second: u32,
1291        ) -> Self {
1292            self.curr_time = create_time(year, month, day, hour, minute, second).unwrap();
1293            self
1294        }
1295
1296        pub fn with_recurse_all(mut self, recurse_all: bool) -> Self {
1297            self.cli.recurse_all = recurse_all;
1298            self
1299        }
1300
1301        pub fn with_min_depth(mut self, min_depth: usize) -> Self {
1302            self.cli.recurse_depth.get_or_insert_default().min_depth = Some(min_depth);
1303            self
1304        }
1305
1306        pub fn with_max_depth(mut self, max_depth: usize) -> Self {
1307            self.cli.recurse_depth.get_or_insert_default().max_depth = Some(max_depth);
1308            self
1309        }
1310
1311        pub fn with_show_indent(mut self, show_indent: bool) -> Self {
1312            self.cli.show_indent = show_indent;
1313            self
1314        }
1315
1316        pub fn with_zip_expand(mut self, zip_expand: bool) -> Self {
1317            self.cli.zip_expand = zip_expand;
1318            self
1319        }
1320
1321        pub fn with_case_sensitive(mut self, case_sensitive: bool) -> Self {
1322            if case_sensitive {
1323                self.cli.case_sensitive = true;
1324                self.cli.case_insensitive = false;
1325            } else {
1326                self.cli.case_sensitive = false;
1327                self.cli.case_insensitive = true;
1328            }
1329            self
1330        }
1331
1332        pub fn with_sort_order(mut self, sort_order: Vec<OrderKind>) -> Self {
1333            self.sort_order = sort_order;
1334            self
1335        }
1336
1337        pub fn with_sort_name(mut self, sort_name: bool) -> Self {
1338            self.sort_name = sort_name;
1339            self
1340        }
1341
1342        pub fn with_filter_recent(mut self, filter_recent: RecentKind<PeriodKind>) -> Self {
1343            self.cli.filter_recent = Some(filter_recent);
1344            self
1345        }
1346
1347        pub fn with_filter_types(mut self, filter_types: Vec<FileKind>) -> Self {
1348            let filter_types = FileSet { inner: filter_types.into_iter().collect() };
1349            self.cli.filter_types = Some(filter_types);
1350            self
1351        }
1352
1353        pub fn with_filter_git(mut self, filter_git: GitFlags) -> Self {
1354            self.cli.filter_git = Some(filter_git);
1355            self
1356        }
1357
1358        pub fn with_show_precise(mut self, show_precise: bool) -> Self {
1359            self.cli.show_precise = show_precise;
1360            self
1361        }
1362
1363        pub fn with_show_utc(mut self, show_utc: bool) -> Self {
1364            self.cli.show_utc = show_utc;
1365            self
1366        }
1367
1368        pub fn with_show_total(mut self, show_total: bool) -> Self {
1369            self.cli.show_total = show_total;
1370            self
1371        }
1372
1373        #[cfg(unix)]
1374        pub fn with_show_owner(mut self, show_owner: bool) -> Self {
1375            self.cli.show_owner = show_owner;
1376            self
1377        }
1378
1379        pub fn with_show_crc(mut self, show_crc: bool) -> Self {
1380            self.cli.show_crc = show_crc;
1381            self
1382        }
1383
1384        pub fn with_show_sig(mut self, show_sig: bool) -> Self {
1385            self.cli.show_sig = show_sig;
1386            self
1387        }
1388
1389        pub fn with_only_path(mut self, only_path: bool) -> Self {
1390            self.cli.only_path = if only_path { 1 } else { 2 };
1391            self
1392        }
1393
1394        pub fn with_escape_path(mut self) -> Self {
1395            self.cli.only_path = 0;
1396            self.cli.null_path = false;
1397            self.piped = true;
1398            self
1399        }
1400
1401        pub fn with_abs_path(mut self, abs_path: bool) -> Self {
1402            self.cli.abs_path = abs_path;
1403            self
1404        }
1405
1406        #[cfg(windows)]
1407        pub fn with_win_ver(mut self, win_ver: bool) -> Self {
1408            self.cli.win_ver = win_ver;
1409            self
1410        }
1411
1412        pub fn with_patterns(mut self, patterns: Vec<&str>) -> Self {
1413            self.cli.patterns = patterns.into_iter().map(String::from).collect();
1414            self
1415        }
1416    }
1417}