use std::io::{self, Write};
use super::format::format_size;
use super::{select_top, OutputConfig};
use crate::category::Category;
use crate::entry::Entry;
pub fn write(entry: &Entry, config: &OutputConfig, out: &mut impl Write) -> io::Result<()> {
writeln!(out, "{} ({})", entry.name, format_size(entry.size))?;
if let Some(children) = entry.children() {
let (items, dropped_count, dropped_size) = select_top(children, config.top);
let len = items.len();
for (i, child) in items.iter().enumerate() {
let is_last = i == len - 1;
write_entry(child, "", is_last, config, 1, out)?;
}
write_overflow(dropped_count, dropped_size, " ", out)?;
}
Ok(())
}
fn write_entry(
entry: &Entry,
prefix: &str,
is_last: bool,
config: &OutputConfig,
current_depth: usize,
out: &mut impl Write,
) -> io::Result<()> {
let connector = if is_last { "└── " } else { "├── " };
let suffix = if entry.is_dir() { "/" } else { "" };
let category_tag = format_category_tag(entry.category);
writeln!(
out,
"{}{}{}{} {}{}",
prefix,
connector,
entry.name,
suffix,
category_tag,
format_size(entry.size),
)?;
if let Some(max_depth) = config.depth {
if current_depth >= max_depth {
return Ok(());
}
}
if let Some(children) = entry.children() {
let child_prefix = format!("{}{}", prefix, if is_last { " " } else { "│ " });
let (items, dropped_count, dropped_size) = select_top(children, config.top);
let len = items.len();
for (i, child) in items.iter().enumerate() {
let child_is_last = i == len - 1;
write_entry(
child,
&child_prefix,
child_is_last,
config,
current_depth + 1,
out,
)?;
}
write_overflow(
dropped_count,
dropped_size,
&format!("{} ", child_prefix),
out,
)?;
}
Ok(())
}
fn format_category_tag(category: Category) -> String {
if category == Category::Other {
String::new()
} else {
format!("[{}] ", category.label())
}
}
fn write_overflow(
dropped_count: usize,
dropped_size: u64,
prefix: &str,
out: &mut impl Write,
) -> io::Result<()> {
if dropped_count > 0 {
writeln!(
out,
"{}... and {} more ({})",
prefix,
dropped_count,
format_size(dropped_size),
)?;
}
Ok(())
}