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.
These methods return Option<&T> as the return type, where None indicates that no items were
selected.
§Multiple selections
If you wish to permit the user to make multiple selections, use one of the similarly named methods:
These methods are analogous to their single-selection variants, except additional items can be
queued with the MatchListEvent::ToggleDown and
MatchListEvent::ToggleUp events. The default
keybindings bind these to ⇥ and shift + ⇥ respectively. In this case, an
Event::Select is handled slightly differently: if there are no queued selections, this
picks the highlighted item, but if there are queued selections, then only the queued selections
are returned.
If the picker restarts while running, the queued item list will be cleared since the previous items are removed.
The selected items are returned as a Selection, which is empty if picker exited with
Event::Quit (or Event::QuitPromptEmpty), and non-empty if not.
§Emulate single selection using a multi-picker
It is possible to emulate single selection with one of the multi-picker methods by setting
PickerOptions::max_selection_count to Some(1). This will force the resulting
Selection to contain either 0 or 1 element, and you can convert to Option<&T> by calling
next on the iterator.
Note that the picker interface will be slightly different: it is still possible to
queue at most one picked item using ⇥. With the non-multi-pickers, it is not possible to
queue items at all.
§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 Picker::restart.
§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> Picker<T, R>
impl<T: Send + Sync + 'static, R> Picker<T, R>
Sourcepub fn new(render: R) -> Selfwhere
R: Render<T>,
pub fn new(render: R) -> Selfwhere
R: Render<T>,
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 Injectors for this picker.
This is the channel to which new injectors will be sent when the picker processes a
restart event. Restart events are not generated by this library. You only
need this channel if you generate restart events in your own code. See the Event documentation
for more detail.
Calling this method will invalidate all earlier observers. If you want multiple copies of the same observer, clone your existing observer.
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.
All items are removed immediately. Existing injectors will continue to function but the items will no longer be received by this instance. The old items will only be dropped when all injectors are dropped.
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 for more detail. Note that method does not clear the query.
Sourcepub fn extend_exact<I>(&self, iter: I)
pub fn extend_exact<I>(&self, iter: I)
A convenience method to add a batch of items directly to the picker.
The number of items in the iterator must be known exactly. This is a convenience wrapper
around Injector::extend_exact.
Sourcepub fn render<'a>(&self, item: &'a T) -> <R as Render<T>>::Str<'a>where
R: Render<T>,
pub fn render<'a>(&self, item: &'a T) -> <R as Render<T>>::Str<'a>where
R: Render<T>,
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>where
R: Render<T>,
pub fn pick(&mut self) -> Result<Option<&T>, PickError>where
R: Render<T>,
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::NotInteractiveif stderr is not interactive.PickError::UserInterruptedif the user pressesctrl + c.
This method will never return PickError::Disconnected.
Sourcepub fn pick_multi(&mut self) -> Result<Selection<'_, T>, PickError>where
R: Render<T>,
pub fn pick_multi(&mut self) -> Result<Selection<'_, T>, PickError>where
R: Render<T>,
Open the interactive picker prompt and return the picked items, if any.
This method permits the user to select multiple items, but is otherwise identical to pick. See those docs as well as the
docs on multiple selections for more detail.
Sourcepub fn pick_with_keybind<F>(
&mut self,
keybind: F,
) -> Result<Option<&T>, PickError>
pub fn pick_with_keybind<F>( &mut self, keybind: F, ) -> Result<Option<&T>, PickError>
Open the interactive picker prompt and return the picked item, if any. The provided keybindings are used in 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::NotInteractiveif stderr is not interactive.PickError::UserInterruptedif a keybinding results in aEvent::UserInterrupt,
This method will never return PickError::Disconnected.
Sourcepub fn pick_multi_with_keybind<F>(
&mut self,
keybind: F,
) -> Result<Selection<'_, T>, PickError>
pub fn pick_multi_with_keybind<F>( &mut self, keybind: F, ) -> Result<Selection<'_, T>, PickError>
Open the interactive picker prompt and return the picked item, if any. The provided keybindings are used in the interactive picker.
This method permits the user to select multiple items, but is otherwise identical to pick_with_keybind. See those docs as well as the
docs on multiple selections for more detail.
Sourcepub fn pick_with_io<E, W>(
&mut self,
event_source: E,
writer: &mut W,
) -> Result<Option<&T>, PickError<<E as EventSource>::AbortErr>>
pub fn pick_with_io<E, W>( &mut self, event_source: E, writer: &mut W, ) -> Result<Option<&T>, PickError<<E as EventSource>::AbortErr>>
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_timeoutfails with aRecvError::Disconnected, the error returned will bePickError::Disconnected. - The error will be
PickError::UserInterruptedif thePickerreceives anEvent::UserInterrupt. - The error will be
PickError::Abortedif thePickerreceives anEvent::Abort.
This method will never return PickError::NotInteractive since interactivity checks
are not done.
Sourcepub fn pick_multi_with_io<E, W>(
&mut self,
event_source: E,
writer: &mut W,
) -> Result<Selection<'_, T>, PickError<<E as EventSource>::AbortErr>>
pub fn pick_multi_with_io<E, W>( &mut self, event_source: E, writer: &mut W, ) -> Result<Selection<'_, T>, PickError<<E as EventSource>::AbortErr>>
Run the picker interactively with a custom event source and writer, allowing the user to select multiple items.
This is otherwise identical to pick_with_io; see those docs as well
as the docs on multiple selections for more detail.
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> !RefUnwindSafe for Picker<T, R>
impl<T, R> !UnwindSafe for Picker<T, R>
impl<T, R> Freeze 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> UnsafeUnpin 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