From e2dc0add8379cf7a14820c50d2f953d85ec77a50 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 19 Jun 2020 23:40:48 -0700 Subject: [PATCH] termwiz: recognize CSI > PP ; Pv m sequence This is an xterm sequence that adjusts how the terminal encodes keyboard output. This commit teaches termwiz to parse and encode the sequence, but doesn't teach the terminal emulator to do anything with it at this time. I'm adding this because vim sends these sequences and I wanted to understand what they were for. --- term/src/terminalstate.rs | 4 +++ termwiz/src/escape/csi.rs | 73 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/term/src/terminalstate.rs b/term/src/terminalstate.rs index 5b1176d97..9e6ba1d7c 100644 --- a/term/src/terminalstate.rs +++ b/term/src/terminalstate.rs @@ -1709,6 +1709,10 @@ impl TerminalState { Mode::SetMode(m) | Mode::ResetMode(m) => { error!("unhandled TerminalMode {:?}", m); } + + Mode::XtermKeyMode { resource, value } => { + error!("unhandled XtermKeyMode {:?} {:?}", resource, value); + } } } diff --git a/termwiz/src/escape/csi.rs b/termwiz/src/escape/csi.rs index 0be77c2de..96d5a7544 100644 --- a/termwiz/src/escape/csi.rs +++ b/termwiz/src/escape/csi.rs @@ -46,6 +46,9 @@ pub struct Unspecified { impl Display for Unspecified { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + for i in &self.intermediates { + write!(f, "{}", *i as char)?; + } for (idx, p) in self.params.iter().enumerate() { if idx > 0 { write!(f, ";{}", p)?; @@ -53,9 +56,6 @@ impl Display for Unspecified { write!(f, "{}", p)?; } } - for i in &self.intermediates { - write!(f, "{}", *i as char)?; - } write!(f, "{}", self.control) } } @@ -419,6 +419,26 @@ impl Display for MouseReport { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum XtermKeyModifierResource { + Keyboard, + CursorKeys, + FunctionKeys, + OtherKeys, +} + +impl XtermKeyModifierResource { + pub fn parse(value: i64) -> Option { + Some(match value { + 0 => XtermKeyModifierResource::Keyboard, + 1 => XtermKeyModifierResource::CursorKeys, + 2 => XtermKeyModifierResource::FunctionKeys, + 4 => XtermKeyModifierResource::OtherKeys, + _ => return None, + }) + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum Mode { SetDecPrivateMode(DecPrivateMode), @@ -427,6 +447,10 @@ pub enum Mode { RestoreDecPrivateMode(DecPrivateMode), SetMode(TerminalMode), ResetMode(TerminalMode), + XtermKeyMode { + resource: XtermKeyModifierResource, + value: Option, + }, } impl Display for Mode { @@ -456,6 +480,22 @@ impl Display for Mode { Mode::RestoreDecPrivateMode(mode) => emit!("r", mode), Mode::SetMode(mode) => emit_mode!("h", mode), Mode::ResetMode(mode) => emit_mode!("l", mode), + Mode::XtermKeyMode { resource, value } => { + write!( + f, + ">{}", + match resource { + XtermKeyModifierResource::Keyboard => 0, + XtermKeyModifierResource::CursorKeys => 1, + XtermKeyModifierResource::FunctionKeys => 2, + XtermKeyModifierResource::OtherKeys => 4, + } + )?; + if let Some(value) = value { + write!(f, ";{}", value)?; + } + write!(f, "m") + } } } } @@ -1366,6 +1406,7 @@ impl<'a> CSIParser<'a> { .map(|mode| CSI::Mode(Mode::SaveDecPrivateMode(mode))), ('m', &[b'<']) | ('M', &[b'<']) => self.mouse_sgr1006(params).map(CSI::Mouse), + ('m', &[b'>']) => self.xterm_key_modifier(params), ('c', &[]) => self .req_primary_device_attributes(params) @@ -1445,6 +1486,32 @@ impl<'a> CSIParser<'a> { } } + fn xterm_key_modifier(&mut self, params: &'a [i64]) -> Result { + if params.len() == 2 { + let resource = XtermKeyModifierResource::parse(params[0]).ok_or_else(|| ())?; + Ok(self.advance_by( + 2, + params, + CSI::Mode(Mode::XtermKeyMode { + resource, + value: Some(params[1]), + }), + )) + } else if params.len() == 1 { + let resource = XtermKeyModifierResource::parse(params[0]).ok_or_else(|| ())?; + Ok(self.advance_by( + 1, + params, + CSI::Mode(Mode::XtermKeyMode { + resource, + value: None, + }), + )) + } else { + Err(()) + } + } + fn decslrm(&mut self, params: &'a [i64]) -> Result { if params.is_empty() { // with no params this is a request to save the cursor