keybinds-rs is a small platform&framework-agnostic 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+sfor complicated key bindings like Vim style. (example) - Provide the core API independent from any platforms and frameworks with minimal (only two crates) dependencies. (example)
- 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. (example)
cargo add keybindsThe following code demonstrates the usage by parsing key bindings configuration from TOML input and dispatching actions
to move the cursor inside terminal with the serde and crossterm optional features. This code can be run as the
example. See the API documentation for more details.
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use crossterm::{cursor, event, execute};
use keybinds::Keybinds;
use serde::Deserialize;
use std::io;
// Actions dispatched by key bindings
#[derive(Deserialize)]
enum Action {
Exit,
Up,
Down,
Left,
Right,
Top,
Bottom,
Home,
End,
}
// Configuration of your application
#[derive(Deserialize)]
struct Config {
keyboard: Keybinds<Action>,
}
const CONFIG_FILE_CONTENT: &str = r#"
[keyboard]
# Standard bindings
"Up" = "Up"
"Down" = "Down"
"Left" = "Left"
"Right" = "Right"
"PageUp" = "Top"
"PageDown" = "Bottom"
"Home" = "Home"
"End" = "End"
"Mod+q" = "Exit"
# Emacs-like bindings
"Ctrl+p" = "Up"
"Ctrl+n" = "Down"
"Ctrl+b" = "Left"
"Ctrl+f" = "Right"
"Alt+<" = "Top"
"Alt+>" = "Bottom"
"Ctrl+a" = "Home"
"Ctrl+e" = "End"
"Ctrl+x Ctrl+c" = "Exit"
# Vim-like bindings
"k" = "Up"
"j" = "Down"
"h" = "Left"
"l" = "Right"
"g g" = "Top"
"G" = "Bottom"
"^" = "Home"
"$" = "End"
"Esc" = "Exit"
"#;
fn main() -> io::Result<()> {
// Parse the configuration from the file content
let config: Config = toml::from_str(CONFIG_FILE_CONTENT).unwrap();
// `Keybinds` instance is a key bindings dispatcher that receives key inputs and
// dispatches the corresponding actions.
let mut keybinds = config.keyboard;
enable_raw_mode()?;
let mut stdout = io::stdout();
// Read the crossterm's key events and pass it to `Keybinds::dispatch` directly.
while let Ok(event) = event::read() {
// If the event triggered some action, handle it using `match`
if let Some(action) = keybinds.dispatch(&event) {
match action {
Action::Exit => break,
Action::Up => execute!(stdout, cursor::MoveUp(1))?,
Action::Down => execute!(stdout, cursor::MoveDown(1))?,
Action::Left => execute!(stdout, cursor::MoveLeft(1))?,
Action::Right => execute!(stdout, cursor::MoveRight(1))?,
Action::Top => execute!(stdout, cursor::MoveUp(9999))?,
Action::Bottom => execute!(stdout, cursor::MoveDown(9999))?,
Action::Home => execute!(stdout, cursor::MoveLeft(9999))?,
Action::End => execute!(stdout, cursor::MoveRight(9999))?,
}
}
}
disable_raw_mode()
}For more usage, please see the working examples. They can be run locally by cargo run inside this
repository. Some examples require some features enabled. For instance, to run the above crossterm example:
cargo run --example crossterm --features=crossterm,serdeThe list of crate features can be found in [features] section of Cargo.toml. Please read the comments
on each features which explains about it.
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.
See the document.
This crate is licensed under the MIT license.