summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--default-plugins/status-bar/src/first_line.rs2
-rw-r--r--default-plugins/status-bar/src/main.rs6
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap2
-rw-r--r--src/tests/fixtures/configs/changed_keys.kdl4
-rw-r--r--zellij-utils/src/data.rs82
-rw-r--r--zellij-utils/src/input/mod.rs10
-rw-r--r--zellij-utils/src/plugin_api/key.rs86
7 files changed, 120 insertions, 72 deletions
diff --git a/default-plugins/status-bar/src/first_line.rs b/default-plugins/status-bar/src/first_line.rs
index 23a6d5869..4ac090646 100644
--- a/default-plugins/status-bar/src/first_line.rs
+++ b/default-plugins/status-bar/src/first_line.rs
@@ -62,6 +62,8 @@ impl KeyShortcut {
} else {
match key {
Key::F(c) => format!("{}", c),
+ Key::CtrlF(n) => format!("F{}", n),
+ Key::AltF(n) => format!("F{}", n),
Key::Ctrl(c) => format!("{}", c),
Key::Char(_) => format!("{}", key),
Key::Alt(c) => format!("{}", c),
diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs
index 2910d6786..1d85c7f69 100644
--- a/default-plugins/status-bar/src/main.rs
+++ b/default-plugins/status-bar/src/main.rs
@@ -333,8 +333,8 @@ pub fn get_common_modifier(keyvec: Vec<&Key>) -> Option<String> {
let mut new_modifier;
for key in keyvec.iter() {
match key {
- Key::Ctrl(_) => new_modifier = "Ctrl",
- Key::Alt(_) => new_modifier = "Alt",
+ Key::Ctrl(_) | Key::CtrlF(_) => new_modifier = "Ctrl",
+ Key::Alt(_) | Key::AltF(_) => new_modifier = "Alt",
_ => return None,
}
if modifier.is_empty() {
@@ -468,7 +468,9 @@ pub fn style_key_with_modifier(
} else {
match key {
Key::Ctrl(c) => format!("{}", Key::Char(*c)),
+ Key::CtrlF(n) => format!("{}", Key::F(*n)),
Key::Alt(c) => format!("{}", c),
+ Key::AltF(n) => format!("{}", Key::F(*n)),
_ => format!("{}", key),
}
}
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap
index 2f983243f..974a63bd8 100644
--- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__status_bar_loads_custom_keybindings.snap
@@ -25,5 +25,5 @@ expression: last_snapshot
│ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
- <F1> LOCK  <F2> PANE  <F3> TAB  <F4> RESIZE  <F5> MOVE  <F6> SEARCH  <F7> SESSION  <F8> QUIT 
+ <F1> LOCK  <F2> PANE  <F3> TAB  <F4> RESIZE  <F5> MOVE  <F6> SEARCH  <Alt+F7> SESSION  <Ctrl+F8> QUIT 
Tip: UNBOUND => open new pane. UNBOUND => navigate between panes. UNBOUND => increase/decrease pane size.
diff --git a/src/tests/fixtures/configs/changed_keys.kdl b/src/tests/fixtures/configs/changed_keys.kdl
index 6123b1d5b..c8bed1be2 100644
--- a/src/tests/fixtures/configs/changed_keys.kdl
+++ b/src/tests/fixtures/configs/changed_keys.kdl
@@ -6,7 +6,7 @@ keybinds clear-defaults=true {
bind "F4" { SwitchToMode "Resize"; }
bind "F5" { SwitchToMode "Move"; }
bind "F6" { SwitchToMode "Scroll"; }
- bind "F7" { SwitchToMode "Session"; }
- bind "F8" { Quit; }
+ bind "Alt F7" { SwitchToMode "Session"; }
+ bind "Ctrl F8" { Quit; }
}
}
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index 998392ff7..204c57e43 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"),
}
diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs
index 1c95f348b..1d30841f3 100644
--- a/zellij-utils/src/input/mod.rs
+++ b/zellij-utils/src/input/mod.rs
@@ -113,7 +113,15 @@ mod not_wasm {
KeyCode::Tab => Key::BackTab, // TODO: ???
KeyCode::Delete => Key::Delete,
KeyCode::Insert => Key::Insert,
- KeyCode::Function(n) => Key::F(n),
+ KeyCode::Function(n) => {
+ if modifiers.contains(Modifiers::ALT) {
+ Key::AltF(n)
+ } else if modifiers.contains(Modifiers::CTRL) {
+ Key::CtrlF(n)
+ } else {
+ Key::F(n)
+ }
+ },
KeyCode::Escape => Key::Esc,
KeyCode::Enter => Key::Char('\n'),
_ => Key::Esc, // there are other keys we can implement here, but we might need additional terminal support to implement them, not just exhausting this enum
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<ProtobufKey> 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<Key> 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<Key> for ProtobufKey {
}
}
+fn fn_index_to_main_key(index: u8) -> Result<MainKey, &'static str> {
+ 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<MainKey>,
@@ -191,6 +209,24 @@ fn char_from_main_key(main_key: Option<MainKey>) -> Result<char, &'static str> {
}
}
+fn fn_index_from_main_key(main_key: Option<MainKey>) -> Result<u8, &'static str> {
+ 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,