diff options
author | Kirill Chibisov <contact@kchibisov.com> | 2024-01-24 18:06:41 +0400 |
---|---|---|
committer | Christian Duerr <contact@christianduerr.com> | 2024-03-19 02:20:53 +0100 |
commit | 03dbae5c769898cb3b04bdf167c42a2c9486dc04 (patch) | |
tree | 77b43b3f97ad98fcb85d9107fd17c8993d6724e1 | |
parent | 97f3a7694ad8910cadf36a2c08bcc5d19114841a (diff) | |
download | alacritty-03dbae5c769898cb3b04bdf167c42a2c9486dc04.tar.gz alacritty-03dbae5c769898cb3b04bdf167c42a2c9486dc04.zip |
Don't report associated text only for C0/C1
This has a side effect that we'll have text reported for Alt+Shift+T
and similar, but only C0/C1 should be excluded and Alt+Shift+T is
emitting neither, thus regular `T` will be reported.
Fixes #7657.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | alacritty/src/input/keyboard.rs | 53 |
2 files changed, 31 insertions, 23 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae72180..80fdc6f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - CLI env variables clearing configuration file variables - Vi inline search/semantic selection expanding across newlines +- C0 and C1 codes being emitted in associated text when using kitty keyboard ### Changed diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index d939c3dc..1df1b13b 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -275,11 +275,18 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec<u8 let context = SequenceBuilder { mode, modifiers, kitty_seq, kitty_encode_all, kitty_event_type }; + let associated_text = key.text_with_all_modifiers().filter(|text| { + mode.contains(TermMode::REPORT_ASSOCIATED_TEXT) + && key.state != ElementState::Released + && !text.is_empty() + && !is_control_character(text) + }); + let sequence_base = context .try_build_numpad(&key) .or_else(|| context.try_build_named(&key)) .or_else(|| context.try_build_control_char_or_mod(&key, &mut modifiers)) - .or_else(|| context.try_build_textual(&key)); + .or_else(|| context.try_build_textual(&key, associated_text)); let (payload, terminator) = match sequence_base { Some(SequenceBase { payload, terminator }) => (payload, terminator), @@ -289,10 +296,7 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec<u8 let mut payload = format!("\x1b[{}", payload); // Add modifiers information. - if kitty_event_type - || !modifiers.is_empty() - || (mode.contains(TermMode::REPORT_ASSOCIATED_TEXT) && key.text.is_some()) - { + if kitty_event_type || !modifiers.is_empty() || associated_text.is_some() { payload.push_str(&format!(";{}", modifiers.encode_esc_sequence())); } @@ -307,19 +311,13 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec<u8 payload.push(event_type); } - // Associated text is not reported when the control/alt/logo is pressesed. - if mode.contains(TermMode::REPORT_ASSOCIATED_TEXT) - && key.state != ElementState::Released - && (modifiers.is_empty() || modifiers == SequenceModifiers::SHIFT) - { - if let Some(text) = key.text { - let mut codepoints = text.chars().map(u32::from); - if let Some(codepoint) = codepoints.next() { - payload.push_str(&format!(";{codepoint}")); - } - for codepoint in codepoints { - payload.push_str(&format!(":{codepoint}")); - } + if let Some(text) = associated_text { + let mut codepoints = text.chars().map(u32::from); + if let Some(codepoint) = codepoints.next() { + payload.push_str(&format!(";{codepoint}")); + } + for codepoint in codepoints { + payload.push_str(&format!(":{codepoint}")); } } @@ -342,7 +340,11 @@ pub struct SequenceBuilder { impl SequenceBuilder { /// Try building sequence from the event's emitting text. - fn try_build_textual(&self, key: &KeyEvent) -> Option<SequenceBase> { + fn try_build_textual( + &self, + key: &KeyEvent, + associated_text: Option<&str>, + ) -> Option<SequenceBase> { let character = match key.logical_key.as_ref() { Key::Character(character) => character, _ => return None, @@ -374,10 +376,7 @@ impl SequenceBuilder { }; Some(SequenceBase::new(payload.into(), SequenceTerminator::Kitty)) - } else if self.kitty_encode_all - && self.mode.contains(TermMode::REPORT_ASSOCIATED_TEXT) - && key.text.is_some() - { + } else if self.kitty_encode_all && associated_text.is_some() { // Fallback when need to report text, but we don't have any key associated with this // text. Some(SequenceBase::new("0".into(), SequenceTerminator::Kitty)) @@ -644,3 +643,11 @@ impl From<ModifiersState> for SequenceModifiers { modifiers } } + +/// Check whether the `text` is `0x7f`, `C0` or `C1` control code. +fn is_control_character(text: &str) -> bool { + // 0x7f (DEL) is included here since it has a dedicated control code (`^?`) which generally + // does not match the reported text (`^H`), despite not technically being part of C0 or C1. + let codepoint = text.bytes().next().unwrap(); + text.len() == 1 && (codepoint < 0x20 || (0x7f..=0x9f).contains(&codepoint)) +} |