diff --git a/Cargo.lock b/Cargo.lock index 1e78a75..6822df2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,12 +8,36 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -23,6 +47,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cc" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" + [[package]] name = "cfg-if" version = "1.0.0" @@ -64,6 +94,25 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "evdev" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab6055a93a963297befb0f4f6e18f314aec9767a4bbe88b151126df2433610a7" +dependencies = [ + "bitvec", + "cfg-if", + "libc", + "nix", + "thiserror", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" version = "0.14.7" @@ -95,6 +144,28 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -164,6 +235,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "sha2" version = "0.10.8" @@ -180,7 +257,8 @@ name = "sweet" version = "0.1.0" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.5.0", + "evdev", "itertools", "pest", "pest_derive", @@ -198,6 +276,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "thiserror" version = "1.0.59" @@ -241,3 +325,12 @@ name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/Cargo.toml b/Cargo.toml index 3d571d4..df87b52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" [dependencies] anyhow = "1.0.80" bitflags = "2.5.0" +evdev = "0.12.2" itertools = "0.12.1" pest = "2.7.7" pest_derive = "2.7.7" diff --git a/README.md b/README.md index a6df930..893a3fa 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Here's what has been worked on so far. - [x] Warn user if input config is not a regular file - [x] Set a maximum file size cap for configs - [ ] Lock files and map them into memory -- [ ] Map keys and modifiers to internal representation (evdev enum variants) in a single pass +- [x] Map keys and modifiers to internal representation (evdev enum variants) in a single pass Want to learn how the code works? Check out [my blog](https://lavafroth.is-a.dev/tags/google-summer-of-code/) where I cover each topic as I implement them. diff --git a/src/evdev_mappings.rs b/src/evdev_mappings.rs new file mode 100644 index 0000000..3e541c6 --- /dev/null +++ b/src/evdev_mappings.rs @@ -0,0 +1,155 @@ +use crate::ParseError; + +pub fn convert(s: &str) -> Result { + let val = match s { + "q" => evdev::Key::KEY_Q, + "w" => evdev::Key::KEY_W, + "e" => evdev::Key::KEY_E, + "r" => evdev::Key::KEY_R, + "t" => evdev::Key::KEY_T, + "y" => evdev::Key::KEY_Y, + "u" => evdev::Key::KEY_U, + "i" => evdev::Key::KEY_I, + "o" => evdev::Key::KEY_O, + "p" => evdev::Key::KEY_P, + "a" => evdev::Key::KEY_A, + "s" => evdev::Key::KEY_S, + "d" => evdev::Key::KEY_D, + "f" => evdev::Key::KEY_F, + "g" => evdev::Key::KEY_G, + "h" => evdev::Key::KEY_H, + "j" => evdev::Key::KEY_J, + "k" => evdev::Key::KEY_K, + "l" => evdev::Key::KEY_L, + "z" => evdev::Key::KEY_Z, + "x" => evdev::Key::KEY_X, + "c" => evdev::Key::KEY_C, + "v" => evdev::Key::KEY_V, + "b" => evdev::Key::KEY_B, + "n" => evdev::Key::KEY_N, + "m" => evdev::Key::KEY_M, + "1" => evdev::Key::KEY_1, + "2" => evdev::Key::KEY_2, + "3" => evdev::Key::KEY_3, + "4" => evdev::Key::KEY_4, + "5" => evdev::Key::KEY_5, + "6" => evdev::Key::KEY_6, + "7" => evdev::Key::KEY_7, + "8" => evdev::Key::KEY_8, + "9" => evdev::Key::KEY_9, + "0" => evdev::Key::KEY_0, + "escape" => evdev::Key::KEY_ESC, + "backspace" => evdev::Key::KEY_BACKSPACE, + "capslock" => evdev::Key::KEY_CAPSLOCK, + "return" => evdev::Key::KEY_ENTER, + "enter" => evdev::Key::KEY_ENTER, + "tab" => evdev::Key::KEY_TAB, + "space" => evdev::Key::KEY_SPACE, + "plus" => evdev::Key::KEY_KPPLUS, // Shouldn't this be kpplu? + "kp0" => evdev::Key::KEY_KP0, + "kp1" => evdev::Key::KEY_KP1, + "kp2" => evdev::Key::KEY_KP2, + "kp3" => evdev::Key::KEY_KP3, + "kp4" => evdev::Key::KEY_KP4, + "kp5" => evdev::Key::KEY_KP5, + "kp6" => evdev::Key::KEY_KP6, + "kp7" => evdev::Key::KEY_KP7, + "kp8" => evdev::Key::KEY_KP8, + "kp9" => evdev::Key::KEY_KP9, + "kpasterisk" => evdev::Key::KEY_KPASTERISK, + "kpcomma" => evdev::Key::KEY_KPCOMMA, + "kpdot" => evdev::Key::KEY_KPDOT, + "kpenter" => evdev::Key::KEY_KPENTER, + "kpequal" => evdev::Key::KEY_KPEQUAL, + "kpjpcomma" => evdev::Key::KEY_KPJPCOMMA, + "kpleftparen" => evdev::Key::KEY_KPLEFTPAREN, + "kpminus" => evdev::Key::KEY_KPMINUS, + "kpplusminus" => evdev::Key::KEY_KPPLUSMINUS, + "kprightparen" => evdev::Key::KEY_KPRIGHTPAREN, + "minus" => evdev::Key::KEY_MINUS, + "-" => evdev::Key::KEY_MINUS, + "equal" => evdev::Key::KEY_EQUAL, + "=" => evdev::Key::KEY_EQUAL, + "grave" => evdev::Key::KEY_GRAVE, + "`" => evdev::Key::KEY_GRAVE, + "print" => evdev::Key::KEY_SYSRQ, + "volumeup" => evdev::Key::KEY_VOLUMEUP, + "xf86audioraisevolume" => evdev::Key::KEY_VOLUMEUP, + "volumedown" => evdev::Key::KEY_VOLUMEDOWN, + "xf86audiolowervolume" => evdev::Key::KEY_VOLUMEDOWN, + "mute" => evdev::Key::KEY_MUTE, + "xf86audiomute" => evdev::Key::KEY_MUTE, + "brightnessup" => evdev::Key::KEY_BRIGHTNESSUP, + "xf86monbrightnessup" => evdev::Key::KEY_BRIGHTNESSUP, + "brightnessdown" => evdev::Key::KEY_BRIGHTNESSDOWN, + "xf86audiomedia" => evdev::Key::KEY_MEDIA, + "xf86audiomicmute" => evdev::Key::KEY_MICMUTE, + "micmute" => evdev::Key::KEY_MICMUTE, + "xf86audionext" => evdev::Key::KEY_NEXTSONG, + "xf86audioplay" => evdev::Key::KEY_PLAYPAUSE, + "xf86audioprev" => evdev::Key::KEY_PREVIOUSSONG, + "xf86audiostop" => evdev::Key::KEY_STOP, + "xf86monbrightnessdown" => evdev::Key::KEY_BRIGHTNESSDOWN, + "," => evdev::Key::KEY_COMMA, + "comma" => evdev::Key::KEY_COMMA, + "." => evdev::Key::KEY_DOT, + "dot" => evdev::Key::KEY_DOT, + "period" => evdev::Key::KEY_DOT, + "/" => evdev::Key::KEY_SLASH, + "question" => evdev::Key::KEY_QUESTION, + "slash" => evdev::Key::KEY_SLASH, + "backslash" => evdev::Key::KEY_BACKSLASH, + "\\" => evdev::Key::KEY_BACKSLASH, + "leftbrace" => evdev::Key::KEY_LEFTBRACE, + "[" => evdev::Key::KEY_LEFTBRACE, + "bracketleft" => evdev::Key::KEY_LEFTBRACE, + "rightbrace" => evdev::Key::KEY_RIGHTBRACE, + "]" => evdev::Key::KEY_RIGHTBRACE, + "bracketright" => evdev::Key::KEY_RIGHTBRACE, + ";" => evdev::Key::KEY_SEMICOLON, + "scroll_lock" => evdev::Key::KEY_SCROLLLOCK, + "semicolon" => evdev::Key::KEY_SEMICOLON, + "'" => evdev::Key::KEY_APOSTROPHE, + "apostrophe" => evdev::Key::KEY_APOSTROPHE, + "left" => evdev::Key::KEY_LEFT, + "right" => evdev::Key::KEY_RIGHT, + "up" => evdev::Key::KEY_UP, + "down" => evdev::Key::KEY_DOWN, + "pause" => evdev::Key::KEY_PAUSE, + "home" => evdev::Key::KEY_HOME, + "delete" => evdev::Key::KEY_DELETE, + "insert" => evdev::Key::KEY_INSERT, + "end" => evdev::Key::KEY_END, + "pause" => evdev::Key::KEY_PAUSE, + "prior" => evdev::Key::KEY_PAGEDOWN, + "next" => evdev::Key::KEY_PAGEUP, + "pagedown" => evdev::Key::KEY_PAGEDOWN, + "pageup" => evdev::Key::KEY_PAGEUP, + "f1" => evdev::Key::KEY_F1, + "f2" => evdev::Key::KEY_F2, + "f3" => evdev::Key::KEY_F3, + "f4" => evdev::Key::KEY_F4, + "f5" => evdev::Key::KEY_F5, + "f6" => evdev::Key::KEY_F6, + "f7" => evdev::Key::KEY_F7, + "f8" => evdev::Key::KEY_F8, + "f9" => evdev::Key::KEY_F9, + "f10" => evdev::Key::KEY_F10, + "f11" => evdev::Key::KEY_F11, + "f12" => evdev::Key::KEY_F12, + "f13" => evdev::Key::KEY_F13, + "f14" => evdev::Key::KEY_F14, + "f15" => evdev::Key::KEY_F15, + "f16" => evdev::Key::KEY_F16, + "f17" => evdev::Key::KEY_F17, + "f18" => evdev::Key::KEY_F18, + "f19" => evdev::Key::KEY_F19, + "f20" => evdev::Key::KEY_F20, + "f21" => evdev::Key::KEY_F21, + "f22" => evdev::Key::KEY_F22, + "f23" => evdev::Key::KEY_F23, + "f24" => evdev::Key::KEY_F24, + _ => return Err(ParseError::InvalidKey(s.to_string())), + }; + Ok(val) +} diff --git a/src/lib.rs b/src/lib.rs index 09afc5f..db6a17d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,9 +10,11 @@ use std::{ path::{Path, PathBuf}, }; use thiserror::Error; +use token::{KeyRepr, Modifier}; +mod evdev_mappings; mod range; pub mod token; -use crate::token::{Key, KeyAttribute, Modifier}; +use crate::token::{Key, KeyAttribute, ModifierRepr}; #[derive(Debug, Error)] pub enum ParseError { @@ -24,6 +26,8 @@ pub enum ParseError { MainSection, #[error(transparent)] ConfigRead(#[from] ConfigReadError), + #[error("`{0}` is not recongnized as a valid evdev key")] + InvalidKey(String), } #[derive(Parser)] @@ -176,7 +180,7 @@ fn unescape(s: &str) -> &str { &s[1..] } -fn parse_key(component: Pair<'_, Rule>) -> Key { +fn parse_key(component: Pair<'_, Rule>) -> KeyRepr { let mut attribute = KeyAttribute::None; let mut key = String::default(); for inner in component.into_inner() { @@ -189,7 +193,7 @@ fn parse_key(component: Pair<'_, Rule>) -> Key { _ => {} } } - Key { key, attribute } + KeyRepr { key, attribute } } #[derive(Default)] @@ -201,32 +205,42 @@ pub struct DefinitionUncompiled { impl DefinitionUncompiled { fn ingest(&mut self, component: Pair<'_, Rule>) -> Result<(), ParseError> { match component.as_rule() { - Rule::modifier => self - .modifiers - .push(vec![Modifier(pair_to_string(component).to_lowercase())]), + Rule::modifier => { + self.modifiers.push(vec![ + ModifierRepr(pair_to_string(component).to_lowercase()).into() + ]) + } Rule::modifier_shorthand | Rule::modifier_omit_shorthand => self.modifiers.push( component .into_inner() - .map(|component| Modifier(pair_to_string(component))) + .map(|component| ModifierRepr(pair_to_string(component)).into()) .collect(), ), Rule::shorthand => { for shorthand_component in component.into_inner() { match shorthand_component.as_rule() { - Rule::key_in_shorthand => self.keys.push(parse_key(shorthand_component)), + Rule::key_in_shorthand => { + self.keys.push(parse_key(shorthand_component).try_into()?) + } Rule::key_range => { let (lower_bound, upper_bound) = Bounds::new(shorthand_component).expand_keys()?; - self.keys.extend((lower_bound..=upper_bound).map(|key| Key { - key: key.to_string(), - attribute: KeyAttribute::None, - })); + let keys = (lower_bound..=upper_bound) + .map(|key| { + KeyRepr { + key: key.to_string(), + attribute: KeyAttribute::None, + } + .try_into() + }) + .collect::, ParseError>>()?; + self.keys.extend(keys); } _ => {} } } } - Rule::key_normal => self.keys.push(parse_key(component)), + Rule::key_normal => self.keys.push(parse_key(component).try_into()?), _ => {} }; Ok(()) diff --git a/src/token.rs b/src/token.rs index 791cdeb..3297fba 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,3 +1,7 @@ +use crate::ParseError; + +use crate::evdev_mappings; + bitflags::bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct KeyAttribute: u8 { @@ -9,18 +13,60 @@ bitflags::bitflags! { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Modifier(pub String); +pub struct ModifierRepr(pub String); + +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub enum Modifier { + Super, + Alt, + Altgr, + Control, + Shift, + Any, +} + +impl From for Modifier { + fn from(value: ModifierRepr) -> Self { + match value.0.to_lowercase().as_str() { + "ctrl" => Modifier::Control, + "control" => Modifier::Control, + "super" | "mod4" | "meta" => Modifier::Super, + "alt" => Modifier::Alt, + "mod1" => Modifier::Alt, + "altgr" => Modifier::Altgr, + "mod5" => Modifier::Altgr, + "shift" => Modifier::Shift, + "any" => Modifier::Any, + _ => panic!("that's not a modifier"), + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Key { - pub key: String, + pub key: evdev::Key, pub attribute: KeyAttribute, } impl Key { - pub fn new>(key: S, attribute: KeyAttribute) -> Self { - Self { - key: key.as_ref().to_owned(), - attribute, - } + pub fn new(key: evdev::Key, attribute: KeyAttribute) -> Self { + Self { key, attribute } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct KeyRepr { + pub key: String, + pub attribute: KeyAttribute, +} + +impl TryFrom for Key { + type Error = ParseError; + + fn try_from(value: KeyRepr) -> Result { + let key = evdev_mappings::convert(&value.key)?; + let attribute = value.attribute; + + Ok(Self { key, attribute }) } } diff --git a/tests/tests.rs b/tests/tests.rs index babf2cb..56eff44 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -31,21 +31,21 @@ t Binding { definition: Definition { modifiers: vec![], - key: Key::new("r", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_R, KeyAttribute::None), }, command: "alacritty".to_string().to_string(), }, Binding { definition: Definition { modifiers: vec![], - key: Key::new("w", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_W, KeyAttribute::None), }, command: "kitty".to_string().to_string(), }, Binding { definition: Definition { modifiers: vec![], - key: Key::new("t", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_T, KeyAttribute::None), }, command: "/bin/firefox".to_string().to_string(), }, @@ -74,14 +74,14 @@ w Binding { definition: Definition { modifiers: vec![], - key: Key::new("r", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_R, KeyAttribute::None), }, command: "alacritty".to_string().to_string(), }, Binding { definition: Definition { modifiers: vec![], - key: Key::new("w", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_W, KeyAttribute::None), }, command: "kitty".to_string().to_string(), }, @@ -102,8 +102,8 @@ super + 5 let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?; let known = vec![Binding { definition: Definition { - modifiers: vec![Modifier("super".to_string())], - key: Key::new("5", KeyAttribute::None), + modifiers: vec![Modifier::Super], + key: Key::new(evdev::Key::KEY_5, KeyAttribute::None), }, command: "alacritty".to_string().to_string(), }]; @@ -178,36 +178,36 @@ super + z let known = vec![ Binding { definition: Definition { - modifiers: vec![Modifier("shift".to_string())], - key: Key::new("k", KeyAttribute::None), + modifiers: vec![Modifier::Shift], + key: Key::new(evdev::Key::KEY_K, KeyAttribute::None), }, command: command.clone(), }, Binding { definition: Definition { - modifiers: vec![Modifier("control".to_string())], - key: Key::new("5", KeyAttribute::None), + modifiers: vec![Modifier::Control], + key: Key::new(evdev::Key::KEY_5, KeyAttribute::None), }, command: command.clone(), }, Binding { definition: Definition { - modifiers: vec![Modifier("alt".to_string())], - key: Key::new("2", KeyAttribute::None), + modifiers: vec![Modifier::Alt], + key: Key::new(evdev::Key::KEY_2, KeyAttribute::None), }, command: command.clone(), }, Binding { definition: Definition { - modifiers: vec![Modifier("altgr".to_string())], - key: Key::new("i", KeyAttribute::None), + modifiers: vec![Modifier::Altgr], + key: Key::new(evdev::Key::KEY_I, KeyAttribute::None), }, command: command.clone(), }, Binding { definition: Definition { - modifiers: vec![Modifier("super".to_string())], - key: Key::new("z", KeyAttribute::None), + modifiers: vec![Modifier::Super], + key: Key::new(evdev::Key::KEY_Z, KeyAttribute::None), }, command: command.clone(), }, @@ -229,7 +229,7 @@ p let known = vec![Binding { definition: Definition { modifiers: vec![], - key: Key::new("p", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_P, KeyAttribute::None), }, command: String::from("xbacklight -inc 10 -fps 30 -time 200"), }]; @@ -297,15 +297,15 @@ super + minus let known = vec![ Binding { definition: Definition { - modifiers: vec![Modifier("super".to_string())], - key: Key::new("Escape", KeyAttribute::None), + modifiers: vec![Modifier::Super], + key: Key::new(evdev::Key::KEY_ESC, KeyAttribute::None), }, command: String::from("pkill -USR1 -x sxhkd ; sxhkd &"), }, Binding { definition: Definition { - modifiers: vec![Modifier("super".to_string())], - key: Key::new("Return", KeyAttribute::None), + modifiers: vec![Modifier::Super], + key: Key::new(evdev::Key::KEY_ENTER, KeyAttribute::None), }, command: String::from( "alacritty -t \"Terminal\" -e \"$HOME/.config/sxhkd/new_tmux_terminal.sh\"", @@ -313,29 +313,29 @@ super + minus }, Binding { definition: Definition { - modifiers: vec![Modifier("super".to_string()), Modifier("shift".to_string())], - key: Key::new("Return", KeyAttribute::None), + modifiers: vec![Modifier::Super, Modifier::Shift], + key: Key::new(evdev::Key::KEY_ENTER, KeyAttribute::None), }, command: String::from("alacritty -t \"Terminal\""), }, Binding { definition: Definition { - modifiers: vec![Modifier("alt".to_string())], - key: Key::new("Return", KeyAttribute::None), + modifiers: vec![Modifier::Alt], + key: Key::new(evdev::Key::KEY_ENTER, KeyAttribute::None), }, command: String::from("alacritty -t \"Terminal\" -e \"tmux\""), }, Binding { definition: Definition { - modifiers: vec![Modifier("ctrl".to_string())], - key: Key::new("0", KeyAttribute::None), + modifiers: vec![Modifier::Control], + key: Key::new(evdev::Key::KEY_0, KeyAttribute::None), }, command: String::from("play-song.sh"), }, Binding { definition: Definition { - modifiers: vec![Modifier("super".to_string())], - key: Key::new("minus", KeyAttribute::None), + modifiers: vec![Modifier::Super], + key: Key::new(evdev::Key::KEY_MINUS, KeyAttribute::None), }, command: String::from("play-song.sh album"), }, @@ -357,7 +357,7 @@ k let known = vec![Binding { definition: Definition { modifiers: vec![], - key: Key::new("k", KeyAttribute::None), + key: Key::new(evdev::Key::KEY_K, KeyAttribute::None), }, command: String::from("mpc ls | dmenu | sed -i 's/foo/bar/g'"), }];