| Crates.io | nucleo-picker |
| lib.rs | nucleo-picker |
| version | 0.9.0 |
| created_at | 2024-08-20 23:15:30.754365+00 |
| updated_at | 2025-09-02 22:46:34.111206+00 |
| description | A performant and Unicode-aware fuzzy picker tui library |
| homepage | |
| repository | https://github.com/autobib/nucleo-picker |
| max_upload_size | |
| id | 1345860 |
| size | 285,413 |
A native Rust library which enables you to incorporate a highly performant and Unicode-aware fuzzy picker directly in your own terminal application.
This library provides a TUI for the nucleo crate with an interface similar to the fzf command-line tool.
examples directory.USAGE.md file.CHANGELOG.md file.Why use this library instead of a general-purpose fuzzy-finder such as fzf or a lower level library such as nucleo?
sqlite3 and then parsing raw text, read directly into in-memory data structures with rusqlite and render the in-memory objects in the picker.fzf, have the picker integrated directly into your binary.fzf, and then parsing the resulting match string back into your data structure, directly obtain the original data structure when matching is complete.nucleo-picker handles terminal rendering subtleties such as multiline rendering, double-width Unicode, automatic overflow scrollthrough, and grapheme-aware query input so you don't have to.nucleo-picker exposes a fully-featured event system which can be used to drive the picker.
This lets you customize keybindings, support interactive restarts, and much more by implementing the EventSource trait.
Simplified versions of such features are available in fzf but essentially require manual configuration via an embedded DSL.Picker for any type T which is Send + Sync + 'static.Render trait.Implement a heavily simplified fzf clone in 25 lines of code.
Try it out with:
cargo build --release --example fzf
cat myfile.txt | ./target/release/examples/fzf
The code to create the binary:
use std::{
io::{self, IsTerminal},
process::exit,
thread::spawn,
};
use nucleo_picker::{render::StrRenderer, Picker};
fn main() -> io::Result<()> {
let mut picker = Picker::new(StrRenderer);
let injector = picker.injector();
spawn(move || {
let stdin = io::stdin();
if !stdin.is_terminal() {
for line in stdin.lines() {
// silently drop IO errors!
if let Ok(s) = line {
injector.push(s);
}
}
}
});
match picker.pick()? {
Some(it) => println!("{it}"),
None => exit(1),
}
Ok(())
}
This crate mainly exists as a result of the author's annoyance with pretty much every fuzzy picker TUI in the rust ecosystem. As far as I am aware, the fully-exposed event system is unique to this crate. Beyond this, here is a brief comparison:
Arc<dyn SkimItem> is inconvenient for a variety of reasons.
skim also has a large number of dependencies and is designed more as a binary than a library.skim and inherits skim's problems.String. It also seems to be un-maintained.FuzzySelect only has a blocking API and only supports matching on String.
The terminal handling also has a few strange bugs.There are a currently a few known problems which have not been addressed (see the issues page on GitHub for a list). Issues and contributions are welcome!