match-maker 0.0.1

A fuzzy finder for the terminal, powered by nucleo
Documentation

m&m Crates.io License

Matchmaker is a fuzzy searcher, powered by nucleo and written in rust.

(pitch + fzf credit: todo)

Features

  • Matching with nucleo.
  • A hierarchical configuration deserialized from a toml file. (Cli parsing not yet implemented.)
  • Interactive preview supports color, scrolling, wrapping, multiple layouts, and even entering into an interactive view.
  • FZF-derived actions.
  • Column support: Split input lines into multiple columns, that you can dynamically search, filter, highlight, return etc.
  • Available as a rust library to use in your own code.

Installation

cargo install matchmaker

Pass it some items:

fd -u | mm

Configuration

To begin, you can dump the default configuration to a file:

matchmaker --dump-config

The default locations are in order:

  • ~/.config/matchmaker/config.toml (If the folder exists already).
  • {PLATFORM_SPECIFIC_CONFIG_DIRECTORY}/matchmaker (Generally the same as above when on linux)

Keybindings

All actions must be defined in in your config.toml.

The list of currently supported actions can be found here.

To get the names of keys, type matchmaker --test-keys.

In addition to keys, actions can also be bound to Events and Crossterm events (check your default config for details).

Library

Matchmaker can also be used as a library.

cargo add matchmaker

Example

Here is how to use Matchmaker to select from a list of strings.

use matchmaker::nucleo::worker::Worker;
use matchmaker::{Matchmaker, PickerError, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let items = vec!["item1", "item2", "item3"];

    let worker = Worker::new_single();
    worker.append(items);
    let identifier = Worker::clone_identifier;

    let mm = matchmaker::new(worker, identifier);

    match mm.pick().await {
        Ok(iter) => {
            for s in iter {
                println!("{s}");
            }
        }
        Err(err) => {
            if let Some(e) = err.downcast_ref::<PickerError>()
                && matches!(e, PickerError::Abort(1))
            {
                eprintln!("cancelled");
            } else {
                eprintln!("Error: {err}");
            }
        }
    }

    Ok(())
}

Dynamic handlers

Some features such as the execute, reload, and print actions, and even the previewer do not have their behavior defined directly in the render loop.

Rather, they are attached as handlers to the Matchmaker, which are triggered by certain events and interrupts generated by the loop.

Some actions can generate these triggers, as well usually performing a minimal amount of other logic.

For example, the Preview(bat {}) command generates a PreviewChanged event, and leaves the string contents as a payload in the render state. This render state is exposed to the handler, and is used to spawn the command which is then displayed to preview.

As you can see, this paradigm fixes very little of the Preview action's behavior. The Execute action is another example: it simply leaves the tui before invoking the execute handler, then re-enters before the next render.

Consequently, there exist severable actions whose behaviors are actually open to modification to your own purposes if you so choose.

On the flip side however, the set of actions is an Enum and thus not generic and not customizable. (For full customizability, matchmaker will probably support in the future sending and receiving custom events).

For more information, check out the examples and Arcitecture.md

See also