#input-event #terminal #events #key-bindings #config #keymapping

keymap

A library for parsing terminal input events from configuration

4 releases (breaking)

0.4.0 Oct 11, 2023
0.3.0 Sep 24, 2023
0.2.0 Aug 1, 2023
0.1.0 Jul 30, 2023

#373 in Command-line interface

Download history 4/week @ 2024-02-26 69/week @ 2024-04-01

69 downloads per month

MIT license

25KB
597 lines

keymap-rs

crates.io Rust License: MIT

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)

Introduction

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.

Getting started

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,
            }
        }
    }
}

Supported Terminal Libraries

Dependencies

~3–13MB
~118K SLoC