tree_display/lib.rs
1//! A library for displaying Rust data structures as syntax-highlighted trees.
2//!
3//! `tree-display` provides a simple derive macro (`#[derive(TreeDisplay)]`)
4//! to render any data structure as a beautifully formatted tree in the terminal.
5//! Features include syntax highlighting, custom value mapping, and full theming support.
6//!
7//! ## Quick Start
8//! ```no_run
9//! use tree_display::{TreeDisplay, Formatter};
10//!
11//! #[derive(Debug, TreeDisplay)]
12//! struct Person {
13//! name: String,
14//! age: u32,
15//! }
16//!
17//! let person = Person {
18//! name: "Alice".to_string(),
19//! age: 30,
20//! };
21//!
22//! println!("{}", Formatter::of(&person).format());
23//! ```
24//!
25//! ## Features
26//! - **Derive macro**: `#[derive(TreeDisplay)]` for automatic tree generation
27//! - **Field attributes**: Control rendering of individual fields:
28//! - `#[tree(map)]` - Apply a custom mapper from [`Context`]
29//! - `#[tree(ignore)]` - Exclude a field from the tree
30//! - `#[tree(label = "...")]` - Override the field's display label
31//! - `#[tree(unlabeled)]` - Display the field without a label
32//! - **Custom mapping**: Transform values with [`Context`] mappers
33//! - **Theming**: Predefined themes (VS Code Dark+, Solarized, etc.)
34//! - **Color support**: Optional ANSI color highlighting
35//! - **Line styles**: ASCII or Unicode box-drawing characters
36//! - **Formatting**: Labels, alignment, and custom content types
37
38pub mod color;
39pub mod context;
40pub mod format;
41pub mod graphics;
42pub mod support;
43pub mod theme;
44
45use format::Content;
46
47// Re-export the most commonly used types at root
48pub use color::Colors;
49pub use context::Context;
50pub use derive::TreeDisplay;
51pub use format::Formatter;
52pub use graphics::Graphics;
53pub use theme::Theme;
54
55// ──── API ───────────────────────────────────────────────────────────────────────────────────────
56
57/// A type that can be displayed as a tree.
58///
59/// This trait is automatically implemented by `#[derive(TreeDisplay)]`
60/// and is also implemented for many standard library types.
61pub trait TreeDisplay {
62 /// Converts the value into a tree structure using the given context.
63 ///
64 /// The context provides custom mappers that can transform values before they are displayed.
65 fn tree(&self, context: &Context) -> Tree;
66}
67
68/// A tree node containing content and child subtrees.
69///
70/// Trees are built from a root node with zero or more child nodes,
71/// each of which can have their own children. Nodes can optionally
72/// have labels that appear alongside their content.
73///
74/// ## Example
75/// ```
76/// use tree_display::{Tree, format::Member};
77///
78/// let tree = Tree::leaf("root")
79/// .labeled(Member::new("label"));
80/// ```
81pub struct Tree {
82 /// Optional label displayed next to the content
83 pub label: Option<Box<dyn Content>>,
84 /// The main content of this node
85 pub content: Box<dyn Content>,
86 /// Child subtrees
87 pub subtrees: Vec<Tree>,
88}
89
90// ──── Utility ───────────────────────────────────────────────────────────────────────────────────
91
92impl Tree {
93 /// Creates a new tree node with content and children.
94 pub fn new(content: impl Content, subtrees: Vec<Tree>) -> Tree {
95 Tree {
96 label: None,
97 content: Box::new(content),
98 subtrees,
99 }
100 }
101
102 /// Creates a leaf node (a node with no children).
103 pub fn leaf(content: impl Content) -> Tree {
104 Tree {
105 label: None,
106 content: Box::new(content),
107 subtrees: Vec::new(),
108 }
109 }
110
111 /// Adds a label to the node.
112 ///
113 /// Labels appear before the content, typically as a key or name.
114 pub fn labeled(mut self, label: impl Content) -> Self {
115 self.label = Some(Box::new(label));
116 self
117 }
118
119 /// Returns whether this node is a leaf (has no children).
120 pub fn is_leaf(&self) -> bool {
121 self.subtrees.is_empty()
122 }
123}