Picker

Struct Picker 

Source
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.

  1. The simplest (and most common) method is to use Picker::pick.
  2. If you wish to customize keybindings, use Picker::pick_with_keybind.
  3. 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>

Source

pub fn new(render: R) -> Self

Initialize a new picker with default configuration and the provided renderer.

Source

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.

Source

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.

Source

pub fn injector_observer( &mut self, with_injector: bool, ) -> Observer<Injector<T, R>>

Returns an Observer containing up-to-date Injectors 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.

Source

pub fn update_config(&mut self, config: Config)

Update the internal nucleo configuration.

Source

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.

Source

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.

Source

pub fn injector(&self) -> Injector<T, R>

Get an Injector to send items to the picker.

Source

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.

Source

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:

  1. PickError::NotInteractive if stderr is not interactive.
  2. PickError::UserInterrupted if the user presses ctrl + c.

This method will never return PickError::Disconnected.

Source

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:

  1. PickError::NotInteractive if stderr is not interactive.
  2. PickError::UserInterrupted if a keybinding results in a Event::UserInterrupt,

This method will never return PickError::Disconnected.

Source

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:

  1. If EventSource::recv_timeout fails with a RecvError::Disconnected, the error returned will be PickError::Disconnected.
  2. The error will be PickError::UserInterrupted if the Picker receives an Event::UserInterrupt.
  3. The error will be PickError::Aborted if the Picker receives an Event::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>

Source§

fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more

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>
where R: Sync + Send,

§

impl<T, R> Sync for Picker<T, R>
where R: Sync + Send,

§

impl<T, R> Unpin for Picker<T, R>

§

impl<T, R> !UnwindSafe for Picker<T, R>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.