Crates.io | keybindings-parser |
lib.rs | keybindings-parser |
version | 0.1.0 |
source | src |
created_at | 2023-11-13 20:31:32.487591 |
updated_at | 2023-11-13 20:31:32.487591 |
description | library for parsing human keyboard shortcuts |
homepage | https://github.com/milchinskiy/keybindings-parser |
repository | https://github.com/milchinskiy/keybindings-parser.git |
max_upload_size | |
id | 1034006 |
size | 22,851 |
Tiny library for parsing keybindings from a string. And handle them via keysym & mod mask.
// init with default configuration
let mut keyb = Keybindings::default();
// add human readable keybinding
keyb.add("command + a", Box::new(TestAction::Kill))?;
// handle keybinging
if let Some(handler) = keyb.handle(ModMask::MOD4, keysymdefs::keys::XK_a) {
assert_eq!(handler.modifier(), ModMask::MOD4);
assert_eq!(handler.key(), keys::XK_a);
assert_eq!(handler.origin(), "command + a");
// action that you provide early
let action = handler.action();
action.run()?;
}
Where action
object is an object that implements KeyAction
trait.
pub trait KeyAction {
fn run(&self) -> Result<(), Box<dyn std::error::Error>>;
}
In real life keybindings handler will be placed somewhere in event loop
, e.g.
// just for example, there are no event::next_event() constructions :)
loop {
let (mask, key) = event::next_event()?;
if let Some(handler) = keyb.handle(mask, key) {
handler.action().run()?;
}
}
MOD4
known as super
key can be described like:
MOD1
known as alt
key can be described like:
MOD3
known as AltGr
(does not exist on modern keyboards)
key can be described like:
CONTROL
key can be described like:
SHIFT
key can be described like:
All modificator keys are described in ModMask
enum.
All modificator keys are u32
value.
All modificator keys are bit flags
.
All modificator keys are case insensitive.
Modificators bitmasks are compatible with X11 KeyPress
Event value detail()
.
Main key of a keybinding. For example, mod4 + a
, where a
is the main key.
Accepts all cleared names from keysymdefs::keys
.
For example:
keys::XK_a
is just a
keys::XF86XK_MonBrightnessUp
is just MonBrightnessUp
You free to use full canonical name of keys, like XK_a
, XF86XK_MonBrightnessUp
, etc.
Unlike modificator keys, main key is not case insensitive. In other words,
mod4 + a
is NOT the same as mod4 + A
. Moreover mod4 + A
does not make
much sense in context of a keybinding. Because A
is already has modificator
SHIFT
. Instead of this mod4 + A
, more correct way is handling mod4 + shift + a
.
Nevertheless, library will accept this as valid and you should handle such cases
yourself, depending on your goals.
let delimiter_char = '/';
let ghost_modifiers = ModMask::MOD4;
let keyb = Keybindings::new(delimiter_char, ghost_modifiers);
keyb.add("command / a", Box::new(TestAction::Kill))?;
// ...
// and then handle
let handler = keyb.handle(ModMask::MOD4, keysymdefs::keys::XK_a)?;
handler.run()?;
enum TestAction {
Kill,
ToggleFloat,
ToggleFullscreen,
ToggleTabBar,
SwapWindows,
Spawn(String),
}
impl KeyAction for TestAction {
fn run(&self) -> Result<(), Box<dyn std::error::Error>> {
match self {
TestAction::Kill => {}
TestAction::Spawn(_) => {}
TestAction::SwapWindows => {}
TestAction::ToggleFloat => {}
TestAction::ToggleFullscreen => {}
TestAction::ToggleTabBar => {}
};
Ok(())
}
}
You are free to use as many KeyAction
implementations as you need for
your purposes. The above example is for demonstration purposes only.
There are keyboard switches that should not affect behavior of keybindings in a general purposes. Among them:
CAPS_LOCK
MOD2
better known as NumLock
MOD5
better known as ScrollLock
All of them are ignored by default in Keybindings::default()
.
If you want to change these preset options, use new()
instead of default()
, e.g.:
let key_delimiter = '/';
let ghost_modifiers = ModMask::MOD4 | ModMask::MOD5;
let keyb = Keybindings::new(key_delimiter, ghost_modifiers);
Print
key)."super"
)super + XK_A
or super + A
are supported but does not
make much sense, most likely you need super + shift + a
or
super + shift + XK_a
respectivelymod4 + a + b
, there are
should be single main keyshort summary of a long story about keysym: You must exchange the keycode from the keypress event with a keysym, which can be obtained from the device details and information about the keyboard key mapping on a specific device. There is no static keycode to keysym mapping table.