Skip to content

Commit

Permalink
Merge pull request #31 from bootandy/nodes_rev
Browse files Browse the repository at this point in the history
Refactor & support reverse
  • Loading branch information
bootandy authored Oct 8, 2019
2 parents c6f4ace + 0effaa7 commit c727eb2
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 151 deletions.
22 changes: 11 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "du-dust"
description = "A more intuitive version of du"
version = "0.3.2"
version = "0.4.0"
authors = ["bootandy <[email protected]>", "nebkor <[email protected]>"]

documentation = "https://github.com/bootandy/dust"
Expand Down
236 changes: 104 additions & 132 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,166 +2,138 @@ extern crate ansi_term;

use self::ansi_term::Colour::Fixed;
use self::ansi_term::Style;
use std::collections::HashSet;
use utils::{ensure_end_slash, strip_end_slash};
use utils::Node;

static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];

pub fn draw_it(
permissions: bool,
short_paths: bool,
depth: Option<u64>,
base_dirs: HashSet<String>,
to_display: Vec<(String, u64)>,
) {
if !permissions {
eprintln!("Did not have permissions for all directories");
}
let mut found = HashSet::new();

for &(ref k, _) in to_display.iter() {
if base_dirs.contains(k) {
display_node(&k, &mut found, &to_display, true, short_paths, depth, "─┬");
}
}
pub struct DisplayData {
pub short_paths: bool,
pub is_reversed: bool,
}

fn get_size(nodes: &[(String, u64)], node_to_print: &str) -> Option<u64> {
for &(ref k, ref v) in nodes.iter() {
if *k == *node_to_print {
return Some(*v);
impl DisplayData {
fn get_first_chars(&self) -> &str {
if self.is_reversed {
"─┴"
} else {
"─┬"
}
}
None
}

fn display_node<S: Into<String>>(
node_to_print: &str,
found: &mut HashSet<String>,
to_display: &[(String, u64)],
is_biggest: bool,
short_paths: bool,
depth: Option<u64>,
indentation_str: S,
) {
if found.contains(node_to_print) {
return;
}
found.insert(node_to_print.to_string());

let new_depth = match depth {
None => None,
Some(0) => return,
Some(d) => Some(d - 1),
};
match get_size(to_display, node_to_print) {
None => println!("Can not find path: {}", node_to_print),
Some(size) => {
let is = indentation_str.into();
print_this_node(node_to_print, size, is_biggest, short_paths, is.as_ref());
let new_indent = clean_indentation_string(is);

let ntp_with_slash = strip_end_slash(node_to_print);

// Annoying edge case for when run on root directory
let num_slashes = if ntp_with_slash == "/" {
1
fn get_tree_chars(
&self,
num_siblings: u64,
max_siblings: u64,
has_children: bool,
) -> &'static str {
if self.is_reversed {
if num_siblings == max_siblings - 1 {
if has_children {
"┌─┴"
} else {
"┌──"
}
} else if has_children {
"├─┴"
} else {
ntp_with_slash.matches('/').count() + 1
};
let mut num_siblings = count_siblings(to_display, num_slashes - 1, node_to_print);

let mut is_biggest = true;
for &(ref k, _) in 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 {
num_siblings -= 1;
let has_children = has_children(to_display, new_depth, k, num_slashes);
display_node(
k,
found,
to_display,
is_biggest,
short_paths,
new_depth,
new_indent.to_string() + get_tree_chars(num_siblings != 0, has_children),
);
is_biggest = false;
"├──"
}
} else {
if num_siblings == 0 {
if has_children {
"└─┬"
} else {
"└──"
}
} else if has_children {
"├─┬"
} else {
"├──"
}
}
}
}

fn clean_indentation_string<S: Into<String>>(s: S) -> String {
let mut is = s.into();
is = is.replace("└─┬", " ");
is = is.replace("└──", " ");
is = is.replace("├──", "│ ");
is = is.replace("├─┬", "│ ");
is = is.replace("─┬", " ");
is
}
fn is_biggest(&self, num_siblings: u64, max_siblings: u64) -> bool {
if self.is_reversed {
num_siblings == 0
} else {
num_siblings == max_siblings - 1
}
}

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
fn get_children_from_node(&self, node: Node) -> impl Iterator<Item = Box<Node>> {
if self.is_reversed {
let n: Vec<Box<Node>> = node.children.into_iter().rev().map(|a| a).collect();
return n.into_iter();
} else {
a
return node.children.into_iter();
}
})
}
}

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;
}
}
pub fn draw_it(permissions: bool, use_full_path: bool, is_reversed: bool, root_node: Node) {
if !permissions {
eprintln!("Did not have permissions for all directories");
}
let display_data = DisplayData {
short_paths: !use_full_path,
is_reversed,
};

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)
}
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 display_node(node: Node, is_biggest: bool, indent: &str, display_data: &DisplayData) {
let short = display_data.short_paths;

let mut num_siblings = node.children.len() as u64;
let max_sibling = num_siblings;
let new_indent = clean_indentation_string(indent);
let name = node.name.clone();
let size = node.size;

if !display_data.is_reversed {
print_this_node(&*name, size, is_biggest, short, indent);
}

for c in display_data.get_children_from_node(node) {
num_siblings -= 1;
let chars = display_data.get_tree_chars(num_siblings, max_sibling, c.children.len() > 0);
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)
}

if display_data.is_reversed {
print_this_node(&*name, size, is_biggest, short, indent);
}
}

fn print_this_node(
node_name: &str,
size: u64,
is_biggest: bool,
short_paths: bool,
indentation: &str,
) {
fn clean_indentation_string(s: &str) -> String {
let mut is: String = s.into();
// For reversed:
is = is.replace("┌─┴", " ");
is = is.replace("┌──", " ");
is = is.replace("├─┴", "│ ");
is = is.replace("─┴", " ");
// For normal
is = is.replace("└─┬", " ");
is = is.replace("└──", " ");
is = is.replace("├─┬", "│ ");
is = is.replace("─┬", " ");
// For both
is = is.replace("├──", "│ ");
is
}

fn print_this_node(name: &str, size: u64, is_biggest: bool, short_paths: bool, indentation: &str) {
let pretty_size = format!("{:>5}", human_readable_number(size),);
println!(
"{}",
format_string(
node_name,
is_biggest,
short_paths,
pretty_size.as_ref(),
indentation
)
format_string(name, is_biggest, short_paths, &*pretty_size, indentation)
)
}

Expand Down
Loading

0 comments on commit c727eb2

Please sign in to comment.