Crate keybinds

Source
Expand description

§Overview

keybinds-rs is a small crate to parse/generate/dispatch key bindings (keyboard shortcuts) written in Safe Rust. You can easily introduce customizable key bindings to your application using this library.

  • Provide the syntax to easily define key bindings in a configuration file like Ctrl+a
  • Support key sequences like Ctrl+x Ctrl+s for complicated key bindings like Vim style
  • Core API independent from any platforms and frameworks with minimal dependencies (only two crates)
  • Support several platforms and frameworks as optional features
  • Support parsing/generating a key bindings configuration using serde optionally
  • Support structure-aware fuzzing using arbitrary optionally.

§Installation

cargo add keybinds

§Minimal example

use keybinds::{Keybinds, KeyInput, Key, Mods};

// Actions dispatched by key bindings
#[derive(PartialEq, Eq, Debug)]
enum Action {
    SayHello,
    OpenFile,
    ExitApp,
}

// Create a key bindings dispatcher to dispatch actions for upcoming key inputs
let mut keybinds = Keybinds::default();

// Register key bindings to dispatch the actions

// Key sequence "h" → "e" → "l" → "l" → "o"
keybinds.bind("h e l l o", Action::SayHello).unwrap();
// Key combination "Ctrl + Alt + Enter"
keybinds.bind("Ctrl+Alt+Enter", Action::OpenFile).unwrap();
// Sequence of key combinations
keybinds.bind("Ctrl+x Ctrl+c", Action::ExitApp).unwrap();

// Dispatch `SayHello` action
assert_eq!(keybinds.dispatch('h'), None);
assert_eq!(keybinds.dispatch('e'), None);
assert_eq!(keybinds.dispatch('l'), None);
assert_eq!(keybinds.dispatch('l'), None);
assert_eq!(keybinds.dispatch('o'), Some(&Action::SayHello));

// Dispatch `OpenFile` action
let action = keybinds.dispatch(KeyInput::new(Key::Enter, Mods::CTRL | Mods::ALT));
assert_eq!(action, Some(&Action::OpenFile));

// Dispatch `ExitApp` action
assert_eq!(keybinds.dispatch(KeyInput::new('x', Mods::CTRL)), None);
assert_eq!(keybinds.dispatch(KeyInput::new('c', Mods::CTRL)), Some(&Action::ExitApp));

§More examples

For more usage, please see the examples. They can be run locally by cargo run inside this repository. Some examples require some features enabled. For instance, to run the crossterm example:

cargo run --example crossterm --features=crossterm,serde

§Features

The list of crate features can be found in [features] section of Cargo.toml. Please read the comments on each features which explains about it.

§Minimal supported Rust version (MSRV)

See rust-version field of Cargo.toml for the minimal supported Rust version. Note that enabling optional features may require some higher Rust versions due to the optional dependencies introduced by them.

§Versioning

This crate conforms to Semantic Versioning 2.0.0, but it has not reached 1.0.0 yet (although the API is stable enough for production use). The versioning rule of this crate is as follows.

  • Major is fixed to 0.
  • Minor is bumped when some breaking change is introduced for example:
    • API breaking changes
    • Major version bumps in the optional dependencies
    • MSRV bump
  • Patch is bumped when some compatible changes are added for example:
    • New features such as adding new framework/library support
    • Fixes

§Syntax for key bindings

This document defines the syntax of key bindings. This can be parsed by KeySeq::parse, KeyInput::parse, and KeybindDispatcher::bind.

§Key binding examples

Here are some examples of key bindings with US keyboard.

NotationCorresponding key input
aA
XShift + X
?Shift + /
Ctrl+tCtrl + T
Alt+MAlt + Shift + M
EnterEnter
Ctrl+EnterCtrl + Enter
Shift+UpShift +
a b cABC
Ctrl+x Ctrl+sCtrl + XCtrl + S
Mod+xCommand + X on macOS, Ctrl + X on other platforms
Super+xCommand + X on macOS, Win + X on other platforms

§Grammar

This is the grammar of key binding representation in W3C EBNF notation.

key-binding     ::= key-sequence
key-sequence    ::= key-combination ((space)+ key-combination)*
space           ::= ' ' | #09 | #0A | #0C | #0D
key-combination ::= (modifier '+')* key
modifier        ::= 'Control' | 'Ctrl' | 'Command' | 'Cmd' | 'Mod' | 'Alt' | 'Super' | 'Option' | 'Shift' |
                    'control' | 'ctrl' | 'command' | 'cmd' | 'mod' | 'alt' | 'super' | 'option' | 'shift' |
                    'CONTROL' | 'CTRL' | 'COMMAND' | 'CMD' | 'MOD' | 'ALT' | 'SUPER' | 'OPTION' | 'SHIFT'
