
A customizable tree rendering library and CLI for Rust
Provides low-level and high-level APIs for rendering hierarchical data structures, similar to tree, npm ls, or cargo tree. Also includes a command-line utility for quick tree visualization.
Installation • Quick Start • CLI Usage • Documentation • Examples
Core Features
- Multiple Styles - Unicode, ASCII, Box drawing, and custom styles
- Macro DSL - Declarative syntax for easy tree construction
- Builder API - Fluent interface for easy tree construction
- Iterator Support - Stream large trees without materializing
- Custom Formatters - Format nodes and leaves to your needs
- Optimized - Pre-computed prefixes and efficient rendering
- Zero Dependencies - Lightweight and fast
Analysis & Statistics
- Tree Statistics - Get depth, width, node/leaf counts, and more
- Tree Traversal - Pre-order, post-order, level-order, and filtered iterators
- Tree Search - Find nodes/leaves by label or content, get paths
Transformation & Manipulation
- Tree Transformation - Map, filter, and prune trees functionally
- Tree Sorting - Sort children by label, depth, or custom comparison
- Tree Merging - Merge trees with different strategies (replace, append, merge-by-label)
Utilities
- Path Utilities - Navigate trees by path, flatten to lists
- Tree Comparison - Compare structure, compute diffs, check subtrees
- Export Formats - Export to HTML, SVG, and Graphviz DOT format
- Tree Validation - Validate tree structure
Installation
As a Library
Add this to your Cargo.toml:
[]
= "0.0.5"
As a CLI Tool
Install the CLI tool using cargo:
Or build from source:
The CLI requires the cli feature and optionally other features depending on the input sources you want to use.
Quick Start
use ;
let tree = Node;
let mut output = Stringnew;
write_tree.unwrap;
println!;
Output:
root
├─ item1
└─ sub
├─ subitem1
└─ subitem2
Usage
use ;
let tree = Node;
let mut output = Stringnew;
write_tree.unwrap;
// root
// └─ item
The tree! macro provides a clean, declarative syntax for constructing trees:
use tree;
let tree = tree! ;
println!;
The macro supports:
- Nodes:
identifier { ... }or"string" { ... } - Leaves:
"string"or bare identifiers (converted to strings) - Nested structures: Arbitrary nesting depth
- Comma-separated: Children separated by commas (trailing comma optional)
use TreeBuilder;
let mut builder = new;
builder.node.leaf.node.leaf.leaf.end.leaf;
let tree = builder.build;
println!;
use Tree;
let tree = Node;
println!;
use ;
let tree = Node;
// Stream lines
for line in lines
// Or collect all at once
let lines: = tree.to_lines;
Styles:
use ;
let tree = Node;
// Predefined styles
tree.render_to_string_with_config;
// Custom style
let style = custom;
tree.render_to_string_with_config;
Formatters (requires formatters feature):
use ;
let tree = Node;
let config = default
.with_node_formatter
.with_leaf_formatter;
tree.render_to_string_with_config;
use ;
use Write;
let tree = Node;
let mut stdout = stdout;
for line in lines
Advanced Features
Get detailed statistics about your tree:
use Tree;
let tree = Node;
// Individual statistics
println!;
println!;
println!;
println!;
// Or get all at once
let stats = tree.stats;
println!;
Iterate over trees in different orders:
use Tree;
let tree = Node;
// Pre-order: root, then children
for node in tree.pre_order
// Post-order: children, then root
for node in tree.post_order
// Level-order: breadth-first
for node in tree.level_order
// Iterate only over nodes or leaves
for node in tree.nodes
for leaf in tree.leaves
Find nodes and leaves in your tree:
use Tree;
let tree = Node;
// Find first node with label
if let Some = tree.find_node
// Find all nodes with label
let all_nodes = tree.find_all_nodes;
// Find leaf containing content
if let Some = tree.find_leaf
// Check if tree contains label/content
if tree.contains
// Get path to a node
if let Some = tree.path_to
Transform trees functionally:
use Tree;
let tree = Node;
// Map node labels
let transformed = tree.map_nodes;
// Map leaf lines
let transformed = tree.map_leaves;
// Filter tree
let filtered = tree.filter;
// Prune tree (inverse of filter)
let pruned = tree.prune;
Sort tree children:
use Tree;
let mut tree = Node;
// Sort by label alphabetically
tree.sort_by_label;
// Sort by depth
tree.sort_by_depth; // deepest first
// Custom sort
let mut compare = ;
tree.sort_children;
Navigate and manipulate trees by path:
use Tree;
let tree = Node;
// Get path to a node
let child = &tree.children.unwrap;
if let Some = tree.get_path
// Get node by path
if let Some = tree.get_by_path
// Modify node by path
let mut tree = tree.clone;
if let Some = tree.get_by_path_mut
// Flatten tree to list
let flattened = tree.flatten;
for entry in flattened
Compare trees and find differences:
use Tree;
let tree1 = Node;
let tree2 = Node;
// Compare structure (ignoring content)
if tree1.eq_structure
// Compute differences
let diffs = tree1.diff;
for diff in diffs
// Check if subtree
let subtree = Leaf;
if subtree.is_subtree_of
Merge trees with different strategies:
use ;
let tree1 = Node;
let tree2 = Node;
// Replace: replace first tree with second
let merged = tree1.merge;
// Append: append all children
let merged = tree1.merge;
// MergeByLabel: merge nodes with matching labels
let merged = tree1.merge;
Export trees to various formats:
use Tree;
use fs;
let tree = Node;
// Create exports directory
create_dir_all.unwrap;
// Export to HTML (with collapsible nodes)
let html = tree.to_html;
write.unwrap;
// Export to SVG
let svg = tree.to_svg;
write.unwrap;
// Export to Graphviz DOT format
let dot = tree.to_dot;
write.unwrap;
// Render with: dot -Tpng exports/tree.dot -o exports/tree.png
Serialization (serde)
Serialize and deserialize trees to/from JSON and YAML:
use Tree;
let tree = Node;
// JSON serialization (requires `json` feature)
// YAML serialization (requires `yaml` feature)
TOML Support
Serialize/deserialize trees to/from TOML (requires both toml and serde features):
use Tree;
let tree = Node;
// Serialize tree to TOML (preserves exact Tree structure)
let toml = tree.to_toml.unwrap;
// Deserialize back
let deserialized = from_toml.unwrap;
File System Integration
Build trees from directory structures (requires walkdir feature):
use Tree;
// Build tree from current directory
let tree = from_dir.unwrap;
// Build tree with maximum depth
let tree = from_dir_max_depth.unwrap;
Graph Integration
Convert between trees and petgraph graphs (requires petgraph feature):
use Tree;
use Graph;
// Tree to graph
let tree = Node;
let graph: = tree.to_graph;
// Graph to tree
let mut graph = new;
let a = graph.add_node;
let b = graph.add_node;
graph.add_edge;
let tree = from_graph;
Cargo Metadata Integration
Visualize Cargo dependency trees (requires cargo-metadata feature):
use Tree;
// Build dependency tree for current project
let tree = from_cargo_metadata.unwrap;
// Build dependency tree for specific package
let tree = from_cargo_package_deps.unwrap;
Git Integration
Visualize Git repository structures (requires git2 feature):
use Tree;
// Build tree from Git repository
let tree = from_git_repo.unwrap;
// Build tree from branches
use Repository;
let repo = open.unwrap;
let tree = from_git_branches.unwrap;
// Build tree from specific commit
let commit = repo.head.unwrap.peel_to_commit.unwrap;
let tree = from_git_commit_tree.unwrap;
XML/HTML Integration
Visualize XML/HTML DOM trees (requires roxmltree feature):
use Tree;
// Build tree from XML string
let xml = r#"<root><child>text</child></root>"#;
let tree = from_arbitrary_xml.unwrap;
// Build tree from XML file
let tree = from_arbitrary_xml_file.unwrap;
Rust AST Integration
Visualize Rust source code AST (requires syn feature):
use Tree;
// Build tree from Rust file
let tree = from_syn_file.unwrap;
// Build tree from syn::File AST
use parse_file;
let ast = parse_file.unwrap;
let tree = from_syn_file_ast;
// Build tree from individual item
use parse_quote;
let item: Item = parse_quote! ;
let tree = from_syn_item;
RON Integration
Serialize and deserialize trees to/from RON (requires ron and serde features):
use Tree;
let tree = Node;
// Serialize to RON
let ron = tree.to_ron.unwrap;
// Serialize to pretty RON
let ron_pretty = tree.to_ron_pretty.unwrap;
// Deserialize from RON
let deserialized = from_ron.unwrap;
Tree-sitter Integration
Visualize tree-sitter parse trees (requires tree-sitter feature):
use Tree;
use ;
// Load a language (tree-sitter-rust is available as a dev-dependency for doctests)
let language: Language = LANGUAGE.into;
let mut parser = new;
parser.set_language.unwrap;
let source_code = "fn main() {}";
let parse_tree = parser.parse.unwrap;
let tree = from_tree_sitter;
// Or parse and convert in one step
let tree = from_tree_sitter_language.unwrap;
Clap Integration
Visualize command-line argument structures (requires clap feature):
use Tree;
use ;
let cmd = new
.subcommand
.arg;
let tree = from_clap_command;
Most advanced features are behind feature flags to keep the core library lightweight:
[]
= { = "0.0.5", = ["traversal", "transform", "path", "comparison", "merge", "export"] }
Available features:
traversal- Tree traversal iterators (pre-order, post-order, level-order)transform- Tree transformation operations (map, filter, prune)path- Tree path utilities (get by path, flatten)comparison- Tree comparison and diff operationsmerge- Tree merging with different strategiesexport- Export to HTML, SVG, and DOT formatsbuilder- Builder API for constructing treesiterator- Iterator API for streaming treesmacro- Macro DSL for tree constructionformatters- Custom formatters for nodes and leavescolor- Color output supportserde- Serde serialization support (Serialize/Deserialize traits)json- JSON serialization/deserialization (requiresserde)yaml- YAML serialization/deserialization (requiresserde)toml- TOML parsing and tree conversionwalkdir- File system tree building from directoriespetgraph- Graph to/from tree conversioncargo-metadata- Cargo dependency tree visualizationgit2- Git repository structure visualizationroxmltree- XML/HTML DOM tree visualizationsyn- Rust AST visualizationron- RON (Rusty Object Notation) serializationtree-sitter- Tree-sitter parse tree visualizationclap- Command-line argument structure visualizationcli- CLI binary (includesclap)
Use all feature to enable everything (note: cli is separate and must be enabled explicitly for the binary):
= { = "0.0.5", = ["all"] }
To build the CLI binary, enable the cli feature along with any input source features you need:
= { = "0.0.5", = ["cli", "walkdir", "json"] }
- Pre-computed prefixes - Efficient string buffer capacity estimation
- Iterator API - Stream large trees without materializing the entire structure
- Stack-based traversal - Memory-efficient tree walking
- Zero-copy operations - Most operations work with references where possible
CLI Usage
The treelog CLI tool provides a convenient way to visualize trees from various sources without writing code. It's built on top of the library and exposes all its features through a command-line interface.
Basic Usage
# Visualize a directory structure
# Visualize Cargo dependencies
# Visualize Git repository structure
# Get tree statistics
|
Input Sources
The CLI supports creating trees from various sources:
- Directory structures:
treelog from dir <path> [--max-depth <n>] - Cargo metadata:
treelog from cargo [--package <name>] - Git repositories:
treelog from git [path] [--branches] [--commit] - XML/HTML files:
treelog from xml <file> - Rust source files:
treelog from rust <file> - JSON/YAML/TOML/RON files:
treelog from json|yaml|toml|ron <file>
Rendering Options
# Use ASCII style
# Custom style
# Output to file
# Export to different formats
Tree Operations
# Get statistics
# Search for nodes
# Sort tree
# Transform tree
# Compare trees
# Merge trees
Piping and Serialization
The CLI supports piping trees between commands using serialized formats:
# Create tree and get statistics
|
# Transform and export
| |
Note: When piping between commands, use --format json (or yaml, toml, ron) to serialize the tree structure. The default text format is for human-readable output only.
Help
Get help for any command:
Examples
The repository includes comprehensive examples demonstrating all features:
Core Examples:
basic- Basic tree construction and renderingbuilder- Using the builder APIiterator- Streaming large treesmacro- Using the macro DSLcustomization- Custom styles and formatterscomplex- Complex tree structuresfile_tree- File system tree example
Advanced Examples:
statistics- Tree statistics and analysistraversal- Tree traversal iteratorssearch- Tree search and query operationstransform- Tree transformation operationssorting- Tree sorting operationspath- Tree path utilitiescomparison- Tree comparison and diffmerge- Tree merging strategiesexport- Export to HTML, SVG, and DOT formats
Integration Examples:
serde- JSON and YAML serializationtoml- TOML parsing and conversionfilesystem- File system tree buildingpetgraph- Graph to/from tree conversioncargo- Cargo dependency tree visualizationgit2- Git repository structure visualizationxml- XML/HTML DOM tree visualizationsyn- Rust AST visualizationron- RON serializationtree_sitter- Tree-sitter parse tree visualizationclap- Command-line argument structure visualization
Run any example with:
Development
Real-time feedback: This project includes VS Code/Cursor settings (.vscode/settings.json) that configure rust-analyzer to provide real-time feedback:
- Formatting: Automatically formats on save (matches
cargo fmt) - Clippy: Shows clippy warnings/errors as you type (matches pre-commit hook settings)
- Tests: Displays test failures in the editor
Git hooks available via pre-commit (see .pre-commit-config.yaml).
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.