refactor: DisplayData

This commit is contained in:
andy.boot
2023-01-29 10:23:39 +00:00
parent 5a3e15d0ce
commit 7d13fe972c
3 changed files with 49 additions and 59 deletions
+38 -49
View File
@@ -17,22 +17,26 @@ use thousands::Separable;
pub static UNITS: [char; 4] = ['T', 'G', 'M', 'K']; pub static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];
static BLOCKS: [char; 5] = ['█', '▓', '▒', '░', ' ']; static BLOCKS: [char; 5] = ['█', '▓', '▒', '░', ' '];
pub struct DisplayData { pub struct InitialDisplayData {
pub short_paths: bool, pub short_paths: bool,
pub is_reversed: bool, pub is_reversed: bool,
pub colors_on: bool, pub colors_on: bool,
pub by_filecount: bool, pub by_filecount: bool,
pub is_screen_reader: bool, pub is_screen_reader: bool,
pub iso: bool,
}
pub struct DisplayData {
pub initial: InitialDisplayData,
pub num_chars_needed_on_left_most: usize, pub num_chars_needed_on_left_most: usize,
pub base_size: u64, pub base_size: u64,
pub longest_string_length: usize, pub longest_string_length: usize,
pub ls_colors: LsColors, pub ls_colors: LsColors,
pub iso: bool,
} }
impl DisplayData { impl DisplayData {
fn get_tree_chars(&self, was_i_last: bool, has_children: bool) -> &'static str { fn get_tree_chars(&self, was_i_last: bool, has_children: bool) -> &'static str {
match (self.is_reversed, was_i_last, has_children) { match (self.initial.is_reversed, was_i_last, has_children) {
(true, true, true) => "┌─┴", (true, true, true) => "┌─┴",
(true, true, false) => "┌──", (true, true, false) => "┌──",
(true, false, true) => "├─┴", (true, false, true) => "├─┴",
@@ -45,7 +49,7 @@ impl DisplayData {
} }
fn is_biggest(&self, num_siblings: usize, max_siblings: u64) -> bool { fn is_biggest(&self, num_siblings: usize, max_siblings: u64) -> bool {
if self.is_reversed { if self.initial.is_reversed {
num_siblings == (max_siblings - 1) as usize num_siblings == (max_siblings - 1) as usize
} else { } else {
num_siblings == 0 num_siblings == 0
@@ -53,7 +57,7 @@ impl DisplayData {
} }
fn is_last(&self, num_siblings: usize, max_siblings: u64) -> bool { fn is_last(&self, num_siblings: usize, max_siblings: u64) -> bool {
if self.is_reversed { if self.initial.is_reversed {
num_siblings == 0 num_siblings == 0
} else { } else {
num_siblings == (max_siblings - 1) as usize num_siblings == (max_siblings - 1) as usize
@@ -84,7 +88,7 @@ impl DrawData<'_> {
// TODO: can we test this? // TODO: can we test this?
fn generate_bar(&self, node: &DisplayNode, level: usize) -> String { fn generate_bar(&self, node: &DisplayNode, level: usize) -> String {
if self.display_data.is_screen_reader { if self.display_data.initial.is_screen_reader {
return level.to_string(); return level.to_string();
} }
let chars_in_bar = self.percent_bar.chars().count(); let chars_in_bar = self.percent_bar.chars().count();
@@ -108,19 +112,12 @@ impl DrawData<'_> {
} }
} }
// TODO: Push these into one object ?
#[allow(clippy::too_many_arguments)]
pub fn draw_it( pub fn draw_it(
use_full_path: bool, idd: InitialDisplayData,
is_reversed: bool,
no_colors: bool,
no_percent_bars: bool, no_percent_bars: bool,
terminal_width: usize, terminal_width: usize,
by_filecount: bool,
root_node: &DisplayNode, root_node: &DisplayNode,
iso: bool,
skip_total: bool, skip_total: bool,
is_screen_reader: bool,
) { ) {
let biggest = match skip_total { let biggest = match skip_total {
false => root_node, false => root_node,
@@ -130,11 +127,11 @@ pub fn draw_it(
.unwrap_or(root_node), .unwrap_or(root_node),
}; };
let num_chars_needed_on_left_most = if by_filecount { let num_chars_needed_on_left_most = if idd.by_filecount {
let max_size = biggest.size; let max_size = biggest.size;
max_size.separate_with_commas().chars().count() max_size.separate_with_commas().chars().count()
} else { } else {
find_biggest_size_str(root_node, iso) find_biggest_size_str(root_node, idd.iso)
}; };
assert!( assert!(
@@ -144,13 +141,8 @@ pub fn draw_it(
let allowed_width = terminal_width - num_chars_needed_on_left_most - 2; let allowed_width = terminal_width - num_chars_needed_on_left_most - 2;
let num_indent_chars = 3; let num_indent_chars = 3;
let longest_string_length = find_longest_dir_name( let longest_string_length =
root_node, find_longest_dir_name(root_node, num_indent_chars, allowed_width, &idd);
num_indent_chars,
allowed_width,
!use_full_path,
is_screen_reader,
);
let max_bar_length = if no_percent_bars || longest_string_length + 7 >= allowed_width { let max_bar_length = if no_percent_bars || longest_string_length + 7 >= allowed_width {
0 0
@@ -161,16 +153,11 @@ pub fn draw_it(
let first_size_bar = repeat(BLOCKS[0]).take(max_bar_length).collect(); let first_size_bar = repeat(BLOCKS[0]).take(max_bar_length).collect();
let display_data = DisplayData { let display_data = DisplayData {
short_paths: !use_full_path, initial: idd,
is_reversed,
colors_on: !no_colors,
by_filecount,
is_screen_reader,
num_chars_needed_on_left_most, num_chars_needed_on_left_most,
base_size: biggest.size, base_size: biggest.size,
longest_string_length, longest_string_length,
ls_colors: LsColors::from_env().unwrap_or_default(), ls_colors: LsColors::from_env().unwrap_or_default(),
iso,
}; };
let draw_data = DrawData { let draw_data = DrawData {
indent: "".to_string(), indent: "".to_string(),
@@ -182,7 +169,7 @@ pub fn draw_it(
display_node(root_node, &draw_data, true, true); display_node(root_node, &draw_data, true, true);
} else { } else {
for (count, c) in root_node for (count, c) in root_node
.get_children_from_node(draw_data.display_data.is_reversed) .get_children_from_node(draw_data.display_data.initial.is_reversed)
.enumerate() .enumerate()
{ {
let is_biggest = display_data.is_biggest(count, root_node.num_siblings()); let is_biggest = display_data.is_biggest(count, root_node.num_siblings());
@@ -204,12 +191,11 @@ fn find_longest_dir_name(
node: &DisplayNode, node: &DisplayNode,
indent: usize, indent: usize,
terminal: usize, terminal: usize,
long_paths: bool, idd: &InitialDisplayData,
is_screen_reader: bool,
) -> usize { ) -> usize {
let printable_name = get_printable_name(&node.name, long_paths); let printable_name = get_printable_name(&node.name, idd.short_paths);
let longest = if is_screen_reader { let longest = if idd.is_screen_reader {
UnicodeWidthStr::width(&*printable_name) + 1 UnicodeWidthStr::width(&*printable_name) + 1
} else { } else {
min( min(
@@ -221,7 +207,7 @@ fn find_longest_dir_name(
// each none root tree drawing is 2 more chars, hence we increment indent by 2 // each none root tree drawing is 2 more chars, hence we increment indent by 2
node.children node.children
.iter() .iter()
.map(|c| find_longest_dir_name(c, indent + 2, terminal, long_paths, is_screen_reader)) .map(|c| find_longest_dir_name(c, indent + 2, terminal, idd))
.fold(longest, max) .fold(longest, max)
} }
@@ -233,7 +219,7 @@ fn display_node(node: &DisplayNode, draw_data: &DrawData, is_biggest: bool, is_l
let to_print = format_string(node, &indent, &bar_text, is_biggest, draw_data.display_data); let to_print = format_string(node, &indent, &bar_text, is_biggest, draw_data.display_data);
if !draw_data.display_data.is_reversed { if !draw_data.display_data.initial.is_reversed {
println!("{to_print}") println!("{to_print}")
} }
@@ -246,7 +232,7 @@ fn display_node(node: &DisplayNode, draw_data: &DrawData, is_biggest: bool, is_l
let num_siblings = node.num_siblings(); let num_siblings = node.num_siblings();
for (count, c) in node for (count, c) in node
.get_children_from_node(draw_data.display_data.is_reversed) .get_children_from_node(draw_data.display_data.initial.is_reversed)
.enumerate() .enumerate()
{ {
let is_biggest = dd.display_data.is_biggest(count, num_siblings); let is_biggest = dd.display_data.is_biggest(count, num_siblings);
@@ -254,7 +240,7 @@ fn display_node(node: &DisplayNode, draw_data: &DrawData, is_biggest: bool, is_l
display_node(c, &dd, is_biggest, was_i_last); display_node(c, &dd, is_biggest, was_i_last);
} }
if draw_data.display_data.is_reversed { if draw_data.display_data.initial.is_reversed {
println!("{to_print}") println!("{to_print}")
} }
} }
@@ -295,7 +281,7 @@ fn get_printable_name<P: AsRef<Path>>(dir_name: &P, short_paths: bool) -> String
} }
fn pad_or_trim_filename(node: &DisplayNode, indent: &str, display_data: &DisplayData) -> String { fn pad_or_trim_filename(node: &DisplayNode, indent: &str, display_data: &DisplayData) -> String {
let name = get_printable_name(&node.name, display_data.short_paths); let name = get_printable_name(&node.name, display_data.initial.short_paths);
let indent_and_name = format!("{indent} {name}"); let indent_and_name = format!("{indent} {name}");
let width = UnicodeWidthStr::width(&*indent_and_name); let width = UnicodeWidthStr::width(&*indent_and_name);
@@ -340,7 +326,7 @@ pub fn format_string(
let pretty_size = get_pretty_size(node, is_biggest, display_data); let pretty_size = get_pretty_size(node, is_biggest, display_data);
let pretty_name = get_pretty_name(node, name_and_padding, display_data); let pretty_name = get_pretty_name(node, name_and_padding, display_data);
// we can clean this and the method below somehow, not sure yet // we can clean this and the method below somehow, not sure yet
if display_data.is_screen_reader { if display_data.initial.is_screen_reader {
// if screen_reader then bars is 'depth' // if screen_reader then bars is 'depth'
format!("{pretty_name} {bars} {pretty_size}{percent}") format!("{pretty_name} {bars} {pretty_size}{percent}")
} else { } else {
@@ -354,7 +340,7 @@ fn get_name_percent(
bar_chart: &str, bar_chart: &str,
display_data: &DisplayData, display_data: &DisplayData,
) -> (String, String) { ) -> (String, String) {
if display_data.is_screen_reader { if display_data.initial.is_screen_reader {
let percent = display_data.percent_size(node) * 100.0; let percent = display_data.percent_size(node) * 100.0;
let percent_size_str = format!("{percent:.0}%"); let percent_size_str = format!("{percent:.0}%");
let percents = format!(" {percent_size_str:>4}",); let percents = format!(" {percent_size_str:>4}",);
@@ -368,22 +354,22 @@ fn get_name_percent(
let name_and_padding = pad_or_trim_filename(node, indent, display_data); let name_and_padding = pad_or_trim_filename(node, indent, display_data);
(percents, name_and_padding) (percents, name_and_padding)
} else { } else {
let n = get_printable_name(&node.name, display_data.short_paths); let n = get_printable_name(&node.name, display_data.initial.short_paths);
let name = maybe_trim_filename(n, indent, display_data); let name = maybe_trim_filename(n, indent, display_data);
("".into(), name) ("".into(), name)
} }
} }
fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayData) -> String { fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayData) -> String {
let output = if display_data.by_filecount { let output = if display_data.initial.by_filecount {
node.size.separate_with_commas() node.size.separate_with_commas()
} else { } else {
human_readable_number(node.size, display_data.iso) human_readable_number(node.size, display_data.initial.iso)
}; };
let spaces_to_add = display_data.num_chars_needed_on_left_most - output.chars().count(); let spaces_to_add = display_data.num_chars_needed_on_left_most - output.chars().count();
let output = " ".repeat(spaces_to_add) + output.as_str(); let output = " ".repeat(spaces_to_add) + output.as_str();
if is_biggest && display_data.colors_on { if is_biggest && display_data.initial.colors_on {
format!("{}", Red.paint(output)) format!("{}", Red.paint(output))
} else { } else {
output output
@@ -395,7 +381,7 @@ fn get_pretty_name(
name_and_padding: String, name_and_padding: String,
display_data: &DisplayData, display_data: &DisplayData,
) -> String { ) -> String {
if display_data.colors_on { if display_data.initial.colors_on {
let meta_result = fs::metadata(&node.name); let meta_result = fs::metadata(&node.name);
let directory_color = display_data let directory_color = display_data
.ls_colors .ls_colors
@@ -433,17 +419,20 @@ mod tests {
#[cfg(test)] #[cfg(test)]
fn get_fake_display_data(longest_string_length: usize) -> DisplayData { fn get_fake_display_data(longest_string_length: usize) -> DisplayData {
DisplayData { let initial = InitialDisplayData {
short_paths: true, short_paths: true,
is_reversed: false, is_reversed: false,
colors_on: false, colors_on: false,
by_filecount: false, by_filecount: false,
is_screen_reader: false, is_screen_reader: false,
iso: false,
};
DisplayData {
initial: initial,
num_chars_needed_on_left_most: 5, num_chars_needed_on_left_most: 5,
base_size: 2_u64.pow(12), // 4.0K base_size: 2_u64.pow(12), // 4.0K
longest_string_length, longest_string_length,
ls_colors: LsColors::from_env().unwrap_or_default(), ls_colors: LsColors::from_env().unwrap_or_default(),
iso: false,
} }
} }
@@ -494,7 +483,7 @@ mod tests {
let percent_bar = "3"; let percent_bar = "3";
let is_biggest = false; let is_biggest = false;
let mut data = get_fake_display_data(20); let mut data = get_fake_display_data(20);
data.is_screen_reader = true; data.initial.is_screen_reader = true;
let s = format_string(&n, indent, percent_bar, is_biggest, &data); let s = format_string(&n, indent, percent_bar, is_biggest, &data);
assert_eq!(s, "short 3 4.0K 100%"); assert_eq!(s, "short 3 4.0K 100%");
+1 -4
View File
@@ -106,10 +106,7 @@ fn always_add_children<'a>(
} }
// Finds children of current, if in allowed_nodes adds them as children to new DisplayNode // Finds children of current, if in allowed_nodes adds them as children to new DisplayNode
fn recursive_rebuilder( fn recursive_rebuilder(allowed_nodes: &HashMap<&Path, &Node>, current: &Node) -> DisplayNode {
allowed_nodes: &HashMap<&Path, &Node>,
current: &Node,
) -> DisplayNode {
let new_children: Vec<_> = current let new_children: Vec<_> = current
.children .children
.iter() .iter()
+10 -6
View File
@@ -12,6 +12,7 @@ mod utils;
use crate::cli::build_cli; use crate::cli::build_cli;
use dir_walker::WalkData; use dir_walker::WalkData;
use display::InitialDisplayData;
use filter::AggregateData; use filter::AggregateData;
use progress::PIndicator; use progress::PIndicator;
use progress::ORDERING; use progress::ORDERING;
@@ -217,17 +218,20 @@ fn main() {
} }
if let Some(root_node) = tree { if let Some(root_node) = tree {
let idd = InitialDisplayData {
short_paths: !config.get_full_paths(&options),
is_reversed: !config.get_reverse(&options),
colors_on: !no_colors,
by_filecount,
iso,
is_screen_reader: config.get_screen_reader(&options),
};
draw_it( draw_it(
config.get_full_paths(&options), idd,
!config.get_reverse(&options),
no_colors,
config.get_no_bars(&options), config.get_no_bars(&options),
terminal_width, terminal_width,
by_filecount,
&root_node, &root_node,
iso,
config.get_skip_total(&options), config.get_skip_total(&options),
config.get_screen_reader(&options),
) )
} }
} }