key             ::= character-key | named-key | function-key
character-key   ::= /* Any unicode character except for spaces */
named-key       ::= 'Space' | 'Plus' | 'Up' | 'Right' | 'Down' | 'Left' | 'Enter' | 'Backspace' | 'Delete' | 'Home' | 'End' | 'PageUp' | 'PageDown' | 'Esc' | 'Tab' | 'Backtab' | 'Insert' | 'Copy' | 'Cut' | 'Paste' | 'Clear' | 'Undo' | 'Redo' | 'ZoomIn' | 'ZoomOut' | 'ZoomToggle' | 'ScrollLock' | 'NumLock' | 'FnLock' | 'PrintScreen' | 'Menu' | 'Play' | 'Pause' | 'PlayPause' | 'Stop' | 'Rewind' | 'NextTrack' | 'PrevTrack' | 'VolumeUp' | 'VolumeDown' | 'Mute' |
                    'space' | 'plus' | 'up' | 'right' | 'down' | 'left' | 'enter' | 'backspace' | 'delete' | 'home' | 'end' | 'pageup' | 'pagedown' | 'esc' | 'tab' | 'backtab' | 'insert' | 'copy' | 'cut' | 'paste' | 'clear' | 'undo' | 'redo' | 'zoomin' | 'zoomout' | 'zoomtoggle' | 'scrolllock' | 'numlock' | 'fnlock' | 'printscreen' | 'menu' | 'play' | 'pause' | 'playpause' | 'stop' | 'rewind' | 'nexttrack' | 'prevtrack' | 'volumeup' | 'volumedown' | 'mute' |
                    'SPACE' | 'PLUS' | 'UP' | 'RIGHT' | 'DOWN' | 'LEFT' | 'ENTER' | 'BACKSPACE' | 'DELETE' | 'HOME' | 'END' | 'PAGEUP' | 'PAGEDOWN' | 'ESC' | 'TAB' | 'BACKTAB' | 'INSERT' | 'COPY' | 'CUT' | 'PASTE' | 'CLEAR' | 'UNDO' | 'REDO' | 'ZOOMIN' | 'ZOOMOUT' | 'ZOOMTOGGLE' | 'SCROLLLOCK' | 'NUMLOCK' | 'FNLOCK' | 'PRINTSCREEN' | 'MENU' | 'PLAY' | 'PAUSE' | 'PLAYPAUSE' | 'STOP' | 'REWIND' | 'NEXTTRACK' | 'PREVTRACK' | 'VOLUMEUP' | 'VOLUMEDOWN' | 'MUTE'
function-key    ::= 'F1' | 'F2' | 'F3' | 'F4' | 'F5' | 'F6' | 'F7' | 'F8' | 'F9' | 'F10' | 'F11' | 'F12' | 'F13' | 'F14' | 'F15' | 'F16' | 'F17' | 'F18' | 'F19' | 'F20' | 'F21' | 'F22' | 'F23' | 'F24' | 'F25' | 'F26' | 'F27' | 'F28' | 'F29' | 'F30' | 'F31' | 'F32' | 'F33' | 'F34' | 'F35'

§Key combination

Key combination is a combination of key strokes like a, Enter, Ctrl+Alt+a. Modifiers are concatenated with + and precedes a normal key. No space is allowed between characters because a space represent a sequence.

Normal keys are a single character (e.g. a, X, ) or a named key (e.g. Up, Enter, Tab). Note that the characters are case-sensitive. A means typing A and Shift keys on US keyboard.

These keys are logical keys which are inputs as the result of key typing. In comparison, physical keys are actual keys on your keyboard. For example, typing the physical keys Shift and 9 produces the logical key input ( with US keyboard, and it also produces the logical key input ) with JP keyboard.

§Key sequence

Key sequence is a sequence of key combinations. Key combinations are concatenated with one or more spaces like a b or Ctrl+x Ctrl+s. Spaces prefixed or suffixed to a sequence are ignored. Empty key sequence is invalid.

§Modifiers

The following modifier keys are available:

  • Ctrl: Ctrl key (alias: Control)
  • Cmd: Command key (alias: Command)
  • Mod: Command key on macOS, Ctrl key on other platforms
  • Super: Windows key on platforms other than macOS, Command key on macOS
  • Alt: Alt or Meta key (alias: Option)
  • Shift: Shift key (can only modify named keys)

!Caution

Shift modifier key is only available with named keys, such as Shift+Up. For example, when you want to define a key binding for Shift + A, you should use the logical input A instead of the physical input Shift+a. This restriction helps avoid some confusing edge cases at this point and may be relaxed in the future.

§Named keys

The following modifier keys are available. Space and Plus are named keys because they have conflicts with the key sequence syntax.

  • Space
  • Plus
  • Up
  • Right
  • Down
  • Left
  • Enter
  • Backspace
  • Delete
  • Home
  • End
  • PageUp
  • PageDown
  • Esc (alias: Escape)
  • Tab
  • Insert
  • Copy
  • Cut
  • Paste
  • Clear
  • Undo
  • Redo
  • ZoomIn
  • ZoomOut
  • ZoomToggle
  • ScrollLock
  • NumLock
  • FnLock
  • PrintScreen
  • Menu
  • Play
  • Pause
  • PlayPause
  • Stop
  • Rewind
  • NextTrack
  • PrevTrack
  • VolumeUp
  • VolumeDown
  • Mute
  • Help
  • F1, F2, F3, …

Modules§

arbitraryarbitrary
Support for arbitrary crate.
crosstermcrossterm
Support for crossterm crate.
icediced
Support for iced crate.
serdeserde
Support for serde crate.
termwiztermwiz
Support for termwiz crate.
winitwinit
Support for winit crate.

Structs§

KeyInput
Single key input by pressing a key and modifiers.
KeySeq
The key sequence bound to some action. It consists of one or more KeyInput instances.
Keybind
Single key binding. A pair of a key sequence and its action.
Keybinds
A dispatcher that takes key inputs and dispatches the corresponding key bindings’ actions.
Mods
Modifier keys such as “Ctrl”.

Enums§

Error
The error type for keybinds crate.
Key
Single logical key on keyboard.
Match
The result of KeySeq::match_to to match a key sequence to key inputs.

Constants§

DEFAULT_TIMEOUT
The default timeout value of the key binding matching by Keybinds.

Type Aliases§

Result
The result type for keybinds crate.