1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 13:52:55 +03:00

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.
This commit is contained in:
Wez Furlong 2020-06-19 23:40:48 -07:00
parent 28eda7663e
commit e2dc0add83
2 changed files with 74 additions and 3 deletions

View File

@ -1709,6 +1709,10 @@ impl TerminalState {
Mode::SetMode(m) | Mode::ResetMode(m) => { Mode::SetMode(m) | Mode::ResetMode(m) => {
error!("unhandled TerminalMode {:?}", m); error!("unhandled TerminalMode {:?}", m);
} }
Mode::XtermKeyMode { resource, value } => {
error!("unhandled XtermKeyMode {:?} {:?}", resource, value);
}
} }
} }

View File

@ -46,6 +46,9 @@ pub struct Unspecified {
impl Display for Unspecified { impl Display for Unspecified {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { 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() { for (idx, p) in self.params.iter().enumerate() {
if idx > 0 { if idx > 0 {
write!(f, ";{}", p)?; write!(f, ";{}", p)?;
@ -53,9 +56,6 @@ impl Display for Unspecified {
write!(f, "{}", p)?; write!(f, "{}", p)?;
} }
} }
for i in &self.intermediates {
write!(f, "{}", *i as char)?;
}
write!(f, "{}", self.control) 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<Self> {
Some(match value {
0 => XtermKeyModifierResource::Keyboard,
1 => XtermKeyModifierResource::CursorKeys,
2 => XtermKeyModifierResource::FunctionKeys,
4 => XtermKeyModifierResource::OtherKeys,
_ => return None,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Mode { pub enum Mode {
SetDecPrivateMode(DecPrivateMode), SetDecPrivateMode(DecPrivateMode),
@ -427,6 +447,10 @@ pub enum Mode {
RestoreDecPrivateMode(DecPrivateMode), RestoreDecPrivateMode(DecPrivateMode),
SetMode(TerminalMode), SetMode(TerminalMode),
ResetMode(TerminalMode), ResetMode(TerminalMode),
XtermKeyMode {
resource: XtermKeyModifierResource,
value: Option<i64>,
},
} }
impl Display for Mode { impl Display for Mode {
@ -456,6 +480,22 @@ impl Display for Mode {
Mode::RestoreDecPrivateMode(mode) => emit!("r", mode), Mode::RestoreDecPrivateMode(mode) => emit!("r", mode),
Mode::SetMode(mode) => emit_mode!("h", mode), Mode::SetMode(mode) => emit_mode!("h", mode),
Mode::ResetMode(mode) => emit_mode!("l", 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))), .map(|mode| CSI::Mode(Mode::SaveDecPrivateMode(mode))),
('m', &[b'<']) | ('M', &[b'<']) => self.mouse_sgr1006(params).map(CSI::Mouse), ('m', &[b'<']) | ('M', &[b'<']) => self.mouse_sgr1006(params).map(CSI::Mouse),
('m', &[b'>']) => self.xterm_key_modifier(params),
('c', &[]) => self ('c', &[]) => self
.req_primary_device_attributes(params) .req_primary_device_attributes(params)
@ -1445,6 +1486,32 @@ impl<'a> CSIParser<'a> {
} }
} }
fn xterm_key_modifier(&mut self, params: &'a [i64]) -> Result<CSI, ()> {
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<CSI, ()> { fn decslrm(&mut self, params: &'a [i64]) -> Result<CSI, ()> {
if params.is_empty() { if params.is_empty() {
// with no params this is a request to save the cursor // with no params this is a request to save the cursor