[!] i wanted a small, fast, rust-based tree-like tool that was actually fun to build and mess with. while working on it i hit a bunch of interesting challenges: ownership issues, error handling, unicode alignment, and even building a simple interactive terminal UI. this is mostly a hobby project, but i think it’s a nice little learning playground too.
[?] what makes it interesting?
[X] unicode tree drawing
[X] lining up box-drawing characters without breaking alignment on weird filenames was way harder than i expected.
i ended up manually building each “branch” and tracking whether a node was the last child so the vertical lines stop correctly.
[X] sorting, filtering, and recursion
combining recursion with sorting and filtering forced me to rethink my borrow/ownership approach. i rewrote the traversal several times before it felt clean.
[X] recursive by default.
handling deep directory trees and large file counts pushed me to keep everything efficient and avoid blocking the UI.
[X] error handling
dealing with unreadable directories, permission issues, and broken symlinks taught me a lot about thiserror / anyhow and why good context matters.
[X] interactive mode (TUI) making a “simple” TUI ended up being more work than adding features.
handling input, redraw logic, and state transitions was its own adventure.
[+] small code walkthrough;
[+] building the tree
build_tree() recursively walks the filesystem, filters entries, applies optional glob patterns, sorts everything, and decreases max_depth to control recursion. ownership gets tricky fast.
[+] printing trees
print_tree() handles branches, connectors, colors, and size info. getting the “last child” logic wrong instantly ruins the visuals.
[+] collapsing single-child directories
collapse_tree() merges directories with only one child to keep the output clean. mutating the structure while recursing was its own headache.
[+] interactive TUI
built using ratatui + crossterm. arrow keys move selection, enter opens files, backspace goes up. separating state (current_path, entries, selected) massively simplified things.
FAQ
[?] why did you make this?
[!] i wanted a small, fast, rust-based tree-like tool that was actually fun to build and mess with. while working on it i hit a bunch of interesting challenges: ownership issues, error handling, unicode alignment, and even building a simple interactive terminal UI. this is mostly a hobby project, but i think it’s a nice little learning playground too.
[?] what makes it interesting?
[X] unicode tree drawing
[X] lining up box-drawing characters without breaking alignment on weird filenames was way harder than i expected.
i ended up manually building each “branch” and tracking whether a node was the last child so the vertical lines stop correctly.
[X] sorting, filtering, and recursion
combining recursion with sorting and filtering forced me to rethink my borrow/ownership approach. i rewrote the traversal several times before it felt clean.
[X] recursive by default.
handling deep directory trees and large file counts pushed me to keep everything efficient and avoid blocking the UI.
[X] error handling
dealing with unreadable directories, permission issues, and broken symlinks taught me a lot about thiserror / anyhow and why good context matters.
[X] interactive mode (TUI) making a “simple” TUI ended up being more work than adding features.
handling input, redraw logic, and state transitions was its own adventure.
[+] small code walkthrough;
[+] building the tree
build_tree() recursively walks the filesystem, filters entries, applies optional glob patterns, sorts everything, and decreases max_depth to control recursion. ownership gets tricky fast.
[+] printing trees
print_tree() handles branches, connectors, colors, and size info. getting the “last child” logic wrong instantly ruins the visuals.
[+] collapsing single-child directories collapse_tree() merges directories with only one child to keep the output clean. mutating the structure while recursing was its own headache.
[+] interactive TUI built using ratatui + crossterm. arrow keys move selection, enter opens files, backspace goes up. separating state (current_path, entries, selected) massively simplified things.
[?] how to try it head over to: https://github.com/hnpf/canopy