pub struct Picker<T: Send + Sync + 'static, R> { /* private fields */ }
Expand description
A fuzzy matching interactive item picker.
The parameter T
is the item type and the parameter R
is the renderer, which
describes how to represent T
in the match list.
Initialize a picker with Picker::new
, or with custom configuration using
PickerOptions
, and add elements to the picker using an Injector
returned
by the Picker::injector
method.
use nucleo_picker::{render::StrRenderer, Picker};
// Initialize a picker using default settings, with item type `String`
let picker: Picker<String, _> = Picker::new(StrRenderer);
See also the usage examples.
§Picker variants
The picker can be run in a number of different modes.
- The simplest (and most common) method is to use
Picker::pick
. - If you wish to customize keybindings, use
Picker::pick_with_keybind
. - If you wish to customize all IO to the picker, use
Picker::pick_with_io
.
§A note on memory usage
Initializing a picker is a relatively expensive operation since the internal match engine uses an arena-based memory approach to minimize allocator costs, and this memory is initialized when the picker is created.
To re-use the picker without additional start-up costs, use the Picker::restart
method.
§Example
Run the picker on Stdout
with no interactivity checks, and quitting
gracefully on ctrl + c
.
use std::io;
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
use nucleo_picker::{
Picker,
event::{Event, StdinReader, keybind_default},
render::StrRenderer,
};
/// Keybindings which use the default keybindings, but instead of aborting on `ctrl + c`,
/// simply perform a normal quit action.
fn keybind_no_interrupt(key_event: KeyEvent) -> Option<Event> {
match key_event {
KeyEvent {
kind: KeyEventKind::Press,
modifiers: KeyModifiers::CONTROL,
code: KeyCode::Char('c'),
..
} => Some(Event::Quit),
e => keybind_default(e),
}
}
fn main() -> io::Result<()> {
let mut picker = Picker::new(StrRenderer);
let choices = vec![
"Alvar Aalto",
"Frank Lloyd Wright",
"Zaha Hadid",
"Le Corbusier",
];
// populate the matcher using the convenience 'extend' implementation
picker.extend(choices);
// launch the interactive picker with the customized keybindings, and draw the picker on
// standard output
match picker.pick_with_io(
StdinReader::new(keybind_no_interrupt),
&mut std::io::stdout(),
)? {
Some(opt) => println!("Your preferred architect is: '{opt}'"),
None => println!("No architect selected!"),
}
Ok(())
}
Implementations§
Source§impl<T: Send + Sync + 'static, R: Render<T>> Picker<T, R>
impl<T: Send + Sync + 'static, R: Render<T>> Picker<T, R>
Sourcepub fn new(render: R) -> Self
pub fn new(render: R) -> Self
Initialize a new picker with default configuration and the provided renderer.
Sourcepub fn update_query<Q: Into<String>>(&mut self, query: Q)
pub fn update_query<Q: Into<String>>(&mut self, query: Q)
Update the default query string. This is mainly useful for modifying the query string
before re-using the Picker
.
See the PickerOptions::query
method to set the query during initialization, and
PromptEvent::Reset
to reset the query during interactive
use.
Sourcepub fn query(&self) -> &str
pub fn query(&self) -> &str
Returns the contents of the query string internal to the picker.
If called after running Picker::pick
, this will contain the contents of the query string
at the moment that the item was selected or the picker quit.
Sourcepub fn injector_observer(
&mut self,
with_injector: bool,
) -> Observer<Injector<T, R>>
pub fn injector_observer( &mut self, with_injector: bool, ) -> Observer<Injector<T, R>>
Returns an Observer
containing up-to-date Injector
s for this picker. For example,
this is the channel to which new injectors will be sent when the picker processes a
restart event. See the Event
documentation for more detail.
Restart events are not generated by this library. You only need this channel if you generate restart events in your own code.
If with_injector
is true
, the channel is intialized with an injector currently valid
for the picker on creation.
Sourcepub fn update_config(&mut self, config: Config)
pub fn update_config(&mut self, config: Config)
Update the internal nucleo configuration.
Sourcepub fn restart(&mut self)
pub fn restart(&mut self)
Restart the match engine, disconnecting all active injectors and clearing the existing search query.
Internally, this is a call to Nucleo::restart
with clear_snapshot = true
.
See the documentation for Nucleo::restart
for more detail.
This method is mainly useful for re-using the picker for multiple matches since the
internal memory buffers are preserved. To restart the picker during interactive use, see
the Event
documentation or the restart
example.
Sourcepub fn reset_renderer(&mut self, render: R)
pub fn reset_renderer(&mut self, render: R)
Restart the match engine, disconnecting all active injectors and replacing the internal renderer.
The provided Render
implementation must be the same type as the one originally
provided; this is most useful for stateful renderers.
See Picker::restart
and Nucleo::restart
for more detail.
Sourcepub fn render<'a>(&self, item: &'a T) -> <R as Render<T>>::Str<'a>
pub fn render<'a>(&self, item: &'a T) -> <R as Render<T>>::Str<'a>
A convenience method to obtain the rendered version of an item as it would appear in the picker.
This is the same as calling Render::render
on the Render
implementation internal
to the picker.
Sourcepub fn pick(&mut self) -> Result<Option<&T>, PickError>
pub fn pick(&mut self) -> Result<Option<&T>, PickError>
Open the interactive picker prompt and return the picked item, if any.
§Stderr lock
The picker prompt is rendered in an alternate screen using the stderr
file handle. In
order to prevent screen corruption, a lock is acquired to stderr
; see
StderrLock
for more detail.
In particular, while the picker is interactive, any other thread which attempts to write to
stderr will block. Note that stdin
and stdout
will remain fully interactive.
§IO customization
To further customize the IO behaviour of the picker, such as to provide your own writer
(for instance to write to Stdout
instead) or use custom keybindings,
see the pick_with_io
and
pick_with_keybind
methods.
§Errors
Underlying IO errors from the standard library or crossterm
will be propagated with the
PickError::IO
variant.
This method also fails with:
PickError::NotInteractive
if stderr is not interactive.PickError::UserInterrupted
if the user pressesctrl + c
.
This method will never return PickError::Disconnected
.
Sourcepub fn pick_with_keybind<F: FnMut(KeyEvent) -> Option<Event>>(
&mut self,
keybind: F,
) -> Result<Option<&T>, PickError>
pub fn pick_with_keybind<F: FnMut(KeyEvent) -> Option<Event>>( &mut self, keybind: F, ) -> Result<Option<&T>, PickError>
Open the interactive picker prompt and return the picked item, if any. Uses the provided keybindings for the interactive picker.
The picker prompt is rendered in an alternate screen using the stderr
file handle. See
the pick
method for more detail.
To further customize event generation, see the pick_with_io
method.
The pick
method is internally a call to this method with keybindings
provided by keybind_default
.
§Errors
Underlying IO errors from the standard library or crossterm
will be propagated with the
PickError::IO
variant.
This method also fails with:
PickError::NotInteractive
if stderr is not interactive.PickError::UserInterrupted
if a keybinding results in aEvent::UserInterrupt
,
This method will never return PickError::Disconnected
.
Sourcepub fn pick_with_io<E, W>(
&mut self,
event_source: E,
writer: &mut W,
) -> Result<Option<&T>, PickError<<E as EventSource>::AbortErr>>where
E: EventSource,
W: Write,
pub fn pick_with_io<E, W>(
&mut self,
event_source: E,
writer: &mut W,
) -> Result<Option<&T>, PickError<<E as EventSource>::AbortErr>>where
E: EventSource,
W: Write,
Run the picker interactively with a custom event source and writer.
The picker is rendered using the given writer. In most situations, you want to check that
the writer is interactive using, for instance, IsTerminal
. The picker reads
events from the EventSource
to update the screen. See the docs for EventSource
for more detail.
§Errors
Underlying IO errors from the standard library or crossterm
will be propagated with the
PickError::IO
variant.
Whether or not this fails with another PickError
variant depends on the EventSource
implementation:
- If
EventSource::recv_timeout
fails with aRecvError::Disconnected
, the error returned will bePickError::Disconnected
. - The error will be
PickError::UserInterrupted
if thePicker
receives anEvent::UserInterrupt
. - The error will be
PickError::Aborted
if thePicker
receives anEvent::Abort
.
This method will never return PickError::NotInteractive
since interactivity checks
are not done.
Trait Implementations§
Source§impl<T: Send + Sync + 'static, R: Render<T>> Extend<T> for Picker<T, R>
impl<T: Send + Sync + 'static, R: Render<T>> Extend<T> for Picker<T, R>
Source§fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)Auto Trait Implementations§
impl<T, R> Freeze for Picker<T, R>
impl<T, R> !RefUnwindSafe for Picker<T, R>
impl<T, R> Send for Picker<T, R>
impl<T, R> Sync for Picker<T, R>
impl<T, R> Unpin for Picker<T, R>
impl<T, R> !UnwindSafe for Picker<T, R>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more