Add reverse flag

Pull several variables related to how output is printed
into DisplayData struct
This commit is contained in:
andy.boot
2019-10-03 23:07:52 +01:00
parent 1d9a56e025
commit e03094a4fa
2 changed files with 122 additions and 133 deletions
+115 -125
View File
@@ -2,65 +2,129 @@ extern crate ansi_term;
use self::ansi_term::Colour::Fixed; use self::ansi_term::Colour::Fixed;
use self::ansi_term::Style; use self::ansi_term::Style;
use std::cmp::max;
use std::collections::HashSet; use std::collections::HashSet;
use utils::{ensure_end_slash, strip_end_slash_including_root}; use utils::{ensure_end_slash, strip_end_slash_including_root};
static UNITS: [char; 4] = ['T', 'G', 'M', 'K']; static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];
pub fn draw_it( pub struct DisplayData {
permissions: bool, pub short_paths: bool,
short_paths: bool, pub is_reversed: bool,
depth: Option<u64>, pub to_display: Vec<(String, u64)>,
base_dirs: HashSet<String>, }
to_display: Vec<(String, u64)>,
is_reversed: bool, impl DisplayData {
) { fn get_first_chars(&self) -> &str {
if !permissions { if self.is_reversed {
eprintln!("Did not have permissions for all directories");
}
let mut found = HashSet::new();
let first_tree_chars = {
if is_reversed {
"─┴" "─┴"
} else { } else {
"─┬" "─┬"
} }
}; }
for &(ref k, _) in to_display.iter() { fn get_tree_chars(
if base_dirs.contains(k) { &self,
display_node( num_siblings: u64,
&k, max_siblings: u64,
&mut found, has_children: bool,
&to_display, ) -> &'static str {
true, if self.is_reversed {
short_paths, if num_siblings == max_siblings - 1 {
depth, if has_children {
first_tree_chars, "┌─┴"
is_reversed, } else {
); "┌──"
}
} else if has_children {
"├─┴"
} else {
"├──"
}
} else {
if num_siblings == 0 {
if has_children {
"└─┬"
} else {
"└──"
}
} else if has_children {
"├─┬"
} else {
"├──"
}
} }
} }
fn biggest(&self, num_siblings: u64, max_siblings: u64) -> bool {
if self.is_reversed {
num_siblings == 0
} else {
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
}
} }
fn get_size(nodes: &[(String, u64)], node_to_print: &str) -> Option<u64> { pub fn draw_it(
for &(ref k, ref v) in nodes.iter() { permissions: bool,
if *k == *node_to_print { depth: Option<u64>,
return Some(*v); base_dirs: HashSet<String>,
display_data: &DisplayData,
) {
if !permissions {
eprintln!("Did not have permissions for all directories");
}
let first_tree_chars = display_data.get_first_chars();
let mut found = HashSet::new();
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);
} }
} }
None
} }
fn display_node( fn display_node(
node: &str, node: &str,
nodes_already_found: &mut HashSet<String>, nodes_already_found: &mut HashSet<String>,
to_display: &[(String, u64)],
is_biggest: bool, is_biggest: bool,
short_paths: bool,
depth: Option<u64>, depth: Option<u64>,
indent: &str, indent: &str,
is_reversed: bool, display_data: &DisplayData,
) { ) {
if nodes_already_found.contains(node) { if nodes_already_found.contains(node) {
return; return;
@@ -73,23 +137,17 @@ fn display_node(
Some(d) => Some(d - 1), Some(d) => Some(d - 1),
}; };
match get_size(to_display, node) { match display_data.get_size(node) {
None => println!("Can not find path: {}", node), None => println!("Can not find path: {}", node),
Some(size) => { Some(size) => {
if !is_reversed { let short_path = display_data.short_paths;
print_this_node(node, size, is_biggest, short_paths, indent); // move this inside display_data?
if !display_data.is_reversed {
print_this_node(node, size, is_biggest, short_path, indent);
} }
fan_out( fan_out(node, nodes_already_found, new_depth, indent, display_data);
node, if display_data.is_reversed {
nodes_already_found, print_this_node(node, size, is_biggest, short_path, indent);
to_display,
short_paths,
new_depth,
indent,
is_reversed,
);
if is_reversed {
print_this_node(node, size, is_biggest, short_paths, indent);
} }
} }
} }
@@ -98,45 +156,33 @@ fn display_node(
fn fan_out( fn fan_out(
node_to_print: &str, node_to_print: &str,
nodes_already_found: &mut HashSet<String>, nodes_already_found: &mut HashSet<String>,
to_display: &[(String, u64)],
short_paths: bool,
new_depth: Option<u64>, new_depth: Option<u64>,
indentation_str: &str, indentation_str: &str,
is_reversed: bool, display_data: &DisplayData,
) { ) {
let new_indent = clean_indentation_string(indentation_str); let new_indent = clean_indentation_string(indentation_str);
let num_slashes = strip_end_slash_including_root(node_to_print) let num_slashes = strip_end_slash_including_root(node_to_print)
.matches('/') .matches('/')
.count(); .count();
let mut num_siblings = count_siblings(to_display, num_slashes, node_to_print); let mut num_siblings = display_data.count_siblings(num_slashes, node_to_print);
let max_siblings = num_siblings; let max_siblings = num_siblings;
for &(ref k, _) in to_display.iter() { for &(ref k, _) in display_data.to_display.iter() {
let temp = String::from(ensure_end_slash(node_to_print)); let temp = String::from(ensure_end_slash(node_to_print));
if k.starts_with(temp.as_str()) && k.matches('/').count() == num_slashes + 1 { if k.starts_with(temp.as_str()) && k.matches('/').count() == num_slashes + 1 {
num_siblings -= 1; num_siblings -= 1;
let has_children = has_children(to_display, new_depth, k, num_slashes + 1); let has_children = display_data.has_children(new_depth, k, num_slashes + 1);
let (new_tree_chars, biggest) = if is_reversed { let new_tree_chars =
( display_data.get_tree_chars(num_siblings, max_siblings, has_children);
get_tree_chars_reversed(num_siblings != max_siblings - 1, has_children), let biggest = display_data.biggest(num_siblings, max_siblings);
num_siblings == 0,
)
} else {
(
get_tree_chars(num_siblings != 0, has_children),
num_siblings == max_siblings - 1,
)
};
display_node( display_node(
k, k,
nodes_already_found, nodes_already_found,
to_display,
biggest, biggest,
short_paths,
new_depth, new_depth,
&*(new_indent.to_string() + new_tree_chars), &*(new_indent.to_string() + new_tree_chars),
is_reversed, display_data,
); );
} }
} }
@@ -159,62 +205,6 @@ fn clean_indentation_string(s: &str) -> String {
is is
} }
fn count_siblings(to_display: &[(String, u64)], num_slashes: usize, ntp: &str) -> u64 {
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(
to_display: &[(String, u64)],
new_depth: Option<u64>,
ntp: &str,
num_slashes: usize,
) -> bool {
if new_depth.is_none() || new_depth.unwrap() != 1 {
for &(ref k2, _) in 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
}
fn get_tree_chars(has_smaller_siblings: bool, has_children: bool) -> &'static str {
if !has_smaller_siblings {
if has_children {
"└─┬"
} else {
"└──"
}
} else if has_children {
"├─┬"
} else {
"├──"
}
}
fn get_tree_chars_reversed(has_smaller_siblings: bool, has_children: bool) -> &'static str {
if !has_smaller_siblings {
if has_children {
"┌─┴"
} else {
"┬──"
}
} else if has_children {
"├─┴"
} else {
"├──"
}
}
fn print_this_node( fn print_this_node(
node_name: &str, node_name: &str,
size: u64, size: u64,
+7 -8
View File
@@ -4,6 +4,7 @@ extern crate assert_cli;
extern crate walkdir; extern crate walkdir;
use self::display::draw_it; use self::display::draw_it;
use self::display::DisplayData;
use clap::{App, AppSettings, Arg}; use clap::{App, AppSettings, Arg};
use utils::{ use utils::{
compare_tuple_smallest_first, find_big_ones, get_dir_tree, simplify_dir_names, sort, compare_tuple_smallest_first, find_big_ones, get_dir_tree, simplify_dir_names, sort,
@@ -103,15 +104,13 @@ fn main() {
if options.is_present("reverse") { if options.is_present("reverse") {
biggest_ones.sort_by(compare_tuple_smallest_first); biggest_ones.sort_by(compare_tuple_smallest_first);
} }
let dd = DisplayData {
short_paths: !use_full_path,
is_reversed: options.is_present("reverse"),
to_display: biggest_ones,
};
draw_it( draw_it(permissions, depth, simplified_dirs, &dd);
permissions,
!use_full_path,
depth,
simplified_dirs,
biggest_ones,
options.is_present("reverse"),
);
} }
#[cfg(test)] #[cfg(test)]