use std::collections::BTreeMap;
use std::path::{Component, PathBuf};
struct Node {
children: BTreeMap<String, Node>,
}
impl Node {
fn new() -> Self {
Node {
children: BTreeMap::new(),
}
}
fn insert(&mut self, components: &[Component]) {
if let Some((first, rest)) = components.split_first() {
let key = match first {
Component::Normal(os_str) => os_str.to_string_lossy().to_string(),
Component::CurDir => ".".to_string(),
Component::ParentDir => "..".to_string(),
Component::RootDir => "/".to_string(),
Component::Prefix(_) => return,
};
let child = self.children.entry(key).or_insert_with(Node::new);
child.insert(rest);
}
}
}
fn render_node(node: &Node, prefix: &str, output: &mut String) {
let child_count = node.children.len();
for (i, (name, child)) in node.children.iter().enumerate() {
let is_child_last = i == child_count - 1;
let marker = if is_child_last { "`-- " } else { "|-- " };
let new_prefix = if is_child_last { " " } else { "| " };
output.push_str(prefix);
output.push_str(marker);
output.push_str(name);
output.push('\n');
render_node(child, &format!("{}{}", prefix, new_prefix), output);
}
}
pub fn render_tree(paths: &[PathBuf]) -> String {
if paths.is_empty() {
return String::new();
}
let mut root = Node::new();
for path in paths {
let components: Vec<_> = path.components().collect();
root.insert(&components);
}
let mut output = String::new();
output.push_str(".\n");
render_node(&root, "", &mut output);
output
}