Skip to main content

ex_cli/
printer.rs

1use crate::cli::file::{ExecKind, FileKind};
2use crate::cli::recent::RecentKind;
3use crate::config::Config;
4use crate::error::MyResult;
5use crate::fs::file::{File, Signature};
6use crate::fs::total::Total;
7use crate::git::flags::GitFlags;
8use crate::regex;
9use crate::util::calendar::Calendar;
10use crate::util::color::ColorMap;
11use chrono::*;
12#[cfg(windows)]
13use regex::Captures;
14use std::collections::HashMap;
15use std::ffi::OsStr;
16use std::path::{Component, Path, PathBuf};
17#[cfg(unix)]
18use std::rc::Rc;
19use std::{cmp, path};
20use termcolor::WriteColor;
21
22const MODE_WIDTH: usize = 10; // (width of "drwxrwxrwx")
23const GIT_WIDTH: usize = 5; // (width of "AMRUI")
24const TIME_WIDTH: usize = 24; // (width of "Sun 31-Dec-2023 23:59:59")
25const MONTH_WIDTH: usize = 8; // (width of "12 month")
26const CRC_WIDTH: usize = 8; // (width of "FFFFFFFF")
27const SIG_WIDTH: usize = 13; // (width of "41424344 ABCD")
28const PAD_WIDTH: usize = 2; // (width of "  ")
29
30pub struct IndentChars {
31    pub branching: char,
32    pub terminating: char,
33    pub horizontal: char,
34    pub vertical: char,
35}
36
37enum IndentToken {
38    BranchMiddle,
39    BranchFinal,
40    SpaceMiddle,
41    SpaceFinal,
42}
43
44#[allow(dead_code)]
45pub struct Printer<'a, W: WriteColor> {
46    config: &'a Config,
47    calendar: Calendar,
48    writer: W,
49    counter: HashMap<PathBuf, isize>,
50    colors: ColorMap,
51    chars: IndentChars,
52    git_bash: bool,
53    separator: char,
54    separator_str: String,
55}
56
57impl<'a, W: WriteColor> Printer<'a, W> {
58    pub fn new<Tz: TimeZone>(
59        config: &'a Config,
60        zone: &Tz,
61        writer: W,
62        colors: ColorMap,
63        chars: IndentChars,
64        git_bash: bool,
65    ) -> Self {
66        let calendar = Calendar::from_time(config.curr_time(), zone);
67        let counter = HashMap::new();
68        #[cfg(windows)]
69        let git_bash = git_bash && !config.win_path();
70        let separator = if git_bash { '/' } else { path::MAIN_SEPARATOR };
71        let separator_str = separator.to_string();
72        Self {
73            config,
74            calendar,
75            writer,
76            counter,
77            colors,
78            chars,
79            git_bash,
80            separator,
81            separator_str,
82        }
83    }
84
85    pub fn print_files<Tz: TimeZone>(
86        &mut self,
87        files: &Vec<File>,
88        total: &Total,
89        zone: &Tz,
90    ) -> MyResult<()> {
91        if self.config.show_indent() {
92            self.count_parents(files);
93        }
94        if self.config.only_path() {
95            for file in files {
96                self.print_path(file, false)?;
97                self.print_newline()?;
98            }
99        } else {
100            let mode_width = measure_mode(self.config);
101            let size_width = if self.config.show_total() {
102                measure_size(self.config, total.total_size)
103            } else {
104                measure_size(self.config, total.max_size)
105            };
106            let time_width = measure_time(self.config);
107            if self.config.filter_recent() != RecentKind::None {
108                self.print_start(total, zone, mode_width, size_width, time_width)?;
109            }
110            for file in files {
111                self.print_file(file, total, zone, size_width)?;
112            }
113            if self.config.show_total() {
114                self.print_total(total, mode_width, size_width, time_width)?;
115            }
116        }
117        Ok(())
118    }
119
120    fn print_start<Tz: TimeZone>(
121        &mut self,
122        total: &Total,
123        zone: &Tz,
124        mode_width: usize,
125        size_width: usize,
126        time_width: usize,
127    ) -> MyResult<()> {
128        let mut print = |label: &str, time: &DateTime<Utc>| -> MyResult<()> {
129            let mut combined_width = mode_width + PAD_WIDTH + size_width;
130            if self.config.filter_git().is_some() {
131                combined_width += 1 + GIT_WIDTH;
132            }
133            #[cfg(unix)]
134            if self.config.show_owner() {
135                combined_width += PAD_WIDTH + total.user_width + 1 + total.group_width;
136            }
137            self.print_text(label, combined_width)?;
138            self.print_time(time, zone, false)?;
139            writeln!(self.writer)?;
140            self.print_hyphens(combined_width + PAD_WIDTH + time_width)?;
141            Ok(())
142        };
143        match total.start_time {
144            RecentKind::None => (),
145            RecentKind::Before(time) => print("Before", &time)?,
146            RecentKind::After(time) => print("After", &time)?,
147        }
148        Ok(())
149    }
150
151    fn print_file<Tz: TimeZone>(
152        &mut self,
153        file: &File,
154        total: &Total,
155        zone: &Tz,
156        size_width: usize,
157    ) -> MyResult<()> {
158        self.print_mode(file.file_type, file.file_mode, file.inner_depth)?;
159        self.print_git(file.git_flags)?;
160        #[cfg(unix)]
161        self.print_owner(&file.owner_user, &file.owner_group, total.user_width, total.group_width)?;
162        self.print_size(file.file_size, size_width)?;
163        self.print_time(&file.file_time, zone, true)?;
164        self.print_crc(file.file_crc)?;
165        self.print_sig(file.file_sig)?;
166        #[cfg(windows)]
167        self.print_version(&file.file_ver, total.ver_width)?;
168        self.print_ext(&file.file_ext, total.ext_width)?;
169        #[cfg(debug_assertions)]
170        self.print_debug(file.file_depth, file.inner_depth)?;
171        self.print_path(file, true)?;
172        writeln!(self.writer)?;
173        Ok(())
174    }
175
176    #[allow(unused_mut)]
177    fn print_total(
178        &mut self,
179        total: &Total,
180        mode_width: usize,
181        size_width: usize,
182        time_width: usize,
183    ) -> MyResult<()> {
184        let mut combined_width = mode_width;
185        if self.config.filter_git().is_some() {
186            combined_width += 1 + GIT_WIDTH;
187        }
188        #[cfg(unix)]
189        if self.config.show_owner() {
190            combined_width += PAD_WIDTH + total.user_width + 1 + total.group_width;
191        }
192        self.print_hyphens(combined_width + PAD_WIDTH + size_width + PAD_WIDTH + time_width)?;
193        self.print_text("Total", combined_width)?;
194        self.print_size(total.total_size, size_width)?;
195        self.print_spaces(PAD_WIDTH + PAD_WIDTH + time_width)?;
196        if self.config.show_crc() {
197            self.print_spaces(PAD_WIDTH + CRC_WIDTH)?;
198        }
199        if self.config.show_sig() {
200            self.print_spaces(PAD_WIDTH + SIG_WIDTH)?;
201        }
202        if total.ext_width > 0 {
203            self.print_spaces(PAD_WIDTH + total.ext_width)?;
204        }
205        self.print_summary(total)?;
206        writeln!(self.writer)?;
207        Ok(())
208    }
209
210    fn print_summary(
211        &mut self,
212        total: &Total,
213    ) -> MyResult<()> {
214        let files = if total.num_files == 1 { "file" } else { "files" };
215        let dirs = if total.num_dirs == 1 { "directory" } else { "directories" };
216        write!(
217            self.writer,
218            "{num_files} {files} {num_dirs} {dirs}",
219            num_files = total.num_files,
220            num_dirs = total.num_dirs,
221        )?;
222        Ok(())
223    }
224
225    fn print_mode(
226        &mut self,
227        file_type: FileKind,
228        file_mode: u32,
229        inner_depth: Option<usize>,
230    ) -> MyResult<()> {
231        if self.config.zip_expand() {
232            if inner_depth.is_some() {
233                write!(self.writer, "z")?;
234            } else {
235                write!(self.writer, "-")?;
236            }
237        }
238        match file_type {
239            FileKind::File(_) => write!(self.writer, "-")?,
240            FileKind::Dir => write!(self.writer, "d")?,
241            FileKind::Link(_) => write!(self.writer, "l")?,
242            FileKind::Block => write!(self.writer, "b")?,
243            FileKind::Char => write!(self.writer, "c")?,
244            FileKind::Pipe => write!(self.writer, "p")?,
245            FileKind::Socket => write!(self.writer, "s")?,
246            FileKind::Other => write!(self.writer, "?")?,
247        };
248        for shift in [6, 3, 0] {
249            let file_mode = file_mode >> shift;
250            if (file_mode & 4) != 0 {
251                write!(self.writer, "r")?;
252            } else {
253                write!(self.writer, "-")?;
254            }
255            if (file_mode & 2) != 0 {
256                write!(self.writer, "w")?;
257            } else {
258                write!(self.writer, "-")?;
259            }
260            if (file_mode & 1) != 0 {
261                write!(self.writer, "x")?;
262            } else {
263                write!(self.writer, "-")?;
264            }
265        }
266        Ok(())
267    }
268
269    fn print_git(
270        &mut self,
271        git_flags: Option<GitFlags>,
272    ) -> MyResult<()> {
273        if self.config.filter_git().is_some() {
274            if let Some(git_flags) = git_flags {
275                write!(self.writer, " ")?;
276                write!(self.writer, "{}", if git_flags.added { 'A' } else { '-' })?;
277                write!(self.writer, "{}", if git_flags.modified { 'M' } else { '-' })?;
278                write!(self.writer, "{}", if git_flags.renamed { 'R' } else { '-' })?;
279                write!(self.writer, "{}", if git_flags.untracked { 'U' } else { '-' })?;
280                write!(self.writer, "{}", if git_flags.ignored { 'I' } else { '-' })?;
281            } else {
282                write!(self.writer, " -----")?;
283            }
284        }
285        Ok(())
286    }
287
288    #[cfg(unix)]
289    fn print_owner(
290        &mut self,
291        owner_user: &Option<Rc<String>>,
292        owner_group: &Option<Rc<String>>,
293        user_width: usize,
294        group_width: usize,
295    ) -> MyResult<()> {
296        if self.config.show_owner() {
297            self.print_spaces(PAD_WIDTH)?;
298            if let Some(user) = owner_user {
299                write!(self.writer, "{0:1$}", user, user_width + 1)?;
300            } else {
301                write!(self.writer, "{0:1$}", "-", user_width + 1)?;
302            }
303            if let Some(group) = owner_group {
304                write!(self.writer, "{0:1$}", group, group_width)?;
305            } else {
306                write!(self.writer, "{0:1$}", "-", group_width)?;
307            }
308        }
309        Ok(())
310    }
311
312    fn print_size(
313        &mut self,
314        file_size: u64,
315        size_width: usize,
316    ) -> MyResult<()> {
317        self.print_spaces(PAD_WIDTH)?;
318        if self.config.show_precise() {
319            self.print_thousand(file_size, size_width)?;
320        } else {
321            if file_size < 1_000 {
322                write!(self.writer, "{0:3} B ", file_size)?;
323            } else if file_size < 1_000_000 {
324                write!(self.writer, "{0:3} KB", file_size / 1_000)?;
325            } else if file_size < 1_000_000_000 {
326                write!(self.writer, "{0:3} MB", file_size / 1_000_000)?;
327            } else if file_size < 1_000_000_000_000 {
328                write!(self.writer, "{0:3} GB", file_size / 1_000_000_000)?;
329            } else if file_size < 1_000_000_000_000_000 {
330                write!(self.writer, "{0:3} TB", file_size / 1_000_000_000_000)?;
331            } else if file_size < 1_000_000_000_000_000_000 {
332                write!(self.writer, "{0:3} PB", file_size / 1_000_000_000_000_000)?;
333            } else {
334                write!(self.writer, "{0:3} EB", file_size / 1_000_000_000_000_000_000)?;
335            }
336        }
337        Ok(())
338    }
339
340    fn print_thousand(
341        &mut self,
342        file_size: u64,
343        size_width: usize,
344    ) -> MyResult<()> {
345        if file_size >= 1000 {
346            self.print_thousand(file_size / 1000, cmp::max(size_width, 4) - 4)?;
347            write!(self.writer, ",{0:03}", file_size % 1000)?;
348        } else {
349            write!(self.writer, "{0:1$}", file_size, size_width)?;
350        }
351        Ok(())
352    }
353
354    fn print_time<Tz: TimeZone>(
355        &mut self,
356        file_time: &DateTime<Utc>,
357        zone: &Tz,
358        padding: bool,
359    ) -> MyResult<()> {
360        self.print_spaces(PAD_WIDTH)?;
361        if self.config.show_precise() {
362            if file_time.timestamp() != 0 {
363                let file_time = file_time.with_timezone(zone);
364                let weekday = convert_weekday(file_time.weekday());
365                let day = file_time.day();
366                let month = convert_month(file_time.month());
367                let year = file_time.year();
368                let hour = file_time.hour();
369                let minute = file_time.minute();
370                let second = file_time.second();
371                write!(self.writer, "{weekday} {day:02}-{month}-{year:04} {hour:02}:{minute:02}:{second:02}")?;
372                if self.config.show_utc() {
373                    write!(self.writer, "Z")?;
374                }
375            } else {
376                write!(self.writer, "{0:-<1$}", "", TIME_WIDTH)?;
377                if self.config.show_utc() {
378                    write!(self.writer, "-")?;
379                }
380            }
381        } else {
382            if file_time.timestamp() != 0 {
383                let recent = RecentKind::from_times(&file_time, self.config.curr_time(), &self.calendar, zone);
384                match recent {
385                    RecentKind::None => {
386                        write!(self.writer, " future")?;
387                        if padding {
388                            write!(self.writer, " ")?;
389                        }
390                    }
391                    RecentKind::Before(period) => period.print_time(&mut self.writer, padding)?,
392                    RecentKind::After(period) => period.print_time(&mut self.writer, padding)?,
393                }
394            } else {
395                write!(self.writer, "{0:-<1$}", "", MONTH_WIDTH)?;
396            }
397        }
398        Ok(())
399    }
400
401    fn print_crc(&mut self, file_crc: u32) -> MyResult<()> {
402        if self.config.show_crc() {
403            self.print_spaces(PAD_WIDTH)?;
404            write!(self.writer, "{:08x}", file_crc)?;
405        }
406        Ok(())
407    }
408
409    fn print_sig(&mut self, file_sig: Signature) -> MyResult<()> {
410        if self.config.show_sig() {
411            self.print_spaces(PAD_WIDTH)?;
412            for byte in file_sig {
413                write!(self.writer, "{:02x}", byte)?;
414            }
415            write!(self.writer, " ")?;
416            for byte in file_sig {
417                write!(self.writer, "{}", printable_char(byte))?;
418            }
419        }
420        Ok(())
421    }
422
423    #[cfg(windows)]
424    fn print_version(
425        &mut self,
426        file_ver: &Option<String>,
427        ver_width: usize,
428    ) -> MyResult<()> {
429        if ver_width > 0 {
430            self.print_spaces(PAD_WIDTH)?;
431            if let Some(file_ver) = file_ver {
432                write!(self.writer, "{0:1$}", file_ver, ver_width)?;
433            } else {
434                self.print_spaces(ver_width)?;
435            }
436        }
437        Ok(())
438    }
439
440    fn print_ext(
441        &mut self,
442        file_ext: &str,
443        ext_width: usize,
444    ) -> MyResult<()> {
445        if ext_width > 0 {
446            self.print_spaces(PAD_WIDTH)?;
447            write!(self.writer, "{0:1$}", file_ext, ext_width)?;
448        }
449        Ok(())
450    }
451
452    #[cfg(debug_assertions)]
453    fn print_debug(
454        &mut self,
455        file_depth: usize,
456        inner_depth: Option<usize>,
457    ) -> MyResult<()> {
458        if self.config.show_debug() {
459            self.writer.set_color(&self.colors.debug_color)?;
460            if self.config.zip_expand() {
461                let inner_depth = inner_depth
462                    .map(|depth| depth.to_string())
463                    .unwrap_or_else(|| "-".to_string());
464                write!(self.writer, "[{}][{}]", file_depth, inner_depth)?;
465            } else {
466                write!(self.writer, "[{}]", file_depth)?;
467            }
468            self.writer.reset()?;
469            write!(self.writer, " ")?;
470        }
471        Ok(())
472    }
473
474    fn print_path(
475        &mut self,
476        file: &File,
477        padding: bool,
478    ) -> MyResult<()> {
479        if padding {
480            self.print_spaces(PAD_WIDTH)?;
481        }
482        if self.config.show_indent() {
483            self.print_prefix(file)?;
484            if file.file_type == FileKind::Dir {
485                self.indent_dir(&file.rel_dir, file.inner_depth, file.file_type.dir_offset())?;
486            } else {
487                self.print_name(&file.file_name, &file.file_ext, file.file_type)?;
488            }
489            self.print_link(&file.link_data)?;
490        } else {
491            let file_dir = file.select_dir(self.config.abs_path());
492            if self.config.sort_name() {
493                self.print_name(&file.file_name, &file.file_ext, file.file_type)?;
494                self.print_dir(file_dir, file.inner_depth, file.file_type.dir_offset(), true)?;
495                self.print_link(&file.link_data)?;
496            } else {
497                self.print_dir(file_dir, file.inner_depth, file.file_type.dir_offset(), false)?;
498                self.print_name(&file.file_name, &file.file_ext, file.file_type)?;
499                if !self.config.escape_path() && !self.config.null_path() {
500                    self.print_link(&file.link_data)?;
501                }
502            }
503        }
504        Ok(())
505    }
506
507    fn print_dir(
508        &mut self,
509        file_dir: &Path,
510        inner_depth: Option<usize>,
511        inner_offset: usize,
512        sort_name: bool,
513    ) -> MyResult<()> {
514        if !is_trivial(file_dir) {
515            if sort_name {
516                write!(self.writer, " (")?;
517                self.iterate_dir(file_dir, inner_depth, inner_offset, false)?;
518                write!(self.writer, ")")?;
519            } else {
520                self.iterate_dir(file_dir, inner_depth, inner_offset, true)?;
521            }
522        }
523        Ok(())
524    }
525
526    fn iterate_dir(
527        &mut self,
528        file_dir: &Path,
529        inner_depth: Option<usize>,
530        inner_offset: usize,
531        trailing_slash: bool,
532    ) -> MyResult<()> {
533        self.writer.set_color(&self.colors.dir_color)?;
534        let components = file_dir.components().into_iter().collect::<Vec<_>>();
535        let count = components.len();
536        for (index, component) in components.iter().enumerate() {
537            if let Some(text) = component.as_os_str().to_str() {
538                let color = inner_depth
539                    .is_some_and(|depth| depth + inner_offset + index == count)
540                    .then(|| get_extension(component))
541                    .and_then(|ext| self.colors.find_color(ext));
542                if let Some(color) = color {
543                    self.writer.set_color(color)?;
544                    self.escape_dir(text)?;
545                    self.writer.set_color(&self.colors.dir_color)?;
546                } else {
547                    self.escape_dir(text)?;
548                }
549                if is_joinable(&component) {
550                    if index + 1 < count || trailing_slash {
551                        write!(self.writer, "{}", self.separator)?;
552                    }
553                }
554            }
555        }
556        self.writer.reset()?;
557        Ok(())
558    }
559
560    fn indent_dir(
561        &mut self,
562        file_dir: &Path,
563        inner_depth: Option<usize>,
564        inner_offset: usize,
565    ) -> MyResult<()> {
566        if let Some(component) = file_dir.components().last() {
567            if let Some(text) = component.as_os_str().to_str() {
568                let color = inner_depth
569                    .is_some_and(|depth| depth + inner_offset == 1)
570                    .then(|| get_extension(&component))
571                    .and_then(|ext| self.colors.find_color(ext))
572                    .unwrap_or(&self.colors.dir_color);
573                self.writer.set_color(color)?;
574                self.escape_dir(text)?;
575                self.writer.reset()?;
576            }
577        }
578        Ok(())
579    }
580
581    #[cfg(windows)]
582    fn escape_dir(
583        &mut self,
584        file_dir: &str,
585    ) -> MyResult<()> {
586        if self.git_bash {
587            let drive_regex = regex!(r#"^([A-Z]):(.*)$"#);
588            let file_dir = file_dir.replace(path::MAIN_SEPARATOR, &self.separator_str);
589            let file_dir = drive_regex.replace(&file_dir, |caps: &Captures| {
590                format!("{}{}{}", self.separator, &caps[1].to_lowercase(), &caps[2])
591            });
592            if self.config.escape_path() {
593                let escape_regex = regex!(r#"([\s"'])"#);
594                let file_dir = escape_regex.replace_all(&file_dir, "\\$1");
595                write!(self.writer, "{file_dir}")?;
596            } else {
597                write!(self.writer, "{file_dir}")?;
598            }
599        } else {
600            write!(self.writer, "{file_dir}")?;
601        }
602        Ok(())
603    }
604
605    #[cfg(not(windows))]
606    fn escape_dir(
607        &mut self,
608        file_dir: &str,
609    ) -> MyResult<()> {
610        if self.config.escape_path() {
611            let escape_regex = regex!(r#"([\s"'\\])"#);
612            let file_dir = escape_regex.replace_all(file_dir, "\\$1");
613            write!(self.writer, "{file_dir}")?;
614        } else {
615            write!(self.writer, "{file_dir}")?;
616        }
617        Ok(())
618    }
619
620    fn print_name(
621        &mut self,
622        file_name: &str,
623        file_ext: &str,
624        file_type: FileKind,
625    ) -> MyResult<()> {
626        if !file_name.is_empty() {
627            match file_type {
628                FileKind::File(exec) => {
629                    if exec == ExecKind::User {
630                        self.writer.set_color(&self.colors.exec_color)?;
631                        self.escape_name(file_name)?;
632                        self.writer.reset()?;
633                    } else if exec == ExecKind::Other {
634                        self.writer.set_color(&self.colors.exec_other)?;
635                        self.escape_name(file_name)?;
636                        self.writer.reset()?;
637                    } else if let Some(color) = self.colors.find_color(file_ext) {
638                        self.writer.set_color(color)?;
639                        self.escape_name(file_name)?;
640                        self.writer.reset()?;
641                    } else {
642                        self.escape_name(file_name)?;
643                    }
644                }
645                FileKind::Dir => {
646                    self.writer.set_color(&self.colors.dir_color)?;
647                    self.escape_name(file_name)?;
648                    write!(self.writer, "{}", self.separator)?;
649                    self.writer.reset()?;
650                }
651                FileKind::Link(resolved) => {
652                    if resolved {
653                        self.writer.set_color(&self.colors.link_color)?;
654                    } else {
655                        self.writer.set_color(&self.colors.bad_color)?;
656                    }
657                    self.escape_name(file_name)?;
658                    self.writer.reset()?;
659                }
660                FileKind::Block => {
661                    self.writer.set_color(&self.colors.block_color)?;
662                    self.escape_name(file_name)?;
663                    self.writer.reset()?;
664                }
665                FileKind::Char => {
666                    self.writer.set_color(&self.colors.char_color)?;
667                    self.escape_name(file_name)?;
668                    self.writer.reset()?;
669                }
670                FileKind::Pipe => {
671                    self.writer.set_color(&self.colors.pipe_color)?;
672                    self.escape_name(file_name)?;
673                    self.writer.reset()?;
674                }
675                FileKind::Socket => {
676                    self.writer.set_color(&self.colors.socket_color)?;
677                    self.escape_name(file_name)?;
678                    self.writer.reset()?;
679                }
680                FileKind::Other => {
681                    self.escape_name(file_name)?;
682                }
683            }
684        }
685        Ok(())
686    }
687
688    #[cfg(windows)]
689    fn escape_name(
690        &mut self,
691        file_name: &str,
692    ) -> MyResult<()> {
693        if self.config.escape_path() && self.git_bash {
694            let escape_regex = regex!(r#"([\s"'])"#);
695            let file_name = escape_regex.replace_all(file_name, "\\$1");
696            write!(self.writer, "{file_name}")?;
697        } else {
698            write!(self.writer, "{file_name}")?;
699        }
700        Ok(())
701    }
702
703    #[cfg(not(windows))]
704    fn escape_name(
705        &mut self,
706        file_name: &str,
707    ) -> MyResult<()> {
708        if self.config.escape_path() {
709            let escape_regex = regex!(r#"([\s"'\\])"#);
710            let file_name = escape_regex.replace_all(file_name, "\\$1");
711            write!(self.writer, "{file_name}")?;
712        } else {
713            write!(self.writer, "{file_name}")?;
714        }
715        Ok(())
716    }
717
718    fn print_link(
719        &mut self,
720        link_data: &Option<(PathBuf, FileKind)>,
721    ) -> MyResult<()> {
722        if let Some((link_path, link_type)) = link_data {
723            if let Some(link_dir) = link_path.parent() {
724                if let Some(link_name) = link_path.file_name().and_then(OsStr::to_str) {
725                    write!(self.writer, " -> ")?;
726                    let link_ext = link_path.extension().and_then(OsStr::to_str).unwrap_or_default();
727                    self.print_dir(link_dir, None, 0, false)?;
728                    self.print_name(link_name, &link_ext, *link_type)?;
729                }
730            }
731        }
732        Ok(())
733    }
734
735    fn count_parents(&mut self, files: &Vec<File>) {
736        for file in files {
737            if file.file_depth > 1 {
738                if let Some(parent) = file.select_parent_for_indent() {
739                    let entry = self.counter.entry(parent).or_insert(0);
740                    *entry += 1;
741                }
742            }
743        }
744    }
745
746    fn print_prefix(&mut self, file: &File) -> MyResult<()> {
747        let tokens = self.create_prefix(file);
748        for token in tokens {
749            match token {
750                IndentToken::BranchMiddle => {
751                    write!(self.writer, " ")?;
752                    self.writer.set_color(&self.colors.dir_color)?;
753                    write!(self.writer, "{}", self.chars.branching)?;
754                    write!(self.writer, "{}", self.chars.horizontal)?;
755                    self.writer.reset()?;
756                    write!(self.writer, " ")?;
757                }
758                IndentToken::BranchFinal => {
759                    write!(self.writer, " ")?;
760                    self.writer.set_color(&self.colors.dir_color)?;
761                    write!(self.writer, "{}", self.chars.terminating)?;
762                    write!(self.writer, "{}", self.chars.horizontal)?;
763                    self.writer.reset()?;
764                    write!(self.writer, " ")?;
765                }
766                IndentToken::SpaceMiddle => {
767                    write!(self.writer, " ")?;
768                    self.writer.set_color(&self.colors.dir_color)?;
769                    write!(self.writer, "{}", self.chars.vertical)?;
770                    self.writer.reset()?;
771                    write!(self.writer, "  ")?;
772                }
773                IndentToken::SpaceFinal => {
774                    write!(self.writer, "    ")?;
775                }
776            }
777        }
778        Ok(())
779    }
780
781    fn create_prefix(&mut self, file: &File) -> Vec<IndentToken> {
782        let mut tokens = Vec::new();
783        if let Some(mut path) = file.select_parent_for_indent() {
784            if let Some(count) = self.counter.get_mut(&path) {
785                *count -= 1;
786                if *count > 0 {
787                    tokens.push(IndentToken::BranchMiddle);
788                } else {
789                    tokens.push(IndentToken::BranchFinal);
790                }
791            }
792            while let Some(parent) = path.parent() {
793                path = PathBuf::from(parent);
794                if let Some(count) = self.counter.get(&path) {
795                    if *count > 0 {
796                        tokens.push(IndentToken::SpaceMiddle);
797                    } else {
798                        tokens.push(IndentToken::SpaceFinal);
799                    }
800                }
801            }
802        }
803        tokens.reverse();
804        tokens
805    }
806
807    fn print_text(&mut self, text: &str, width: usize) -> MyResult<()> {
808        write!(self.writer, "{0:<1$}", text, width)?;
809        Ok(())
810    }
811
812    fn print_spaces(&mut self, width: usize) -> MyResult<()> {
813        write!(self.writer, "{0:<1$}", "", width)?;
814        Ok(())
815    }
816
817    fn print_hyphens(&mut self, width: usize) -> MyResult<()> {
818        writeln!(self.writer, "{0:-<1$}", "", width)?;
819        Ok(())
820    }
821
822    fn print_newline(&mut self) -> MyResult<()> {
823        if self.config.null_path() {
824            write!(self.writer, "\x00")?;
825        } else {
826            writeln!(self.writer)?;
827        }
828        Ok(())
829    }
830}
831
832fn measure_mode(config: &Config) -> usize {
833    if config.zip_expand() {
834        MODE_WIDTH + 1
835    } else {
836        MODE_WIDTH
837    }
838}
839
840fn measure_size(config: &Config, size: u64) -> usize {
841    if config.show_precise() {
842        recurse_size(size)
843    } else {
844        6
845    }
846}
847
848fn recurse_size(size: u64) -> usize {
849    if size >= 1000 {
850        recurse_size(size / 1000) + 4
851    } else {
852        3
853    }
854}
855
856fn measure_time(config: &Config) -> usize {
857    if config.show_precise() {
858        if config.show_utc() {
859            TIME_WIDTH + 1 // (with extra "Z")
860        } else {
861            TIME_WIDTH
862        }
863    } else {
864        MONTH_WIDTH
865    }
866}
867
868fn convert_weekday(weekday: Weekday) -> &'static str {
869    match weekday {
870        Weekday::Mon => "Mon",
871        Weekday::Tue => "Tue",
872        Weekday::Wed => "Wed",
873        Weekday::Thu => "Thu",
874        Weekday::Fri => "Fri",
875        Weekday::Sat => "Sat",
876        Weekday::Sun => "Sun",
877    }
878}
879
880fn convert_month(month: u32) -> &'static str {
881    match month {
882        1 => "Jan",
883        2 => "Feb",
884        3 => "Mar",
885        4 => "Apr",
886        5 => "May",
887        6 => "Jun",
888        7 => "Jul",
889        8 => "Aug",
890        9 => "Sep",
891        10 => "Oct",
892        11 => "Nov",
893        12 => "Dec",
894        _ => "???",
895    }
896}
897
898#[inline]
899fn printable_char(byte: u8) -> char {
900    if byte >= 32 && byte <= 126 { byte as char } else { '.' }
901}
902
903fn is_trivial(file_dir: &Path) -> bool {
904    let file_dir = file_dir.to_str().unwrap_or_default();
905    file_dir.is_empty() || file_dir == "."
906}
907
908fn is_joinable(component: &Component) -> bool {
909    match component {
910        Component::Prefix(_) => false,
911        Component::RootDir => false,
912        Component::CurDir => true,
913        Component::ParentDir => true,
914        Component::Normal(_) => true,
915    }
916}
917
918fn get_extension<'a>(component: &'a Component) -> &'a str {
919    let component = component.as_os_str();
920    let (_, ext) = rsplit_file_at_dot(component);
921    ext.and_then(OsStr::to_str).unwrap_or_default()
922}
923
924// Borrowed from standard library.
925fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
926    if file.as_encoded_bytes() == b".." {
927        (Some(file), None)
928    } else {
929        // The unsafety here stems from converting between &OsStr and &[u8]
930        // and back. This is safe to do because (1) we only look at ASCII
931        // contents of the encoding and (2) new &OsStr values are produced
932        // only from ASCII-bounded slices of existing &OsStr values.
933        let mut iter = file.as_encoded_bytes().rsplitn(2, |b| *b == b'.');
934        let after = iter.next();
935        let before = iter.next();
936        if before == Some(b"") {
937            (Some(file), None)
938        } else {
939            unsafe {
940                let before = before.map(|s| OsStr::from_encoded_bytes_unchecked(s));
941                let after = after.map(|s| OsStr::from_encoded_bytes_unchecked(s));
942                (before, after)
943            }
944        }
945    }
946}
947
948#[cfg(test)]
949mod tests {
950    use crate::cli::file::{ExecKind, FileKind};
951    use crate::cli::recent::{PeriodKind, RecentKind};
952    use crate::config::Config;
953    use crate::error::MyResult;
954    use crate::fs::file::File;
955    use crate::fs::total::Total;
956    use crate::git::flags::GitFlags;
957    use crate::printer::{measure_mode, measure_size, IndentChars, Printer};
958    use crate::util::color::ColorMap;
959    use crate::util::time::tests::{create_date, create_time};
960    use chrono::Utc;
961    use googletest::prelude::*;
962    use path_clean::PathClean;
963    use std::cmp::Ordering;
964    use std::io;
965    use std::io::Write;
966    use std::path::{Component, Path, PathBuf};
967    use termcolor::{Color, ColorSpec, WriteColor};
968
969    #[gtest]
970    fn test_measures_mode_no_expand() {
971        let config = Config::default()
972            .with_zip_expand(false);
973        expect_eq!(measure_mode(&config), 10);
974    }
975
976    #[gtest]
977    fn test_measures_mode_with_expand() {
978        let config = Config::default()
979            .with_zip_expand(true);
980        expect_eq!(measure_mode(&config), 11);
981    }
982
983    #[gtest]
984    fn test_prints_type_no_expand() {
985        expect_eq!(wrap_mode(false, None, 0o000, FileKind::File(ExecKind::None)), "----------");
986        expect_eq!(wrap_mode(false, None, 0o000, FileKind::File(ExecKind::User)), "----------");
987        expect_eq!(wrap_mode(false, None, 0o000, FileKind::File(ExecKind::Other)), "----------");
988        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Dir), "d---------");
989        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Link(false)), "l---------");
990        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Link(true)), "l---------");
991        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Block), "b---------");
992        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Char), "c---------");
993        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Pipe), "p---------");
994        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Socket), "s---------");
995        expect_eq!(wrap_mode(false, None, 0o000, FileKind::Other), "?---------");
996        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::File(ExecKind::None)), "----------");
997        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::File(ExecKind::User)), "----------");
998        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::File(ExecKind::Other)), "----------");
999        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Dir), "d---------");
1000        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Link(false)), "l---------");
1001        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Link(true)), "l---------");
1002        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Block), "b---------");
1003        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Char), "c---------");
1004        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Pipe), "p---------");
1005        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Socket), "s---------");
1006        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::Other), "?---------");
1007    }
1008
1009    #[gtest]
1010    fn test_prints_type_with_expand() {
1011        expect_eq!(wrap_mode(true, None, 0o000, FileKind::File(ExecKind::None)), "-----------");
1012        expect_eq!(wrap_mode(true, None, 0o000, FileKind::File(ExecKind::User)), "-----------");
1013        expect_eq!(wrap_mode(true, None, 0o000, FileKind::File(ExecKind::Other)), "-----------");
1014        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Dir), "-d---------");
1015        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Link(false)), "-l---------");
1016        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Link(true)), "-l---------");
1017        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Block), "-b---------");
1018        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Char), "-c---------");
1019        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Pipe), "-p---------");
1020        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Socket), "-s---------");
1021        expect_eq!(wrap_mode(true, None, 0o000, FileKind::Other), "-?---------");
1022        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::File(ExecKind::None)), "z----------");
1023        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::File(ExecKind::User)), "z----------");
1024        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::File(ExecKind::Other)), "z----------");
1025        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Dir), "zd---------");
1026        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Link(false)), "zl---------");
1027        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Link(true)), "zl---------");
1028        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Block), "zb---------");
1029        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Char), "zc---------");
1030        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Pipe), "zp---------");
1031        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Socket), "zs---------");
1032        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::Other), "z?---------");
1033    }
1034
1035    #[gtest]
1036    fn test_prints_mode_no_expand() {
1037        expect_eq!(wrap_mode(false, None, 0o000, FileKind::File(ExecKind::None)), "----------");
1038        expect_eq!(wrap_mode(false, None, 0o400, FileKind::File(ExecKind::None)), "-r--------");
1039        expect_eq!(wrap_mode(false, None, 0o200, FileKind::File(ExecKind::None)), "--w-------");
1040        expect_eq!(wrap_mode(false, None, 0o100, FileKind::File(ExecKind::None)), "---x------");
1041        expect_eq!(wrap_mode(false, None, 0o040, FileKind::File(ExecKind::None)), "----r-----");
1042        expect_eq!(wrap_mode(false, None, 0o020, FileKind::File(ExecKind::None)), "-----w----");
1043        expect_eq!(wrap_mode(false, None, 0o010, FileKind::File(ExecKind::None)), "------x---");
1044        expect_eq!(wrap_mode(false, None, 0o004, FileKind::File(ExecKind::None)), "-------r--");
1045        expect_eq!(wrap_mode(false, None, 0o002, FileKind::File(ExecKind::None)), "--------w-");
1046        expect_eq!(wrap_mode(false, None, 0o001, FileKind::File(ExecKind::None)), "---------x");
1047        expect_eq!(wrap_mode(false, None, 0o777, FileKind::File(ExecKind::None)), "-rwxrwxrwx");
1048        expect_eq!(wrap_mode(false, Some(0), 0o000, FileKind::File(ExecKind::None)), "----------");
1049        expect_eq!(wrap_mode(false, Some(0), 0o400, FileKind::File(ExecKind::None)), "-r--------");
1050        expect_eq!(wrap_mode(false, Some(0), 0o200, FileKind::File(ExecKind::None)), "--w-------");
1051        expect_eq!(wrap_mode(false, Some(0), 0o100, FileKind::File(ExecKind::None)), "---x------");
1052        expect_eq!(wrap_mode(false, Some(0), 0o040, FileKind::File(ExecKind::None)), "----r-----");
1053        expect_eq!(wrap_mode(false, Some(0), 0o020, FileKind::File(ExecKind::None)), "-----w----");
1054        expect_eq!(wrap_mode(false, Some(0), 0o010, FileKind::File(ExecKind::None)), "------x---");
1055        expect_eq!(wrap_mode(false, Some(0), 0o004, FileKind::File(ExecKind::None)), "-------r--");
1056        expect_eq!(wrap_mode(false, Some(0), 0o002, FileKind::File(ExecKind::None)), "--------w-");
1057        expect_eq!(wrap_mode(false, Some(0), 0o001, FileKind::File(ExecKind::None)), "---------x");
1058        expect_eq!(wrap_mode(false, Some(0), 0o777, FileKind::File(ExecKind::None)), "-rwxrwxrwx");
1059    }
1060
1061    #[gtest]
1062    fn test_prints_mode_with_expand() {
1063        expect_eq!(wrap_mode(true, None, 0o000, FileKind::File(ExecKind::None)), "-----------");
1064        expect_eq!(wrap_mode(true, None, 0o400, FileKind::File(ExecKind::None)), "--r--------");
1065        expect_eq!(wrap_mode(true, None, 0o200, FileKind::File(ExecKind::None)), "---w-------");
1066        expect_eq!(wrap_mode(true, None, 0o100, FileKind::File(ExecKind::None)), "----x------");
1067        expect_eq!(wrap_mode(true, None, 0o040, FileKind::File(ExecKind::None)), "-----r-----");
1068        expect_eq!(wrap_mode(true, None, 0o020, FileKind::File(ExecKind::None)), "------w----");
1069        expect_eq!(wrap_mode(true, None, 0o010, FileKind::File(ExecKind::None)), "-------x---");
1070        expect_eq!(wrap_mode(true, None, 0o004, FileKind::File(ExecKind::None)), "--------r--");
1071        expect_eq!(wrap_mode(true, None, 0o002, FileKind::File(ExecKind::None)), "---------w-");
1072        expect_eq!(wrap_mode(true, None, 0o001, FileKind::File(ExecKind::None)), "----------x");
1073        expect_eq!(wrap_mode(true, None, 0o777, FileKind::File(ExecKind::None)), "--rwxrwxrwx");
1074        expect_eq!(wrap_mode(true, Some(0), 0o000, FileKind::File(ExecKind::None)), "z----------");
1075        expect_eq!(wrap_mode(true, Some(0), 0o400, FileKind::File(ExecKind::None)), "z-r--------");
1076        expect_eq!(wrap_mode(true, Some(0), 0o200, FileKind::File(ExecKind::None)), "z--w-------");
1077        expect_eq!(wrap_mode(true, Some(0), 0o100, FileKind::File(ExecKind::None)), "z---x------");
1078        expect_eq!(wrap_mode(true, Some(0), 0o040, FileKind::File(ExecKind::None)), "z----r-----");
1079        expect_eq!(wrap_mode(true, Some(0), 0o020, FileKind::File(ExecKind::None)), "z-----w----");
1080        expect_eq!(wrap_mode(true, Some(0), 0o010, FileKind::File(ExecKind::None)), "z------x---");
1081        expect_eq!(wrap_mode(true, Some(0), 0o004, FileKind::File(ExecKind::None)), "z-------r--");
1082        expect_eq!(wrap_mode(true, Some(0), 0o002, FileKind::File(ExecKind::None)), "z--------w-");
1083        expect_eq!(wrap_mode(true, Some(0), 0o001, FileKind::File(ExecKind::None)), "z---------x");
1084        expect_eq!(wrap_mode(true, Some(0), 0o777, FileKind::File(ExecKind::None)), "z-rwxrwxrwx");
1085    }
1086
1087    #[gtest]
1088    fn test_measures_size_for_integer() {
1089        let config = Config::default()
1090            .with_show_precise(true);
1091        expect_eq!(measure_size(&config, 0), 3);
1092        expect_eq!(measure_size(&config, 999), 3);
1093        expect_eq!(measure_size(&config, 1_000), 7);
1094        expect_eq!(measure_size(&config, 999_999), 7);
1095        expect_eq!(measure_size(&config, 1_000_000), 11);
1096        expect_eq!(measure_size(&config, 999_999_999), 11);
1097    }
1098
1099    #[gtest]
1100    fn test_measures_size_for_si_units() {
1101        let config = Config::default()
1102            .with_show_precise(false);
1103        expect_eq!(measure_size(&config, 0), 6);
1104        expect_eq!(measure_size(&config, 999), 6);
1105        expect_eq!(measure_size(&config, 1_000), 6);
1106        expect_eq!(measure_size(&config, 999_999), 6);
1107        expect_eq!(measure_size(&config, 1_000_000), 6);
1108        expect_eq!(measure_size(&config, 999_999_999), 6);
1109    }
1110
1111    #[gtest]
1112    fn test_prints_unpadded_size_as_integer() {
1113        let config = Config::default()
1114            .with_show_precise(true);
1115        expect_eq!(wrap_size(&config, 0, 0), "  0");
1116        expect_eq!(wrap_size(&config, 9, 0), "  9");
1117        expect_eq!(wrap_size(&config, 10, 0), "  10");
1118        expect_eq!(wrap_size(&config, 99, 0), "  99");
1119        expect_eq!(wrap_size(&config, 100, 0), "  100");
1120        expect_eq!(wrap_size(&config, 999, 0), "  999");
1121        expect_eq!(wrap_size(&config, 1_000, 0), "  1,000");
1122        expect_eq!(wrap_size(&config, 9_999, 0), "  9,999");
1123        expect_eq!(wrap_size(&config, 10_000, 0), "  10,000");
1124        expect_eq!(wrap_size(&config, 99_999, 0), "  99,999");
1125        expect_eq!(wrap_size(&config, 100_000, 0), "  100,000");
1126        expect_eq!(wrap_size(&config, 999_999, 0), "  999,999");
1127        expect_eq!(wrap_size(&config, 1_000_000, 0), "  1,000,000");
1128        expect_eq!(wrap_size(&config, 9_999_999, 0), "  9,999,999");
1129        expect_eq!(wrap_size(&config, 10_000_000, 0), "  10,000,000");
1130        expect_eq!(wrap_size(&config, 99_999_999, 0), "  99,999,999");
1131        expect_eq!(wrap_size(&config, 100_000_000, 0), "  100,000,000");
1132        expect_eq!(wrap_size(&config, 999_999_999, 0), "  999,999,999");
1133        expect_eq!(wrap_size(&config, 1_000_000_000, 0), "  1,000,000,000");
1134        expect_eq!(wrap_size(&config, 9_999_999_999, 0), "  9,999,999,999");
1135        expect_eq!(wrap_size(&config, 10_000_000_000, 0), "  10,000,000,000");
1136        expect_eq!(wrap_size(&config, 99_999_999_999, 0), "  99,999,999,999");
1137        expect_eq!(wrap_size(&config, 100_000_000_000, 0), "  100,000,000,000");
1138        expect_eq!(wrap_size(&config, 999_999_999_999, 0), "  999,999,999,999");
1139        expect_eq!(wrap_size(&config, 1_000_000_000_000, 0), "  1,000,000,000,000");
1140        expect_eq!(wrap_size(&config, 9_999_999_999_999, 0), "  9,999,999,999,999");
1141        expect_eq!(wrap_size(&config, 10_000_000_000_000, 0), "  10,000,000,000,000");
1142        expect_eq!(wrap_size(&config, 99_999_999_999_999, 0), "  99,999,999,999,999");
1143        expect_eq!(wrap_size(&config, 100_000_000_000_000, 0), "  100,000,000,000,000");
1144        expect_eq!(wrap_size(&config, 999_999_999_999_999, 0), "  999,999,999,999,999");
1145        expect_eq!(wrap_size(&config, 1_000_000_000_000_000, 0), "  1,000,000,000,000,000");
1146        expect_eq!(wrap_size(&config, 9_999_999_999_999_999, 0), "  9,999,999,999,999,999");
1147        expect_eq!(wrap_size(&config, 10_000_000_000_000_000, 0), "  10,000,000,000,000,000");
1148        expect_eq!(wrap_size(&config, 99_999_999_999_999_999, 0), "  99,999,999,999,999,999");
1149        expect_eq!(wrap_size(&config, 100_000_000_000_000_000, 0), "  100,000,000,000,000,000");
1150        expect_eq!(wrap_size(&config, 999_999_999_999_999_999, 0), "  999,999,999,999,999,999");
1151        expect_eq!(wrap_size(&config, 1_000_000_000_000_000_000, 0), "  1,000,000,000,000,000,000");
1152        expect_eq!(wrap_size(&config, 9_999_999_999_999_999_999, 0), "  9,999,999,999,999,999,999");
1153        expect_eq!(wrap_size(&config, 10_000_000_000_000_000_000, 0), "  10,000,000,000,000,000,000");
1154    }
1155
1156    #[gtest]
1157    fn test_prints_padded_size_as_integer() {
1158        let config = Config::default()
1159            .with_show_precise(true);
1160        expect_eq!(wrap_size(&config, 0, 26), "                           0");
1161        expect_eq!(wrap_size(&config, 9, 26), "                           9");
1162        expect_eq!(wrap_size(&config, 10, 26), "                          10");
1163        expect_eq!(wrap_size(&config, 99, 26), "                          99");
1164        expect_eq!(wrap_size(&config, 100, 26), "                         100");
1165        expect_eq!(wrap_size(&config, 999, 26), "                         999");
1166        expect_eq!(wrap_size(&config, 1_000, 26), "                       1,000");
1167        expect_eq!(wrap_size(&config, 9_999, 26), "                       9,999");
1168        expect_eq!(wrap_size(&config, 10_000, 26), "                      10,000");
1169        expect_eq!(wrap_size(&config, 99_999, 26), "                      99,999");
1170        expect_eq!(wrap_size(&config, 100_000, 26), "                     100,000");
1171        expect_eq!(wrap_size(&config, 999_999, 26), "                     999,999");
1172        expect_eq!(wrap_size(&config, 1_000_000, 26), "                   1,000,000");
1173        expect_eq!(wrap_size(&config, 9_999_999, 26), "                   9,999,999");
1174        expect_eq!(wrap_size(&config, 10_000_000, 26), "                  10,000,000");
1175        expect_eq!(wrap_size(&config, 99_999_999, 26), "                  99,999,999");
1176        expect_eq!(wrap_size(&config, 100_000_000, 26), "                 100,000,000");
1177        expect_eq!(wrap_size(&config, 999_999_999, 26), "                 999,999,999");
1178        expect_eq!(wrap_size(&config, 1_000_000_000, 26), "               1,000,000,000");
1179        expect_eq!(wrap_size(&config, 9_999_999_999, 26), "               9,999,999,999");
1180        expect_eq!(wrap_size(&config, 10_000_000_000, 26), "              10,000,000,000");
1181        expect_eq!(wrap_size(&config, 99_999_999_999, 26), "              99,999,999,999");
1182        expect_eq!(wrap_size(&config, 100_000_000_000, 26), "             100,000,000,000");
1183        expect_eq!(wrap_size(&config, 999_999_999_999, 26), "             999,999,999,999");
1184        expect_eq!(wrap_size(&config, 1_000_000_000_000, 26), "           1,000,000,000,000");
1185        expect_eq!(wrap_size(&config, 9_999_999_999_999, 26), "           9,999,999,999,999");
1186        expect_eq!(wrap_size(&config, 10_000_000_000_000, 26), "          10,000,000,000,000");
1187        expect_eq!(wrap_size(&config, 99_999_999_999_999, 26), "          99,999,999,999,999");
1188        expect_eq!(wrap_size(&config, 100_000_000_000_000, 26), "         100,000,000,000,000");
1189        expect_eq!(wrap_size(&config, 999_999_999_999_999, 26), "         999,999,999,999,999");
1190        expect_eq!(wrap_size(&config, 1_000_000_000_000_000, 26), "       1,000,000,000,000,000");
1191        expect_eq!(wrap_size(&config, 9_999_999_999_999_999, 26), "       9,999,999,999,999,999");
1192        expect_eq!(wrap_size(&config, 10_000_000_000_000_000, 26), "      10,000,000,000,000,000");
1193        expect_eq!(wrap_size(&config, 99_999_999_999_999_999, 26), "      99,999,999,999,999,999");
1194        expect_eq!(wrap_size(&config, 100_000_000_000_000_000, 26), "     100,000,000,000,000,000");
1195        expect_eq!(wrap_size(&config, 999_999_999_999_999_999, 26), "     999,999,999,999,999,999");
1196        expect_eq!(wrap_size(&config, 1_000_000_000_000_000_000, 26), "   1,000,000,000,000,000,000");
1197        expect_eq!(wrap_size(&config, 9_999_999_999_999_999_999, 26), "   9,999,999,999,999,999,999");
1198        expect_eq!(wrap_size(&config, 10_000_000_000_000_000_000, 26), "  10,000,000,000,000,000,000");
1199    }
1200
1201    #[gtest]
1202    fn test_prints_unpadded_size_in_si_units() {
1203        let config = Config::default()
1204            .with_show_precise(false);
1205        expect_eq!(wrap_size(&config, 0, 0), "    0 B ");
1206        expect_eq!(wrap_size(&config, 9, 0), "    9 B ");
1207        expect_eq!(wrap_size(&config, 10, 0), "   10 B ");
1208        expect_eq!(wrap_size(&config, 99, 0), "   99 B ");
1209        expect_eq!(wrap_size(&config, 100, 0), "  100 B ");
1210        expect_eq!(wrap_size(&config, 999, 0), "  999 B ");
1211        expect_eq!(wrap_size(&config, 1_000, 0), "    1 KB");
1212        expect_eq!(wrap_size(&config, 9_999, 0), "    9 KB");
1213        expect_eq!(wrap_size(&config, 10_000, 0), "   10 KB");
1214        expect_eq!(wrap_size(&config, 99_999, 0), "   99 KB");
1215        expect_eq!(wrap_size(&config, 100_000, 0), "  100 KB");
1216        expect_eq!(wrap_size(&config, 999_999, 0), "  999 KB");
1217        expect_eq!(wrap_size(&config, 1_000_000, 0), "    1 MB");
1218        expect_eq!(wrap_size(&config, 9_999_999, 0), "    9 MB");
1219        expect_eq!(wrap_size(&config, 10_000_000, 0), "   10 MB");
1220        expect_eq!(wrap_size(&config, 99_999_999, 0), "   99 MB");
1221        expect_eq!(wrap_size(&config, 100_000_000, 0), "  100 MB");
1222        expect_eq!(wrap_size(&config, 999_999_999, 0), "  999 MB");
1223        expect_eq!(wrap_size(&config, 1_000_000_000, 0), "    1 GB");
1224        expect_eq!(wrap_size(&config, 9_999_999_999, 0), "    9 GB");
1225        expect_eq!(wrap_size(&config, 10_000_000_000, 0), "   10 GB");
1226        expect_eq!(wrap_size(&config, 99_999_999_999, 0), "   99 GB");
1227        expect_eq!(wrap_size(&config, 100_000_000_000, 0), "  100 GB");
1228        expect_eq!(wrap_size(&config, 999_999_999_999, 0), "  999 GB");
1229        expect_eq!(wrap_size(&config, 1_000_000_000_000, 0), "    1 TB");
1230        expect_eq!(wrap_size(&config, 9_999_999_999_999, 0), "    9 TB");
1231        expect_eq!(wrap_size(&config, 10_000_000_000_000, 0), "   10 TB");
1232        expect_eq!(wrap_size(&config, 99_999_999_999_999, 0), "   99 TB");
1233        expect_eq!(wrap_size(&config, 100_000_000_000_000, 0), "  100 TB");
1234        expect_eq!(wrap_size(&config, 999_999_999_999_999, 0), "  999 TB");
1235        expect_eq!(wrap_size(&config, 1_000_000_000_000_000, 0), "    1 PB");
1236        expect_eq!(wrap_size(&config, 9_999_999_999_999_999, 0), "    9 PB");
1237        expect_eq!(wrap_size(&config, 10_000_000_000_000_000, 0), "   10 PB");
1238        expect_eq!(wrap_size(&config, 99_999_999_999_999_999, 0), "   99 PB");
1239        expect_eq!(wrap_size(&config, 100_000_000_000_000_000, 0), "  100 PB");
1240        expect_eq!(wrap_size(&config, 999_999_999_999_999_999, 0), "  999 PB");
1241        expect_eq!(wrap_size(&config, 1_000_000_000_000_000_000, 0), "    1 EB");
1242        expect_eq!(wrap_size(&config, 9_999_999_999_999_999_999, 0), "    9 EB");
1243        expect_eq!(wrap_size(&config, 10_000_000_000_000_000_000, 0), "   10 EB");
1244    }
1245
1246    #[gtest]
1247    fn test_prints_time_as_local_timestamp() {
1248        let config = Config::default()
1249            .with_curr_time(2024, 10, 10, 10, 10, 30)
1250            .with_show_precise(true)
1251            .with_show_utc(false);
1252        expect_eq!(wrap_time(&config, 2024, 1, 31, 0, 0, 0), "  Wed 31-Jan-2024 00:00:00");
1253        expect_eq!(wrap_time(&config, 2024, 2, 29, 2, 5, 15), "  Thu 29-Feb-2024 02:05:15");
1254        expect_eq!(wrap_time(&config, 2024, 3, 31, 4, 10, 30), "  Sun 31-Mar-2024 04:10:30");
1255        expect_eq!(wrap_time(&config, 2024, 4, 30, 6, 15, 45), "  Tue 30-Apr-2024 06:15:45");
1256        expect_eq!(wrap_time(&config, 2024, 5, 31, 8, 20, 0), "  Fri 31-May-2024 08:20:00");
1257        expect_eq!(wrap_time(&config, 2024, 6, 30, 10, 25, 15), "  Sun 30-Jun-2024 10:25:15");
1258        expect_eq!(wrap_time(&config, 2024, 7, 31, 12, 30, 30), "  Wed 31-Jul-2024 12:30:30");
1259        expect_eq!(wrap_time(&config, 2024, 8, 31, 14, 35, 45), "  Sat 31-Aug-2024 14:35:45");
1260        expect_eq!(wrap_time(&config, 2024, 9, 30, 16, 40, 0), "  Mon 30-Sep-2024 16:40:00");
1261        expect_eq!(wrap_time(&config, 2024, 10, 31, 18, 45, 15), "  Thu 31-Oct-2024 18:45:15");
1262        expect_eq!(wrap_time(&config, 2024, 11, 30, 20, 50, 30), "  Sat 30-Nov-2024 20:50:30");
1263        expect_eq!(wrap_time(&config, 2024, 12, 31, 22, 55, 45), "  Tue 31-Dec-2024 22:55:45");
1264        expect_eq!(wrap_time(&config, 1970, 1, 1, 0, 0, 0), "  ------------------------");
1265    }
1266
1267    #[gtest]
1268    fn test_prints_time_as_utc_timestamp() {
1269        let config = Config::default()
1270            .with_curr_time(2024, 10, 10, 10, 10, 30)
1271            .with_show_precise(true)
1272            .with_show_utc(true);
1273        expect_eq!(wrap_time(&config, 2024, 1, 31, 0, 0, 0), "  Wed 31-Jan-2024 00:00:00Z");
1274        expect_eq!(wrap_time(&config, 2024, 2, 29, 2, 5, 15), "  Thu 29-Feb-2024 02:05:15Z");
1275        expect_eq!(wrap_time(&config, 2024, 3, 31, 4, 10, 30), "  Sun 31-Mar-2024 04:10:30Z");
1276        expect_eq!(wrap_time(&config, 2024, 4, 30, 6, 15, 45), "  Tue 30-Apr-2024 06:15:45Z");
1277        expect_eq!(wrap_time(&config, 2024, 5, 31, 8, 20, 0), "  Fri 31-May-2024 08:20:00Z");
1278        expect_eq!(wrap_time(&config, 2024, 6, 30, 10, 25, 15), "  Sun 30-Jun-2024 10:25:15Z");
1279        expect_eq!(wrap_time(&config, 2024, 7, 31, 12, 30, 30), "  Wed 31-Jul-2024 12:30:30Z");
1280        expect_eq!(wrap_time(&config, 2024, 8, 31, 14, 35, 45), "  Sat 31-Aug-2024 14:35:45Z");
1281        expect_eq!(wrap_time(&config, 2024, 9, 30, 16, 40, 0), "  Mon 30-Sep-2024 16:40:00Z");
1282        expect_eq!(wrap_time(&config, 2024, 10, 31, 18, 45, 15), "  Thu 31-Oct-2024 18:45:15Z");
1283        expect_eq!(wrap_time(&config, 2024, 11, 30, 20, 50, 30), "  Sat 30-Nov-2024 20:50:30Z");
1284        expect_eq!(wrap_time(&config, 2024, 12, 31, 22, 55, 45), "  Tue 31-Dec-2024 22:55:45Z");
1285        expect_eq!(wrap_time(&config, 1970, 1, 1, 0, 0, 0), "  -------------------------");
1286    }
1287
1288    #[gtest]
1289    fn test_prints_time_as_duration() {
1290        let config = Config::default()
1291            .with_curr_time(2024, 10, 10, 10, 10, 30)
1292            .with_show_precise(false);
1293        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 10, 31), "   future ");
1294        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 10, 30), "   0 sec  ");
1295        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 10, 29), "   1 sec  ");
1296        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 9, 31), "  59 sec  ");
1297        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 9, 30), "   1 min  ");
1298        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 9, 29), "   1 min  ");
1299        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 8, 31), "   1 min  ");
1300        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 8, 30), "   2 min  ");
1301        expect_eq!(wrap_time(&config, 2024, 10, 10, 10, 8, 29), "   2 min  ");
1302        expect_eq!(wrap_time(&config, 2024, 10, 10, 9, 11, 31), "  58 min  ");
1303        expect_eq!(wrap_time(&config, 2024, 10, 10, 9, 11, 30), "  59 min  ");
1304        expect_eq!(wrap_time(&config, 2024, 10, 10, 9, 11, 29), "  59 min  ");
1305        expect_eq!(wrap_time(&config, 2024, 10, 10, 9, 10, 31), "  59 min  ");
1306        expect_eq!(wrap_time(&config, 2024, 10, 10, 9, 10, 30), "   1 hour ");
1307        expect_eq!(wrap_time(&config, 2024, 10, 10, 9, 10, 29), "   1 hour ");
1308        expect_eq!(wrap_time(&config, 2024, 10, 10, 8, 10, 31), "   1 hour ");
1309        expect_eq!(wrap_time(&config, 2024, 10, 10, 8, 10, 30), "   2 hour ");
1310        expect_eq!(wrap_time(&config, 2024, 10, 10, 8, 10, 29), "   2 hour ");
1311        expect_eq!(wrap_time(&config, 2024, 10, 9, 11, 10, 31), "  22 hour ");
1312        expect_eq!(wrap_time(&config, 2024, 10, 9, 11, 10, 30), "  23 hour ");
1313        expect_eq!(wrap_time(&config, 2024, 10, 9, 11, 10, 29), "  23 hour ");
1314        expect_eq!(wrap_time(&config, 2024, 10, 9, 10, 10, 31), "  23 hour ");
1315        expect_eq!(wrap_time(&config, 2024, 10, 9, 10, 10, 30), "   1 day  ");
1316        expect_eq!(wrap_time(&config, 2024, 10, 9, 10, 10, 29), "   1 day  ");
1317        expect_eq!(wrap_time(&config, 2024, 10, 8, 10, 10, 31), "   1 day  ");
1318        expect_eq!(wrap_time(&config, 2024, 10, 8, 10, 10, 30), "   2 day  ");
1319        expect_eq!(wrap_time(&config, 2024, 10, 8, 10, 10, 29), "   2 day  ");
1320        expect_eq!(wrap_time(&config, 2024, 9, 11, 10, 10, 31), "  28 day  ");
1321        expect_eq!(wrap_time(&config, 2024, 9, 11, 10, 10, 30), "  29 day  ");
1322        expect_eq!(wrap_time(&config, 2024, 9, 11, 10, 10, 29), "  29 day  ");
1323        expect_eq!(wrap_time(&config, 2024, 9, 10, 10, 10, 31), "  29 day  ");
1324        expect_eq!(wrap_time(&config, 2024, 9, 10, 10, 10, 30), "   1 month");
1325        expect_eq!(wrap_time(&config, 2024, 9, 10, 10, 10, 29), "   1 month");
1326        expect_eq!(wrap_time(&config, 2024, 8, 10, 10, 10, 31), "   1 month");
1327        expect_eq!(wrap_time(&config, 2024, 8, 10, 10, 10, 30), "   2 month");
1328        expect_eq!(wrap_time(&config, 2024, 8, 10, 10, 10, 29), "   2 month");
1329        expect_eq!(wrap_time(&config, 2023, 11, 10, 10, 10, 31), "  10 month");
1330        expect_eq!(wrap_time(&config, 2023, 11, 10, 10, 10, 30), "  11 month");
1331        expect_eq!(wrap_time(&config, 2023, 11, 10, 10, 10, 29), "  11 month");
1332        expect_eq!(wrap_time(&config, 2023, 10, 10, 10, 10, 31), "  11 month");
1333        expect_eq!(wrap_time(&config, 2023, 10, 10, 10, 10, 30), "   1 year ");
1334        expect_eq!(wrap_time(&config, 2023, 10, 10, 10, 10, 29), "   1 year ");
1335        expect_eq!(wrap_time(&config, 2022, 10, 10, 10, 10, 31), "   1 year ");
1336        expect_eq!(wrap_time(&config, 2022, 10, 10, 10, 10, 30), "   2 year ");
1337        expect_eq!(wrap_time(&config, 2022, 10, 10, 10, 10, 29), "   2 year ");
1338        expect_eq!(wrap_time(&config, 1970, 1, 1, 0, 0, 0), "  --------");
1339    }
1340
1341    #[gtest]
1342    #[cfg(windows)]
1343    fn test_prints_unpadded_version() {
1344        expect_eq!(wrap_version(None, 0), "");
1345        expect_eq!(wrap_version(Some(""), 0), "");
1346        expect_eq!(wrap_version(Some("9.9.9.9"), 0), "");
1347        expect_eq!(wrap_version(Some("999.999.999.999"), 0), "");
1348    }
1349
1350    #[gtest]
1351    #[cfg(windows)]
1352    fn test_prints_padded_version() {
1353        expect_eq!(wrap_version(None, 10), "            ");
1354        expect_eq!(wrap_version(Some(""), 10), "            ");
1355        expect_eq!(wrap_version(Some("9.9.9.9"), 10), "  9.9.9.9   ");
1356        expect_eq!(wrap_version(Some("999.999.999.999"), 10), "  999.999.999.999");
1357    }
1358
1359    #[gtest]
1360    fn test_prints_unpadded_ext() {
1361        expect_eq!(wrap_ext("", 0), "");
1362        expect_eq!(wrap_ext(".txt", 0), "");
1363        expect_eq!(wrap_ext(".extension", 0), "");
1364    }
1365
1366    #[gtest]
1367    fn test_prints_padded_ext() {
1368        expect_eq!(wrap_ext("", 6), "        ");
1369        expect_eq!(wrap_ext(".txt", 6), "  .txt  ");
1370        expect_eq!(wrap_ext(".extension", 6), "  .extension");
1371    }
1372
1373    #[gtest]
1374    fn test_prints_total() {
1375        expect_eq!(wrap_total(0, 0), "0 files 0 directories");
1376        expect_eq!(wrap_total(1, 0), "1 file 0 directories");
1377        expect_eq!(wrap_total(2, 0), "2 files 0 directories");
1378        expect_eq!(wrap_total(0, 1), "0 files 1 directory");
1379        expect_eq!(wrap_total(0, 2), "0 files 2 directories");
1380    }
1381
1382    #[gtest]
1383    #[cfg(windows)]
1384    fn test_prints_relative_paths_on_windows() {
1385        let expected = "\
1386drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[Reset]
1387-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
1388drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\[Reset]
1389drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\colours\\[Reset]
1390-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1391-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
1392-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
1393-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
1394drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset]
1395lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1396lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1397lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1398drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\one two\\[Reset]
1399-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1400";
1401        let files = create_files("D:", "/root", "");
1402        let config = Config::default()
1403            .with_show_precise(true)
1404            .with_abs_path(false);
1405        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1406    }
1407
1408    #[gtest]
1409    #[cfg(windows)]
1410    fn test_prints_relative_paths_on_git_bash() {
1411        let expected = "\
1412drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1413-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1414drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
1415drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
1416-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1417-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1418-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1419-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1420drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
1421lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1422lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1423lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1424drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
1425-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1426";
1427        let files = create_files("D:", "/root", "");
1428        let config = Config::default()
1429            .with_show_precise(true)
1430            .with_abs_path(false);
1431        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1432    }
1433
1434    #[gtest]
1435    #[cfg(not(windows))]
1436    fn test_prints_relative_paths_on_linux() {
1437        let expected = "\
1438drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1439-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1440drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
1441drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
1442-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1443-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1444-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1445-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1446drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
1447lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1448lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1449lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1450drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
1451-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1452";
1453        let files = create_files("", "/root", "");
1454        let config = Config::default()
1455            .with_show_precise(true)
1456            .with_abs_path(false);
1457        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1458    }
1459
1460    #[gtest]
1461    #[cfg(windows)]
1462    fn test_prints_absolute_paths_on_windows() {
1463        let expected = "\
1464drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\[Reset]
1465-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]D:\\root\\example\\[Reset][DkGreen]find.sh[Reset]
1466drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\files\\[Reset]
1467drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\files\\colours\\[Reset]
1468-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]D:\\root\\example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1469-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\files\\colours\\[Reset]blue.txt
1470-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\files\\colours\\[Reset]green.txt
1471-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\files\\colours\\[Reset]red.txt
1472drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\files\\numbers\\[Reset]
1473lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1474lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1475lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1476drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\files\\numbers\\one two\\[Reset]
1477-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1478";
1479        let files = create_files("D:", "/root", "");
1480        let config = Config::default()
1481            .with_show_precise(true)
1482            .with_abs_path(true);
1483        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1484    }
1485
1486    #[gtest]
1487    #[cfg(windows)]
1488    fn test_prints_absolute_paths_on_git_bash() {
1489        let expected = "\
1490drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/[Reset]
1491-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]/d/root/example/[Reset][DkGreen]find.sh[Reset]
1492drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/files/[Reset]
1493drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/files/colours/[Reset]
1494-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]/d/root/example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1495-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]/d/root/example/files/colours/[Reset]blue.txt
1496-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]/d/root/example/files/colours/[Reset]green.txt
1497-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]/d/root/example/files/colours/[Reset]red.txt
1498drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/files/numbers/[Reset]
1499lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1500lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1501lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1502drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/files/numbers/one two/[Reset]
1503-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]/d/root/example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1504";
1505        let files = create_files("D:", "/root", "");
1506        let config = Config::default()
1507            .with_show_precise(true)
1508            .with_abs_path(true);
1509        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1510    }
1511
1512    #[gtest]
1513    #[cfg(not(windows))]
1514    fn test_prints_absolute_paths_on_linux() {
1515        let expected = "\
1516drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/[Reset]
1517-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]/root/example/[Reset][DkGreen]find.sh[Reset]
1518drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/files/[Reset]
1519drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/files/colours/[Reset]
1520-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]/root/example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1521-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]/root/example/files/colours/[Reset]blue.txt
1522-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]/root/example/files/colours/[Reset]green.txt
1523-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]/root/example/files/colours/[Reset]red.txt
1524drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/files/numbers/[Reset]
1525lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]/root/example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1526lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]/root/example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1527lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]/root/example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1528drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/files/numbers/one two/[Reset]
1529-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]/root/example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1530";
1531        let files = create_files("", "/root", "");
1532        let config = Config::default()
1533            .with_show_precise(true)
1534            .with_abs_path(true);
1535        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1536    }
1537
1538    #[gtest]
1539    #[cfg(windows)]
1540    fn test_prints_relative_paths_with_zip_on_windows() {
1541        let expected = "\
1542-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[Reset]
1543--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
1544zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[LtRed]files.zip[LtBlue]\\[Reset]
1545zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]
1546z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1547z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]blue.txt
1548z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]green.txt
1549z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]red.txt
1550zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset]
1551zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1552zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1553zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1554zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\one two\\[Reset]
1555z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1556";
1557        let files = create_files("D:", "/root", "");
1558        let files = modify_files_for_zip(files);
1559        let config = Config::default()
1560            .with_zip_expand(true)
1561            .with_show_precise(true)
1562            .with_abs_path(false);
1563        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1564    }
1565
1566    #[gtest]
1567    #[cfg(windows)]
1568    fn test_prints_relative_paths_with_zip_on_git_bash() {
1569        let expected = "\
1570-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1571--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1572zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/[Reset]
1573zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]
1574z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset][LtGreen]alpha.sh[Reset]
1575z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]blue.txt
1576z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]green.txt
1577z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]red.txt
1578zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset]
1579zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1580zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1581zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1582zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]
1583z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]\"three\" 'four'.txt
1584";
1585        let files = create_files("D:", "/root", "");
1586        let files = modify_files_for_zip(files);
1587        let config = Config::default()
1588            .with_zip_expand(true)
1589            .with_show_precise(true)
1590            .with_abs_path(false);
1591        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1592    }
1593
1594    #[gtest]
1595    #[cfg(not(windows))]
1596    fn test_prints_relative_paths_with_zip_on_linux() {
1597        let expected = "\
1598-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1599--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1600zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/[Reset]
1601zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]
1602z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset][LtGreen]alpha.sh[Reset]
1603z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]blue.txt
1604z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]green.txt
1605z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/colours/[Reset]red.txt
1606zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset]
1607zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1608zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1609zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1610zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]
1611z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]\"three\" 'four'.txt
1612";
1613        let files = create_files("", "/root", "");
1614        let files = modify_files_for_zip(files);
1615        let config = Config::default()
1616            .with_zip_expand(true)
1617            .with_show_precise(true)
1618            .with_abs_path(false);
1619        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1620    }
1621
1622    #[gtest]
1623    #[cfg(windows)]
1624    fn test_prints_absolute_paths_with_zip_on_windows() {
1625        let expected = "\
1626-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\[Reset]
1627--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]D:\\root\\example\\[Reset][DkGreen]find.sh[Reset]
1628zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\[Reset]
1629zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]
1630z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1631z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]blue.txt
1632z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]green.txt
1633z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours\\[Reset]red.txt
1634zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset]
1635zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1636zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1637zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1638zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\one two\\[Reset]
1639z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1640";
1641        let files = create_files("D:", "/root", "");
1642        let files = modify_files_for_zip(files);
1643        let config = Config::default()
1644            .with_zip_expand(true)
1645            .with_show_precise(true)
1646            .with_abs_path(true);
1647        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1648    }
1649
1650    #[gtest]
1651    #[cfg(windows)]
1652    fn test_prints_absolute_paths_with_zip_on_git_bash() {
1653        let expected = "\
1654-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/[Reset]
1655--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]/d/root/example/[Reset][DkGreen]find.sh[Reset]
1656zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/[Reset]
1657zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]
1658z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset][LtGreen]alpha.sh[Reset]
1659z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]blue.txt
1660z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]green.txt
1661z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]red.txt
1662zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset]
1663zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1664zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1665zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1666zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]
1667z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]\"three\" 'four'.txt
1668";
1669        let files = create_files("D:", "/root", "");
1670        let files = modify_files_for_zip(files);
1671        let config = Config::default()
1672            .with_zip_expand(true)
1673            .with_show_precise(true)
1674            .with_abs_path(true);
1675        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1676    }
1677
1678    #[gtest]
1679    #[cfg(not(windows))]
1680    fn test_prints_absolute_paths_with_zip_on_linux() {
1681        let expected = "\
1682-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/[Reset]
1683--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]/root/example/[Reset][DkGreen]find.sh[Reset]
1684zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/[Reset]
1685zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]
1686z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset][LtGreen]alpha.sh[Reset]
1687z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]blue.txt
1688z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]green.txt
1689z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours/[Reset]red.txt
1690zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset]
1691zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1692zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1693zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1694zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]
1695z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/one two/[Reset]\"three\" 'four'.txt
1696";
1697        let files = create_files("", "/root", "");
1698        let files = modify_files_for_zip(files);
1699        let config = Config::default()
1700            .with_zip_expand(true)
1701            .with_show_precise(true)
1702            .with_abs_path(true);
1703        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1704    }
1705
1706    #[gtest]
1707    #[cfg(windows)]
1708    fn test_prints_paths_with_before_header_on_windows() {
1709        let expected = "\
1710Before           Sun 01-Jan-2023 00:00:00
1711-----------------------------------------
1712drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[Reset]
1713-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
1714drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\[Reset]
1715drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\colours\\[Reset]
1716-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1717-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
1718-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
1719-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
1720drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset]
1721lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1722lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1723lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1724drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\one two\\[Reset]
1725-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1726";
1727        let files = create_files("D:", "/root", "");
1728        let config = Config::default()
1729            .with_filter_recent(RecentKind::Before(PeriodKind::Sec(1)))
1730            .with_show_precise(true)
1731            .with_abs_path(false);
1732        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1733    }
1734
1735    #[gtest]
1736    #[cfg(windows)]
1737    fn test_prints_paths_with_before_header_on_git_bash() {
1738        let expected = "\
1739Before           Sun 01-Jan-2023 00:00:00
1740-----------------------------------------
1741drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1742-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1743drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
1744drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
1745-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1746-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1747-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1748-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1749drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
1750lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1751lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1752lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1753drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
1754-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1755";
1756        let files = create_files("D:", "/root", "");
1757        let config = Config::default()
1758            .with_filter_recent(RecentKind::Before(PeriodKind::Sec(1)))
1759            .with_show_precise(true)
1760            .with_abs_path(false);
1761        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1762    }
1763
1764    #[gtest]
1765    #[cfg(not(windows))]
1766    fn test_prints_paths_with_before_header_on_linux() {
1767        let expected = "\
1768Before           Sun 01-Jan-2023 00:00:00
1769-----------------------------------------
1770drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1771-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1772drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
1773drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
1774-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1775-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1776-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1777-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1778drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
1779lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1780lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1781lrw-r--r--    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1782drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
1783-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1784";
1785        let files = create_files("", "/root", "");
1786        let config = Config::default()
1787            .with_filter_recent(RecentKind::Before(PeriodKind::Sec(1)))
1788            .with_show_precise(true)
1789            .with_abs_path(false);
1790        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1791    }
1792
1793    #[gtest]
1794    #[cfg(windows)]
1795    fn test_prints_paths_with_after_header_and_utc_on_windows() {
1796        let expected = "\
1797After            Sun 01-Jan-2023 00:00:00Z
1798------------------------------------------
1799drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example\\[Reset]
1800-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00Z  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
1801drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example\\files\\[Reset]
1802drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example\\files\\colours\\[Reset]
1803-rwxr--r--   20  Sun 01-Oct-2023 00:00:00Z  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1804-rw-r--r--   30  Fri 01-Sep-2023 00:00:00Z  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
1805-rw-r--r--   40  Tue 01-Aug-2023 00:00:00Z  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
1806-rw-r--r--   50  Sat 01-Jul-2023 00:00:00Z  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
1807drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example\\files\\numbers\\[Reset]
1808lrwxr--r--   60  Thu 01-Jun-2023 00:00:00Z  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1809lrw-r--r--  999  Mon 01-May-2023 00:00:00Z  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1810lrw-r--r--    0  Sat 01-Apr-2023 00:00:00Z        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1811drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example\\files\\numbers\\one two\\[Reset]
1812-rw-r--r--   70  Wed 01-Mar-2023 00:00:00Z  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1813";
1814        let files = create_files("D:", "/root", "");
1815        let config = Config::default()
1816            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
1817            .with_show_precise(true)
1818            .with_show_utc(true)
1819            .with_abs_path(false);
1820        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1821    }
1822
1823    #[gtest]
1824    #[cfg(windows)]
1825    fn test_prints_paths_with_after_header_and_utc_on_git_bash() {
1826        let expected = "\
1827After            Sun 01-Jan-2023 00:00:00Z
1828------------------------------------------
1829drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/[Reset]
1830-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00Z  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1831drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/[Reset]
1832drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/colours/[Reset]
1833-rwxr--r--   20  Sun 01-Oct-2023 00:00:00Z  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1834-rw-r--r--   30  Fri 01-Sep-2023 00:00:00Z  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1835-rw-r--r--   40  Tue 01-Aug-2023 00:00:00Z  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1836-rw-r--r--   50  Sat 01-Jul-2023 00:00:00Z  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1837drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/numbers/[Reset]
1838lrwxr--r--   60  Thu 01-Jun-2023 00:00:00Z  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1839lrw-r--r--  999  Mon 01-May-2023 00:00:00Z  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1840lrw-r--r--    0  Sat 01-Apr-2023 00:00:00Z        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1841drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/numbers/one two/[Reset]
1842-rw-r--r--   70  Wed 01-Mar-2023 00:00:00Z  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1843";
1844        let files = create_files("D:", "/root", "");
1845        let config = Config::default()
1846            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
1847            .with_show_precise(true)
1848            .with_show_utc(true)
1849            .with_abs_path(false);
1850        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1851    }
1852
1853    #[gtest]
1854    #[cfg(not(windows))]
1855    fn test_prints_paths_with_after_header_and_utc_on_linux() {
1856        let expected = "\
1857After            Sun 01-Jan-2023 00:00:00Z
1858------------------------------------------
1859drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/[Reset]
1860-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00Z  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1861drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/[Reset]
1862drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/colours/[Reset]
1863-rwxr--r--   20  Sun 01-Oct-2023 00:00:00Z  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1864-rw-r--r--   30  Fri 01-Sep-2023 00:00:00Z  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1865-rw-r--r--   40  Tue 01-Aug-2023 00:00:00Z  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1866-rw-r--r--   50  Sat 01-Jul-2023 00:00:00Z  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1867drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/numbers/[Reset]
1868lrwxr--r--   60  Thu 01-Jun-2023 00:00:00Z  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1869lrw-r--r--  999  Mon 01-May-2023 00:00:00Z  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1870lrw-r--r--    0  Sat 01-Apr-2023 00:00:00Z        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1871drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00Z        [LtBlue]example/files/numbers/one two/[Reset]
1872-rw-r--r--   70  Wed 01-Mar-2023 00:00:00Z  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1873";
1874        let files = create_files("", "/root", "");
1875        let config = Config::default()
1876            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
1877            .with_show_precise(true)
1878            .with_show_utc(true)
1879            .with_abs_path(false);
1880        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1881    }
1882
1883    #[gtest]
1884    #[cfg(windows)]
1885    fn test_prints_paths_with_total_footer_on_windows() {
1886        let expected = "\
1887drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[Reset]
1888-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
1889drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\[Reset]
1890drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\colours\\[Reset]
1891-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1892-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
1893-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
1894-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
1895drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset]
1896lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1897lrw-r--r--      999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1898lrw-r--r--        0  Sat 01-Apr-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1899drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\one two\\[Reset]
1900-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1901---------------------------------------------
1902Total         1,279                                  9 files 5 directories
1903";
1904        let files = create_files("D:", "/root", "");
1905        let config = Config::default()
1906            .with_show_precise(true)
1907            .with_show_total(true)
1908            .with_abs_path(false);
1909        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1910    }
1911
1912    #[gtest]
1913    #[cfg(windows)]
1914    fn test_prints_paths_with_total_footer_on_git_bash() {
1915        let expected = "\
1916drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1917-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1918drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
1919drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
1920-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1921-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1922-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1923-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1924drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
1925lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1926lrw-r--r--      999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1927lrw-r--r--        0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1928drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
1929-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1930---------------------------------------------
1931Total         1,279                                  9 files 5 directories
1932";
1933        let files = create_files("D:", "/root", "");
1934        let config = Config::default()
1935            .with_show_precise(true)
1936            .with_show_total(true)
1937            .with_abs_path(false);
1938        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
1939    }
1940
1941    #[gtest]
1942    #[cfg(not(windows))]
1943    fn test_prints_paths_with_total_footer_on_linux() {
1944        let expected = "\
1945drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
1946-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
1947drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
1948drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
1949-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
1950-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
1951-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
1952-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
1953drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
1954lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
1955lrw-r--r--      999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
1956lrw-r--r--        0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
1957drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
1958-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
1959---------------------------------------------
1960Total         1,279                                  9 files 5 directories
1961";
1962        let files = create_files("", "/root", "");
1963        let config = Config::default()
1964            .with_show_precise(true)
1965            .with_show_total(true)
1966            .with_abs_path(false);
1967        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1968    }
1969
1970    #[gtest]
1971    #[cfg(windows)]
1972    fn test_prints_pretty_fields_on_windows() {
1973        let expected = "\
1974drwxr-xr-x    0 B    1 day          [LtBlue]example\\[Reset]
1975-rwxr-xr-x   10 B    2 month  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
1976drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\[Reset]
1977drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\colours\\[Reset]
1978-rwxr--r--   20 B    3 month  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
1979-rw-r--r--   30 B    4 month  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
1980-rw-r--r--   40 B    5 month  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
1981-rw-r--r--   50 B    6 month  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
1982drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\numbers\\[Reset]
1983lrwxr--r--   60 B    7 month  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
1984lrw-r--r--  999 B    8 month  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
1985lrw-r--r--    0 B    9 month        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
1986drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\numbers\\one two\\[Reset]
1987-rw-r--r--   70 B   10 month  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
1988";
1989        let files = create_files("D:", "/root", "");
1990        let config = Config::default()
1991            .with_curr_time(2024, 1, 1, 0, 0, 0)
1992            .with_show_precise(false)
1993            .with_abs_path(false);
1994        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
1995    }
1996
1997    #[gtest]
1998    #[cfg(windows)]
1999    fn test_prints_pretty_fields_on_git_bash() {
2000        let expected = "\
2001drwxr-xr-x    0 B    1 day          [LtBlue]example/[Reset]
2002-rwxr-xr-x   10 B    2 month  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2003drwxr-xr-x    0 B    1 day          [LtBlue]example/files/[Reset]
2004drwxr-xr-x    0 B    1 day          [LtBlue]example/files/colours/[Reset]
2005-rwxr--r--   20 B    3 month  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2006-rw-r--r--   30 B    4 month  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2007-rw-r--r--   40 B    5 month  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2008-rw-r--r--   50 B    6 month  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2009drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/[Reset]
2010lrwxr--r--   60 B    7 month  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2011lrw-r--r--  999 B    8 month  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2012lrw-r--r--    0 B    9 month        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2013drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/one two/[Reset]
2014-rw-r--r--   70 B   10 month  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2015";
2016        let files = create_files("D:", "/root", "");
2017        let config = Config::default()
2018            .with_curr_time(2024, 1, 1, 0, 0, 0)
2019            .with_show_precise(false)
2020            .with_abs_path(false);
2021        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2022    }
2023
2024    #[gtest]
2025    #[cfg(not(windows))]
2026    fn test_prints_pretty_fields_on_linux() {
2027        let expected = "\
2028drwxr-xr-x    0 B    1 day          [LtBlue]example/[Reset]
2029-rwxr-xr-x   10 B    2 month  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2030drwxr-xr-x    0 B    1 day          [LtBlue]example/files/[Reset]
2031drwxr-xr-x    0 B    1 day          [LtBlue]example/files/colours/[Reset]
2032-rwxr--r--   20 B    3 month  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2033-rw-r--r--   30 B    4 month  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2034-rw-r--r--   40 B    5 month  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2035-rw-r--r--   50 B    6 month  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2036drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/[Reset]
2037lrwxr--r--   60 B    7 month  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2038lrw-r--r--  999 B    8 month  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2039lrw-r--r--    0 B    9 month        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2040drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/one two/[Reset]
2041-rw-r--r--   70 B   10 month  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2042";
2043        let files = create_files("", "/root", "");
2044        let config = Config::default()
2045            .with_curr_time(2024, 1, 1, 0, 0, 0)
2046            .with_show_precise(false)
2047            .with_abs_path(false);
2048        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2049    }
2050
2051    #[gtest]
2052    #[cfg(windows)]
2053    fn test_prints_pretty_fields_with_header_and_footer_on_windows() {
2054        let expected = "\
2055After                1 year
2056----------------------------
2057drwxr-xr-x    0 B    1 day          [LtBlue]example\\[Reset]
2058-rwxr-xr-x   10 B    2 month  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2059drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\[Reset]
2060drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\colours\\[Reset]
2061-rwxr--r--   20 B    3 month  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2062-rw-r--r--   30 B    4 month  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2063-rw-r--r--   40 B    5 month  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2064-rw-r--r--   50 B    6 month  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2065drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\numbers\\[Reset]
2066lrwxr--r--   60 B    7 month  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2067lrw-r--r--  999 B    8 month  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2068lrw-r--r--    0 B    9 month        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2069drwxr-xr-x    0 B    1 day          [LtBlue]example\\files\\numbers\\one two\\[Reset]
2070-rw-r--r--   70 B   10 month  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2071----------------------------
2072Total         1 KB                  9 files 5 directories
2073";
2074        let files = create_files("D:", "/root", "");
2075        let config = Config::default()
2076            .with_curr_time(2024, 1, 1, 0, 0, 0)
2077            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2078            .with_show_precise(false)
2079            .with_show_total(true)
2080            .with_abs_path(false);
2081        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2082    }
2083
2084    #[gtest]
2085    #[cfg(windows)]
2086    fn test_prints_pretty_fields_with_header_and_footer_on_git_bash() {
2087        let expected = "\
2088After                1 year
2089----------------------------
2090drwxr-xr-x    0 B    1 day          [LtBlue]example/[Reset]
2091-rwxr-xr-x   10 B    2 month  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2092drwxr-xr-x    0 B    1 day          [LtBlue]example/files/[Reset]
2093drwxr-xr-x    0 B    1 day          [LtBlue]example/files/colours/[Reset]
2094-rwxr--r--   20 B    3 month  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2095-rw-r--r--   30 B    4 month  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2096-rw-r--r--   40 B    5 month  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2097-rw-r--r--   50 B    6 month  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2098drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/[Reset]
2099lrwxr--r--   60 B    7 month  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2100lrw-r--r--  999 B    8 month  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2101lrw-r--r--    0 B    9 month        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2102drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/one two/[Reset]
2103-rw-r--r--   70 B   10 month  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2104----------------------------
2105Total         1 KB                  9 files 5 directories
2106";
2107        let files = create_files("D:", "/root", "");
2108        let config = Config::default()
2109            .with_curr_time(2024, 1, 1, 0, 0, 0)
2110            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2111            .with_show_precise(false)
2112            .with_show_total(true)
2113            .with_abs_path(false);
2114        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2115    }
2116
2117    #[gtest]
2118    #[cfg(not(windows))]
2119    fn test_prints_pretty_fields_with_header_and_footer_on_linux() {
2120        let expected = "\
2121After                1 year
2122----------------------------
2123drwxr-xr-x    0 B    1 day          [LtBlue]example/[Reset]
2124-rwxr-xr-x   10 B    2 month  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2125drwxr-xr-x    0 B    1 day          [LtBlue]example/files/[Reset]
2126drwxr-xr-x    0 B    1 day          [LtBlue]example/files/colours/[Reset]
2127-rwxr--r--   20 B    3 month  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2128-rw-r--r--   30 B    4 month  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2129-rw-r--r--   40 B    5 month  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2130-rw-r--r--   50 B    6 month  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2131drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/[Reset]
2132lrwxr--r--   60 B    7 month  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2133lrw-r--r--  999 B    8 month  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2134lrw-r--r--    0 B    9 month        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2135drwxr-xr-x    0 B    1 day          [LtBlue]example/files/numbers/one two/[Reset]
2136-rw-r--r--   70 B   10 month  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2137----------------------------
2138Total         1 KB                  9 files 5 directories
2139";
2140        let files = create_files("", "/root", "");
2141        let config = Config::default()
2142            .with_curr_time(2024, 1, 1, 0, 0, 0)
2143            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2144            .with_show_precise(false)
2145            .with_show_total(true)
2146            .with_abs_path(false);
2147        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2148    }
2149
2150    #[gtest]
2151    #[cfg(windows)]
2152    fn test_prints_git_flags_on_windows() {
2153        let expected = "\
2154drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[Reset]
2155-rwxr-xr-x AMRUI   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2156drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\[Reset]
2157drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\colours\\[Reset]
2158-rwxr--r-- A----   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2159-rw-r--r-- -M---   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2160-rw-r--r-- --R--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2161-rw-r--r-- ---U-   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2162drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset]
2163lrwxr--r-- -----   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2164lrw-r--r-- -----  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2165lrw-r--r-- -----    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2166drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\one two\\[Reset]
2167-rw-r--r-- ----I   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2168";
2169        let files = create_files("D:", "/root", "");
2170        let config = Config::default()
2171            .with_filter_git(GitFlags::default())
2172            .with_show_precise(true);
2173        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2174    }
2175
2176    #[gtest]
2177    #[cfg(windows)]
2178    fn test_prints_git_flags_on_git_bash() {
2179        let expected = "\
2180drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
2181-rwxr-xr-x AMRUI   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2182drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
2183drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
2184-rwxr--r-- A----   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2185-rw-r--r-- -M---   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2186-rw-r--r-- --R--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2187-rw-r--r-- ---U-   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2188drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
2189lrwxr--r-- -----   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2190lrw-r--r-- -----  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2191lrw-r--r-- -----    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2192drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
2193-rw-r--r-- ----I   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2194";
2195        let files = create_files("D:", "/root", "");
2196        let config = Config::default()
2197            .with_filter_git(GitFlags::default())
2198            .with_show_precise(true);
2199        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2200    }
2201
2202    #[gtest]
2203    #[cfg(not(windows))]
2204    fn test_prints_git_flags_on_linux() {
2205        let expected = "\
2206drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
2207-rwxr-xr-x AMRUI   10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2208drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
2209drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
2210-rwxr--r-- A----   20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2211-rw-r--r-- -M---   30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2212-rw-r--r-- --R--   40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2213-rw-r--r-- ---U-   50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2214drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
2215lrwxr--r-- -----   60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2216lrw-r--r-- -----  999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2217lrw-r--r-- -----    0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2218drwxr-xr-x -----    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
2219-rw-r--r-- ----I   70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2220";
2221        let files = create_files("", "/root", "");
2222        let config = Config::default()
2223            .with_filter_git(GitFlags::default())
2224            .with_show_precise(true);
2225        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2226    }
2227
2228    #[gtest]
2229    #[cfg(windows)]
2230    fn test_prints_git_flags_with_header_and_footer_on_windows() {
2231        let expected = "\
2232After                      Sun 01-Jan-2023 00:00:00
2233---------------------------------------------------
2234drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\[Reset]
2235-rwxr-xr-x AMRUI       10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2236drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\[Reset]
2237drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\colours\\[Reset]
2238-rwxr--r-- A----       20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2239-rw-r--r-- -M---       30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2240-rw-r--r-- --R--       40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2241-rw-r--r-- ---U-       50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2242drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset]
2243lrwxr--r-- -----       60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2244lrw-r--r-- -----      999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2245lrw-r--r-- -----        0  Sat 01-Apr-2023 00:00:00        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2246drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example\\files\\numbers\\one two\\[Reset]
2247-rw-r--r-- ----I       70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2248---------------------------------------------------
2249Total               1,279                                  9 files 5 directories
2250";
2251        let files = create_files("D:", "/root", "");
2252        let config = Config::default()
2253            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2254            .with_show_precise(true)
2255            .with_show_total(true)
2256            .with_filter_git(GitFlags::default());
2257        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2258    }
2259
2260    #[gtest]
2261    #[cfg(windows)]
2262    fn test_prints_git_flags_with_header_and_footer_on_git_bash() {
2263        let expected = "\
2264After                      Sun 01-Jan-2023 00:00:00
2265---------------------------------------------------
2266drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
2267-rwxr-xr-x AMRUI       10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2268drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
2269drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
2270-rwxr--r-- A----       20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2271-rw-r--r-- -M---       30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2272-rw-r--r-- --R--       40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2273-rw-r--r-- ---U-       50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2274drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
2275lrwxr--r-- -----       60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2276lrw-r--r-- -----      999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2277lrw-r--r-- -----        0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2278drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
2279-rw-r--r-- ----I       70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2280---------------------------------------------------
2281Total               1,279                                  9 files 5 directories
2282";
2283        let files = create_files("D:", "/root", "");
2284        let config = Config::default()
2285            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2286            .with_show_precise(true)
2287            .with_show_total(true)
2288            .with_filter_git(GitFlags::default());
2289        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2290    }
2291
2292    #[gtest]
2293    #[cfg(not(windows))]
2294    fn test_prints_git_flags_with_header_and_footer_on_linux() {
2295        let expected = "\
2296After                      Sun 01-Jan-2023 00:00:00
2297---------------------------------------------------
2298drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/[Reset]
2299-rwxr-xr-x AMRUI       10  Wed 01-Nov-2023 00:00:00  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2300drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/[Reset]
2301drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/colours/[Reset]
2302-rwxr--r-- A----       20  Sun 01-Oct-2023 00:00:00  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2303-rw-r--r-- -M---       30  Fri 01-Sep-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2304-rw-r--r-- --R--       40  Tue 01-Aug-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2305-rw-r--r-- ---U-       50  Sat 01-Jul-2023 00:00:00  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2306drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/[Reset]
2307lrwxr--r-- -----       60  Thu 01-Jun-2023 00:00:00  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2308lrw-r--r-- -----      999  Mon 01-May-2023 00:00:00  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2309lrw-r--r-- -----        0  Sat 01-Apr-2023 00:00:00        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2310drwxr-xr-x -----        0  Sun 31-Dec-2023 00:00:00        [LtBlue]example/files/numbers/one two/[Reset]
2311-rw-r--r-- ----I       70  Wed 01-Mar-2023 00:00:00  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2312---------------------------------------------------
2313Total               1,279                                  9 files 5 directories
2314";
2315        let files = create_files("", "/root", "");
2316        let config = Config::default()
2317            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2318            .with_show_precise(true)
2319            .with_show_total(true)
2320            .with_filter_git(GitFlags::default());
2321        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2322    }
2323
2324    #[gtest]
2325    #[cfg(windows)]
2326    fn test_prints_file_crc_on_windows() {
2327        let expected = "\
2328drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\[Reset]
2329-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  983f4ec5  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2330drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\[Reset]
2331drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\colours\\[Reset]
2332-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  983f4ec5  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2333-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  a8a32700  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2334-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  c3074b19  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2335-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  6cc61d05  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2336drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\numbers\\[Reset]
2337lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  983f4ec5  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2338lrw-r--r--  999  Mon 01-May-2023 00:00:00  00000000  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2339lrw-r--r--    0  Sat 01-Apr-2023 00:00:00  00000000        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2340drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\numbers\\one two\\[Reset]
2341-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  95c416b2  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2342";
2343        let files = create_files("D:", "/root", "");
2344        let config = Config::default()
2345            .with_show_precise(true)
2346            .with_show_crc(true);
2347        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2348    }
2349
2350    #[gtest]
2351    #[cfg(windows)]
2352    fn test_prints_file_crc_on_git_bash() {
2353        let expected = "\
2354drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/[Reset]
2355-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2356drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/[Reset]
2357drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/colours/[Reset]
2358-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2359-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  a8a32700  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2360-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  c3074b19  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2361-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  6cc61d05  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2362drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset]
2363lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2364lrw-r--r--  999  Mon 01-May-2023 00:00:00  00000000  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2365lrw-r--r--    0  Sat 01-Apr-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2366drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/one two/[Reset]
2367-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  95c416b2  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2368";
2369        let files = create_files("D:", "/root", "");
2370        let config = Config::default()
2371            .with_show_precise(true)
2372            .with_show_crc(true);
2373        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2374    }
2375
2376    #[gtest]
2377    #[cfg(not(windows))]
2378    fn test_prints_file_crc_on_linux() {
2379        let expected = "\
2380drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/[Reset]
2381-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2382drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/[Reset]
2383drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/colours/[Reset]
2384-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2385-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  a8a32700  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2386-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  c3074b19  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2387-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  6cc61d05  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2388drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset]
2389lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2390lrw-r--r--  999  Mon 01-May-2023 00:00:00  00000000  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2391lrw-r--r--    0  Sat 01-Apr-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2392drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/one two/[Reset]
2393-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  95c416b2  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2394";
2395        let files = create_files("", "/root", "");
2396        let config = Config::default()
2397            .with_show_precise(true)
2398            .with_show_crc(true);
2399        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2400    }
2401
2402    #[gtest]
2403    #[cfg(windows)]
2404    fn test_prints_file_crc_with_header_and_footer_on_windows() {
2405        let expected = "\
2406After                Sun 01-Jan-2023 00:00:00
2407---------------------------------------------
2408drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\[Reset]
2409-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  983f4ec5  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2410drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\[Reset]
2411drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\colours\\[Reset]
2412-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  983f4ec5  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2413-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  a8a32700  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2414-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  c3074b19  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2415-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  6cc61d05  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2416drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\numbers\\[Reset]
2417lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  983f4ec5  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2418lrw-r--r--      999  Mon 01-May-2023 00:00:00  00000000  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2419lrw-r--r--        0  Sat 01-Apr-2023 00:00:00  00000000        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2420drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example\\files\\numbers\\one two\\[Reset]
2421-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  95c416b2  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2422---------------------------------------------
2423Total         1,279                                            9 files 5 directories
2424";
2425        let files = create_files("D:", "/root", "");
2426        let config = Config::default()
2427            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2428            .with_show_precise(true)
2429            .with_show_total(true)
2430            .with_show_crc(true);
2431        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2432    }
2433
2434    #[gtest]
2435    #[cfg(windows)]
2436    fn test_prints_file_crc_with_header_and_footer_on_git_bash() {
2437        let expected = "\
2438After                Sun 01-Jan-2023 00:00:00
2439---------------------------------------------
2440drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/[Reset]
2441-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2442drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/[Reset]
2443drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/colours/[Reset]
2444-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2445-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  a8a32700  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2446-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  c3074b19  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2447-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  6cc61d05  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2448drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset]
2449lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2450lrw-r--r--      999  Mon 01-May-2023 00:00:00  00000000  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2451lrw-r--r--        0  Sat 01-Apr-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2452drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/one two/[Reset]
2453-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  95c416b2  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2454---------------------------------------------
2455Total         1,279                                            9 files 5 directories
2456";
2457        let files = create_files("D:", "/root", "");
2458        let config = Config::default()
2459            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2460            .with_show_precise(true)
2461            .with_show_total(true)
2462            .with_show_crc(true);
2463        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2464    }
2465
2466    #[gtest]
2467    #[cfg(not(windows))]
2468    fn test_prints_file_crc_with_header_and_footer_on_linux() {
2469        let expected = "\
2470After                Sun 01-Jan-2023 00:00:00
2471---------------------------------------------
2472drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/[Reset]
2473-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2474drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/[Reset]
2475drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/colours/[Reset]
2476-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2477-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  a8a32700  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2478-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  c3074b19  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2479-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  6cc61d05  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2480drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset]
2481lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  983f4ec5  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2482lrw-r--r--      999  Mon 01-May-2023 00:00:00  00000000  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2483lrw-r--r--        0  Sat 01-Apr-2023 00:00:00  00000000        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2484drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000        [LtBlue]example/files/numbers/one two/[Reset]
2485-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  95c416b2  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2486---------------------------------------------
2487Total         1,279                                            9 files 5 directories
2488";
2489        let files = create_files("", "/root", "");
2490        let config = Config::default()
2491            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2492            .with_show_precise(true)
2493            .with_show_total(true)
2494            .with_show_crc(true);
2495        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2496    }
2497
2498    #[gtest]
2499    #[cfg(windows)]
2500    fn test_prints_file_signature_on_windows() {
2501        let expected = "\
2502drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\[Reset]
2503-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2504drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\[Reset]
2505drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\colours\\[Reset]
2506-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2507-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  424c5545 BLUE  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2508-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  47524545 GREE  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2509-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  52454400 RED.  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2510drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\numbers\\[Reset]
2511lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2512lrw-r--r--  999  Mon 01-May-2023 00:00:00  00000000 ....  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2513lrw-r--r--    0  Sat 01-Apr-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2514drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\numbers\\one two\\[Reset]
2515-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  fffe3334 ..34  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2516";
2517        let files = create_files("D:", "/root", "");
2518        let config = Config::default()
2519            .with_show_precise(true)
2520            .with_show_sig(true);
2521        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2522    }
2523
2524    #[gtest]
2525    #[cfg(windows)]
2526    fn test_prints_file_signature_on_git_bash() {
2527        let expected = "\
2528drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/[Reset]
2529-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2530drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/[Reset]
2531drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/colours/[Reset]
2532-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2533-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  424c5545 BLUE  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2534-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  47524545 GREE  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2535-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  52454400 RED.  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2536drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset]
2537lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2538lrw-r--r--  999  Mon 01-May-2023 00:00:00  00000000 ....  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2539lrw-r--r--    0  Sat 01-Apr-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2540drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/one two/[Reset]
2541-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  fffe3334 ..34  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2542";
2543        let files = create_files("D:", "/root", "");
2544        let config = Config::default()
2545            .with_show_precise(true)
2546            .with_show_sig(true);
2547        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2548    }
2549
2550    #[gtest]
2551    #[cfg(not(windows))]
2552    fn test_prints_file_signature_on_linux() {
2553        let expected = "\
2554drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/[Reset]
2555-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2556drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/[Reset]
2557drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/colours/[Reset]
2558-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2559-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  424c5545 BLUE  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2560-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  47524545 GREE  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2561-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  52454400 RED.  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2562drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset]
2563lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2564lrw-r--r--  999  Mon 01-May-2023 00:00:00  00000000 ....  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2565lrw-r--r--    0  Sat 01-Apr-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2566drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/one two/[Reset]
2567-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  fffe3334 ..34  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2568";
2569        let files = create_files("", "/root", "");
2570        let config = Config::default()
2571            .with_show_precise(true)
2572            .with_show_sig(true);
2573        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2574    }
2575
2576    #[gtest]
2577    #[cfg(windows)]
2578    fn test_prints_file_signature_with_header_and_footer_on_windows() {
2579        let expected = "\
2580After                Sun 01-Jan-2023 00:00:00
2581---------------------------------------------
2582drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\[Reset]
2583-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2584drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\[Reset]
2585drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\colours\\[Reset]
2586-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2587-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  424c5545 BLUE  .txt  [LtBlue]example\\files\\colours\\[Reset]blue.txt
2588-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  47524545 GREE  .txt  [LtBlue]example\\files\\colours\\[Reset]green.txt
2589-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  52454400 RED.  .txt  [LtBlue]example\\files\\colours\\[Reset]red.txt
2590drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\numbers\\[Reset]
2591lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2592lrw-r--r--      999  Mon 01-May-2023 00:00:00  00000000 ....  .gz   [LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2593lrw-r--r--        0  Sat 01-Apr-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2594drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example\\files\\numbers\\one two\\[Reset]
2595-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  fffe3334 ..34  .txt  [LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2596---------------------------------------------
2597Total         1,279                                                 9 files 5 directories
2598";
2599        let files = create_files("D:", "/root", "");
2600        let config = Config::default()
2601            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2602            .with_show_precise(true)
2603            .with_show_total(true)
2604            .with_show_sig(true);
2605        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2606    }
2607
2608    #[gtest]
2609    #[cfg(windows)]
2610    fn test_prints_file_signature_with_header_and_footer_on_git_bash() {
2611        let expected = "\
2612After                Sun 01-Jan-2023 00:00:00
2613---------------------------------------------
2614drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/[Reset]
2615-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2616drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/[Reset]
2617drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/colours/[Reset]
2618-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2619-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  424c5545 BLUE  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2620-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  47524545 GREE  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2621-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  52454400 RED.  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2622drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset]
2623lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2624lrw-r--r--      999  Mon 01-May-2023 00:00:00  00000000 ....  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2625lrw-r--r--        0  Sat 01-Apr-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2626drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/one two/[Reset]
2627-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  fffe3334 ..34  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2628---------------------------------------------
2629Total         1,279                                                 9 files 5 directories
2630";
2631        let files = create_files("D:", "/root", "");
2632        let config = Config::default()
2633            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2634            .with_show_precise(true)
2635            .with_show_total(true)
2636            .with_show_sig(true);
2637        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2638    }
2639
2640    #[gtest]
2641    #[cfg(not(windows))]
2642    fn test_prints_file_signature_with_header_and_footer_on_linux() {
2643        let expected = "\
2644After                Sun 01-Jan-2023 00:00:00
2645---------------------------------------------
2646drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/[Reset]
2647-rwxr-xr-x       10  Wed 01-Nov-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2648drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/[Reset]
2649drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/colours/[Reset]
2650-rwxr--r--       20  Sun 01-Oct-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2651-rw-r--r--       30  Fri 01-Sep-2023 00:00:00  424c5545 BLUE  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2652-rw-r--r--       40  Tue 01-Aug-2023 00:00:00  47524545 GREE  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2653-rw-r--r--       50  Sat 01-Jul-2023 00:00:00  52454400 RED.  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2654drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset]
2655lrwxr--r--       60  Thu 01-Jun-2023 00:00:00  23212f75 #!/u  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2656lrw-r--r--      999  Mon 01-May-2023 00:00:00  00000000 ....  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2657lrw-r--r--        0  Sat 01-Apr-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2658drwxr-xr-x        0  Sun 31-Dec-2023 00:00:00  00000000 ....        [LtBlue]example/files/numbers/one two/[Reset]
2659-rw-r--r--       70  Wed 01-Mar-2023 00:00:00  fffe3334 ..34  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2660---------------------------------------------
2661Total         1,279                                                 9 files 5 directories
2662";
2663        let files = create_files("", "/root", "");
2664        let config = Config::default()
2665            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2666            .with_show_precise(true)
2667            .with_show_total(true)
2668            .with_show_sig(true);
2669        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2670    }
2671
2672    #[gtest]
2673    #[cfg(not(windows))]
2674    #[cfg(unix)]
2675    fn test_prints_owner_information_on_linux() {
2676        let expected = "\
2677drwxr-xr-x  alice public    0 B    1 day          [LtBlue]example/[Reset]
2678-rwxr-xr-x  root  root     10 B    2 month  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2679drwxr-xr-x  alice public    0 B    1 day          [LtBlue]example/files/[Reset]
2680drwxr-xr-x  alice public    0 B    1 day          [LtBlue]example/files/colours/[Reset]
2681-rwxr--r--  alice public   20 B    3 month  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2682-rw-r--r--  alice public   30 B    4 month  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2683-rw-r--r--  alice public   40 B    5 month  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2684-rw-r--r--  alice public   50 B    6 month  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2685drwxr-xr-x  bob   public    0 B    1 day          [LtBlue]example/files/numbers/[Reset]
2686lrwxr--r--  bob   public   60 B    7 month  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2687lrw-r--r--  bob   public  999 B    8 month  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2688lrw-r--r--  bob   public    0 B    9 month        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2689drwxr-xr-x  -     -         0 B    1 day          [LtBlue]example/files/numbers/one two/[Reset]
2690-rw-r--r--  -     -        70 B   10 month  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2691";
2692        let files = create_files("", "/root", "");
2693        let config = Config::default()
2694            .with_curr_time(2024, 1, 1, 0, 0, 0)
2695            .with_show_precise(false)
2696            .with_show_owner(true)
2697            .with_abs_path(false);
2698        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2699    }
2700
2701    #[gtest]
2702    #[cfg(not(windows))]
2703    #[cfg(unix)]
2704    fn test_prints_owner_information_with_header_and_footer_on_linux() {
2705        let expected = "\
2706After                              1 year
2707------------------------------------------
2708drwxr-xr-x  alice public    0 B    1 day          [LtBlue]example/[Reset]
2709-rwxr-xr-x  root  root     10 B    2 month  .sh   [LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2710drwxr-xr-x  alice public    0 B    1 day          [LtBlue]example/files/[Reset]
2711drwxr-xr-x  alice public    0 B    1 day          [LtBlue]example/files/colours/[Reset]
2712-rwxr--r--  alice public   20 B    3 month  .sh   [LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2713-rw-r--r--  alice public   30 B    4 month  .txt  [LtBlue]example/files/colours/[Reset]blue.txt
2714-rw-r--r--  alice public   40 B    5 month  .txt  [LtBlue]example/files/colours/[Reset]green.txt
2715-rw-r--r--  alice public   50 B    6 month  .txt  [LtBlue]example/files/colours/[Reset]red.txt
2716drwxr-xr-x  bob   public    0 B    1 day          [LtBlue]example/files/numbers/[Reset]
2717lrwxr--r--  bob   public   60 B    7 month  .sh   [LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2718lrw-r--r--  bob   public  999 B    8 month  .gz   [LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2719lrw-r--r--  bob   public    0 B    9 month        [LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2720drwxr-xr-x  -     -         0 B    1 day          [LtBlue]example/files/numbers/one two/[Reset]
2721-rw-r--r--  -     -        70 B   10 month  .txt  [LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2722------------------------------------------
2723Total                       1 KB                  9 files 5 directories
2724";
2725        let files = create_files("", "/root", "");
2726        let config = Config::default()
2727            .with_curr_time(2024, 1, 1, 0, 0, 0)
2728            .with_filter_recent(RecentKind::After(PeriodKind::Year(1)))
2729            .with_show_precise(false)
2730            .with_show_owner(true)
2731            .with_show_total(true)
2732            .with_abs_path(false);
2733        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2734    }
2735
2736    #[gtest]
2737    #[cfg(windows)]
2738    fn test_prints_version_numbers_on_windows() {
2739        let expected = "\
2740-rwxr--r--  999  Mon 01-Jan-2024 00:00:00  12.3.4.0   .exe  [LtGreen]binary.exe[Reset]
2741-rwxr--r--  999  Mon 01-Jan-2024 00:00:00  5.67.89.0  .dll  library.dll
2742-rw-r--r--  999  Mon 01-Jan-2024 00:00:00             .txt  readme.txt
2743";
2744        let files = create_files_with_version();
2745        let config = Config::default()
2746            .with_show_precise(true)
2747            .with_win_ver(true);
2748        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2749    }
2750
2751    #[gtest]
2752    #[cfg(windows)]
2753    fn test_prints_version_numbers_on_git_bash() {
2754        let expected = "\
2755-rwxr--r--  999  Mon 01-Jan-2024 00:00:00  12.3.4.0   .exe  [LtGreen]binary.exe[Reset]
2756-rwxr--r--  999  Mon 01-Jan-2024 00:00:00  5.67.89.0  .dll  library.dll
2757-rw-r--r--  999  Mon 01-Jan-2024 00:00:00             .txt  readme.txt
2758";
2759        let files = create_files_with_version();
2760        let config = Config::default()
2761            .with_show_precise(true)
2762            .with_win_ver(true);
2763        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2764    }
2765
2766    #[gtest]
2767    #[cfg(windows)]
2768    fn test_prints_relative_paths_no_attributes_on_windows() {
2769        let expected = "\
2770[LtBlue]example\\[Reset]
2771[LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2772[LtBlue]example\\files\\[Reset]
2773[LtBlue]example\\files\\colours\\[Reset]
2774[LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2775[LtBlue]example\\files\\colours\\[Reset]blue.txt
2776[LtBlue]example\\files\\colours\\[Reset]green.txt
2777[LtBlue]example\\files\\colours\\[Reset]red.txt
2778[LtBlue]example\\files\\numbers\\[Reset]
2779[LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2780[LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2781[LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2782[LtBlue]example\\files\\numbers\\one two\\[Reset]
2783[LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2784";
2785        let files = create_files("D:", "/root", "");
2786        let config = Config::default()
2787            .with_only_path(true)
2788            .with_abs_path(false);
2789        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2790    }
2791
2792    #[gtest]
2793    #[cfg(windows)]
2794    fn test_prints_relative_paths_no_attributes_on_git_bash() {
2795        let expected = "\
2796[LtBlue]example/[Reset]
2797[LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2798[LtBlue]example/files/[Reset]
2799[LtBlue]example/files/colours/[Reset]
2800[LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2801[LtBlue]example/files/colours/[Reset]blue.txt
2802[LtBlue]example/files/colours/[Reset]green.txt
2803[LtBlue]example/files/colours/[Reset]red.txt
2804[LtBlue]example/files/numbers/[Reset]
2805[LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2806[LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2807[LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2808[LtBlue]example/files/numbers/one two/[Reset]
2809[LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2810";
2811        let files = create_files("D:", "/root", "");
2812        let config = Config::default()
2813            .with_only_path(true)
2814            .with_abs_path(false);
2815        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2816    }
2817
2818    #[gtest]
2819    #[cfg(not(windows))]
2820    fn test_prints_relative_paths_no_attributes_on_linux() {
2821        let expected = "\
2822[LtBlue]example/[Reset]
2823[LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2824[LtBlue]example/files/[Reset]
2825[LtBlue]example/files/colours/[Reset]
2826[LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2827[LtBlue]example/files/colours/[Reset]blue.txt
2828[LtBlue]example/files/colours/[Reset]green.txt
2829[LtBlue]example/files/colours/[Reset]red.txt
2830[LtBlue]example/files/numbers/[Reset]
2831[LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2832[LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2833[LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2834[LtBlue]example/files/numbers/one two/[Reset]
2835[LtBlue]example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2836";
2837        let files = create_files("", "/root", "");
2838        let config = Config::default()
2839            .with_only_path(true)
2840            .with_abs_path(false);
2841        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2842    }
2843
2844    #[gtest]
2845    #[cfg(windows)]
2846    fn test_prints_absolute_paths_no_attributes_on_windows() {
2847        let expected = "\
2848[LtBlue]D:\\root\\example\\[Reset]
2849[LtBlue]D:\\root\\example\\[Reset][DkGreen]find.sh[Reset]
2850[LtBlue]D:\\root\\example\\files\\[Reset]
2851[LtBlue]D:\\root\\example\\files\\colours\\[Reset]
2852[LtBlue]D:\\root\\example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2853[LtBlue]D:\\root\\example\\files\\colours\\[Reset]blue.txt
2854[LtBlue]D:\\root\\example\\files\\colours\\[Reset]green.txt
2855[LtBlue]D:\\root\\example\\files\\colours\\[Reset]red.txt
2856[LtBlue]D:\\root\\example\\files\\numbers\\[Reset]
2857[LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
2858[LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
2859[LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
2860[LtBlue]D:\\root\\example\\files\\numbers\\one two\\[Reset]
2861[LtBlue]D:\\root\\example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2862";
2863        let files = create_files("D:", "/root", "");
2864        let config = Config::default()
2865            .with_only_path(true)
2866            .with_abs_path(true);
2867        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2868    }
2869
2870    #[gtest]
2871    #[cfg(windows)]
2872    fn test_prints_absolute_paths_no_attributes_on_git_bash() {
2873        let expected = "\
2874[LtBlue]/d/root/example/[Reset]
2875[LtBlue]/d/root/example/[Reset][DkGreen]find.sh[Reset]
2876[LtBlue]/d/root/example/files/[Reset]
2877[LtBlue]/d/root/example/files/colours/[Reset]
2878[LtBlue]/d/root/example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2879[LtBlue]/d/root/example/files/colours/[Reset]blue.txt
2880[LtBlue]/d/root/example/files/colours/[Reset]green.txt
2881[LtBlue]/d/root/example/files/colours/[Reset]red.txt
2882[LtBlue]/d/root/example/files/numbers/[Reset]
2883[LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2884[LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2885[LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2886[LtBlue]/d/root/example/files/numbers/one two/[Reset]
2887[LtBlue]/d/root/example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2888";
2889        let files = create_files("D:", "/root", "");
2890        let config = Config::default()
2891            .with_only_path(true)
2892            .with_abs_path(true);
2893        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2894    }
2895
2896    #[gtest]
2897    #[cfg(not(windows))]
2898    fn test_prints_absolute_paths_no_attributes_on_linux() {
2899        let expected = "\
2900[LtBlue]/root/example/[Reset]
2901[LtBlue]/root/example/[Reset][DkGreen]find.sh[Reset]
2902[LtBlue]/root/example/files/[Reset]
2903[LtBlue]/root/example/files/colours/[Reset]
2904[LtBlue]/root/example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2905[LtBlue]/root/example/files/colours/[Reset]blue.txt
2906[LtBlue]/root/example/files/colours/[Reset]green.txt
2907[LtBlue]/root/example/files/colours/[Reset]red.txt
2908[LtBlue]/root/example/files/numbers/[Reset]
2909[LtBlue]/root/example/files/numbers/[Reset][LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
2910[LtBlue]/root/example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
2911[LtBlue]/root/example/files/numbers/[Reset][LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
2912[LtBlue]/root/example/files/numbers/one two/[Reset]
2913[LtBlue]/root/example/files/numbers/one two/[Reset]\"three\" 'four'.txt
2914";
2915        let files = create_files("", "/root", "");
2916        let config = Config::default()
2917            .with_only_path(true)
2918            .with_abs_path(true);
2919        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2920    }
2921
2922    #[gtest]
2923    #[cfg(windows)]
2924    fn test_prints_relative_paths_with_escaping_on_windows() {
2925        let expected = "\
2926[LtBlue]example\\[Reset]
2927[LtBlue]example\\[Reset][DkGreen]find.sh[Reset]
2928[LtBlue]example\\files\\[Reset]
2929[LtBlue]example\\files\\colours\\[Reset]
2930[LtBlue]example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
2931[LtBlue]example\\files\\colours\\[Reset]blue.txt
2932[LtBlue]example\\files\\colours\\[Reset]green.txt
2933[LtBlue]example\\files\\colours\\[Reset]red.txt
2934[LtBlue]example\\files\\numbers\\[Reset]
2935[LtBlue]example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset]
2936[LtBlue]example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset]
2937[LtBlue]example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset]
2938[LtBlue]example\\files\\numbers\\one two\\[Reset]
2939[LtBlue]example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
2940";
2941        let files = create_files("D:", "/root", "");
2942        let config = Config::default()
2943            .with_escape_path()
2944            .with_abs_path(false);
2945        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2946    }
2947
2948    #[gtest]
2949    #[cfg(windows)]
2950    fn test_prints_relative_paths_with_escaping_on_git_bash() {
2951        let expected = "\
2952[LtBlue]example/[Reset]
2953[LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2954[LtBlue]example/files/[Reset]
2955[LtBlue]example/files/colours/[Reset]
2956[LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2957[LtBlue]example/files/colours/[Reset]blue.txt
2958[LtBlue]example/files/colours/[Reset]green.txt
2959[LtBlue]example/files/colours/[Reset]red.txt
2960[LtBlue]example/files/numbers/[Reset]
2961[LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset]
2962[LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset]
2963[LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset]
2964[LtBlue]example/files/numbers/one\\ two/[Reset]
2965[LtBlue]example/files/numbers/one\\ two/[Reset]\\\"three\\\"\\ \\'four\\'.txt
2966";
2967        let files = create_files("D:", "/root", "");
2968        let config = Config::default()
2969            .with_escape_path()
2970            .with_abs_path(false);
2971        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
2972    }
2973
2974    #[gtest]
2975    #[cfg(not(windows))]
2976    fn test_prints_relative_paths_with_escaping_on_linux() {
2977        let expected = "\
2978[LtBlue]example/[Reset]
2979[LtBlue]example/[Reset][DkGreen]find.sh[Reset]
2980[LtBlue]example/files/[Reset]
2981[LtBlue]example/files/colours/[Reset]
2982[LtBlue]example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
2983[LtBlue]example/files/colours/[Reset]blue.txt
2984[LtBlue]example/files/colours/[Reset]green.txt
2985[LtBlue]example/files/colours/[Reset]red.txt
2986[LtBlue]example/files/numbers/[Reset]
2987[LtBlue]example/files/numbers/[Reset][LtCyan]count.sh[Reset]
2988[LtBlue]example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset]
2989[LtBlue]example/files/numbers/[Reset][LtCyan]ordinals[Reset]
2990[LtBlue]example/files/numbers/one\\ two/[Reset]
2991[LtBlue]example/files/numbers/one\\ two/[Reset]\\\"three\\\"\\ \\'four\\'.txt
2992";
2993        let files = create_files("", "/root", "");
2994        let config = Config::default()
2995            .with_escape_path()
2996            .with_abs_path(false);
2997        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
2998    }
2999
3000    #[gtest]
3001    #[cfg(windows)]
3002    fn test_prints_absolute_paths_with_escaping_on_windows() {
3003        let expected = "\
3004[LtBlue]D:\\root\\example\\[Reset]
3005[LtBlue]D:\\root\\example\\[Reset][DkGreen]find.sh[Reset]
3006[LtBlue]D:\\root\\example\\files\\[Reset]
3007[LtBlue]D:\\root\\example\\files\\colours\\[Reset]
3008[LtBlue]D:\\root\\example\\files\\colours\\[Reset][LtGreen]alpha.sh[Reset]
3009[LtBlue]D:\\root\\example\\files\\colours\\[Reset]blue.txt
3010[LtBlue]D:\\root\\example\\files\\colours\\[Reset]green.txt
3011[LtBlue]D:\\root\\example\\files\\colours\\[Reset]red.txt
3012[LtBlue]D:\\root\\example\\files\\numbers\\[Reset]
3013[LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]count.sh[Reset]
3014[LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]googolplex.gz[Reset]
3015[LtBlue]D:\\root\\example\\files\\numbers\\[Reset][LtCyan]ordinals[Reset]
3016[LtBlue]D:\\root\\example\\files\\numbers\\one two\\[Reset]
3017[LtBlue]D:\\root\\example\\files\\numbers\\one two\\[Reset]\"three\" 'four'.txt
3018";
3019        let files = create_files("D:", "/root", "");
3020        let config = Config::default()
3021            .with_escape_path()
3022            .with_abs_path(true);
3023        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3024    }
3025
3026    #[gtest]
3027    #[cfg(windows)]
3028    fn test_prints_absolute_paths_with_escaping_on_git_bash() {
3029        let expected = "\
3030[LtBlue]/d/root/example/[Reset]
3031[LtBlue]/d/root/example/[Reset][DkGreen]find.sh[Reset]
3032[LtBlue]/d/root/example/files/[Reset]
3033[LtBlue]/d/root/example/files/colours/[Reset]
3034[LtBlue]/d/root/example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
3035[LtBlue]/d/root/example/files/colours/[Reset]blue.txt
3036[LtBlue]/d/root/example/files/colours/[Reset]green.txt
3037[LtBlue]/d/root/example/files/colours/[Reset]red.txt
3038[LtBlue]/d/root/example/files/numbers/[Reset]
3039[LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]count.sh[Reset]
3040[LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset]
3041[LtBlue]/d/root/example/files/numbers/[Reset][LtCyan]ordinals[Reset]
3042[LtBlue]/d/root/example/files/numbers/one\\ two/[Reset]
3043[LtBlue]/d/root/example/files/numbers/one\\ two/[Reset]\\\"three\\\"\\ \\'four\\'.txt
3044";
3045        let files = create_files("D:", "/root", "");
3046        let config = Config::default()
3047            .with_escape_path()
3048            .with_abs_path(true);
3049        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3050    }
3051
3052    #[gtest]
3053    #[cfg(not(windows))]
3054    fn test_prints_absolute_paths_with_escaping_on_linux() {
3055        let expected = "\
3056[LtBlue]/root/example/[Reset]
3057[LtBlue]/root/example/[Reset][DkGreen]find.sh[Reset]
3058[LtBlue]/root/example/files/[Reset]
3059[LtBlue]/root/example/files/colours/[Reset]
3060[LtBlue]/root/example/files/colours/[Reset][LtGreen]alpha.sh[Reset]
3061[LtBlue]/root/example/files/colours/[Reset]blue.txt
3062[LtBlue]/root/example/files/colours/[Reset]green.txt
3063[LtBlue]/root/example/files/colours/[Reset]red.txt
3064[LtBlue]/root/example/files/numbers/[Reset]
3065[LtBlue]/root/example/files/numbers/[Reset][LtCyan]count.sh[Reset]
3066[LtBlue]/root/example/files/numbers/[Reset][LtCyan]googolplex.gz[Reset]
3067[LtBlue]/root/example/files/numbers/[Reset][LtCyan]ordinals[Reset]
3068[LtBlue]/root/example/files/numbers/one\\ two/[Reset]
3069[LtBlue]/root/example/files/numbers/one\\ two/[Reset]\\\"three\\\"\\ \\'four\\'.txt
3070";
3071        let files = create_files("", "/root", "");
3072        let config = Config::default()
3073            .with_escape_path()
3074            .with_abs_path(true);
3075        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3076    }
3077
3078    #[gtest]
3079    #[cfg(windows)]
3080    fn test_prints_relative_paths_sorted_by_name_on_windows() {
3081        let expected = "\
3082[LtGreen]alpha.sh[Reset] ([LtBlue]example\\files\\colours[Reset])
3083blue.txt ([LtBlue]example\\files\\colours[Reset])
3084[LtCyan]count.sh[Reset] ([LtBlue]example\\files\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3085[DkGreen]find.sh[Reset] ([LtBlue]example[Reset])
3086[LtCyan]googolplex.gz[Reset] ([LtBlue]example\\files\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3087green.txt ([LtBlue]example\\files\\colours[Reset])
3088[LtCyan]ordinals[Reset] ([LtBlue]example\\files\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3089red.txt ([LtBlue]example\\files\\colours[Reset])
3090\"three\" 'four'.txt ([LtBlue]example\\files\\numbers\\one two[Reset])
3091";
3092        let files = create_files("D:", "/root", "");
3093        let files = modify_files_by_name(files);
3094        let config = Config::default()
3095            .with_sort_name(true)
3096            .with_only_path(true)
3097            .with_abs_path(false);
3098        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3099    }
3100
3101    #[gtest]
3102    #[cfg(windows)]
3103    fn test_prints_relative_paths_sorted_by_name_on_git_bash() {
3104        let expected = "\
3105[LtGreen]alpha.sh[Reset] ([LtBlue]example/files/colours[Reset])
3106blue.txt ([LtBlue]example/files/colours[Reset])
3107[LtCyan]count.sh[Reset] ([LtBlue]example/files/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3108[DkGreen]find.sh[Reset] ([LtBlue]example[Reset])
3109[LtCyan]googolplex.gz[Reset] ([LtBlue]example/files/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3110green.txt ([LtBlue]example/files/colours[Reset])
3111[LtCyan]ordinals[Reset] ([LtBlue]example/files/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3112red.txt ([LtBlue]example/files/colours[Reset])
3113\"three\" 'four'.txt ([LtBlue]example/files/numbers/one two[Reset])
3114";
3115        let files = create_files("D:", "/root", "");
3116        let files = modify_files_by_name(files);
3117        let config = Config::default()
3118            .with_sort_name(true)
3119            .with_only_path(true)
3120            .with_abs_path(false);
3121        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3122    }
3123
3124    #[gtest]
3125    #[cfg(not(windows))]
3126    fn test_prints_relative_paths_sorted_by_name_on_linux() {
3127        let expected = "\
3128[LtGreen]alpha.sh[Reset] ([LtBlue]example/files/colours[Reset])
3129blue.txt ([LtBlue]example/files/colours[Reset])
3130[LtCyan]count.sh[Reset] ([LtBlue]example/files/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3131[DkGreen]find.sh[Reset] ([LtBlue]example[Reset])
3132[LtCyan]googolplex.gz[Reset] ([LtBlue]example/files/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3133green.txt ([LtBlue]example/files/colours[Reset])
3134[LtCyan]ordinals[Reset] ([LtBlue]example/files/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3135red.txt ([LtBlue]example/files/colours[Reset])
3136\"three\" 'four'.txt ([LtBlue]example/files/numbers/one two[Reset])
3137";
3138        let files = create_files("", "/root", "");
3139        let files = modify_files_by_name(files);
3140        let config = Config::default()
3141            .with_sort_name(true)
3142            .with_only_path(true)
3143            .with_abs_path(false);
3144        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3145    }
3146
3147    #[gtest]
3148    #[cfg(windows)]
3149    fn test_prints_absolute_paths_sorted_by_name_on_windows() {
3150        let expected = "\
3151[LtGreen]alpha.sh[Reset] ([LtBlue]D:\\root\\example\\files\\colours[Reset])
3152blue.txt ([LtBlue]D:\\root\\example\\files\\colours[Reset])
3153[LtCyan]count.sh[Reset] ([LtBlue]D:\\root\\example\\files\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3154[DkGreen]find.sh[Reset] ([LtBlue]D:\\root\\example[Reset])
3155[LtCyan]googolplex.gz[Reset] ([LtBlue]D:\\root\\example\\files\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3156green.txt ([LtBlue]D:\\root\\example\\files\\colours[Reset])
3157[LtCyan]ordinals[Reset] ([LtBlue]D:\\root\\example\\files\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3158red.txt ([LtBlue]D:\\root\\example\\files\\colours[Reset])
3159\"three\" 'four'.txt ([LtBlue]D:\\root\\example\\files\\numbers\\one two[Reset])
3160";
3161        let files = create_files("D:", "/root", "");
3162        let files = modify_files_by_name(files);
3163        let config = Config::default()
3164            .with_sort_name(true)
3165            .with_only_path(true)
3166            .with_abs_path(true);
3167        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3168    }
3169
3170    #[gtest]
3171    #[cfg(windows)]
3172    fn test_prints_absolute_paths_sorted_by_name_on_git_bash() {
3173        let expected = "\
3174[LtGreen]alpha.sh[Reset] ([LtBlue]/d/root/example/files/colours[Reset])
3175blue.txt ([LtBlue]/d/root/example/files/colours[Reset])
3176[LtCyan]count.sh[Reset] ([LtBlue]/d/root/example/files/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3177[DkGreen]find.sh[Reset] ([LtBlue]/d/root/example[Reset])
3178[LtCyan]googolplex.gz[Reset] ([LtBlue]/d/root/example/files/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3179green.txt ([LtBlue]/d/root/example/files/colours[Reset])
3180[LtCyan]ordinals[Reset] ([LtBlue]/d/root/example/files/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3181red.txt ([LtBlue]/d/root/example/files/colours[Reset])
3182\"three\" 'four'.txt ([LtBlue]/d/root/example/files/numbers/one two[Reset])
3183";
3184        let files = create_files("D:", "/root", "");
3185        let files = modify_files_by_name(files);
3186        let config = Config::default()
3187            .with_sort_name(true)
3188            .with_only_path(true)
3189            .with_abs_path(true);
3190        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3191    }
3192
3193    #[gtest]
3194    #[cfg(not(windows))]
3195    fn test_prints_absolute_paths_sorted_by_name_on_linux() {
3196        let expected = "\
3197[LtGreen]alpha.sh[Reset] ([LtBlue]/root/example/files/colours[Reset])
3198blue.txt ([LtBlue]/root/example/files/colours[Reset])
3199[LtCyan]count.sh[Reset] ([LtBlue]/root/example/files/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3200[DkGreen]find.sh[Reset] ([LtBlue]/root/example[Reset])
3201[LtCyan]googolplex.gz[Reset] ([LtBlue]/root/example/files/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3202green.txt ([LtBlue]/root/example/files/colours[Reset])
3203[LtCyan]ordinals[Reset] ([LtBlue]/root/example/files/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3204red.txt ([LtBlue]/root/example/files/colours[Reset])
3205\"three\" 'four'.txt ([LtBlue]/root/example/files/numbers/one two[Reset])
3206";
3207        let files = create_files("", "/root", "");
3208        let files = modify_files_by_name(files);
3209        let config = Config::default()
3210            .with_sort_name(true)
3211            .with_only_path(true)
3212            .with_abs_path(true);
3213        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3214    }
3215
3216    #[gtest]
3217    #[cfg(windows)]
3218    fn test_prints_relative_paths_with_zip_sorted_by_name_on_windows() {
3219        let expected = "\
3220[LtGreen]alpha.sh[Reset] ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3221blue.txt ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3222[LtCyan]count.sh[Reset] ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3223[DkGreen]find.sh[Reset] ([LtBlue]example[Reset])
3224[LtCyan]googolplex.gz[Reset] ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3225green.txt ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3226[LtCyan]ordinals[Reset] ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3227red.txt ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3228\"three\" 'four'.txt ([LtBlue]example\\[LtRed]files.zip[LtBlue]\\numbers\\one two[Reset])
3229";
3230        let files = create_files("D:", "/root", "");
3231        let files = modify_files_by_name(files);
3232        let files = modify_files_for_zip(files);
3233        let config = Config::default()
3234            .with_zip_expand(true)
3235            .with_sort_name(true)
3236            .with_only_path(true)
3237            .with_abs_path(false);
3238        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3239    }
3240
3241    #[gtest]
3242    #[cfg(windows)]
3243    fn test_prints_relative_paths_with_zip_sorted_by_name_on_git_bash() {
3244        let expected = "\
3245[LtGreen]alpha.sh[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3246blue.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3247[LtCyan]count.sh[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3248[DkGreen]find.sh[Reset] ([LtBlue]example[Reset])
3249[LtCyan]googolplex.gz[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3250green.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3251[LtCyan]ordinals[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3252red.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3253\"three\" 'four'.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/one two[Reset])
3254";
3255        let files = create_files("D:", "/root", "");
3256        let files = modify_files_by_name(files);
3257        let files = modify_files_for_zip(files);
3258        let config = Config::default()
3259            .with_zip_expand(true)
3260            .with_sort_name(true)
3261            .with_only_path(true)
3262            .with_abs_path(false);
3263        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3264    }
3265
3266    #[gtest]
3267    #[cfg(not(windows))]
3268    fn test_prints_relative_paths_with_zip_sorted_by_name_on_linux() {
3269        let expected = "\
3270[LtGreen]alpha.sh[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3271blue.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3272[LtCyan]count.sh[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3273[DkGreen]find.sh[Reset] ([LtBlue]example[Reset])
3274[LtCyan]googolplex.gz[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3275green.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3276[LtCyan]ordinals[Reset] ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3277red.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/colours[Reset])
3278\"three\" 'four'.txt ([LtBlue]example/[LtRed]files.zip[LtBlue]/numbers/one two[Reset])
3279";
3280        let files = create_files("", "/root", "");
3281        let files = modify_files_by_name(files);
3282        let files = modify_files_for_zip(files);
3283        let config = Config::default()
3284            .with_zip_expand(true)
3285            .with_sort_name(true)
3286            .with_only_path(true)
3287            .with_abs_path(false);
3288        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3289    }
3290
3291    #[gtest]
3292    #[cfg(windows)]
3293    fn test_prints_absolute_paths_with_zip_sorted_by_name_on_windows() {
3294        let expected = "\
3295[LtGreen]alpha.sh[Reset] ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3296blue.txt ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3297[LtCyan]count.sh[Reset] ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3298[DkGreen]find.sh[Reset] ([LtBlue]D:\\root\\example[Reset])
3299[LtCyan]googolplex.gz[Reset] ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3300green.txt ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3301[LtCyan]ordinals[Reset] ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers[Reset]) -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3302red.txt ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\colours[Reset])
3303\"three\" 'four'.txt ([LtBlue]D:\\root\\example\\[LtRed]files.zip[LtBlue]\\numbers\\one two[Reset])
3304";
3305        let files = create_files("D:", "/root", "");
3306        let files = modify_files_by_name(files);
3307        let files = modify_files_for_zip(files);
3308        let config = Config::default()
3309            .with_zip_expand(true)
3310            .with_sort_name(true)
3311            .with_only_path(true)
3312            .with_abs_path(true);
3313        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3314    }
3315
3316    #[gtest]
3317    #[cfg(windows)]
3318    fn test_prints_absolute_paths_with_zip_sorted_by_name_on_git_bash() {
3319        let expected = "\
3320[LtGreen]alpha.sh[Reset] ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3321blue.txt ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3322[LtCyan]count.sh[Reset] ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3323[DkGreen]find.sh[Reset] ([LtBlue]/d/root/example[Reset])
3324[LtCyan]googolplex.gz[Reset] ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3325green.txt ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3326[LtCyan]ordinals[Reset] ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3327red.txt ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3328\"three\" 'four'.txt ([LtBlue]/d/root/example/[LtRed]files.zip[LtBlue]/numbers/one two[Reset])
3329";
3330        let files = create_files("D:", "/root", "");
3331        let files = modify_files_by_name(files);
3332        let files = modify_files_for_zip(files);
3333        let config = Config::default()
3334            .with_zip_expand(true)
3335            .with_sort_name(true)
3336            .with_only_path(true)
3337            .with_abs_path(true);
3338        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3339    }
3340
3341    #[gtest]
3342    #[cfg(not(windows))]
3343    fn test_prints_absolute_paths_with_zip_sorted_by_name_on_linux() {
3344        let expected = "\
3345[LtGreen]alpha.sh[Reset] ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3346blue.txt ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3347[LtCyan]count.sh[Reset] ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3348[DkGreen]find.sh[Reset] ([LtBlue]/root/example[Reset])
3349[LtCyan]googolplex.gz[Reset] ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3350green.txt ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3351[LtCyan]ordinals[Reset] ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers[Reset]) -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3352red.txt ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/colours[Reset])
3353\"three\" 'four'.txt ([LtBlue]/root/example/[LtRed]files.zip[LtBlue]/numbers/one two[Reset])
3354";
3355        let files = create_files("", "/root", "");
3356        let files = modify_files_by_name(files);
3357        let files = modify_files_for_zip(files);
3358        let config = Config::default()
3359            .with_zip_expand(true)
3360            .with_sort_name(true)
3361            .with_only_path(true)
3362            .with_abs_path(true);
3363        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3364    }
3365
3366    #[gtest]
3367    #[cfg(windows)]
3368    fn test_prints_indented_paths_with_attributes_on_windows() {
3369        let expected = "\
3370drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example[Reset]
3371-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh    [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3372drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00         [LtBlue]\\-[Reset] [LtBlue]files[Reset]
3373drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3374-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh        [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3375-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3376-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3377-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3378drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3379lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh            [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3380lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz            [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3381lrw-r--r--    0  Sat 01-Apr-2023 00:00:00                 [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3382drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00                 [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3383-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt               [LtBlue]\\-[Reset] \"three\" 'four'.txt
3384";
3385        let files = create_files("D:", "/root", "../..");
3386        let config = Config::default()
3387            .with_show_precise(true)
3388            .with_show_indent(true)
3389            .with_only_path(false)
3390            .with_abs_path(true);
3391        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3392    }
3393
3394    #[gtest]
3395    #[cfg(windows)]
3396    fn test_prints_indented_paths_with_attributes_on_git_bash() {
3397        let expected = "\
3398drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example[Reset]
3399-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh    [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3400drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00         [LtBlue]\\-[Reset] [LtBlue]files[Reset]
3401drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3402-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh        [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3403-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3404-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3405-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3406drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3407lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh            [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3408lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz            [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3409lrw-r--r--    0  Sat 01-Apr-2023 00:00:00                 [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3410drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00                 [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3411-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt               [LtBlue]\\-[Reset] \"three\" 'four'.txt
3412";
3413        let files = create_files("D:", "/root", "../..");
3414        let config = Config::default()
3415            .with_show_precise(true)
3416            .with_show_indent(true)
3417            .with_only_path(false)
3418            .with_abs_path(true);
3419        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3420    }
3421
3422    #[gtest]
3423    #[cfg(not(windows))]
3424    fn test_prints_indented_paths_with_attributes_on_linux() {
3425        let expected = "\
3426drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example[Reset]
3427-rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh    [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3428drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00         [LtBlue]\\-[Reset] [LtBlue]files[Reset]
3429drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3430-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh        [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3431-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3432-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3433-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3434drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3435lrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh            [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3436lrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz            [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3437lrw-r--r--    0  Sat 01-Apr-2023 00:00:00                 [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3438drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00                 [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3439-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt               [LtBlue]\\-[Reset] \"three\" 'four'.txt
3440";
3441        let files = create_files("", "/root", "../..");
3442        let config = Config::default()
3443            .with_show_precise(true)
3444            .with_show_indent(true)
3445            .with_only_path(false)
3446            .with_abs_path(true);
3447        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3448    }
3449
3450    #[gtest]
3451    #[cfg(windows)]
3452    fn test_prints_indented_paths_no_attributes_on_windows() {
3453        let expected = "\
3454[LtBlue]example[Reset]
3455 [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3456 [LtBlue]\\-[Reset] [LtBlue]files[Reset]
3457     [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3458     [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3459     [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3460     [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3461     [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3462     [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3463         [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3464         [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3465         [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3466         [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3467             [LtBlue]\\-[Reset] \"three\" 'four'.txt
3468";
3469        let files = create_files("D:", "/root", "../..");
3470        let config = Config::default()
3471            .with_show_indent(true)
3472            .with_only_path(true)
3473            .with_abs_path(true);
3474        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3475    }
3476
3477    #[gtest]
3478    #[cfg(windows)]
3479    fn test_prints_indented_paths_no_attributes_on_git_bash() {
3480        let expected = "\
3481[LtBlue]example[Reset]
3482 [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3483 [LtBlue]\\-[Reset] [LtBlue]files[Reset]
3484     [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3485     [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3486     [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3487     [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3488     [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3489     [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3490         [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3491         [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3492         [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3493         [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3494             [LtBlue]\\-[Reset] \"three\" 'four'.txt
3495";
3496        let files = create_files("D:", "/root", "../..");
3497        let config = Config::default()
3498            .with_show_indent(true)
3499            .with_only_path(true)
3500            .with_abs_path(true);
3501        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3502    }
3503
3504    #[gtest]
3505    #[cfg(not(windows))]
3506    fn test_prints_indented_paths_no_attributes_on_linux() {
3507        let expected = "\
3508[LtBlue]example[Reset]
3509 [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3510 [LtBlue]\\-[Reset] [LtBlue]files[Reset]
3511     [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3512     [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3513     [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3514     [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3515     [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3516     [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3517         [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3518         [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3519         [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3520         [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3521             [LtBlue]\\-[Reset] \"three\" 'four'.txt
3522";
3523        let files = create_files("", "/root", "../..");
3524        let config = Config::default()
3525            .with_show_indent(true)
3526            .with_only_path(true)
3527            .with_abs_path(true);
3528        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3529    }
3530
3531    #[gtest]
3532    #[cfg(windows)]
3533    fn test_prints_indented_paths_with_zip_with_attributes_on_windows() {
3534        let expected = "\
3535-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example[Reset]
3536--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh    [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3537zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00         [LtBlue]\\-[Reset] [LtRed]files.zip[Reset]
3538zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3539z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh        [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3540z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3541z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3542z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3543zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3544zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh            [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3545zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz            [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3546zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00                 [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3547zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00                 [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3548z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt               [LtBlue]\\-[Reset] \"three\" 'four'.txt
3549";
3550        let files = create_files("D:", "/root", "../..");
3551        let files = modify_files_for_zip(files);
3552        let config = Config::default()
3553            .with_zip_expand(true)
3554            .with_show_precise(true)
3555            .with_show_indent(true)
3556            .with_only_path(false)
3557            .with_abs_path(true);
3558        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3559    }
3560
3561    #[gtest]
3562    #[cfg(windows)]
3563    fn test_prints_indented_paths_with_zip_with_attributes_on_git_bash() {
3564        let expected = "\
3565-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example[Reset]
3566--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh    [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3567zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00         [LtBlue]\\-[Reset] [LtRed]files.zip[Reset]
3568zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3569z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh        [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3570z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3571z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3572z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3573zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3574zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh            [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3575zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz            [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3576zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00                 [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3577zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00                 [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3578z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt               [LtBlue]\\-[Reset] \"three\" 'four'.txt
3579";
3580        let files = create_files("D:", "/root", "../..");
3581        let files = modify_files_for_zip(files);
3582        let config = Config::default()
3583            .with_zip_expand(true)
3584            .with_show_precise(true)
3585            .with_show_indent(true)
3586            .with_only_path(false)
3587            .with_abs_path(true);
3588        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3589    }
3590
3591    #[gtest]
3592    #[cfg(not(windows))]
3593    fn test_prints_indented_paths_with_zip_with_attributes_on_linux() {
3594        let expected = "\
3595-drwxr-xr-x    0  Sun 31-Dec-2023 00:00:00        [LtBlue]example[Reset]
3596--rwxr-xr-x   10  Wed 01-Nov-2023 00:00:00  .sh    [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3597zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00         [LtBlue]\\-[Reset] [LtRed]files.zip[Reset]
3598zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3599z-rwxr--r--   20  Sun 01-Oct-2023 00:00:00  .sh        [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3600z-rw-r--r--   30  Fri 01-Sep-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3601z-rw-r--r--   40  Tue 01-Aug-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3602z-rw-r--r--   50  Sat 01-Jul-2023 00:00:00  .txt       [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3603zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00             [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3604zlrwxr--r--   60  Thu 01-Jun-2023 00:00:00  .sh            [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3605zlrw-r--r--  999  Mon 01-May-2023 00:00:00  .gz            [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3606zlrw-r--r--    0  Sat 01-Apr-2023 00:00:00                 [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3607zdrwxr-xr-x    0  Sun 31-Dec-2023 00:00:00                 [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3608z-rw-r--r--   70  Wed 01-Mar-2023 00:00:00  .txt               [LtBlue]\\-[Reset] \"three\" 'four'.txt
3609";
3610        let files = create_files("", "/root", "../..");
3611        let files = modify_files_for_zip(files);
3612        let config = Config::default()
3613            .with_zip_expand(true)
3614            .with_show_precise(true)
3615            .with_show_indent(true)
3616            .with_only_path(false)
3617            .with_abs_path(true);
3618        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3619    }
3620
3621    #[gtest]
3622    #[cfg(windows)]
3623    fn test_prints_indented_paths_with_zip_no_attributes_on_windows() {
3624        let expected = "\
3625[LtBlue]example[Reset]
3626 [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3627 [LtBlue]\\-[Reset] [LtRed]files.zip[Reset]
3628     [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3629     [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3630     [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3631     [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3632     [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3633     [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3634         [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtGreen]count.sh[Reset]
3635         [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtRed]googolplex.gz[Reset]
3636         [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]D:\\etc\\numbers\\[Reset][LtBlue]ordinals\\[Reset]
3637         [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3638             [LtBlue]\\-[Reset] \"three\" 'four'.txt
3639";
3640        let files = create_files("D:", "/root", "../..");
3641        let files = modify_files_for_zip(files);
3642        let config = Config::default()
3643            .with_zip_expand(true)
3644            .with_show_indent(true)
3645            .with_only_path(true)
3646            .with_abs_path(true);
3647        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3648    }
3649
3650    #[gtest]
3651    #[cfg(windows)]
3652    fn test_prints_indented_paths_with_zip_no_attributes_on_git_bash() {
3653        let expected = "\
3654[LtBlue]example[Reset]
3655 [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3656 [LtBlue]\\-[Reset] [LtRed]files.zip[Reset]
3657     [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3658     [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3659     [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3660     [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3661     [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3662     [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3663         [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3664         [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3665         [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/d/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3666         [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3667             [LtBlue]\\-[Reset] \"three\" 'four'.txt
3668";
3669        let files = create_files("D:", "/root", "../..");
3670        let files = modify_files_for_zip(files);
3671        let config = Config::default()
3672            .with_zip_expand(true)
3673            .with_show_indent(true)
3674            .with_only_path(true)
3675            .with_abs_path(true);
3676        pretty_assertions::assert_eq!(wrap_files(&config, true, &files), expected);
3677    }
3678
3679    #[gtest]
3680    #[cfg(not(windows))]
3681    fn test_prints_indented_paths_with_zip_no_attributes_on_linux() {
3682        let expected = "\
3683[LtBlue]example[Reset]
3684 [LtBlue]+-[Reset] [DkGreen]find.sh[Reset]
3685 [LtBlue]\\-[Reset] [LtRed]files.zip[Reset]
3686     [LtBlue]+-[Reset] [LtBlue]colours[Reset]
3687     [LtBlue]|[Reset]   [LtBlue]+-[Reset] [LtGreen]alpha.sh[Reset]
3688     [LtBlue]|[Reset]   [LtBlue]+-[Reset] blue.txt
3689     [LtBlue]|[Reset]   [LtBlue]+-[Reset] green.txt
3690     [LtBlue]|[Reset]   [LtBlue]\\-[Reset] red.txt
3691     [LtBlue]\\-[Reset] [LtBlue]numbers[Reset]
3692         [LtBlue]+-[Reset] [LtCyan]count.sh[Reset] -> [LtBlue]/etc/numbers/[Reset][LtGreen]count.sh[Reset]
3693         [LtBlue]+-[Reset] [LtCyan]googolplex.gz[Reset] -> [LtBlue]/etc/numbers/[Reset][LtRed]googolplex.gz[Reset]
3694         [LtBlue]+-[Reset] [LtCyan]ordinals[Reset] -> [LtBlue]/etc/numbers/[Reset][LtBlue]ordinals/[Reset]
3695         [LtBlue]\\-[Reset] [LtBlue]one two[Reset]
3696             [LtBlue]\\-[Reset] \"three\" 'four'.txt
3697";
3698        let files = create_files("", "/root", "../..");
3699        let files = modify_files_for_zip(files);
3700        let config = Config::default()
3701            .with_zip_expand(true)
3702            .with_show_indent(true)
3703            .with_only_path(true)
3704            .with_abs_path(true);
3705        pretty_assertions::assert_eq!(wrap_files(&config, false, &files), expected);
3706    }
3707
3708    fn wrap_mode(
3709        zip_expand: bool,
3710        inner_depth: Option<usize>,
3711        file_mode: u32,
3712        file_type: FileKind,
3713    ) -> String {
3714        let config = Config::default().with_zip_expand(zip_expand);
3715        wrap_function(&config, false, |p| p.print_mode(file_type, file_mode, inner_depth))
3716    }
3717
3718    fn wrap_size(config: &Config, file_size: u64, size_width: usize) -> String {
3719        wrap_function(config, false, |p| p.print_size(file_size, size_width))
3720    }
3721
3722    fn wrap_time(
3723        config: &Config,
3724        year: i32,
3725        month: u32,
3726        day: u32,
3727        hour: u32,
3728        minute: u32,
3729        second: u32,
3730    ) -> String {
3731        let time = create_time(year, month, day, hour, minute, second).unwrap();
3732        wrap_function(config, false, |p| p.print_time(&time, &Utc, true))
3733    }
3734
3735    #[cfg(windows)]
3736    fn wrap_version(file_ver: Option<&str>, ver_width: usize) -> String {
3737        let config = Config::default();
3738        let file_ver = file_ver.map(str::to_string);
3739        wrap_function(&config, false, |p| p.print_version(&file_ver, ver_width))
3740    }
3741
3742    fn wrap_ext(file_ext: &str, ext_width: usize) -> String {
3743        let config = Config::default();
3744        wrap_function(&config, false, |p| p.print_ext(file_ext, ext_width))
3745    }
3746
3747    fn wrap_total(num_files: usize, num_dirs: usize) -> String {
3748        let config = Config::default();
3749        let mut total = Total::new(RecentKind::None);
3750        total.num_files = num_files;
3751        total.num_dirs = num_dirs;
3752        wrap_function(&config, false, |p| p.print_summary(&total))
3753    }
3754
3755    fn wrap_files(config: &Config, git_bash: bool, files: &Vec<File>) -> String {
3756        let total = create_total(config, files);
3757        wrap_function(config, git_bash, |p| p.print_files(files, &total, &Utc))
3758    }
3759
3760    fn wrap_function<F>(config: &Config, git_bash: bool, func: F) -> String where
3761        F: FnOnce(&mut Printer<BufferWrapper>) -> MyResult<()>,
3762    {
3763        let mut buffer = String::new();
3764        let writer = unsafe { BufferWrapper::new(buffer.as_mut_vec()) };
3765        let colors = Some(String::from("*.gz=01;31:*.zip=01;31:*.png=01;35"));
3766        let colors = ColorMap::new(colors);
3767        let chars = IndentChars {
3768            branching: '+',
3769            terminating: '\\',
3770            horizontal: '-',
3771            vertical: '|',
3772        };
3773        let mut printer = Printer::new(
3774            config,
3775            &Utc,
3776            writer,
3777            colors,
3778            chars,
3779            git_bash,
3780        );
3781        func(&mut printer).unwrap();
3782        buffer
3783    }
3784
3785    fn create_files(drive: &str, abs_prefix: &str, rel_prefix: &str) -> Vec<File> {
3786        let abs_prefix = drive.to_string() + abs_prefix;
3787        let link_exec = PathBuf::from(drive.to_string() + "/etc/numbers/count.sh").clean();
3788        let link_file = PathBuf::from(drive.to_string() + "/etc/numbers/googolplex.gz").clean();
3789        let link_dir = PathBuf::from(drive.to_string() + "/etc/numbers/ordinals").clean();
3790        vec![
3791            create_file(&abs_prefix, rel_prefix, "example", "", "")
3792                .with_type(FileKind::Dir)
3793                .with_mode(0o755)
3794                .with_owner_ref("alice", "public")
3795                .with_size(0)
3796                .with_date(2023, 12, 31),
3797            create_file(&abs_prefix, rel_prefix, "example", "find", ".sh")
3798                .with_type(FileKind::File(ExecKind::Other))
3799                .with_mode(0o755)
3800                .with_owner_ref("root", "root")
3801                .with_size(10)
3802                .with_date(2023, 11, 01)
3803                .with_git(Some(GitFlags::default()
3804                    .with_added(true)
3805                    .with_modified(true)
3806                    .with_renamed(true)
3807                    .with_untracked(true)
3808                    .with_ignored(true)))
3809                .with_sig_str("#!/u"),
3810            create_file(&abs_prefix, rel_prefix, "example/files", "", "")
3811                .with_type(FileKind::Dir)
3812                .with_mode(0o755)
3813                .with_owner_ref("alice", "public")
3814                .with_size(0)
3815                .with_date(2023, 12, 31),
3816            create_file(&abs_prefix, rel_prefix, "example/files/colours", "", "")
3817                .with_type(FileKind::Dir)
3818                .with_mode(0o755)
3819                .with_owner_ref("alice", "public")
3820                .with_size(0)
3821                .with_date(2023, 12, 31),
3822            create_file(&abs_prefix, rel_prefix, "example/files/colours", "alpha", ".sh")
3823                .with_type(FileKind::File(ExecKind::User))
3824                .with_mode(0o744)
3825                .with_owner_ref("alice", "public")
3826                .with_size(20)
3827                .with_date(2023, 10, 01)
3828                .with_git(Some(GitFlags::default().with_added(true)))
3829                .with_sig_str("#!/u"),
3830            create_file(&abs_prefix, rel_prefix, "example/files/colours", "blue", ".txt")
3831                .with_type(FileKind::File(ExecKind::None))
3832                .with_mode(0o644)
3833                .with_owner_ref("alice", "public")
3834                .with_size(30)
3835                .with_date(2023, 09, 01)
3836                .with_git(Some(GitFlags::default().with_modified(true)))
3837                .with_sig_str("BLUE"),
3838            create_file(&abs_prefix, rel_prefix, "example/files/colours", "green", ".txt")
3839                .with_type(FileKind::File(ExecKind::None))
3840                .with_mode(0o644)
3841                .with_owner_ref("alice", "public")
3842                .with_size(40)
3843                .with_date(2023, 08, 01)
3844                .with_git(Some(GitFlags::default().with_renamed(true)))
3845                .with_sig_str("GREE"),
3846            create_file(&abs_prefix, rel_prefix, "example/files/colours", "red", ".txt")
3847                .with_type(FileKind::File(ExecKind::None))
3848                .with_mode(0o644)
3849                .with_owner_ref("alice", "public")
3850                .with_size(50)
3851                .with_date(2023, 07, 01)
3852                .with_git(Some(GitFlags::default().with_untracked(true)))
3853                .with_sig_str("RED"),
3854            create_file(&abs_prefix, rel_prefix, "example/files/numbers", "", "")
3855                .with_type(FileKind::Dir)
3856                .with_mode(0o755)
3857                .with_owner_ref("bob", "public")
3858                .with_size(0)
3859                .with_date(2023, 12, 31),
3860            create_file(&abs_prefix, rel_prefix, "example/files/numbers", "count", ".sh")
3861                .with_type(FileKind::Link(true))
3862                .with_mode(0o744)
3863                .with_owner_ref("bob", "public")
3864                .with_size(60)
3865                .with_date(2023, 06, 01)
3866                .with_sig_str("#!/u")
3867                .with_link(link_exec, FileKind::File(ExecKind::User)),
3868            create_file(&abs_prefix, rel_prefix, "example/files/numbers", "googolplex", ".gz")
3869                .with_type(FileKind::Link(true))
3870                .with_mode(0o644)
3871                .with_owner_ref("bob", "public")
3872                .with_size(999)
3873                .with_date(2023, 05, 01)
3874                .with_link(link_file, FileKind::File(ExecKind::None)),
3875            create_file(&abs_prefix, rel_prefix, "example/files/numbers", "ordinals", "")
3876                .with_type(FileKind::Link(true))
3877                .with_mode(0o644)
3878                .with_owner_ref("bob", "public")
3879                .with_size(0)
3880                .with_date(2023, 04, 01)
3881                .with_link(link_dir, FileKind::Dir),
3882            create_file(&abs_prefix, rel_prefix, "example/files/numbers/one two", "", "")
3883                .with_type(FileKind::Dir)
3884                .with_mode(0o755)
3885                .with_size(0)
3886                .with_date(2023, 12, 31),
3887            create_file(&abs_prefix, rel_prefix, "example/files/numbers/one two", "\"three\" 'four'", ".txt")
3888                .with_type(FileKind::File(ExecKind::None))
3889                .with_mode(0o644)
3890                .with_size(70)
3891                .with_date(2023, 03, 01)
3892                .with_git(Some(GitFlags::default().with_ignored(true)))
3893                .with_sig_vec([0xff, 0xfe, 0x33, 0x34]),
3894        ]
3895    }
3896
3897    fn modify_files_by_name(files: Vec<File>) -> Vec<File> {
3898        let mut files = files.into_iter()
3899            .filter(|file| file.file_type != FileKind::Dir)
3900            .collect::<Vec<File>>();
3901        files.sort_by(&compare_files_by_name);
3902        files
3903    }
3904
3905    fn compare_files_by_name(left: &File, right: &File) -> Ordering {
3906        let left = left.file_name.trim_start_matches("\"");
3907        let right = right.file_name.trim_start_matches("\"");
3908        left.cmp(&right)
3909    }
3910
3911    fn modify_files_for_zip(files: Vec<File>) -> Vec<File> {
3912        files.into_iter().map(modify_file_for_zip).collect()
3913    }
3914
3915    fn modify_file_for_zip(file: File) -> File {
3916        let (abs_dir, mut inner_depth) = modify_dir_for_zip(&file.abs_dir);
3917        let (rel_dir, _) = modify_dir_for_zip(&file.rel_dir);
3918        if file.file_type != FileKind::Dir {
3919            inner_depth = inner_depth.map(|depth| depth + 1);
3920        }
3921        file.with_dirs(abs_dir, rel_dir).with_inner_depth(inner_depth)
3922    }
3923
3924    fn modify_dir_for_zip(old_dir: &Path) -> (PathBuf, Option<usize>) {
3925        let mut new_dir = PathBuf::new();
3926        let mut inner_depth = None;
3927        for component in old_dir.components() {
3928            if let Component::Normal(dir) = component {
3929                if dir == "files" {
3930                    new_dir.push("files.zip");
3931                    inner_depth = Some(0);
3932                    continue;
3933                }
3934            }
3935            new_dir.push(component);
3936            inner_depth = inner_depth.map(|depth| depth + 1);
3937        }
3938        (new_dir, inner_depth)
3939    }
3940
3941    #[cfg(windows)]
3942    fn create_files_with_version() -> Vec<File> {
3943        vec![
3944            create_file("", "", "", "binary", ".exe")
3945                .with_type(FileKind::File(ExecKind::User))
3946                .with_mode(0o744)
3947                .with_size(999)
3948                .with_date(2024, 01, 01)
3949                .with_version(String::from("12.3.4.0")),
3950            create_file("", "", "", "library", ".dll")
3951                .with_type(FileKind::File(ExecKind::None))
3952                .with_mode(0o744)
3953                .with_size(999)
3954                .with_date(2024, 01, 01)
3955                .with_version(String::from("5.67.89.0")),
3956            create_file("", "", "", "readme", ".txt")
3957                .with_type(FileKind::File(ExecKind::None))
3958                .with_mode(0o644)
3959                .with_size(999)
3960                .with_date(2024, 01, 01),
3961        ]
3962    }
3963
3964    fn create_file(
3965        abs_prefix: &str,
3966        rel_prefix: &str,
3967        file_dir: &str,
3968        file_name: &str,
3969        file_ext: &str,
3970    ) -> File {
3971        let abs_dir = PathBuf::from(abs_prefix).join(file_dir).clean();
3972        let rel_dir = PathBuf::from(rel_prefix).join(file_dir).clean();
3973        let file_depth = PathBuf::from(file_dir).join(file_name).components().count();
3974        let file_name = format!("{file_name}{file_ext}");
3975        let file_ext = String::from(file_ext);
3976        File::new(abs_dir, rel_dir, file_depth, None, file_name, file_ext, FileKind::Other)
3977    }
3978
3979    fn create_total(config: &Config, files: &Vec<File>) -> Total {
3980        let start_time = create_date(2023, 1, 1).unwrap();
3981        let start_time = match config.filter_recent() {
3982            RecentKind::None => RecentKind::None,
3983            RecentKind::Before(_) => RecentKind::Before(start_time),
3984            RecentKind::After(_) => RecentKind::After(start_time),
3985        };
3986        Total::from_files(start_time, config, files)
3987    }
3988
3989    struct BufferWrapper<'a> {
3990        buffer: &'a mut Vec<u8>,
3991    }
3992
3993    impl<'a> BufferWrapper<'a> {
3994        fn new(buffer: &'a mut Vec<u8>) -> Self {
3995            Self { buffer }
3996        }
3997    }
3998
3999    impl<'a> Write for BufferWrapper<'a> {
4000        fn write(&mut self, buffer: &[u8]) -> io::Result<usize> {
4001            self.buffer.write(buffer)
4002        }
4003
4004        fn flush(&mut self) -> io::Result<()> {
4005            Ok(())
4006        }
4007    }
4008
4009    impl<'a> WriteColor for BufferWrapper<'a> {
4010        fn supports_color(&self) -> bool {
4011            false
4012        }
4013
4014        fn set_color(&mut self, color: &ColorSpec) -> io::Result<()> {
4015            let bold = if color.bold() { "Lt" } else { "Dk" };
4016            let fg = match color.fg() {
4017                Some(Color::Black) => "Black",
4018                Some(Color::Blue) => "Blue",
4019                Some(Color::Green) => "Green",
4020                Some(Color::Red) => "Red",
4021                Some(Color::Cyan) => "Cyan",
4022                Some(Color::Magenta) => "Magenta",
4023                Some(Color::Yellow) => "Yellow",
4024                Some(Color::White) => "White",
4025                Some(_) => "Other",
4026                None => "None",
4027            };
4028            write!(&mut self.buffer, "[{bold}{fg}]")?;
4029            Ok(())
4030        }
4031
4032        fn reset(&mut self) -> io::Result<()> {
4033            write!(&mut self.buffer, "[Reset]")?;
4034            Ok(())
4035        }
4036    }
4037}