mirror of
https://github.com/bootandy/dust.git
synced 2026-01-15 22:32:59 -08:00
Compare commits
2 Commits
d7fa260bba
...
fix_depth_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2cef68dfd | ||
|
|
222cd83ff3 |
35
Cargo.lock
generated
35
Cargo.lock
generated
@@ -344,7 +344,6 @@ dependencies = [
|
||||
"sysinfo",
|
||||
"tempfile",
|
||||
"terminal_size",
|
||||
"termion",
|
||||
"thousands",
|
||||
"unicode-width",
|
||||
"winapi-util",
|
||||
@@ -487,7 +486,6 @@ checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -564,12 +562,6 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
@@ -665,21 +657,6 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.6"
|
||||
@@ -864,18 +841,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "4.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3669a69de26799d6321a5aa713f55f7e2cd37bd47be044b50f2acafc42c122bb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libredox",
|
||||
"numtoa",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termtree"
|
||||
version = "0.5.1"
|
||||
|
||||
@@ -43,7 +43,6 @@ directories = "4"
|
||||
sysinfo = "0.27"
|
||||
ctrlc = "3.4"
|
||||
chrono = "0.4"
|
||||
termion="4"
|
||||
|
||||
[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
|
||||
portable-atomic = "1.4"
|
||||
|
||||
117
src/display.rs
117
src/display.rs
@@ -4,7 +4,6 @@ use crate::node::FileTime;
|
||||
use ansi_term::Colour::Red;
|
||||
use lscolors::{LsColors, Style};
|
||||
|
||||
use termion::raw::RawTerminal;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use stfu8::encode_u8;
|
||||
@@ -13,8 +12,6 @@ use chrono::{DateTime, Local, TimeZone, Utc};
|
||||
use std::cmp::max;
|
||||
use std::cmp::min;
|
||||
use std::fs;
|
||||
use std::io::Stdout;
|
||||
use std::io::Write;
|
||||
use std::iter::repeat_n;
|
||||
use std::path::Path;
|
||||
use thousands::Separable;
|
||||
@@ -32,7 +29,6 @@ pub struct InitialDisplayData {
|
||||
pub is_screen_reader: bool,
|
||||
pub output_format: String,
|
||||
pub bars_on_right: bool,
|
||||
pub selected_index: i32,
|
||||
}
|
||||
|
||||
pub struct DisplayData {
|
||||
@@ -85,7 +81,6 @@ struct DrawData<'a> {
|
||||
display_data: &'a DisplayData,
|
||||
}
|
||||
|
||||
|
||||
impl DrawData<'_> {
|
||||
fn get_new_indent(&self, has_children: bool, was_i_last: bool) -> String {
|
||||
let chars = self.display_data.get_tree_chars(was_i_last, has_children);
|
||||
@@ -134,7 +129,6 @@ pub fn draw_it(
|
||||
no_percent_bars: bool,
|
||||
terminal_width: usize,
|
||||
skip_total: bool,
|
||||
stdout: &mut RawTerminal<Stdout>,
|
||||
) {
|
||||
let num_chars_needed_on_left_most = if idd.by_filecount {
|
||||
let max_size = root_node.size;
|
||||
@@ -176,14 +170,8 @@ pub fn draw_it(
|
||||
display_data: &display_data,
|
||||
};
|
||||
|
||||
let mut test = if display_data.initial.is_reversed {
|
||||
recursive_child_count(root_node)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if !skip_total {
|
||||
display_node(root_node, stdout, &draw_data, true, true, test);
|
||||
display_node(root_node, &draw_data, true, true);
|
||||
} else {
|
||||
for (count, c) in root_node
|
||||
.get_children_from_node(draw_data.display_data.initial.is_reversed)
|
||||
@@ -191,13 +179,7 @@ pub fn draw_it(
|
||||
{
|
||||
let is_biggest = display_data.is_biggest(count, root_node.num_siblings());
|
||||
let was_i_last = display_data.is_last(count, root_node.num_siblings());
|
||||
display_node(c, stdout, &draw_data, is_biggest, was_i_last, test);
|
||||
// not yet tested:
|
||||
if display_data.initial.is_reversed {
|
||||
test += recursive_child_count(c);
|
||||
} else {
|
||||
test += recursive_child_count(c);
|
||||
}
|
||||
display_node(c, &draw_data, is_biggest, was_i_last);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,46 +218,16 @@ fn find_longest_dir_name(
|
||||
.fold(longest, max)
|
||||
}
|
||||
|
||||
pub fn recursive_child_count(node: &DisplayNode) -> i32 {
|
||||
let mut total = 1;
|
||||
for n in node.children.iter() {
|
||||
total += recursive_child_count(&n);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
fn display_node(
|
||||
node: &DisplayNode,
|
||||
stdout: &mut RawTerminal<Stdout>,
|
||||
draw_data: &DrawData,
|
||||
is_biggest: bool,
|
||||
is_last: bool,
|
||||
test: i32,
|
||||
) {
|
||||
fn display_node(node: &DisplayNode, draw_data: &DrawData, is_biggest: bool, is_last: bool) {
|
||||
// hacky way of working out how deep we are in the tree
|
||||
let indent = draw_data.get_new_indent(!node.children.is_empty(), is_last);
|
||||
let level = ((indent.chars().count() - 1) / 2) - 1;
|
||||
let bar_text = draw_data.generate_bar(node, level);
|
||||
|
||||
let cnt = if draw_data.display_data.initial.is_reversed {
|
||||
recursive_child_count(node)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
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,
|
||||
test - cnt,
|
||||
);
|
||||
|
||||
let mut tt = test;
|
||||
if !draw_data.display_data.initial.is_reversed {
|
||||
tt += 1;
|
||||
write!(stdout, "{to_print}").unwrap()
|
||||
println!("{to_print}")
|
||||
}
|
||||
|
||||
let dd = DrawData {
|
||||
@@ -292,17 +244,11 @@ fn display_node(
|
||||
{
|
||||
let is_biggest = dd.display_data.is_biggest(count, num_siblings);
|
||||
let was_i_last = dd.display_data.is_last(count, num_siblings);
|
||||
|
||||
display_node(c, stdout, &dd, is_biggest, was_i_last, tt);
|
||||
if draw_data.display_data.initial.is_reversed {
|
||||
tt -= recursive_child_count(c)
|
||||
} else {
|
||||
tt += recursive_child_count(c)
|
||||
}
|
||||
display_node(c, &dd, is_biggest, was_i_last);
|
||||
}
|
||||
|
||||
if draw_data.display_data.initial.is_reversed {
|
||||
write!(stdout, "{to_print}").unwrap()
|
||||
println!("{to_print}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,22 +325,18 @@ pub fn format_string(
|
||||
bars: &str,
|
||||
is_biggest: bool,
|
||||
display_data: &DisplayData,
|
||||
test: i32,
|
||||
) -> String {
|
||||
let (percent, name_and_padding) = get_name_percent(node, indent, bars, display_data);
|
||||
let pretty_size = get_pretty_size(node, is_biggest, display_data, test);
|
||||
let pretty_size = get_pretty_size(node, is_biggest, display_data);
|
||||
let pretty_name = get_pretty_name(node, name_and_padding, display_data);
|
||||
let marked = get_name_if_marked(test==display_data.initial.selected_index, pretty_name);
|
||||
let indent = get_indent_if_marked(test==display_data.initial.selected_index, indent);
|
||||
|
||||
// we can clean this and the method below somehow, not sure yet
|
||||
if display_data.initial.is_screen_reader {
|
||||
// if screen_reader then bars is 'depth'
|
||||
format!("{marked} {bars} {pretty_size}{percent}")
|
||||
format!("{pretty_name} {bars} {pretty_size}{percent}")
|
||||
} else if display_data.initial.by_filetime.is_some() {
|
||||
format!("{pretty_size} {indent}{marked}")
|
||||
format!("{pretty_size} {indent}{pretty_name}")
|
||||
} else {
|
||||
format!("{pretty_size} {indent} {marked}{percent}")
|
||||
format!("{pretty_size} {indent} {pretty_name}{percent}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,19 +366,13 @@ fn get_name_percent(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pretty_size(
|
||||
node: &DisplayNode,
|
||||
is_biggest: bool,
|
||||
display_data: &DisplayData,
|
||||
n: i32,
|
||||
) -> String {
|
||||
fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayData) -> String {
|
||||
let output = if display_data.initial.by_filecount {
|
||||
node.size.separate_with_commas()
|
||||
} else if display_data.initial.by_filetime.is_some() {
|
||||
get_pretty_file_modified_time(node.size as i64)
|
||||
} else {
|
||||
// human_readable_number(n, &display_data.initial.output_format)
|
||||
format!("{n}")
|
||||
human_readable_number(node.size, &display_data.initial.output_format)
|
||||
};
|
||||
let spaces_to_add = display_data.num_chars_needed_on_left_most - output.chars().count();
|
||||
let output = " ".repeat(spaces_to_add) + output.as_str();
|
||||
@@ -456,33 +392,6 @@ fn get_pretty_file_modified_time(timestamp: i64) -> String {
|
||||
local_datetime.format("%Y-%m-%dT%H:%M:%S").to_string()
|
||||
}
|
||||
|
||||
fn get_indent_if_marked(test: bool, indent: &str) -> String {
|
||||
if test {
|
||||
let mut new_name = String::new();
|
||||
for _ in indent.chars() {
|
||||
new_name.push(BLOCKS[0])
|
||||
}
|
||||
new_name
|
||||
} else {
|
||||
indent.into()
|
||||
}
|
||||
}
|
||||
fn get_name_if_marked(test: bool, name: String) -> String {
|
||||
if test {
|
||||
let mut new_name = String::new();
|
||||
for c in name.chars() {
|
||||
if c == ' ' {
|
||||
new_name.push(BLOCKS[0])
|
||||
} else {
|
||||
new_name.push(c)
|
||||
}
|
||||
}
|
||||
new_name
|
||||
} else {
|
||||
name.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pretty_name(
|
||||
node: &DisplayNode,
|
||||
name_and_padding: String,
|
||||
|
||||
@@ -32,23 +32,22 @@ pub fn get_biggest(
|
||||
|
||||
if number_top_level_nodes == 0 {
|
||||
root = total_node_builder(0, vec![])
|
||||
} else {
|
||||
if number_top_level_nodes > 1 {
|
||||
let size = if by_filetime.is_some() {
|
||||
top_level_nodes
|
||||
.iter()
|
||||
.map(|node| node.size)
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
} else {
|
||||
top_level_nodes.iter().map(|node| node.size).sum()
|
||||
};
|
||||
|
||||
let nodes = handle_duplicate_top_level_names(top_level_nodes, display_data.short_paths);
|
||||
root = total_node_builder(size, nodes);
|
||||
} else if number_top_level_nodes > 1 {
|
||||
let size = if by_filetime.is_some() {
|
||||
top_level_nodes
|
||||
.iter()
|
||||
.map(|node| node.size)
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
} else {
|
||||
root = top_level_nodes.into_iter().next().unwrap();
|
||||
}
|
||||
top_level_nodes.iter().map(|node| node.size).sum()
|
||||
};
|
||||
|
||||
let nodes = handle_duplicate_top_level_names(top_level_nodes, display_data.short_paths);
|
||||
root = total_node_builder(size, nodes);
|
||||
heap = always_add_children(&display_data, &root, heap);
|
||||
} else {
|
||||
root = top_level_nodes.into_iter().next().unwrap();
|
||||
heap = add_children(&display_data, &root, heap);
|
||||
}
|
||||
|
||||
|
||||
106
src/main.rs
106
src/main.rs
@@ -12,7 +12,6 @@ mod utils;
|
||||
|
||||
use crate::cli::Cli;
|
||||
use crate::config::Config;
|
||||
use crate::display::recursive_child_count;
|
||||
use crate::display_node::DisplayNode;
|
||||
use crate::progress::RuntimeErrors;
|
||||
use clap::Parser;
|
||||
@@ -21,27 +20,17 @@ use display::InitialDisplayData;
|
||||
use filter::AggregateData;
|
||||
use progress::PIndicator;
|
||||
use regex::Error;
|
||||
use std::cmp::min;
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs::read_to_string;
|
||||
use std::io;
|
||||
use std::io::Stdout;
|
||||
use std::io::stdin;
|
||||
use std::io::stdout;
|
||||
use std::panic;
|
||||
use std::process;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use sysinfo::{System, SystemExt};
|
||||
use termion::raw::RawTerminal;
|
||||
use utils::canonicalize_absolute_path;
|
||||
|
||||
use std::io::Write;
|
||||
use termion::event::{Event, Key};
|
||||
use termion::input::TermRead;
|
||||
use termion::raw::IntoRawMode;
|
||||
|
||||
use self::display::draw_it;
|
||||
use config::get_config;
|
||||
use dir_walker::walk_it;
|
||||
@@ -320,93 +309,24 @@ fn main() {
|
||||
let print_errors = config.get_print_errors(&options);
|
||||
print_any_errors(print_errors, walk_data.errors);
|
||||
|
||||
let stdin = stdin();
|
||||
let mut out = stdout().into_raw_mode().unwrap();
|
||||
|
||||
write!(
|
||||
out,
|
||||
"{}{}Dust interactive (q to quit)",
|
||||
termion::clear::All,
|
||||
termion::cursor::Goto(1, 1)
|
||||
)
|
||||
.unwrap();
|
||||
write!(out, "{}", termion::cursor::Goto(1, 2)).unwrap();
|
||||
print_output(
|
||||
&config,
|
||||
&options,
|
||||
&tree,
|
||||
config,
|
||||
options,
|
||||
tree,
|
||||
walk_data.by_filecount,
|
||||
is_colors,
|
||||
terminal_width,
|
||||
&mut out,
|
||||
0,
|
||||
);
|
||||
out.flush().unwrap();
|
||||
|
||||
let mut state = 0;
|
||||
for c in stdin.events() {
|
||||
write!(
|
||||
out,
|
||||
"{}{}Dust interactive (q to quit) {state}",
|
||||
termion::clear::All,
|
||||
termion::cursor::Goto(1, 1)
|
||||
)
|
||||
.unwrap();
|
||||
write!(out, "{}", termion::cursor::Goto(1, 2)).unwrap();
|
||||
let evt = c.unwrap();
|
||||
match evt {
|
||||
Event::Key(Key::Char('q')) => break,
|
||||
Event::Key(Key::Up | Key::Char('k')) => {
|
||||
write!(out, "up\n").unwrap();
|
||||
if !config.get_reverse(&options){
|
||||
state += 1;
|
||||
} else {
|
||||
state -= 1;
|
||||
}
|
||||
}
|
||||
Event::Key(Key::Down | Key::Char('j')) => {
|
||||
write!(out, "down\n").unwrap();
|
||||
if !config.get_reverse(&options){
|
||||
state -= 1;
|
||||
} else {
|
||||
state += 1;
|
||||
}
|
||||
}
|
||||
Event::Key(Key::Left | Key::Char('h')) => {
|
||||
write!(out, "left\n").unwrap();
|
||||
}
|
||||
Event::Key(Key::Right | Key::Char('l')) => {
|
||||
write!(out, "right\n").unwrap();
|
||||
}
|
||||
Event::Key(Key::Char(x)) => {
|
||||
write!(out, "{x} key\n").unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
state = max(0, state);
|
||||
state = min(recursive_child_count(&tree)-1, state);
|
||||
write!(out, "{}", termion::cursor::Goto(1, 3)).unwrap();
|
||||
print_output(
|
||||
&config,
|
||||
&options,
|
||||
&tree,
|
||||
is_colors,
|
||||
terminal_width,
|
||||
&mut out,
|
||||
state,
|
||||
);
|
||||
out.flush().unwrap();
|
||||
}
|
||||
})
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn print_output(
|
||||
config: &Config,
|
||||
options: &Cli,
|
||||
tree: &DisplayNode,
|
||||
config: Config,
|
||||
options: Cli,
|
||||
tree: DisplayNode,
|
||||
by_filecount: bool,
|
||||
is_colors: bool,
|
||||
terminal_width: usize,
|
||||
stdout: &mut RawTerminal<Stdout>,
|
||||
selected_index: i32,
|
||||
) {
|
||||
let output_format = config.get_output_format(&options);
|
||||
|
||||
@@ -420,21 +340,19 @@ fn print_output(
|
||||
short_paths: !config.get_full_paths(&options),
|
||||
is_reversed: !config.get_reverse(&options),
|
||||
colors_on: is_colors,
|
||||
by_filecount: options.filecount,
|
||||
by_filecount,
|
||||
by_filetime: config.get_filetime(&options),
|
||||
is_screen_reader: config.get_screen_reader(&options),
|
||||
output_format,
|
||||
bars_on_right: config.get_bars_on_right(&options),
|
||||
selected_index: selected_index,
|
||||
};
|
||||
|
||||
draw_it(
|
||||
idd,
|
||||
tree,
|
||||
&tree,
|
||||
config.get_no_bars(&options),
|
||||
terminal_width,
|
||||
config.get_skip_total(&options),
|
||||
stdout,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,14 @@ pub fn test_d_flag_works() {
|
||||
assert!(!output.contains("hello_file"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_d0_works_on_multiple() {
|
||||
// We should see the top level directory but not the sub dirs / files:
|
||||
let output = build_command(vec!["-d", "0", "tests/test_dir/", "tests/test_dir2"]);
|
||||
assert!(output.contains("test_dir "));
|
||||
assert!(output.contains("test_dir2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_threads_flag_works() {
|
||||
let output = build_command(vec!["-T", "1", "tests/test_dir/"]);
|
||||
|
||||
Reference in New Issue
Block a user