Skip to main content

Crate kbd

Crate kbd 

Source
Expand description

Pure-logic hotkey engine.

kbd provides the domain types and synchronous matching logic behind the rest of the workspace: physical keys, modifiers, bindings, layers, sequences, tap-hold behavior, device-aware matching, and introspection. It has no platform dependencies and can be embedded in any event loop.

§Quick start

Describe your bindings — as strings or programmatically — and the dispatcher tells you when incoming key events match:

use kbd::action::Action;
use kbd::dispatcher::{Dispatcher, MatchResult};
use kbd::hotkey::{Hotkey, Modifier};
use kbd::key::Key;
use kbd::key_state::KeyTransition;

let mut dispatcher = Dispatcher::new();

// Register via string parsing
dispatcher.register("Ctrl+S", Action::Suppress)?;

// Register programmatically — useful for dynamic or computed bindings
dispatcher.register(
    Hotkey::new(Key::A).modifier(Modifier::Ctrl).modifier(Modifier::Shift),
    Action::Suppress,
)?;

// process() returns Matched, Pending (partial sequence), or NoMatch
let result = dispatcher.process(
    Hotkey::new(Key::S).modifier(Modifier::Ctrl),
    KeyTransition::Press,
);
assert!(matches!(result, MatchResult::Matched { .. }));

Most integrations revolve around dispatcher::Dispatcher. Supporting modules cover hotkey parsing, layers, binding metadata and policies, per-device matching, and read-only introspection snapshots.

§Layers

Layers are named, stackable groups of bindings. When active, a layer’s bindings take priority over the layers beneath it. Use them for modes, context-dependent shortcuts, or temporary overrides.

use kbd::action::Action;
use kbd::dispatcher::Dispatcher;
use kbd::key::Key;
use kbd::layer::Layer;

let mut dispatcher = Dispatcher::new();

let layer = Layer::new("vim-normal")
    .bind(Key::J, || println!("down"))?
    .bind(Key::K, || println!("up"))?;

dispatcher.define_layer(layer)?;
dispatcher.push_layer("vim-normal")?;

Layers can be oneshot (auto-pop after one match), swallowing (consume unmatched keys), or time-limited. See layer for the full API.

§Sequences

Multi-step bindings like Ctrl+K, Ctrl+C:

use kbd::action::Action;
use kbd::dispatcher::{Dispatcher, MatchResult};
use kbd::hotkey::{Hotkey, Modifier};
use kbd::key::Key;
use kbd::key_state::KeyTransition;

let mut dispatcher = Dispatcher::new();

// Register via string — parsed into a HotkeySequence
dispatcher.register_sequence("Ctrl+K, Ctrl+C", Action::Suppress)?;

// Or build the sequence programmatically
let steps = vec![
    Hotkey::new(Key::K).modifier(Modifier::Ctrl),
    Hotkey::new(Key::D).modifier(Modifier::Ctrl),
];
dispatcher.register_sequence(steps, Action::Suppress)?;

// First step — dispatcher remembers the partial match
let r = dispatcher.process(
    Hotkey::new(Key::K).modifier(Modifier::Ctrl),
    KeyTransition::Press,
);
assert!(matches!(r, MatchResult::Pending { .. }));

// Second step — sequence completes
let r = dispatcher.process(
    Hotkey::new(Key::C).modifier(Modifier::Ctrl),
    KeyTransition::Press,
);
assert!(matches!(r, MatchResult::Matched { .. }));

§Physical keys

kbd matches physical key positions, not characters. Key::A means “the key in the A position on a QWERTY layout” regardless of whether the user’s layout is AZERTY, Dvorak, or Colemak. This is the W3C KeyboardEvent.code model.

Physical keys are layout-independent and predictable — the same binding works on any layout without knowing which one is active.

§Feature flags

FlagDefaultEffect
serdeoffAdds Serialize and Deserialize to key and hotkey-related types

§See also

Modules§

action
The Action enum — what happens when a binding matches.
binding
The unified binding types — pattern + action + options.
device
Input device identification, filtering, and context.
dispatcher
Binding dispatcher — finds which binding (if any) matches a key event.
error
Error types for hotkey operations.
hotkey
Hotkey composition types: Modifier, Hotkey, HotkeySequence.
introspection
Introspection types — snapshots of dispatcher state for UI and debugging.
key
Physical key type: Key.
key_state
Key state tracking — single source of truth for what’s pressed.
layer
Layers — named, stackable collections of bindings.
policy
Dispatch policies for bindings.
sequence
Sequence-matching configuration and runtime snapshots.
tap_hold
Tap-hold binding types — dual-function keys with time-based resolution.