aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2021-05-13 16:09:07 +0200
committerGitHub <noreply@github.com>2021-05-13 16:09:07 +0200
commitb93e51cf88d23e57b844be193829caa68dadbcf1 (patch)
tree999b6ae4488b32477462824bfe5c234446d03109
parentMerge pull request #465 from a-kenji/set-data-dir (diff)
downloadsl0ppij-b93e51cf88d23e57b844be193829caa68dadbcf1.tar.gz
sl0ppij-b93e51cf88d23e57b844be193829caa68dadbcf1.tar.xz
sl0ppij-b93e51cf88d23e57b844be193829caa68dadbcf1.zip
fix(compatibility): implement device reports (#500)
* fix(compatibility): implement device reports * docs(changelog): update change
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/client/panes/grid.rs67
-rw-r--r--src/client/panes/terminal_pane.rs3
-rw-r--r--src/client/panes/unit/grid_tests.rs12
-rw-r--r--src/client/panes/unit/snapshots/zellij__client__panes__grid__grid_tests__terminal_reports.snap6
-rw-r--r--src/client/tab.rs9
-rw-r--r--src/common/utils/shared.rs21
-rw-r--r--src/tests/fixtures/terminal_reports1
8 files changed, 120 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c477958..90e97afd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Fix propagation of plugin ui request (https://github.com/zellij-org/zellij/pull/495)
* Handle pasted text properly (https://github.com/zellij-org/zellij/pull/494)
* Fix default keybinds for tab -> resize mode (https://github.com/zellij-org/zellij/pull/497)
+* Terminal compatibility: device reports (https://github.com/zellij-org/zellij/pull/500)
## [0.9.0] - 2021-05-11
* Add more functionality to unbinding the default keybindings (https://github.com/zellij-org/zellij/pull/468)
diff --git a/src/client/panes/grid.rs b/src/client/panes/grid.rs
index c59e279b..e51b1ed5 100644
--- a/src/client/panes/grid.rs
+++ b/src/client/panes/grid.rs
@@ -9,7 +9,9 @@ use vte::{Params, Perform};
const TABSTOP_WIDTH: usize = 8; // TODO: is this always right?
const SCROLL_BACK: usize = 10_000;
+use crate::utils::consts::VERSION;
use crate::utils::logging::debug_log_to_file;
+use crate::utils::shared::version_number;
use crate::panes::terminal_character::{
CharacterStyles, CharsetIndex, Cursor, CursorShape, StandardCharset, TerminalCharacter,
@@ -186,6 +188,7 @@ pub struct Grid {
pub clear_viewport_before_rendering: bool,
pub width: usize,
pub height: usize,
+ pub pending_messages_to_pty: Vec<Vec<u8>>,
}
impl Debug for Grid {
@@ -222,6 +225,7 @@ impl Grid {
alternative_lines_above_viewport_and_cursor: None,
clear_viewport_before_rendering: false,
active_charset: Default::default(),
+ pending_messages_to_pty: vec![],
}
}
pub fn contains_widechar(&self) -> bool {
@@ -1283,6 +1287,64 @@ impl Perform for Grid {
for _ in 0..next_param_or(1) {
self.move_to_previous_tabstop();
}
+ } else if c == 'c' {
+ // identify terminal
+ // https://vt100.net/docs/vt510-rm/DA1.html
+ match intermediates.get(0) {
+ None | Some(0) => {
+ // primary device attributes
+ let terminal_capabilities = "\u{1b}[?6c";
+ self.pending_messages_to_pty
+ .push(terminal_capabilities.as_bytes().to_vec());
+ }
+ Some(b'>') => {
+ // secondary device attributes
+ let version = version_number(VERSION);
+ let text = format!("\u{1b}[>0;{};1c", version);
+ self.pending_messages_to_pty.push(text.as_bytes().to_vec());
+ }
+ _ => {}
+ }
+ } else if c == 'n' {
+ // DSR - device status report
+ // https://vt100.net/docs/vt510-rm/DSR.html
+ match next_param_or(0) {
+ 5 => {
+ // report terminal status
+ let all_good = "\u{1b}[0n";
+ self.pending_messages_to_pty
+ .push(all_good.as_bytes().to_vec());
+ }
+ 6 => {
+ // CPR - cursor position report
+ let position_report =
+ format!("\x1b[{};{}R", self.cursor.y + 1, self.cursor.x + 1);
+ self.pending_messages_to_pty
+ .push(position_report.as_bytes().to_vec());
+ }
+ _ => {}
+ }
+ } else if c == 't' {
+ match next_param_or(1) as usize {
+ 14 => {
+ // TODO: report text area size in pixels, currently unimplemented
+ // to solve this we probably need to query the user's terminal for the cursor
+ // size and then use it as a multiplier
+ }
+ 18 => {
+ // report text area
+ let text_area_report = format!("\x1b[8;{};{}t", self.height, self.width);
+ self.pending_messages_to_pty
+ .push(text_area_report.as_bytes().to_vec());
+ }
+ 22 => {
+ // TODO: push title
+ }
+ 23 => {
+ // TODO: pop title
+ }
+ _ => {}
+ }
} else {
let result = debug_log_to_file(format!("Unhandled csi: {}->{:?}", c, params));
#[cfg(not(test))]
@@ -1341,6 +1403,11 @@ impl Perform for Grid {
(b'7', None) => {
self.save_cursor_position();
}
+ (b'Z', None) => {
+ let terminal_capabilities = "\u{1b}[?6c";
+ self.pending_messages_to_pty
+ .push(terminal_capabilities.as_bytes().to_vec());
+ }
(b'8', None) => {
self.restore_cursor_position();
}
diff --git a/src/client/panes/terminal_pane.rs b/src/client/panes/terminal_pane.rs
index 98021110..5c4f55c8 100644
--- a/src/client/panes/terminal_pane.rs
+++ b/src/client/panes/terminal_pane.rs
@@ -301,6 +301,9 @@ impl Pane for TerminalPane {
CursorShape::BlinkingBeam => "\u{1b}[5 q".to_string(),
}
}
+ fn drain_messages_to_pty(&mut self) -> Vec<Vec<u8>> {
+ self.grid.pending_messages_to_pty.drain(..).collect()
+ }
}
impl TerminalPane {
diff --git a/src/client/panes/unit/grid_tests.rs b/src/client/panes/unit/grid_tests.rs
index b6a2ec6c..8517a975 100644
--- a/src/client/panes/unit/grid_tests.rs
+++ b/src/client/panes/unit/grid_tests.rs
@@ -383,3 +383,15 @@ fn csi_capital_z() {
}
assert_snapshot!(format!("{:?}", grid));
}
+
+#[test]
+fn terminal_reports() {
+ let mut vte_parser = vte::Parser::new();
+ let mut grid = Grid::new(51, 97);
+ let fixture_name = "terminal_reports";
+ let content = read_fixture(fixture_name);
+ for byte in content {
+ vte_parser.advance(&mut grid, byte);
+ }
+ assert_snapshot!(format!("{:?}", grid.pending_messages_to_pty));
+}
diff --git a/src/client/panes/unit/snapshots/zellij__client__panes__grid__grid_tests__terminal_reports.snap b/src/client/panes/unit/snapshots/zellij__client__panes__grid__grid_tests__terminal_reports.snap
new file mode 100644
index 00000000..b2dca273
--- /dev/null
+++ b/src/client/panes/unit/snapshots/zellij__client__panes__grid__grid_tests__terminal_reports.snap
@@ -0,0 +1,6 @@
+---
+source: src/client/panes/./unit/grid_tests.rs
+expression: "format!(\"{:?}\", grid . pending_messages_to_pty)"
+
+---
+[[27, 91, 63, 54, 99], [27, 91, 56, 59, 53, 49, 59, 57, 55, 116], [27, 91, 63, 54, 99], [27, 91, 48, 110], [27, 91, 49, 59, 49, 82]]
diff --git a/src/client/tab.rs b/src/client/tab.rs
index 785a650e..29a41530 100644
--- a/src/client/tab.rs
+++ b/src/client/tab.rs
@@ -218,6 +218,11 @@ pub trait Pane {
fn invisible_borders(&self) -> bool {
false
}
+ fn drain_messages_to_pty(&mut self) -> Vec<Vec<u8>> {
+ // TODO: this is only relevant to terminal panes
+ // we should probably refactor away from this trait at some point
+ vec![]
+ }
}
impl Tab {
@@ -601,6 +606,10 @@ impl Tab {
// the reason
if let Some(terminal_output) = self.panes.get_mut(&PaneId::Terminal(pid)) {
terminal_output.handle_pty_bytes(bytes);
+ let messages_to_pty = terminal_output.drain_messages_to_pty();
+ for message in messages_to_pty {
+ self.write_to_pane_id(message, PaneId::Terminal(pid));
+ }
}
}
pub fn write_to_terminals_on_current_tab(&mut self, input_bytes: Vec<u8>) {
diff --git a/src/common/utils/shared.rs b/src/common/utils/shared.rs
index ace5674b..26a2f90a 100644
--- a/src/common/utils/shared.rs
+++ b/src/common/utils/shared.rs
@@ -85,3 +85,24 @@ pub fn _detect_theme(bg: PaletteColor) -> Theme {
_ => Theme::Dark,
}
}
+
+// (this was shamelessly copied from alacritty)
+//
+// This returns the current terminal version as a unique number based on the
+// semver version. The different versions are padded to ensure that a higher semver version will
+// always report a higher version number.
+pub 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
+}
diff --git a/src/tests/fixtures/terminal_reports b/src/tests/fixtures/terminal_reports
new file mode 100644
index 00000000..9ec87eba
--- /dev/null
+++ b/src/tests/fixtures/terminal_reports
@@ -0,0 +1 @@
+Z