mirror of
https://github.com/bootandy/dust.git
synced 2026-06-08 11:29:05 +03:00
hack
This commit is contained in:
+75
-16
@@ -11,9 +11,13 @@ use stfu8::encode_u8;
|
|||||||
use chrono::{DateTime, Local, TimeZone, Utc};
|
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::collections::VecDeque;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use thousands::Separable;
|
use thousands::Separable;
|
||||||
|
|
||||||
@@ -38,6 +42,7 @@ pub struct DisplayData {
|
|||||||
pub base_size: u64,
|
pub base_size: u64,
|
||||||
pub longest_string_length: usize,
|
pub longest_string_length: usize,
|
||||||
pub ls_colors: LsColors,
|
pub ls_colors: LsColors,
|
||||||
|
pub duplicate_names: HashMap<String, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DisplayData {
|
impl DisplayData {
|
||||||
@@ -135,6 +140,9 @@ pub fn draw_it(
|
|||||||
root_node: &DisplayNode,
|
root_node: &DisplayNode,
|
||||||
skip_total: bool,
|
skip_total: bool,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
let duplicate_names = check_for_dup_names(&root_node);
|
||||||
|
|
||||||
let num_chars_needed_on_left_most = if idd.by_filecount {
|
let num_chars_needed_on_left_most = if idd.by_filecount {
|
||||||
let max_size = root_node.size;
|
let max_size = root_node.size;
|
||||||
max_size.separate_with_commas().chars().count()
|
max_size.separate_with_commas().chars().count()
|
||||||
@@ -154,7 +162,7 @@ pub fn draw_it(
|
|||||||
let allowed_width = terminal_width - num_chars_needed_on_left_most - 2;
|
let allowed_width = terminal_width - num_chars_needed_on_left_most - 2;
|
||||||
let num_indent_chars = 3;
|
let num_indent_chars = 3;
|
||||||
let longest_string_length =
|
let longest_string_length =
|
||||||
find_longest_dir_name(root_node, num_indent_chars, allowed_width, &idd);
|
find_longest_dir_name(root_node, num_indent_chars, allowed_width, &idd, &duplicate_names);
|
||||||
|
|
||||||
let max_bar_length = if no_percent_bars || longest_string_length + 7 >= allowed_width {
|
let max_bar_length = if no_percent_bars || longest_string_length + 7 >= allowed_width {
|
||||||
0
|
0
|
||||||
@@ -170,6 +178,7 @@ pub fn draw_it(
|
|||||||
base_size: root_node.size,
|
base_size: root_node.size,
|
||||||
longest_string_length,
|
longest_string_length,
|
||||||
ls_colors: LsColors::from_env().unwrap_or_default(),
|
ls_colors: LsColors::from_env().unwrap_or_default(),
|
||||||
|
duplicate_names
|
||||||
};
|
};
|
||||||
let draw_data = DrawData {
|
let draw_data = DrawData {
|
||||||
indent: "".to_string(),
|
indent: "".to_string(),
|
||||||
@@ -190,18 +199,44 @@ pub fn draw_it(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fn find_duplicate_names(node: &DisplayNode, short_paths: bool) -> HashSet<DisplayNode> {
|
fn check_for_dup_names(result:&DisplayNode) -> HashMap<String, u32> {
|
||||||
// if !short_paths {
|
let mut names = HashMap::new();
|
||||||
// return HashSet::new()
|
let mut dup_names = HashMap::new();
|
||||||
// } else {
|
// let empty = HashSet::new();
|
||||||
// get_printable_name(node.dir_name, short_paths)
|
|
||||||
// // or maybe if we find them from diff root nodes we can mark them.
|
let mut results = VecDeque::new();
|
||||||
// }
|
results.push_back((result, 0));
|
||||||
// }
|
|
||||||
|
while results.len() > 0 {
|
||||||
|
let (current, level) = results.pop_front().unwrap();
|
||||||
|
|
||||||
|
let mut folders = current.name.iter().rev();
|
||||||
|
let mut s = String::new();
|
||||||
|
|
||||||
|
// Look at parent folder names - if they differ and we are printing them
|
||||||
|
// we dont need the helper
|
||||||
|
for _ in 0..level {
|
||||||
|
s.push_str( &encode_u8(folders.next().unwrap().as_bytes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if names.contains_key(&s){
|
||||||
|
// TODO: compare s with names[s]
|
||||||
|
// and walk back until you find a difference.
|
||||||
|
dup_names.insert(s, level);
|
||||||
|
} else {
|
||||||
|
names.insert(s, vec![¤t.name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
current.children.iter().for_each(|node| {results.push_back((&node, level+1));});
|
||||||
|
}
|
||||||
|
println!("{:?}", names);
|
||||||
|
println!("{:?}", dup_names);
|
||||||
|
dup_names
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_printable_name<P: AsRef<Path>>(dir_name: &P, short_paths: bool) -> String {
|
pub fn get_printable_name(node: &DisplayNode, short_paths: bool, dup_names: &HashMap<String, u32>) -> String {
|
||||||
let dir_name = dir_name.as_ref();
|
let dir_name = &node.name;
|
||||||
let printable_name = {
|
let printable_name = {
|
||||||
if short_paths {
|
if short_paths {
|
||||||
match dir_name.parent() {
|
match dir_name.parent() {
|
||||||
@@ -215,7 +250,30 @@ pub fn get_printable_name<P: AsRef<Path>>(dir_name: &P, short_paths: bool) -> St
|
|||||||
dir_name
|
dir_name
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
encode_u8(printable_name.display().to_string().as_bytes())
|
let core = encode_u8(printable_name.display().to_string().as_bytes());
|
||||||
|
|
||||||
|
if dup_names.contains_key(&core) {
|
||||||
|
let level = dup_names[&core];
|
||||||
|
|
||||||
|
let mut folders = node.name.iter().rev();
|
||||||
|
folders.next();
|
||||||
|
let mut extra = VecDeque::new();
|
||||||
|
for _ in (0..level){
|
||||||
|
extra.push_back( encode_u8(folders.next().unwrap().as_bytes()) );
|
||||||
|
}
|
||||||
|
let h = extra.iter().fold(String::new(), |acc, entry| {
|
||||||
|
acc + entry
|
||||||
|
});
|
||||||
|
// let helper = extra.make_contiguous().iter().collect::<Vec<&String>>();
|
||||||
|
// let h = helper.join("/");
|
||||||
|
|
||||||
|
// let mut folders = dir_name.iter().rev(); //.next().next().unwrap();
|
||||||
|
// folders.next();
|
||||||
|
// let par = encode_u8(folders.next().unwrap().as_bytes());
|
||||||
|
format!("{core} ({h})")
|
||||||
|
} else {
|
||||||
|
core
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_biggest_size_str(node: &DisplayNode, output_format: &str) -> usize {
|
fn find_biggest_size_str(node: &DisplayNode, output_format: &str) -> usize {
|
||||||
@@ -233,8 +291,9 @@ fn find_longest_dir_name(
|
|||||||
indent: usize,
|
indent: usize,
|
||||||
terminal: usize,
|
terminal: usize,
|
||||||
idd: &InitialDisplayData,
|
idd: &InitialDisplayData,
|
||||||
|
dup_names: &HashMap<String, u32>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let printable_name = get_printable_name(&node.name, idd.short_paths);
|
let printable_name = get_printable_name(&node, idd.short_paths, dup_names);
|
||||||
|
|
||||||
let longest = if idd.is_screen_reader {
|
let longest = if idd.is_screen_reader {
|
||||||
UnicodeWidthStr::width(&*printable_name) + 1
|
UnicodeWidthStr::width(&*printable_name) + 1
|
||||||
@@ -248,7 +307,7 @@ fn find_longest_dir_name(
|
|||||||
// each none root tree drawing is 2 more chars, hence we increment indent by 2
|
// each none root tree drawing is 2 more chars, hence we increment indent by 2
|
||||||
node.children
|
node.children
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| find_longest_dir_name(c, indent + 2, terminal, idd))
|
.map(|c| find_longest_dir_name(c, indent + 2, terminal, idd, dup_names))
|
||||||
.fold(longest, max)
|
.fold(longest, max)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +363,7 @@ fn clean_indentation_string(s: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pad_or_trim_filename(node: &DisplayNode, indent: &str, display_data: &DisplayData) -> String {
|
fn pad_or_trim_filename(node: &DisplayNode, indent: &str, display_data: &DisplayData) -> String {
|
||||||
let name = get_printable_name(&node.name, display_data.initial.short_paths);
|
let name = get_printable_name(&node, display_data.initial.short_paths, &display_data.duplicate_names);
|
||||||
let indent_and_name = format!("{indent} {name}");
|
let indent_and_name = format!("{indent} {name}");
|
||||||
let width = UnicodeWidthStr::width(&*indent_and_name);
|
let width = UnicodeWidthStr::width(&*indent_and_name);
|
||||||
|
|
||||||
@@ -379,7 +438,7 @@ fn get_name_percent(
|
|||||||
let name_and_padding = pad_or_trim_filename(node, indent, display_data);
|
let name_and_padding = pad_or_trim_filename(node, indent, display_data);
|
||||||
(percents, name_and_padding)
|
(percents, name_and_padding)
|
||||||
} else {
|
} else {
|
||||||
let n = get_printable_name(&node.name, display_data.initial.short_paths);
|
let n = get_printable_name(&node, display_data.initial.short_paths, &display_data.duplicate_names);
|
||||||
let name = maybe_trim_filename(n, indent, display_data);
|
let name = maybe_trim_filename(n, indent, display_data);
|
||||||
("".into(), name)
|
("".into(), name)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-23
@@ -1,6 +1,3 @@
|
|||||||
use stfu8::encode_u8;
|
|
||||||
|
|
||||||
use crate::display::get_printable_name;
|
|
||||||
use crate::display_node::DisplayNode;
|
use crate::display_node::DisplayNode;
|
||||||
use crate::node::FileTime;
|
use crate::node::FileTime;
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
@@ -44,23 +41,6 @@ pub fn get_biggest(
|
|||||||
top_level_nodes.iter().map(|node| node.size).sum()
|
top_level_nodes.iter().map(|node| node.size).sum()
|
||||||
};
|
};
|
||||||
|
|
||||||
// If top level folders have same name -> change them.
|
|
||||||
let names = top_level_nodes.iter().map(|node| node.name.to_str());
|
|
||||||
// todo pass in short_paths flag
|
|
||||||
let print_nam = top_level_nodes.iter().map(|node| get_printable_name(&node.name, true)).collect::<String>();
|
|
||||||
// if has same name
|
|
||||||
|
|
||||||
for n in top_level_nodes.iter_mut(){
|
|
||||||
let tmp = n.name.parent().unwrap().components().last().unwrap().as_os_str().to_str().unwrap();
|
|
||||||
let orig = n.name.display().to_string();
|
|
||||||
n.name = PathBuf::from(format!("{orig}({tmp})"));
|
|
||||||
println!("{:?}", n.name);
|
|
||||||
}
|
|
||||||
// build up list of dup-names
|
|
||||||
|
|
||||||
// Repeatedly add parent path until all are not dup
|
|
||||||
|
|
||||||
|
|
||||||
root = Node {
|
root = Node {
|
||||||
name: PathBuf::from("(total)"),
|
name: PathBuf::from("(total)"),
|
||||||
size,
|
size,
|
||||||
@@ -76,12 +56,13 @@ pub fn get_biggest(
|
|||||||
heap = add_children(&display_data, &root, heap);
|
heap = add_children(&display_data, &root, heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(fill_remaining_lines(
|
let result = fill_remaining_lines(
|
||||||
heap,
|
heap,
|
||||||
&root,
|
&root,
|
||||||
display_data,
|
display_data,
|
||||||
keep_collapsed,
|
keep_collapsed,
|
||||||
))
|
);
|
||||||
|
Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_remaining_lines<'a>(
|
pub fn fill_remaining_lines<'a>(
|
||||||
@@ -177,8 +158,9 @@ fn flat_rebuilder(allowed_nodes: HashMap<&Path, &Node>, current: &Node) -> Displ
|
|||||||
|
|
||||||
fn build_display_node(mut new_children: Vec<DisplayNode>, current: &Node) -> DisplayNode {
|
fn build_display_node(mut new_children: Vec<DisplayNode>, current: &Node) -> DisplayNode {
|
||||||
new_children.sort_by(|lhs, rhs| lhs.cmp(rhs).reverse());
|
new_children.sort_by(|lhs, rhs| lhs.cmp(rhs).reverse());
|
||||||
|
// println!("{:?}", current.name);
|
||||||
DisplayNode {
|
DisplayNode {
|
||||||
name: current.name.clone(),
|
name: PathBuf::from(current.name.display().to_string()),
|
||||||
size: current.size,
|
size: current.size,
|
||||||
children: new_children,
|
children: new_children,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user