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