Skip to main content

discovery/
discovery.rs

1//! List bindings and search them. The library exposes the data (`iter()` plus
2//! `KeyInput`'s `Display`); the fuzzy/search engine is your choice — here a tiny
3//! case-insensitive substring filter.
4//!
5//! Run with: `cargo run -p keymap-core --example discovery`
6
7use keymap_core::{Key, KeyInput, Keymap, Modifiers};
8
9#[derive(Clone, Debug)]
10struct Command {
11    id: &'static str,
12    description: &'static str,
13}
14
15fn main() {
16    let mut keymap = Keymap::new();
17    keymap.bind(
18        KeyInput::new(Key::Char('q'), Modifiers::CTRL),
19        Command {
20            id: "quit",
21            description: "Quit the application",
22        },
23    );
24    keymap.bind(
25        KeyInput::new(Key::Char('s'), Modifiers::CTRL),
26        Command {
27            id: "save",
28            description: "Save the current file",
29        },
30    );
31    keymap.bind(
32        KeyInput::new(Key::F(1), Modifiers::NONE),
33        Command {
34            id: "help",
35            description: "Show the help overlay",
36        },
37    );
38
39    // Listing: collect and sort by the canonical key string.
40    let mut listing: Vec<(String, &Command)> = keymap
41        .iter()
42        .map(|(input, cmd)| (input.to_string(), cmd))
43        .collect();
44    listing.sort_by(|a, b| a.0.cmp(&b.0));
45
46    println!("all bindings:");
47    for (key, cmd) in &listing {
48        println!("  {key:>8}  {:<6} — {}", cmd.id, cmd.description);
49    }
50
51    search(&listing, "sav");
52    search(&listing, "zzz");
53}
54
55fn search(listing: &[(String, &Command)], query: &str) {
56    let needle = query.to_lowercase();
57    let matches: Vec<&(String, &Command)> = listing
58        .iter()
59        .filter(|(key, cmd)| {
60            let haystack = format!("{key} {} {}", cmd.id, cmd.description).to_lowercase();
61            haystack.contains(&needle)
62        })
63        .collect();
64
65    println!("\nsearch {query:?}:");
66    if matches.is_empty() {
67        // Don't leave the user guessing whether nothing matched or nothing exists.
68        println!("  no bindings match {query:?}");
69    } else {
70        for (key, cmd) in matches {
71            println!("  {key:>8}  {}", cmd.id);
72        }
73    }
74}