tree
A cross-platform tree command written in Rust, providing a fast directory listing with features like glob filtering, icons, gitignore support, and colorized output. Works on Windows, macOS, and Linux.
Overview
- Language: Rust
- Repo: peteretelej/tree
- Install:
cargo install rust_tree --locked - Status: active (v1.3.0)
Architecture
This is a single-crate project (published as rust_tree on crates.io) with a thin binary and a full library surface.
Binary (src/main.rs): A 17-line wrapper that calls run_cli() and handles broken pipe errors gracefully. All logic lives in the library.
Library (src/lib.rs -> src/rust_tree/): Seven modules, each with a focused responsibility:
cli.rs- Argument parsing via clap derive, maps CLI flags toTreeOptionsoptions.rs- TheTreeOptionsstruct, a flat config object with ~25 boolean/option fields controlling every aspect of outputtraversal.rs- The core engine.list_directory()is the public API entry point, which delegates to eitherlist_from_filesystem()orlist_from_input()(for--fromfilemode). Recursive traversal viatraverse_directory()which takes a genericWritesink, enabling both stdout and string capture (list_directory_as_string())display.rs- ANSI colorization by file type/extension usingansi_term, plus Unix permission formattingicons.rs-IconManagerwith a JSON-based icon theme system. Default theme is embedded as a const string with ~100 extension-to-emoji mappings, well-known filenames (Dockerfile, Cargo.toml), and fallback categories. Supports loading custom themes from filegitignore.rs- Respects.gitignorerules during traversal, with per-directory rule extensionfromfile.rs- Parses file listings from stdin/file into aVirtualTree, enablingtreeto display structure from piped inpututils.rs- Helpers likebytes_to_human_readableandis_broken_pipe_error
Data flow: CLI args -> TreeOptions -> list_directory(path, &options) -> recursive traverse_directory() with filtering, sorting, and entry formatting -> writes to a BufWriter<impl Write>.
Key Design Decisions
Library-first: The binary is intentionally thin. The list_directory and list_directory_as_string functions are the public API, making it usable as a Rust crate for programmatic directory listing.
Generic writer pattern: traverse_directory accepts impl Write, so the same traversal code powers both stdout output and string capture. The prune feature uses this too, probing subtrees by traversing into io::sink().
No chrono: Date formatting is implemented manually using stdlib’s SystemTime and manual calendar math, avoiding the chrono dependency and its cross-compilation complexity.
Icon system via JSON: Rather than hardcoding icons or using a match statement, the icon theme is a JSON structure deserialized at startup. This makes it extensible (custom theme files) while keeping the default embedded in the binary.
Windows 7 compatibility: The project maintains a separate Cargo-win7.lock lockfile for building with Rust 1.75 on Windows 7. The MSRV is pinned at the workspace level, and static CRT linking is configured for Windows targets.
Glob filtering: Uses the glob crate’s Pattern type for both include (-P) and exclude (-I) patterns, with support for pruning empty directories and matching directory names.
Development
cargo build --release
cargo test
cargo fmt --check
cargo clippy
# Run the pre-push quality script
./scripts/pre-push
# Windows 7 build
rustup run 1.75.0 cargo build --release