diff --git a/book/src/remapping.md b/book/src/remapping.md index d762c6add..650929498 100644 --- a/book/src/remapping.md +++ b/book/src/remapping.md @@ -50,8 +50,22 @@ # create a new minor mode bound to `+` ## Special keys and modifiers -Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes -`C-`, `S-` and `A-`. Special keys are encoded as follows: +Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes `C-`, `S-` and `A-`. + +The [Super key](https://en.wikipedia.org/wiki/Super_key_(keyboard_button)) - the Windows/Linux +key or the Command key on Mac keyboards - is also supported when using a terminal emulator that +supports the [enhanced keyboard protocol](https://github.com/helix-editor/helix/wiki/Terminal-Support#enhanced-keyboard-protocol). +The super key is encoded with prefixes `Meta-`, `Cmd-` or `Win-`. These are all synonyms for the +super modifier - binding a key with a `Win-` modifier will mean it can be used with the +Windows/Linux key or the Command key. + +```toml +[keys.normal] +C-s = ":write" # Ctrl and 's' to write +Cmd-s = ":write" # Cmd or Win or Meta and 's' to write +``` + +Special keys are encoded as follows: | Key name | Representation | | --- | --- | diff --git a/helix-view/src/input.rs b/helix-view/src/input.rs index 5f5067eac..acf366aac 100644 --- a/helix-view/src/input.rs +++ b/helix-view/src/input.rs @@ -162,7 +162,12 @@ pub(crate) mod keys { impl fmt::Display for KeyEvent { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!( - "{}{}{}", + "{}{}{}{}", + if self.modifiers.contains(KeyModifiers::SUPER) { + "Meta-" + } else { + "" + }, if self.modifiers.contains(KeyModifiers::SHIFT) { "S-" } else { @@ -312,6 +317,10 @@ fn width(&self) -> usize { if self.modifiers.contains(KeyModifiers::CONTROL) { width += 2; } + if self.modifiers.contains(KeyModifiers::SUPER) { + // "-Meta" + width += 5; + } width } @@ -396,6 +405,7 @@ fn from_str(s: &str) -> Result { "S" => KeyModifiers::SHIFT, "A" => KeyModifiers::ALT, "C" => KeyModifiers::CONTROL, + "Meta" | "Cmd" | "Win" => KeyModifiers::SUPER, _ => return Err(anyhow!("Invalid key modifier '{}-'", token)), }; @@ -709,6 +719,28 @@ fn parsing_modified_keys() { modifiers: KeyModifiers::NONE } ); + + assert_eq!( + str::parse::("Meta-c").unwrap(), + KeyEvent { + code: KeyCode::Char('c'), + modifiers: KeyModifiers::SUPER + } + ); + assert_eq!( + str::parse::("Win-s").unwrap(), + KeyEvent { + code: KeyCode::Char('s'), + modifiers: KeyModifiers::SUPER + } + ); + assert_eq!( + str::parse::("Cmd-d").unwrap(), + KeyEvent { + code: KeyCode::Char('d'), + modifiers: KeyModifiers::SUPER + } + ); } #[test] diff --git a/helix-view/src/keyboard.rs b/helix-view/src/keyboard.rs index 080bce8dd..d816a52ef 100644 --- a/helix-view/src/keyboard.rs +++ b/helix-view/src/keyboard.rs @@ -7,6 +7,7 @@ pub struct KeyModifiers: u8 { const SHIFT = 0b0000_0001; const CONTROL = 0b0000_0010; const ALT = 0b0000_0100; + const SUPER = 0b0000_1000; const NONE = 0b0000_0000; } } @@ -27,6 +28,9 @@ fn from(key_modifiers: KeyModifiers) -> Self { if key_modifiers.contains(KeyModifiers::ALT) { result.insert(CKeyModifiers::ALT); } + if key_modifiers.contains(KeyModifiers::SUPER) { + result.insert(CKeyModifiers::SUPER); + } result } @@ -48,6 +52,9 @@ fn from(val: crossterm::event::KeyModifiers) -> Self { if val.contains(CKeyModifiers::ALT) { result.insert(KeyModifiers::ALT); } + if val.contains(CKeyModifiers::SUPER) { + result.insert(KeyModifiers::SUPER); + } result }