mirror of
https://github.com/bootandy/dust.git
synced 2025-12-05 20:40:11 -08:00
Fix: Allow -n to be used with -d
Allow -n for number_of_lines to be used with -d 'max depth' Remove depth specific functions, the job is now handled by the mainline Add depth as a field onto the Node object.
This commit is contained in:
@@ -34,7 +34,7 @@ pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: WalkData) -> (Vec<Node>, bool)
|
||||
let top_level_nodes: Vec<_> = dirs
|
||||
.into_iter()
|
||||
.filter_map(|d| {
|
||||
let n = walk(d, &permissions_flag, &walk_data);
|
||||
let n = walk(d, &permissions_flag, &walk_data, 0);
|
||||
match n {
|
||||
Some(n) => {
|
||||
let mut inodes: HashSet<(u64, u64)> = HashSet::new();
|
||||
@@ -73,6 +73,7 @@ fn clean_inodes(
|
||||
size: x.size + new_children.iter().map(|c| c.size).sum::<u64>(),
|
||||
children: new_children,
|
||||
inode_device: x.inode_device,
|
||||
depth: x.depth,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,7 +109,12 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
|
||||
(is_dot_file && walk_data.ignore_hidden) || is_ignored_path
|
||||
}
|
||||
|
||||
fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Option<Node> {
|
||||
fn walk(
|
||||
dir: PathBuf,
|
||||
permissions_flag: &AtomicBool,
|
||||
walk_data: &WalkData,
|
||||
depth: usize,
|
||||
) -> Option<Node> {
|
||||
let mut children = vec![];
|
||||
|
||||
if let Ok(entries) = fs::read_dir(dir.clone()) {
|
||||
@@ -126,7 +132,7 @@ fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Op
|
||||
if !ignore_file(entry, walk_data) {
|
||||
if let Ok(data) = entry.file_type() {
|
||||
if data.is_dir() && !data.is_symlink() {
|
||||
return walk(entry.path(), permissions_flag, walk_data);
|
||||
return walk(entry.path(), permissions_flag, walk_data, depth + 1);
|
||||
}
|
||||
return build_node(
|
||||
entry.path(),
|
||||
@@ -137,6 +143,7 @@ fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Op
|
||||
data.is_symlink(),
|
||||
data.is_file(),
|
||||
walk_data.by_filecount,
|
||||
depth,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -158,6 +165,7 @@ fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Op
|
||||
false,
|
||||
false,
|
||||
walk_data.by_filecount,
|
||||
depth,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -172,6 +180,7 @@ mod tests {
|
||||
size: 10,
|
||||
children: vec![],
|
||||
inode_device: Some((5, 6)),
|
||||
depth: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,10 @@ use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_by_depth(top_level_nodes: Vec<Node>, n: usize) -> Option<DisplayNode> {
|
||||
if top_level_nodes.is_empty() {
|
||||
// perhaps change this, bring back Error object?
|
||||
return None;
|
||||
}
|
||||
let root = get_new_root(top_level_nodes);
|
||||
Some(build_by_depth(&root, n - 1))
|
||||
}
|
||||
|
||||
pub fn get_biggest(
|
||||
top_level_nodes: Vec<Node>,
|
||||
n: usize,
|
||||
depth: usize,
|
||||
using_a_filter: bool,
|
||||
) -> Option<DisplayNode> {
|
||||
if top_level_nodes.is_empty() {
|
||||
@@ -30,14 +22,14 @@ pub fn get_biggest(
|
||||
let mut allowed_nodes = HashSet::new();
|
||||
|
||||
allowed_nodes.insert(&root.name);
|
||||
heap = add_children(using_a_filter, &root, heap);
|
||||
heap = add_children(using_a_filter, &root, depth, heap);
|
||||
|
||||
for _ in number_top_level_nodes..n {
|
||||
let line = heap.pop();
|
||||
match line {
|
||||
Some(line) => {
|
||||
allowed_nodes.insert(&line.name);
|
||||
heap = add_children(using_a_filter, line, heap);
|
||||
heap = add_children(using_a_filter, line, depth, heap);
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
@@ -78,16 +70,19 @@ pub fn get_all_file_types(top_level_nodes: Vec<Node>, n: usize) -> Option<Displa
|
||||
fn add_children<'a>(
|
||||
using_a_filter: bool,
|
||||
line: &'a Node,
|
||||
depth: usize,
|
||||
mut heap: BinaryHeap<&'a Node>,
|
||||
) -> BinaryHeap<&'a Node> {
|
||||
if using_a_filter {
|
||||
line.children.iter().for_each(|c| {
|
||||
if c.name.is_file() || c.size > 0 {
|
||||
heap.push(c)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
line.children.iter().for_each(|c| heap.push(c));
|
||||
if depth > line.depth {
|
||||
if using_a_filter {
|
||||
line.children.iter().for_each(|c| {
|
||||
if c.name.is_file() || c.size > 0 {
|
||||
heap.push(c)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
line.children.iter().for_each(|c| heap.push(c));
|
||||
}
|
||||
}
|
||||
heap
|
||||
}
|
||||
@@ -111,29 +106,6 @@ fn build_by_all_file_types(top_level_nodes: Vec<Node>, counter: &mut HashMap<Str
|
||||
}
|
||||
}
|
||||
|
||||
fn build_by_depth(node: &Node, depth: usize) -> DisplayNode {
|
||||
let new_children = {
|
||||
if depth == 0 {
|
||||
vec![]
|
||||
} else {
|
||||
let mut new_children: Vec<_> = node
|
||||
.children
|
||||
.iter()
|
||||
.map(|c| build_by_depth(c, depth - 1))
|
||||
.collect();
|
||||
new_children.sort();
|
||||
new_children.reverse();
|
||||
new_children
|
||||
}
|
||||
};
|
||||
|
||||
DisplayNode {
|
||||
name: node.name.clone(),
|
||||
size: node.size,
|
||||
children: new_children,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_new_root(top_level_nodes: Vec<Node>) -> Node {
|
||||
if top_level_nodes.len() > 1 {
|
||||
let total_size = top_level_nodes.iter().map(|node| node.size).sum();
|
||||
@@ -142,6 +114,7 @@ fn get_new_root(top_level_nodes: Vec<Node>) -> Node {
|
||||
size: total_size,
|
||||
children: top_level_nodes,
|
||||
inode_device: None,
|
||||
depth: 0,
|
||||
}
|
||||
} else {
|
||||
top_level_nodes.into_iter().next().unwrap()
|
||||
|
||||
54
src/main.rs
54
src/main.rs
@@ -10,7 +10,7 @@ use self::display::draw_it;
|
||||
use clap::{crate_version, Arg};
|
||||
use clap::{Command, Values};
|
||||
use dir_walker::{walk_it, WalkData};
|
||||
use filter::{get_all_file_types, get_biggest, get_by_depth};
|
||||
use filter::{get_all_file_types, get_biggest};
|
||||
use regex::Regex;
|
||||
use std::cmp::max;
|
||||
use std::path::PathBuf;
|
||||
@@ -99,9 +99,6 @@ fn get_regex_value(maybe_value: Option<Values>) -> Vec<Regex> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let default_height = get_height_of_terminal();
|
||||
let def_num_str = default_height.to_string();
|
||||
|
||||
let options = Command::new("Dust")
|
||||
.about("Like du but more intuitive")
|
||||
.version(crate_version!())
|
||||
@@ -112,7 +109,7 @@ fn main() {
|
||||
.long("depth")
|
||||
.help("Depth to show")
|
||||
.takes_value(true)
|
||||
.conflicts_with("number_of_lines"),
|
||||
.default_value(usize::MAX.to_string().as_ref())
|
||||
)
|
||||
.arg(
|
||||
Arg::new("number_of_lines")
|
||||
@@ -120,7 +117,6 @@ fn main() {
|
||||
.long("number-of-lines")
|
||||
.help("Number of lines of output to show. (Default is terminal_height - 10)")
|
||||
.takes_value(true)
|
||||
.default_value(def_num_str.as_ref()),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("display_full_paths")
|
||||
@@ -188,7 +184,6 @@ fn main() {
|
||||
.multiple_occurrences(true)
|
||||
.conflicts_with("filter")
|
||||
.conflicts_with("types")
|
||||
.conflicts_with("depth")
|
||||
.help("Exclude filepaths matching this regex. To ignore png files type: -v \"\\.png$\" "),
|
||||
)
|
||||
.arg(
|
||||
@@ -199,7 +194,6 @@ fn main() {
|
||||
.number_of_values(1)
|
||||
.multiple_occurrences(true)
|
||||
.conflicts_with("types")
|
||||
.conflicts_with("depth")
|
||||
.help("Only include filepaths matching this regex. For png files type: -e \"\\.png$\" "),
|
||||
)
|
||||
.arg(
|
||||
@@ -236,26 +230,36 @@ fn main() {
|
||||
let filter_regexs = get_regex_value(options.values_of("filter"));
|
||||
let invert_filter_regexs = get_regex_value(options.values_of("invert_filter"));
|
||||
|
||||
let number_of_lines = match options.value_of_t("number_of_lines") {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
eprintln!("Ignoring bad value for number_of_lines");
|
||||
default_height
|
||||
}
|
||||
};
|
||||
|
||||
let terminal_width = match options.value_of_t("width") {
|
||||
Ok(v) => v,
|
||||
Err(_) => get_width_of_terminal(),
|
||||
};
|
||||
|
||||
let depth = options.value_of("depth").and_then(|depth| {
|
||||
depth
|
||||
.parse::<usize>()
|
||||
.map(|v| v + 1)
|
||||
.map_err(|_| eprintln!("Ignoring bad value for depth"))
|
||||
.ok()
|
||||
});
|
||||
let depth = match options.value_of_t("depth") {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
eprintln!("Ignoring bad value for depth");
|
||||
usize::MAX
|
||||
}
|
||||
};
|
||||
// If depth is set we set the default number_of_lines to be max
|
||||
// instead of screen height
|
||||
let default_height = if depth != usize::MAX {
|
||||
usize::MAX
|
||||
} else {
|
||||
get_height_of_terminal()
|
||||
};
|
||||
|
||||
let number_of_lines = match options.value_of("number_of_lines") {
|
||||
Some(v) => match v.parse::<usize>() {
|
||||
Ok(num_lines) => num_lines,
|
||||
Err(_) => {
|
||||
eprintln!("Ignoring bad value for number_of_lines");
|
||||
default_height
|
||||
}
|
||||
},
|
||||
None => default_height,
|
||||
};
|
||||
|
||||
let no_colors = init_color(options.is_present("no_colors"));
|
||||
let use_apparent_size = options.is_present("display_apparent_size");
|
||||
@@ -297,10 +301,10 @@ fn main() {
|
||||
let tree = {
|
||||
match (depth, summarize_file_types) {
|
||||
(_, true) => get_all_file_types(top_level_nodes, number_of_lines),
|
||||
(Some(depth), _) => get_by_depth(top_level_nodes, depth),
|
||||
(_, _) => get_biggest(
|
||||
(depth, _) => get_biggest(
|
||||
top_level_nodes,
|
||||
number_of_lines,
|
||||
depth,
|
||||
options.values_of("filter").is_some()
|
||||
|| options.value_of("invert_filter").is_some(),
|
||||
),
|
||||
|
||||
@@ -12,6 +12,7 @@ pub struct Node {
|
||||
pub size: u64,
|
||||
pub children: Vec<Node>,
|
||||
pub inode_device: Option<(u64, u64)>,
|
||||
pub depth: usize,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -24,6 +25,7 @@ pub fn build_node(
|
||||
is_symlink: bool,
|
||||
is_file: bool,
|
||||
by_filecount: bool,
|
||||
depth: usize,
|
||||
) -> Option<Node> {
|
||||
match get_metadata(&dir, use_apparent_size) {
|
||||
Some(data) => {
|
||||
@@ -50,6 +52,7 @@ pub fn build_node(
|
||||
size,
|
||||
children,
|
||||
inode_device,
|
||||
depth,
|
||||
})
|
||||
}
|
||||
None => None,
|
||||
|
||||
Reference in New Issue
Block a user