Massive refactor

WIP

Replace array of (string, int) pairs with tree of nodes.

A tree of nodes more accurately represents the underlying file structure
and hence is a better fit for the problem space.

Regression: Reverse doesn't work in this commit.

I suspect more methods can be simplifed and reduced.
This commit is contained in:
andy.boot
2019-10-05 17:57:47 +01:00
parent e03094a4fa
commit db6c8a019d
3 changed files with 76 additions and 127 deletions
+27 -110
View File
@@ -2,16 +2,13 @@ extern crate ansi_term;
use self::ansi_term::Colour::Fixed;
use self::ansi_term::Style;
use std::cmp::max;
use std::collections::HashSet;
use utils::{ensure_end_slash, strip_end_slash_including_root};
use utils::Node;
static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];
pub struct DisplayData {
pub short_paths: bool,
pub is_reversed: bool,
pub to_display: Vec<(String, u64)>,
}
impl DisplayData {
@@ -63,128 +60,54 @@ impl DisplayData {
num_siblings == max_siblings - 1
}
}
fn get_size(&self, node_to_print: &str) -> Option<u64> {
for &(ref k, ref v) in self.to_display.iter() {
if *k == *node_to_print {
return Some(*v);
}
}
None
}
fn count_siblings(&self, num_slashes: usize, ntp: &str) -> u64 {
self.to_display.iter().fold(0, |a, b| {
if b.0.starts_with(ntp) && b.0.as_str().matches('/').count() == num_slashes + 1 {
a + 1
} else {
a
}
})
}
fn has_children(&self, new_depth: Option<u64>, ntp: &str, num_slashes: usize) -> bool {
// this shouldn't be needed we should have already stripped
if new_depth.is_none() || new_depth.unwrap() != 1 {
for &(ref k2, _) in self.to_display.iter() {
let ntp_with_slash = String::from(ntp.to_owned() + "/");
if k2.starts_with(ntp_with_slash.as_str())
&& k2.matches('/').count() == num_slashes + 1
{
return true;
}
}
}
false
}
}
pub fn draw_it(
permissions: bool,
depth: Option<u64>,
base_dirs: HashSet<String>,
display_data: &DisplayData,
use_full_path: bool,
is_reversed: bool,
root_node: Node,
) {
if !permissions {
eprintln!("Did not have permissions for all directories");
}
let first_tree_chars = display_data.get_first_chars();
let mut found = HashSet::new();
let display_data = DisplayData {
short_paths: !use_full_path,
is_reversed,
};
for &(ref k, _) in display_data.to_display.iter() {
if base_dirs.contains(k) {
display_node(&k, &mut found, true, depth, first_tree_chars, display_data);
}
for c in root_node.children {
let first_tree_chars = display_data.get_first_chars();
display_node(*c, true, depth, first_tree_chars, &display_data)
}
}
fn display_node(
node: &str,
nodes_already_found: &mut HashSet<String>,
node: Node,
is_biggest: bool,
depth: Option<u64>,
indent: &str,
display_data: &DisplayData,
) {
if nodes_already_found.contains(node) {
return;
}
nodes_already_found.insert(node.to_string());
let new_depth = match depth {
None => None,
Some(0) => return,
Some(d) => Some(d - 1),
};
let short = display_data.short_paths;
print_this_node(&node, is_biggest, short, indent);
match display_data.get_size(node) {
None => println!("Can not find path: {}", node),
Some(size) => {
let short_path = display_data.short_paths;
// move this inside display_data?
if !display_data.is_reversed {
print_this_node(node, size, is_biggest, short_path, indent);
}
fan_out(node, nodes_already_found, new_depth, indent, display_data);
if display_data.is_reversed {
print_this_node(node, size, is_biggest, short_path, indent);
}
}
}
}
let mut num_siblings = node.children.len() as u64;
let max_sibling = num_siblings;
let new_indent = clean_indentation_string(indent);
fn fan_out(
node_to_print: &str,
nodes_already_found: &mut HashSet<String>,
new_depth: Option<u64>,
indentation_str: &str,
display_data: &DisplayData,
) {
let new_indent = clean_indentation_string(indentation_str);
let num_slashes = strip_end_slash_including_root(node_to_print)
.matches('/')
.count();
let mut num_siblings = display_data.count_siblings(num_slashes, node_to_print);
let max_siblings = num_siblings;
for &(ref k, _) in display_data.to_display.iter() {
let temp = String::from(ensure_end_slash(node_to_print));
if k.starts_with(temp.as_str()) && k.matches('/').count() == num_slashes + 1 {
num_siblings -= 1;
let has_children = display_data.has_children(new_depth, k, num_slashes + 1);
let new_tree_chars =
display_data.get_tree_chars(num_siblings, max_siblings, has_children);
let biggest = display_data.biggest(num_siblings, max_siblings);
display_node(
k,
nodes_already_found,
biggest,
new_depth,
&*(new_indent.to_string() + new_tree_chars),
display_data,
);
}
for c in node.children {
num_siblings -= 1;
let chars = display_data.get_tree_chars(num_siblings, max_sibling, c.children.len() > 0);
let is_biggest = display_data.biggest(num_siblings, max_sibling);
let full_indent = (new_indent.clone() + chars);
display_node(*c, is_biggest, new_depth, &*full_indent, display_data)
}
}
@@ -205,18 +128,12 @@ fn clean_indentation_string(s: &str) -> String {
is
}
fn print_this_node(
node_name: &str,
size: u64,
is_biggest: bool,
short_paths: bool,
indentation: &str,
) {
let pretty_size = format!("{:>5}", human_readable_number(size),);
fn print_this_node(node: &Node, is_biggest: bool, short_paths: bool, indentation: &str) {
let pretty_size = format!("{:>5}", human_readable_number(node.size),);
println!(
"{}",
format_string(
node_name,
&*node.name,
is_biggest,
short_paths,
pretty_size.as_ref(),
@@ -224,7 +141,7 @@ fn print_this_node(
)
)
}
// idea: squash these 2
pub fn format_string(
dir_name: &str,
is_biggest: bool,