ex_cli/
printer.rs

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