keymap-rs
is a library for parsing terminal input event from configurations and mapping them to the terminal library's event. (e.g. crossterm or termion)
Using terminal library's input event directly is sometimes not ideal. Let consider the following example of matching ctrl-z
event:
match read() {
// `ctrl-z`
Event::Key(KeyEvent {
modifiers: KeyModifiers::CONTROL,
KeyCode::Char('z'),
..
}) => {}
}
This code works perfectly fine. But if we want the end users to customize the key mappings to a different one (e.g. ctrl-x
, shift-c
, etc.). How can we achieve that? The answer is keymap
.
keymap
provides flexibility by allowing developers to define input event in plain-text, which can be used in any configuration formats (e.g. yaml
, toml
, etc.) and convert them to the terminal's event.
[keys]
ctrl-z = "..."
The ctrl-z
above will be converted to KeyEvent { ... }
in the first example.
Please check the examples directory for complete examples.
Click to show Cargo.toml
.
[dependencies]
keymap = "0.1"
Let's started by defining a simple structure for mapping input key to String
.
use keymap::KeyMap;
use serde::Deserialize;
#[derive(Deserialize)]
struct Config(pub HashMap<KeyMap, String>)
const CONFIG: &str = r#"
up = "Up"
down = "Down"
ctrl-c = "Quit"
"#;
Then in your terminal library of choice (we'll be using crossterm here). You can use any deserializer (e.g. toml
, json
, etc.) to deserialize a key from the configuration above into the terminal library's event (e.g. crossterm::event::KeyEvent
).
let config: Config = toml::from_str(CONFIG).unwrap();
// Read input event
match read()? {
Event::Key(key) => {
// `KeyMap::from` will convert `crossterm::event::KeyEvent` to `keymap::KeyMap`
if let Some(action) = config.0.get(&Key::from(key)) {
match action {
"Up" => println!("Move up!"),
"Down" => println!("Move down!"),
// ...
"Quit" => break,
}
}
}
}