From a4ca78dbe41267a60931b19fe3875e78cf721b72 Mon Sep 17 00:00:00 2001 From: "andy.boot" Date: Sun, 8 Dec 2019 14:46:45 +0000 Subject: [PATCH 1/3] Add option flag for no colors https://github.com/bootandy/dust/issues/37 --- src/display.rs | 45 ++++++++++++++++++++++++++++++++++++--------- src/main.rs | 7 +++++++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/display.rs b/src/display.rs index 752f12c..5a9733b 100644 --- a/src/display.rs +++ b/src/display.rs @@ -72,7 +72,13 @@ impl DisplayData { } } -pub fn draw_it(permissions: bool, use_full_path: bool, is_reversed: bool, root_node: Node) { +pub fn draw_it( + permissions: bool, + use_full_path: bool, + is_reversed: bool, + colors_on: bool, + root_node: Node, +) { if !permissions { eprintln!("Did not have permissions for all directories"); } @@ -83,11 +89,17 @@ pub fn draw_it(permissions: bool, use_full_path: bool, is_reversed: bool, root_n for c in display_data.get_children_from_node(root_node) { let first_tree_chars = display_data.get_first_chars(); - display_node(c, true, first_tree_chars, &display_data) + display_node(c, true, colors_on, first_tree_chars, &display_data) } } -fn display_node(node: Node, is_biggest: bool, indent: &str, display_data: &DisplayData) { +fn display_node( + node: Node, + is_biggest: bool, + colors_on: bool, + indent: &str, + display_data: &DisplayData, +) { let short = display_data.short_paths; let mut num_siblings = node.children.len() as u64; @@ -97,7 +109,7 @@ fn display_node(node: Node, is_biggest: bool, indent: &str, display_data: &Displ let size = node.size; if !display_data.is_reversed { - print_this_node(&*name, size, is_biggest, short, indent); + print_this_node(&*name, size, is_biggest, short, colors_on, indent); } for c in display_data.get_children_from_node(node) { @@ -105,11 +117,11 @@ fn display_node(node: Node, is_biggest: bool, indent: &str, display_data: &Displ let chars = display_data.get_tree_chars(num_siblings, max_sibling, !c.children.is_empty()); let is_biggest = display_data.is_biggest(num_siblings, max_sibling); let full_indent = new_indent.clone() + chars; - display_node(c, is_biggest, &*full_indent, display_data) + display_node(c, is_biggest, colors_on, &*full_indent, display_data) } if display_data.is_reversed { - print_this_node(&*name, size, is_biggest, short, indent); + print_this_node(&*name, size, is_biggest, short, colors_on, indent); } } @@ -130,11 +142,25 @@ fn clean_indentation_string(s: &str) -> String { is } -fn print_this_node(name: &str, size: u64, is_biggest: bool, short_paths: bool, indentation: &str) { +fn print_this_node( + name: &str, + size: u64, + is_biggest: bool, + short_paths: bool, + colors_on: bool, + indentation: &str, +) { let pretty_size = format!("{:>5}", human_readable_number(size),); println!( "{}", - format_string(name, is_biggest, short_paths, &*pretty_size, indentation) + format_string( + name, + is_biggest, + short_paths, + colors_on, + &*pretty_size, + indentation + ) ) } @@ -142,6 +168,7 @@ pub fn format_string( dir_name: &str, is_biggest: bool, short_paths: bool, + colors_on: bool, size: &str, indentation: &str, ) -> String { @@ -154,7 +181,7 @@ pub fn format_string( }; format!( "{} {} {}", - if is_biggest { + if is_biggest && colors_on { Fixed(196).paint(size) } else { Style::new().paint(size) diff --git a/src/main.rs b/src/main.rs index 29c4642..93369dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,6 +57,12 @@ fn main() { .long("reverse") .help("If applied tree will be printed upside down (biggest lowest)"), ) + .arg( + Arg::with_name("no_colors") + .short("c") + .long("no_colors") + .help("If applied no colors will be printed (normally largest directories are marked in red"), + ) .arg(Arg::with_name("inputs").multiple(true)) .get_matches(); @@ -112,6 +118,7 @@ fn main() { permissions, use_full_path, options.is_present("reverse"), + !options.is_present("no_colors"), tree, ); } From 6a65570f3f327bd72ade762c6bfb220f0c58a68c Mon Sep 17 00:00:00 2001 From: "andy.boot" Date: Sun, 8 Dec 2019 22:44:36 +0000 Subject: [PATCH 2/3] Refactor tests Make use of the 'is' more to test the entire output. Add test for no_color mode. Replace several calls to format_string with calls that build a string directly. I feel format_string is becoming unweildly and this simplfies the tests --- src/display.rs | 41 +++----- src/main.rs | 5 +- src/tests.rs | 272 ++++++++++++++++++++----------------------------- 3 files changed, 125 insertions(+), 193 deletions(-) diff --git a/src/display.rs b/src/display.rs index 5a9733b..86667f5 100644 --- a/src/display.rs +++ b/src/display.rs @@ -9,6 +9,7 @@ static UNITS: [char; 4] = ['T', 'G', 'M', 'K']; pub struct DisplayData { pub short_paths: bool, pub is_reversed: bool, + pub colors_on: bool, } impl DisplayData { @@ -76,7 +77,7 @@ pub fn draw_it( permissions: bool, use_full_path: bool, is_reversed: bool, - colors_on: bool, + no_colors: bool, root_node: Node, ) { if !permissions { @@ -85,23 +86,16 @@ pub fn draw_it( let display_data = DisplayData { short_paths: !use_full_path, is_reversed, + colors_on: !no_colors, }; for c in display_data.get_children_from_node(root_node) { let first_tree_chars = display_data.get_first_chars(); - display_node(c, true, colors_on, first_tree_chars, &display_data) + display_node(c, true, first_tree_chars, &display_data) } } -fn display_node( - node: Node, - is_biggest: bool, - colors_on: bool, - indent: &str, - display_data: &DisplayData, -) { - let short = display_data.short_paths; - +fn display_node(node: Node, is_biggest: bool, indent: &str, display_data: &DisplayData) { let mut num_siblings = node.children.len() as u64; let max_sibling = num_siblings; let new_indent = clean_indentation_string(indent); @@ -109,7 +103,7 @@ fn display_node( let size = node.size; if !display_data.is_reversed { - print_this_node(&*name, size, is_biggest, short, colors_on, indent); + print_this_node(&*name, size, is_biggest, display_data, indent); } for c in display_data.get_children_from_node(node) { @@ -117,11 +111,11 @@ fn display_node( let chars = display_data.get_tree_chars(num_siblings, max_sibling, !c.children.is_empty()); let is_biggest = display_data.is_biggest(num_siblings, max_sibling); let full_indent = new_indent.clone() + chars; - display_node(c, is_biggest, colors_on, &*full_indent, display_data) + display_node(c, is_biggest, &*full_indent, display_data) } if display_data.is_reversed { - print_this_node(&*name, size, is_biggest, short, colors_on, indent); + print_this_node(&*name, size, is_biggest, display_data, indent); } } @@ -146,34 +140,25 @@ fn print_this_node( name: &str, size: u64, is_biggest: bool, - short_paths: bool, - colors_on: bool, + display_data: &DisplayData, indentation: &str, ) { let pretty_size = format!("{:>5}", human_readable_number(size),); println!( "{}", - format_string( - name, - is_biggest, - short_paths, - colors_on, - &*pretty_size, - indentation - ) + format_string(name, is_biggest, display_data, &*pretty_size, indentation) ) } pub fn format_string( dir_name: &str, is_biggest: bool, - short_paths: bool, - colors_on: bool, + display_data: &DisplayData, size: &str, indentation: &str, ) -> String { let printable_name = { - if short_paths { + if display_data.short_paths { dir_name.split('/').last().unwrap_or(dir_name) } else { dir_name @@ -181,7 +166,7 @@ pub fn format_string( }; format!( "{} {} {}", - if is_biggest && colors_on { + if is_biggest && display_data.colors_on { Fixed(196).paint(size) } else { Style::new().paint(size) diff --git a/src/main.rs b/src/main.rs index 93369dd..90a6030 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,7 +101,6 @@ fn main() { } let use_apparent_size = options.is_present("display_apparent_size"); - let use_full_path = options.is_present("display_full_paths"); let simplified_dirs = simplify_dir_names(target_dirs); let (permissions, nodes) = get_dir_tree(&simplified_dirs, use_apparent_size, threads); @@ -116,9 +115,9 @@ fn main() { draw_it( permissions, - use_full_path, + options.is_present("display_full_paths"), options.is_present("reverse"), - !options.is_present("no_colors"), + options.is_present("no_colors"), tree, ); } diff --git a/src/tests.rs b/src/tests.rs index 53c1c36..e733904 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,4 +1,5 @@ use super::*; +use crate::display::DisplayData; use display::format_string; use std::fs::File; use std::io::Write; @@ -37,67 +38,83 @@ pub fn test_main_multi_arg() { #[cfg(target_os = "macos")] fn main_output(short_paths: bool) -> String { + let d = DisplayData { + short_paths, + is_reversed: false, + colors_on: true, + }; format!( "{} {} {} {}", - format_string("src/test_dir", true, short_paths, " 4.0K", "─┬"), - format_string("src/test_dir/many", true, short_paths, " 4.0K", " └─┬",), - format_string( - "src/test_dir/many/hello_file", - true, - short_paths, - " 4.0K", - " ├──", - ), - format_string( - "src/test_dir/many/a_file", - false, - short_paths, - " 0B", - " └──", - ), + format_string("src/test_dir", true, &d, " 4.0K", "─┬"), + format_string("src/test_dir/many", true, &d, " 4.0K", " └─┬",), + format_string("src/test_dir/many/hello_file", true, &d, " 4.0K", " ├──",), + format_string("src/test_dir/many/a_file", false, &d, " 0B", " └──",), ) } #[cfg(target_os = "linux")] fn main_output(short_paths: bool) -> String { + let d = DisplayData { + short_paths, + is_reversed: false, + colors_on: true, + }; format!( "{} {} {} {}", - format_string("src/test_dir", true, short_paths, " 12K", "─┬"), - format_string("src/test_dir/many", true, short_paths, " 8.0K", " └─┬",), - format_string( - "src/test_dir/many/hello_file", - true, - short_paths, - " 4.0K", - " ├──", - ), - format_string( - "src/test_dir/many/a_file", - false, - short_paths, - " 0B", - " └──", - ), + format_string("src/test_dir", true, &d, " 12K", "─┬"), + format_string("src/test_dir/many", true, &d, " 8.0K", " └─┬",), + format_string("src/test_dir/many/hello_file", true, &d, " 4.0K", " ├──",), + format_string("src/test_dir/many/a_file", false, &d, " 0B", " └──",), ) } +#[test] +pub fn test_no_color_flag() { + assert_cli::Assert::main_binary() + .with_args(&["-c", "src/test_dir/"]) + .stdout() + .is(no_color_flag_output()) + .unwrap(); +} + +#[cfg(target_os = "macos")] +fn no_color_flag_output() -> String { + " + 4.0K ─┬ test_dir + 4.0K └─┬ many + 4.0K ├── hello_file + 0B └── a_file + " + .to_string() +} + +#[cfg(target_os = "linux")] +fn no_color_flag_output() -> String { + " + 12K ─┬ test_dir + 8.0K └─┬ many + 4.0K ├── hello_file + 0B └── a_file + " + .to_string() +} + #[test] pub fn test_apparent_size() { + let d = DisplayData { + short_paths: true, + is_reversed: false, + colors_on: true, + }; let r = format!( "{}", - format_string( - "src/test_dir/many/hello_file", - true, - true, - " 6B", - " ├──", - ), + format_string("src/test_dir/many/hello_file", true, &d, " 6B", " ├──",), ); assert_cli::Assert::main_binary() @@ -161,41 +178,21 @@ pub fn test_soft_sym_link() { .output(); assert!(c.is_ok()); - let r = soft_sym_link_output(dir_s, file_path_s, link_name_s); + let a = format!(" ─┬ {}", dir_s); + let b = format!(" ├── {}", file_path_s); + let c = format!(" └── {}", link_name_s); - // We cannot guarantee which version will appear first. - // TODO: Consider adding predictable iteration order (sort file entries by name?) assert_cli::Assert::main_binary() - .with_args(&[dir_s]) + .with_args(&["-p", &dir_s]) .stdout() - .contains(r) + .contains(a) + .stdout() + .contains(b) + .stdout() + .contains(c) .unwrap(); } -#[cfg(target_os = "macos")] -fn soft_sym_link_output(dir: &str, file_path: &str, link_name: &str) -> String { - format!( - "{} -{} -{}", - format_string(dir, true, true, " 8.0K", "─┬"), - format_string(file_path, true, true, " 4.0K", " ├──",), - format_string(link_name, false, true, " 4.0K", " └──",), - ) -} - -#[cfg(target_os = "linux")] -fn soft_sym_link_output(dir: &str, file_path: &str, link_name: &str) -> String { - format!( - "{} -{} -{}", - format_string(dir, true, true, " 8.0K", "─┬"), - format_string(file_path, true, true, " 4.0K", " ├──",), - format_string(link_name, false, true, " 0B", " └──",), - ) -} - // Hard links are ignored as the inode is the same as the file #[test] pub fn test_hard_sym_link() { @@ -212,62 +209,33 @@ pub fn test_hard_sym_link() { .output(); assert!(c.is_ok()); - let (r, r2) = hard_link_output(dir_s, file_path_s, link_name_s); + let a = format!(" ─┬ {}", dir_s); + let b = format!(" └── {}", link_name_s); + let b2 = format!(" └── {}", file_path_s); // Because this is a hard link the file and hard link look identical. Therefore // we cannot guarantee which version will appear first. - // TODO: Consider adding predictable iteration order (sort file entries by name?) let result = panic::catch_unwind(|| { assert_cli::Assert::main_binary() - .with_args(&[dir_s]) + .with_args(&["-p", dir_s]) .stdout() - .contains(r) + .contains(a.clone()) + .stdout() + .contains(b) .unwrap(); }); if result.is_err() { assert_cli::Assert::main_binary() - .with_args(&[dir_s]) + .with_args(&["-p", dir_s]) .stdout() - .contains(r2) + .contains(a) + .stdout() + .contains(b2) .unwrap(); } } -#[cfg(target_os = "macos")] -fn hard_link_output(dir_s: &str, file_path_s: &str, link_name_s: &str) -> (String, String) { - let r = format!( - "{} -{}", - format_string(dir_s, true, true, " 4.0K", "─┬"), - format_string(file_path_s, true, true, " 4.0K", " └──") - ); - let r2 = format!( - "{} -{}", - format_string(dir_s, true, true, " 4.0K", "─┬"), - format_string(link_name_s, true, true, " 4.0K", " └──") - ); - (r, r2) -} - -#[cfg(target_os = "linux")] -fn hard_link_output(dir_s: &str, file_path_s: &str, link_name_s: &str) -> (String, String) { - let r = format!( - "{} -{}", - format_string(dir_s, true, true, " 8.0K", "─┬"), - format_string(file_path_s, true, true, " 4.0K", " └──") - ); - let r2 = format!( - "{} -{}", - format_string(dir_s, true, true, " 8.0K", "─┬"), - format_string(link_name_s, true, true, " 4.0K", " └──") - ); - (r, r2) -} - -//Check we don't recurse down an infinite symlink tree +// Check we don't recurse down an infinite symlink tree #[test] pub fn test_recursive_sym_link() { let dir = Builder::new().tempdir().unwrap(); @@ -283,70 +251,50 @@ pub fn test_recursive_sym_link() { .output(); assert!(c.is_ok()); - assert_cli::Assert::main_binary() - .with_args(&[dir_s]) - .stdout() - .contains(recursive_sym_link_output(dir_s, link_name_s)) - .unwrap(); -} + let a = format!(" ─┬ {}", dir_s); + let b = format!(" └── {}", link_name_s); -#[cfg(target_os = "macos")] -fn recursive_sym_link_output(dir: &str, link_name: &str) -> String { - format!( - "{} -{}", - format_string(dir, true, true, " 4.0K", "─┬"), - format_string(link_name, true, true, " 4.0K", " └──",), - ) -} -#[cfg(target_os = "linux")] -fn recursive_sym_link_output(dir: &str, link_name: &str) -> String { - format!( - "{} -{}", - format_string(dir, true, true, " 4.0K", "─┬"), - format_string(link_name, true, true, " 0B", " └──",), - ) -} - -// Check against directories and files whos names are substrings of each other -#[test] -#[cfg(target_os = "macos")] -pub fn test_substring_of_names() { assert_cli::Assert::main_binary() - .with_args(&["src/test_dir2"]) + .with_args(&["-p", dir_s]) .stdout() - .contains(" ─┬ test_dir2") + .contains(a) .stdout() - .contains(" ├─┬ dir") - .stdout() - .contains(" │ └── hello") - .stdout() - .contains(" ├── dir_name_clash") - .stdout() - .contains(" └─┬ dir_substring") - .stdout() - .contains(" └── hello") + .contains(b) .unwrap(); } // Check against directories and files whos names are substrings of each other #[test] -#[cfg(target_os = "linux")] pub fn test_substring_of_names() { assert_cli::Assert::main_binary() - .with_args(&["src/test_dir2"]) + .with_args(&["-c", "src/test_dir2"]) .stdout() - .contains(" ─┬ test_dir2") - .stdout() - .contains(" ├─┬ dir") - .stdout() - .contains(" │ └── hello") - .stdout() - .contains(" ├─┬ dir_substring") - .stdout() - .contains(" │ └── hello") - .stdout() - .contains(" └── dir_name_clash") + .is(no_substring_of_names_output()) .unwrap(); } + +#[cfg(target_os = "linux")] +fn no_substring_of_names_output() -> String { + " + 24K ─┬ test_dir2 + 8.0K ├─┬ dir + 4.0K │ └── hello + 8.0K ├─┬ dir_substring + 4.0K │ └── hello + 4.0K └── dir_name_clash + " + .into() +} + +#[cfg(target_os = "macos")] +fn no_substring_of_names_output() -> String { + " + 12K ─┬ test_dir2 + 4.0K ├─┬ dir + 4.0K │ └── hello + 4.0K ├── dir_name_clash + 4.0K └─┬ dir_substring + 4.0K └── hello + " + .into() +} From 7e47d5b47a5ad1adf2b785d9bab54ba65d4f18ba Mon Sep 17 00:00:00 2001 From: "andy.boot" Date: Sun, 8 Dec 2019 23:35:49 +0000 Subject: [PATCH 3/3] Increment version number --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e05768c..e365e12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,7 +187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "du-dust" -version = "0.4.1" +version = "0.4.2" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 47f6ce4..10597f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "du-dust" description = "A more intuitive version of du" -version = "0.4.1" +version = "0.4.2" authors = ["bootandy ", "nebkor "] edition = "2018"