1 unstable release
0.1.0 | Nov 13, 2023 |
---|
#2367 in Parser implementations
13KB
182 lines
keybindings-parser
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()?;
}
}
Acceptable Modificator keys
MOD4
known as super
key can be described like:
- super
- mod4
- win
- windows
- cmd
- command
MOD1
known as alt
key can be described like:
- alt
- mod1
- meta
- alt_l
- alt_r
- meta_l
- meta_r
MOD3
known as AltGr
(does not exist on modern keyboards)
key can be described like:
- alt_gr
- altgr
- mod3
- meta_gr
- metagr
CONTROL
key can be described like:
- ctrl
- control
- ctrl_l
- ctrl_r
SHIFT
key can be described like:
- shift
- shift_l
- shift_r
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
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 justa
keys::XF86XK_MonBrightnessUp
is justMonBrightnessUp
- etc.
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.
Change defaults
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()?;
Custom KeyAction implementation, used in examples
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.
Ghost modifiers
There are keyboard switches that should not affect behavior of keybindings in a general purposes. Among them:
CAPS_LOCK
MOD2
better known asNumLock
MOD5
better known asScrollLock
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);
Limitations and cautions
- There are no limitations on the number of keybindings. You can add as many as you want.
- There are no limitations on the number of actions. You can add as many as you want.
- Keyboard shortcuts may not contain modifiers at all (e.g.
Print
key). - But the keyboard shortcuts can't be without the main key (e.g.
"super"
) - Modificator keys are case insensitive, main key is not
- Сomplete duplication of keyboard shortcuts will cause an error when adding
- Although, it is possible to add keybindings with the same main key and different modificator keys
- Shortcuts like
super + XK_A
orsuper + A
are supported but does not make much sense, most likely you needsuper + shift + a
orsuper + shift + XK_a
respectively - There is no support for key combinations like
mod4 + a + b
, there are should be single main key
where should I get keysym?
short 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.
Dependencies
~650KB
~18K SLoC