Add secondary DA support

This adds support for the secondary DA escape sequence response.
Alacritty's version is formatted allowing for up to 99 minor and patch
versions, which should be sufficient.

The tertiary DA is intentionally not implemented and marked as rejected
in the documentation, since a lot of terminals do not support it, or
report useless data (XTerm/URxvt/Kitty).

Fixes #3100.
This commit is contained in:
Christian Duerr 2020-07-23 21:55:15 +00:00 committed by GitHub
parent dd32447bc2
commit 0dfd8601c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 9 deletions

View File

@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## 0.6.0-dev
### Added
- Secondary device attributes escape (`CSI > 0 c`)
## 0.5.0-dev
### Packaging

View File

@ -164,7 +164,7 @@ pub trait Handler {
/// Identify the terminal (should write back to the pty stream).
///
/// TODO this should probably return an io::Result
fn identify_terminal<W: io::Write>(&mut self, _: &mut W) {}
fn identify_terminal<W: io::Write>(&mut self, _: &mut W, _intermediate: Option<char>) {}
/// Report device status.
fn device_status<W: io::Write>(&mut self, _: &mut W, _: usize) {}
@ -973,8 +973,8 @@ where
('C', None) | ('a', None) => {
handler.move_forward(Column(arg_or_default!(idx: 0, default: 1) as usize))
},
('c', None) if arg_or_default!(idx: 0, default: 0) == 0 => {
handler.identify_terminal(writer)
('c', intermediate) if arg_or_default!(idx: 0, default: 0) == 0 => {
handler.identify_terminal(writer, intermediate.map(|&i| i as char))
},
('D', None) => {
handler.move_backward(Column(arg_or_default!(idx: 0, default: 1) as usize))
@ -1148,7 +1148,7 @@ where
},
(b'H', None) => self.handler.set_horizontal_tabstop(),
(b'M', None) => self.handler.reverse_index(),
(b'Z', None) => self.handler.identify_terminal(self.writer),
(b'Z', None) => self.handler.identify_terminal(self.writer, None),
(b'c', None) => self.handler.reset_state(),
(b'0', intermediate) => {
configure_charset!(StandardCharset::SpecialCharacterAndLineDrawing, intermediate)
@ -1408,7 +1408,7 @@ mod tests {
self.index = index;
}
fn identify_terminal<W: io::Write>(&mut self, _: &mut W) {
fn identify_terminal<W: io::Write>(&mut self, _: &mut W, _intermediate: Option<char>) {
self.identity_reported = true;
}

View File

@ -1496,9 +1496,19 @@ impl<T: EventListener> Handler for Term<T> {
}
#[inline]
fn identify_terminal<W: io::Write>(&mut self, writer: &mut W) {
trace!("Reporting terminal identity");
let _ = writer.write_all(b"\x1b[?6c");
fn identify_terminal<W: io::Write>(&mut self, writer: &mut W, intermediate: Option<char>) {
match intermediate {
None => {
trace!("Reporting primary device attributes");
let _ = writer.write_all(b"\x1b[?6c");
},
Some('>') => {
trace!("Reporting secondary device attributes");
let version = version_number(env!("CARGO_PKG_VERSION"));
let _ = writer.write_all(format!("\x1b[>0;{};1c", version).as_bytes());
},
_ => debug!("Unsupported device attributes intermediate"),
}
}
#[inline]
@ -2184,6 +2194,27 @@ impl<T: EventListener> Handler for Term<T> {
}
}
/// Terminal version for escape sequence reports.
///
/// This returns the current terminal version as a unique number based on alacritty_terminal's
/// semver version. The different versions are padded to ensure that a higher semver version will
/// always report a higher version number.
fn version_number(mut version: &str) -> usize {
if let Some(separator) = version.rfind('-') {
version = &version[..separator];
}
let mut version_number = 0;
let semver_versions = version.split('.');
for (i, semver_version) in semver_versions.rev().enumerate() {
let semver_number = semver_version.parse::<usize>().unwrap_or(0);
version_number += usize::pow(100, i as u32) * semver_number;
}
version_number
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ClipboardType {
Clipboard,
@ -2688,6 +2719,15 @@ mod tests {
term.set_title(None);
assert_eq!(term.title, None);
}
#[test]
fn parse_cargo_version() {
assert!(version_number(env!("CARGO_PKG_VERSION")) >= 10_01);
assert_eq!(version_number("0.0.1-dev"), 1);
assert_eq!(version_number("0.1.2-dev"), 1_02);
assert_eq!(version_number("1.2.3-dev"), 1_02_03);
assert_eq!(version_number("999.99.99"), 9_99_99_99);
}
}
#[cfg(all(test, feature = "bench"))]

View File

@ -43,7 +43,7 @@ brevity.
| `CSI B` | IMPLEMENTED | |
| `CSI b` | IMPLEMENTED | |
| `CSI C` | IMPLEMENTED | |
| `CSI c` | PARTIAL | No parameter support |
| `CSI c` | IMPLEMENTED | |
| `CSI D` | IMPLEMENTED | |
| `CSI d` | IMPLEMENTED | |
| `CSI E` | IMPLEMENTED | |