From 312817fcf6eb86e394ee72986bd00bede76d70f4 Mon Sep 17 00:00:00 2001 From: Bradford Hovinen Date: Mon, 25 Mar 2024 15:04:38 +0100 Subject: fix(config): add support for Ctrl and Alt modifiers on function keys in keybindings (#3179) Previously, it was not possible to define keybindings with a modifier and a function key. The `Key` enum only supported combinging the Ctrl and Alt modifiers with letters. This is somewhat limiting: I would like to make the Zellij keybindings more "distant" than those used in the programs I use from within Zelilj, so that Zellij does not intefere with those programs. Thus I would like to move some of the keybindings from Ctrl+ to Ctrl+. This change adds: * support for function keys with the Ctrl and Alt modifiers in the `Key` enum, * support for parsing such keybindings from the configuration file, * support for such keybindings in the protobuf which communicates the keybindings to plugins, and * support for these keybindings in the plugin API. This is tested by modifying one of the e2e tests to include an example of such keybindings. This verifies that the configuration is correctly parsed, communicated with the plugin, and rendered. --- zellij-utils/src/plugin_api/key.rs | 86 +++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 25 deletions(-) (limited to 'zellij-utils/src/plugin_api') diff --git a/zellij-utils/src/plugin_api/key.rs b/zellij-utils/src/plugin_api/key.rs index 7cef4ba76..c5ce10870 100644 --- a/zellij-utils/src/plugin_api/key.rs +++ b/zellij-utils/src/plugin_api/key.rs @@ -12,12 +12,21 @@ impl TryFrom for Key { let key_modifier = parse_optional_modifier(&protobuf_key); match key_modifier { Some(KeyModifier::Ctrl) => { - let character = char_from_main_key(protobuf_key.main_key)?; - Ok(Key::Ctrl(character)) + if let Ok(character) = char_from_main_key(protobuf_key.main_key.clone()) { + Ok(Key::Ctrl(character)) + } else { + let index = fn_index_from_main_key(protobuf_key.main_key)?; + Ok(Key::CtrlF(index)) + } }, Some(KeyModifier::Alt) => { - let char_or_arrow = CharOrArrow::from_main_key(protobuf_key.main_key)?; - Ok(Key::Alt(char_or_arrow)) + if let Ok(char_or_arrow) = CharOrArrow::from_main_key(protobuf_key.main_key.clone()) + { + Ok(Key::Alt(char_or_arrow)) + } else { + let index = fn_index_from_main_key(protobuf_key.main_key)?; + Ok(Key::AltF(index)) + } }, None => match protobuf_key.main_key.as_ref().ok_or("invalid key")? { MainKey::Char(_key_index) => { @@ -81,27 +90,18 @@ impl TryFrom for ProtobufKey { modifier: None, main_key: Some(MainKey::Key(NamedKey::Insert as i32)), }), - Key::F(index) => { - let main_key = match index { - 1 => Some(MainKey::Key(NamedKey::F1 as i32)), - 2 => Some(MainKey::Key(NamedKey::F2 as i32)), - 3 => Some(MainKey::Key(NamedKey::F3 as i32)), - 4 => Some(MainKey::Key(NamedKey::F4 as i32)), - 5 => Some(MainKey::Key(NamedKey::F5 as i32)), - 6 => Some(MainKey::Key(NamedKey::F6 as i32)), - 7 => Some(MainKey::Key(NamedKey::F7 as i32)), - 8 => Some(MainKey::Key(NamedKey::F8 as i32)), - 9 => Some(MainKey::Key(NamedKey::F9 as i32)), - 10 => Some(MainKey::Key(NamedKey::F10 as i32)), - 11 => Some(MainKey::Key(NamedKey::F11 as i32)), - 12 => Some(MainKey::Key(NamedKey::F12 as i32)), - _ => return Err("Invalid key"), - }; - Ok(ProtobufKey { - modifier: None, - main_key, - }) - }, + Key::F(index) => Ok(ProtobufKey { + modifier: None, + main_key: Some(fn_index_to_main_key(index)?), + }), + Key::CtrlF(index) => Ok(ProtobufKey { + modifier: Some(KeyModifier::Ctrl as i32), + main_key: Some(fn_index_to_main_key(index)?), + }), + Key::AltF(index) => Ok(ProtobufKey { + modifier: Some(KeyModifier::Alt as i32), + main_key: Some(fn_index_to_main_key(index)?), + }), Key::Char(character) => Ok(ProtobufKey { modifier: None, main_key: Some(MainKey::Char((character as u8) as i32)), @@ -147,6 +147,24 @@ impl TryFrom for ProtobufKey { } } +fn fn_index_to_main_key(index: u8) -> Result { + match index { + 1 => Ok(MainKey::Key(NamedKey::F1 as i32)), + 2 => Ok(MainKey::Key(NamedKey::F2 as i32)), + 3 => Ok(MainKey::Key(NamedKey::F3 as i32)), + 4 => Ok(MainKey::Key(NamedKey::F4 as i32)), + 5 => Ok(MainKey::Key(NamedKey::F5 as i32)), + 6 => Ok(MainKey::Key(NamedKey::F6 as i32)), + 7 => Ok(MainKey::Key(NamedKey::F7 as i32)), + 8 => Ok(MainKey::Key(NamedKey::F8 as i32)), + 9 => Ok(MainKey::Key(NamedKey::F9 as i32)), + 10 => Ok(MainKey::Key(NamedKey::F10 as i32)), + 11 => Ok(MainKey::Key(NamedKey::F11 as i32)), + 12 => Ok(MainKey::Key(NamedKey::F12 as i32)), + _ => Err("Invalid key"), + } +} + impl CharOrArrow { pub fn from_main_key( main_key: std::option::Option, @@ -191,6 +209,24 @@ fn char_from_main_key(main_key: Option) -> Result { } } +fn fn_index_from_main_key(main_key: Option) -> Result { + match main_key { + Some(MainKey::Key(n)) if n == NamedKey::F1 as i32 => Ok(1), + Some(MainKey::Key(n)) if n == NamedKey::F2 as i32 => Ok(2), + Some(MainKey::Key(n)) if n == NamedKey::F3 as i32 => Ok(3), + Some(MainKey::Key(n)) if n == NamedKey::F4 as i32 => Ok(4), + Some(MainKey::Key(n)) if n == NamedKey::F5 as i32 => Ok(5), + Some(MainKey::Key(n)) if n == NamedKey::F6 as i32 => Ok(6), + Some(MainKey::Key(n)) if n == NamedKey::F7 as i32 => Ok(7), + Some(MainKey::Key(n)) if n == NamedKey::F8 as i32 => Ok(8), + Some(MainKey::Key(n)) if n == NamedKey::F9 as i32 => Ok(9), + Some(MainKey::Key(n)) if n == NamedKey::F10 as i32 => Ok(10), + Some(MainKey::Key(n)) if n == NamedKey::F11 as i32 => Ok(11), + Some(MainKey::Key(n)) if n == NamedKey::F12 as i32 => Ok(12), + _ => Err("Unsupported key"), + } +} + fn named_key_to_key(named_key: NamedKey) -> Key { match named_key { NamedKey::PageDown => Key::PageDown, -- cgit v1.2.3