5 ms·
Show HN: Lstr – A modern, interactive tree command written in Rust
Hi HN,
(First time poster!)
I'm the author of `lstr`. I've always loved the classic Linux `tree` command for its simplicity, but I often found myself wanting more modern features like interactivity and Git integration. So, I decided to build my own version in Rust with a philosophy of being fast, minimalist, and interactive. It was also an excuse to help learn more about Rust\!
Here's a quick look at the interactive mode:
https://raw.githubusercontent.com/bgreenwell/lstr/main/assets/lstr-demo.gif https://raw.githubusercontent.com/bgreenwell/lstr/main/asset...
I've just released v0.2.0 with some features I think this community might find useful:
* **Interactive TUI Mode:** You can launch it with `lstr interactive`. It allows for keyboard-driven navigation, expanding/collapsing directories, and opening files in your default editor.
* **Git Status Integration:** Using the `-G` flag, `lstr` will show the Git status of every file and directory right in the tree output.
* **Shell Integration:** This is my favorite feature. In interactive mode, you can press `Ctrl+s` to quit and have `lstr` print the selected path to stdout. This lets you pipe it into other commands or use it as a visual `cd`. For example, you can add this function to your `.bashrc`/`.zshrc`:
```bash
lcd() {
local selected_path
selected_path="$(lstr interactive -gG)"
if [[ -n "$selected_path" && -d "$selected_path" ]]; then
cd "$selected_path"
fi
}
```
Then just run `lcd` to visually pick a directory and jump to it.
It also supports file-type icons (via Nerd Fonts), file sizes, permissions, and respects your `.gitignore`.
The project is open-source and I would love to get your feedback.
GitHub: https://github.com/bgreenwell/lstr https://github.com/bgreenwell/lstr
Crates.io: https://crates.io/crates/lstr https://crates.io/crates/lstr
Thanks for checking it out!
- w108bmg 1y agoReally appreciate all the comments and useful feedback (first Rust package). Especially ways to reduce the size of the binary!
- aystatic 1y agoNeat, looks like a combination of erdtree[0] and broot[1]. I use both on a daily basis, are there any features that stand out from the two? [0]: https://github.com/solidiquis/erdtree https://github.com/solidiquis/erdtree [1]: https://github.com/Canop/broot https://github.com/Canop/broot
- deleted 1y ago[deleted]
- drabbiticus 1y agoFirst off, the display looks great! Second off, I didn't realize how deep the dep tree would be for this type of program -- 141 total! So much of it is the url crate, itself a dep of the git crate, but there's a bunch of others too. I'm just getting into learning Rust -- is this typical of Rust projects or perhaps typical of TUI projects in general? (EDIT to strikeout) ~~The binary is also 53M as a result whereas /usr/sbin/tree is 80K on my machine -- not really a problem on today's storage, but very roughly 500-1000x different in size isn't nothing.~~ Maybe it's linking-related? I don't know how to check really. (EDIT: many have pointed out that you can run `cargo build --release` with other options to get a much smaller binary. Thanks for teaching me!)
- CGamesPlay 1y agoLikely needs features tuned. I compared Eza, similarly in Rust, and it's 1.6 MiB compiled. Looking at the Cargo.toml, it includes git2 with default-features = false. https://github.com/eza-community/eza/blob/main/Cargo.toml https://github.com/eza-community/eza/blob/main/Cargo.toml
- fabrice_d 1y agoYou are probably looking at a debug build. On Linux, a release build (cargo build -r) is ~4.3M, and down to ~3.5M once stripped. This could be reduced further with some tricks applied to the release build profile.
- pveierland 1y agoBuilding in release: cargo build --release du -sh ./target/release/lstr -> 4.4M Building with other release options brings it down to 2.3M: [profile.release] codegen-units = 1 opt-level = "s" lto = true panic = "abort" strip = "symbols"
- cyann 1y agoI did some benchmarks on one of our CLI and found that `opt-level = "z"` reduced the size from 2.68M to 2.28M, and shaved 10% on the build time, worth a try. I'll try with `panic = "abort"` for our next release, thanks for the reminder.
- ipdashc 1y agoSeems quite cool! Though the demo gif with (what seem to be?) broken icons is a bold choice :p
- w108bmg 1y agolol good catch, and I totally missed it I used vhs to record the gif which must not run the script in my native terminal! I’ll have to see about fixing it!
- yonatan8070 1y agoI've seen a lot of people use asciinema to record and share terminal recordings, it works quite well
- diggan 1y agoYou still end up having to turn it into a GIF if you want it to autoplay on GitHub's markdown viewer, or video if you want it to run on the page but require a click-to-play.
- yonatan8070 1y agoHuh, I though you could embed those into READMEs on GitHub, but turns out you can't
- nightpool 1y agoHow would that solve the font problem? I feel like that would only make the problem of having unsupported fonts even worse.
- wonger_ 1y agoOne solution could be to use the docker version of vhs, and edit the dockerfile to pull your desired font.
- sdegutis 1y agoI didn't notice, I was too busy seeing how impressive and useful this tool is. And with fuzzy matching built in? Just amazing. Good job OP.
- sdegutis 1y agoSo after writing this to learn Rust, what are your thoughts on Rust? What do you especially like and dislike about it, or what were you surprised about?
- w108bmg 1y agoI appreciate the ecosystem of packages that seem really well maintained. I don’t love the syntax and find Rust harder to read and learn so far compared to something like golang (I’m used to R which is not a compiled language but has a great dev community). I do love the compiler and support tools built into Cargo (fmt, clippy, etc.).
- sdegutis 1y agoThat's been similar to my experience. The ecosystem is extremely polished and smooth, the build tools and package manager and IDE support, all of it. Especially compared to C++ which I cuold barely get working here.
- be87581d 1y ago[dead]
- ironuchan 1y ago[dead]
- rewgs 1y agoThis looks awesome! Right up my alley. Side-note: what theme are you using in the linked gif? It's right in the middle of my two favorite themes, onedark and gruvbox.
- berkes 1y agoI really love all the "modern" takes on classic tools by the Rust community. I'm using eza (aka exa), aliased as ls, which has "tree" built in (aliased as lt), amongst others, as replacement for "ls" and it's one of my biggest production boosts in daily commandline use. Because eza has the tree built in, and the tree is also insanely fast, I won't be needing this tool - yet. Maybe one day the interactive mode will pull me over. Congrats on releasing. And kudo's to how well you've released it: solid README, good description, good-looking gifs with exactly the right feature highlights
- fer 1y agoOn interactive mode "ls tree" tools, an interesting one is broot. https://github.com/Canop/broot https://github.com/Canop/broot
- deleted 1y ago[deleted]
- b0a04gl 1y ago[dead]
- dboreham 1y agoNo async which is nice. TIL that Rayon has an almost Occam like syntax: https://github.com/bgreenwell/lstr/blob/44b9bbf118ca905581383d1ec35be88c2859e36e/src/main.rs#L110C21-L110C29 https://github.com/bgreenwell/lstr/blob/44b9bbf118ca90558138... although you subsequently went with a library that bundles parallel filesystem traversal.
- gorgoiler 1y agoDoing this in just over 1000 lines of code is really inspiring. I was bracing myself for something quite a lot larger and, honestly, gearing up to use that as an excuse not to delve through the code. No such luck… good!