aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils/src/data.rs
diff options
context:
space:
mode:
authorBradford Hovinen <hovinen@gmail.com>2024-03-25 15:04:38 +0100
committerGitHub <noreply@github.com>2024-03-25 15:04:38 +0100
commit312817fcf6eb86e394ee72986bd00bede76d70f4 (patch)
tree38aa85346a611dc2c9151a27ca60ce64ee295d72 /zellij-utils/src/data.rs
parentstyle(fmt): fix warnings (#3223) (diff)
downloadsl0ppij-312817fcf6eb86e394ee72986bd00bede76d70f4.tar.gz
sl0ppij-312817fcf6eb86e394ee72986bd00bede76d70f4.tar.xz
sl0ppij-312817fcf6eb86e394ee72986bd00bede76d70f4.zip
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+<character> to Ctrl+<function key>. 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.
Diffstat (limited to 'zellij-utils/src/data.rs')
-rw-r--r--zellij-utils/src/data.rs82
1 files changed, 41 insertions, 41 deletions
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index 998392ff..204c57e4 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -62,6 +62,8 @@ pub enum Key {
BackTab,
Null,
Esc,
+ AltF(u8),
+ CtrlF(u8),
}
impl FromStr for Key {
@@ -78,14 +80,7 @@ impl FromStr for Key {
}
match (modifier, main_key) {
(Some("Ctrl"), Some(main_key)) => {
- let mut key_chars = main_key.chars();
- let key_count = main_key.chars().count();
- if key_count == 1 {
- let key_char = key_chars.next().unwrap();
- Ok(Key::Ctrl(key_char))
- } else {
- Err(format!("Failed to parse key: {}", key_str).into())
- }
+ parse_main_key(main_key, key_str, Key::Ctrl, Key::CtrlF)
},
(Some("Alt"), Some(main_key)) => {
match main_key {
@@ -96,16 +91,12 @@ impl FromStr for Key {
"Right" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Right))),
"Up" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Up))),
"Down" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Down))),
- _ => {
- let mut key_chars = main_key.chars();
- let key_count = main_key.chars().count();
- if key_count == 1 {
- let key_char = key_chars.next().unwrap();
- Ok(Key::Alt(CharOrArrow::Char(key_char)))
- } else {
- Err(format!("Failed to parse key: {}", key_str).into())
- }
- },
+ _ => parse_main_key(
+ main_key,
+ key_str,
+ |c| Key::Alt(CharOrArrow::Char(c)),
+ Key::AltF,
+ ),
}
},
(None, Some(main_key)) => match main_key {
@@ -124,35 +115,42 @@ impl FromStr for Key {
"Space" => Ok(Key::Char(' ')),
"Enter" => Ok(Key::Char('\n')),
"Esc" => Ok(Key::Esc),
- _ => {
- let mut key_chars = main_key.chars();
- let key_count = main_key.chars().count();
- if key_count == 1 {
- let key_char = key_chars.next().unwrap();
- Ok(Key::Char(key_char))
- } else if key_count > 1 {
- if let Some(first_char) = key_chars.next() {
- if first_char == 'F' {
- let f_index: String = key_chars.collect();
- let f_index: u8 = f_index
- .parse()
- .map_err(|e| format!("Failed to parse F index: {}", e))?;
- if f_index >= 1 && f_index <= 12 {
- return Ok(Key::F(f_index));
- }
- }
- }
- Err(format!("Failed to parse key: {}", key_str).into())
- } else {
- Err(format!("Failed to parse key: {}", key_str).into())
- }
- },
+ _ => parse_main_key(main_key, key_str, Key::Char, Key::F),
},
_ => Err(format!("Failed to parse key: {}", key_str).into()),
}
}
}
+fn parse_main_key(
+ main_key: &str,
+ key_str: &str,
+ to_char_key: impl FnOnce(char) -> Key,
+ to_fn_key: impl FnOnce(u8) -> Key,
+) -> Result<Key, Box<dyn std::error::Error>> {
+ let mut key_chars = main_key.chars();
+ let key_count = main_key.chars().count();
+ if key_count == 1 {
+ let key_char = key_chars.next().unwrap();
+ Ok(to_char_key(key_char))
+ } else if key_count > 1 {
+ if let Some(first_char) = key_chars.next() {
+ if first_char == 'F' {
+ let f_index: String = key_chars.collect();
+ let f_index: u8 = f_index
+ .parse()
+ .map_err(|e| format!("Failed to parse F index: {}", e))?;
+ if f_index >= 1 && f_index <= 12 {
+ return Ok(to_fn_key(f_index));
+ }
+ }
+ }
+ Err(format!("Failed to parse key: {}", key_str).into())
+ } else {
+ Err(format!("Failed to parse key: {}", key_str).into())
+ }
+}
+
impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@@ -177,6 +175,8 @@ impl fmt::Display for Key {
},
Key::Alt(c) => write!(f, "Alt+{}", c),
Key::Ctrl(c) => write!(f, "Ctrl+{}", Key::Char(*c)),
+ Key::AltF(n) => write!(f, "Alt+F{}", n),
+ Key::CtrlF(n) => write!(f, "Ctrl+F{}", n),
Key::Null => write!(f, "NULL"),
Key::Esc => write!(f, "ESC"),
}