pub trait TreeDisplay {
fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result;
fn print_tree(&self, f: &mut std::fmt::Formatter, shorten: bool) -> std::fmt::Result {
self.tree_print(f, TreeState { depth: 0, shorten })
}
fn write_tree(&self, f: &mut impl std::io::Write) -> std::io::Result<()> {
write!(f, "{}", WriteFmt(|f| self.print_tree(f, false)))
}
}
struct WriteFmt<F>(pub F)
where
F: Fn(&mut std::fmt::Formatter<'_>) -> std::fmt::Result;
impl<F> std::fmt::Display for WriteFmt<F>
where
F: Fn(&mut std::fmt::Formatter<'_>) -> std::fmt::Result,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0(f)
}
}
const INDENT: usize = 2;
#[derive(derive_more::Deref, Clone, Copy)]
pub struct TreeState {
#[deref]
depth: usize,
pub shorten: bool,
}
impl TreeState {
pub fn new(shorten: bool) -> Self {
Self { depth: 0, shorten }
}
pub fn indent(&mut self) {
self.depth += INDENT
}
pub fn indented(&self) -> Self {
Self {
depth: self.depth + INDENT,
shorten: self.shorten,
}
}
}
impl From<usize> for TreeState {
fn from(depth: usize) -> Self {
TreeState {
depth,
shorten: true,
}
}
}
pub struct FormatTree<'a, T: TreeDisplay>(pub &'a T);
impl<T: TreeDisplay> std::fmt::Display for FormatTree<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.tree_print(f, 2.into())
}
}