fix(compatibility): improve vttest (#1671)
* Improve 'vttest' scenarios: 1. Report terminal as VT220 with sixel rather than VT400 family with sixel. This fixes a hang when launching vttest as it is waiting for a response to DECRQSS. 2. Test 6.2: Support NewLine mode (CR --> CRLF). 3. Test 6.3: Fix DSR cursor position report to honor scrolling region. 4. Test 6.7: Parse and respond to DECREQTPARM (Request Terminal Parameters - CSI x). This is a VT100 sequence that xterm used to respond to always, but more recently only responds to when explicitly set to VT100 level. * cargo fmt * Fix failing unit test snapshot * fix clippy error * VT100 UK character set
This commit is contained in:
parent
639de16c5e
commit
a316577d1e
5 changed files with 85 additions and 12 deletions
|
|
@ -352,6 +352,7 @@ pub struct Grid {
|
||||||
pub sixel_scrolling: bool, // DECSDM
|
pub sixel_scrolling: bool, // DECSDM
|
||||||
pub insert_mode: bool,
|
pub insert_mode: bool,
|
||||||
pub disable_linewrap: bool,
|
pub disable_linewrap: bool,
|
||||||
|
pub new_line_mode: bool, // Automatic newline LNM
|
||||||
pub clear_viewport_before_rendering: bool,
|
pub clear_viewport_before_rendering: bool,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
|
|
@ -478,6 +479,7 @@ impl Grid {
|
||||||
sixel_scrolling: false,
|
sixel_scrolling: false,
|
||||||
insert_mode: false,
|
insert_mode: false,
|
||||||
disable_linewrap: false,
|
disable_linewrap: false,
|
||||||
|
new_line_mode: false,
|
||||||
alternate_screen_state: None,
|
alternate_screen_state: None,
|
||||||
clear_viewport_before_rendering: false,
|
clear_viewport_before_rendering: false,
|
||||||
active_charset: Default::default(),
|
active_charset: Default::default(),
|
||||||
|
|
@ -1515,6 +1517,7 @@ impl Grid {
|
||||||
self.active_charset = Default::default();
|
self.active_charset = Default::default();
|
||||||
self.erasure_mode = false;
|
self.erasure_mode = false;
|
||||||
self.disable_linewrap = false;
|
self.disable_linewrap = false;
|
||||||
|
self.new_line_mode = false;
|
||||||
self.cursor.change_shape(CursorShape::Initial);
|
self.cursor.change_shape(CursorShape::Initial);
|
||||||
self.output_buffer.update_all_lines();
|
self.output_buffer.update_all_lines();
|
||||||
self.changed_colors = None;
|
self.changed_colors = None;
|
||||||
|
|
@ -2350,8 +2353,18 @@ impl Perform for Grid {
|
||||||
_ => {},
|
_ => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if let Some(4) = params_iter.next().map(|param| param[0]) {
|
} else {
|
||||||
self.insert_mode = false;
|
for param in params_iter.map(|param| param[0]) {
|
||||||
|
match param {
|
||||||
|
4 => {
|
||||||
|
self.insert_mode = false;
|
||||||
|
},
|
||||||
|
20 => {
|
||||||
|
self.new_line_mode = false;
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if c == 'h' {
|
} else if c == 'h' {
|
||||||
let first_intermediate_is_questionmark = match intermediates.get(0) {
|
let first_intermediate_is_questionmark = match intermediates.get(0) {
|
||||||
|
|
@ -2434,8 +2447,18 @@ impl Perform for Grid {
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(4) = params_iter.next().map(|param| param[0]) {
|
} else {
|
||||||
self.insert_mode = true;
|
for param in params_iter.map(|param| param[0]) {
|
||||||
|
match param {
|
||||||
|
4 => {
|
||||||
|
self.insert_mode = true;
|
||||||
|
},
|
||||||
|
20 => {
|
||||||
|
self.new_line_mode = true;
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if c == 'r' {
|
} else if c == 'r' {
|
||||||
if params.len() > 1 {
|
if params.len() > 1 {
|
||||||
|
|
@ -2602,8 +2625,8 @@ impl Perform for Grid {
|
||||||
// https://vt100.net/docs/vt510-rm/DA1.html
|
// https://vt100.net/docs/vt510-rm/DA1.html
|
||||||
match intermediates.get(0) {
|
match intermediates.get(0) {
|
||||||
None | Some(0) => {
|
None | Some(0) => {
|
||||||
// primary device attributes
|
// primary device attributes - VT220 with sixel
|
||||||
let terminal_capabilities = "\u{1b}[?64;4c";
|
let terminal_capabilities = "\u{1b}[?62;4c";
|
||||||
self.pending_messages_to_pty
|
self.pending_messages_to_pty
|
||||||
.push(terminal_capabilities.as_bytes().to_vec());
|
.push(terminal_capabilities.as_bytes().to_vec());
|
||||||
},
|
},
|
||||||
|
|
@ -2627,13 +2650,41 @@ impl Perform for Grid {
|
||||||
},
|
},
|
||||||
6 => {
|
6 => {
|
||||||
// CPR - cursor position report
|
// CPR - cursor position report
|
||||||
let position_report =
|
|
||||||
format!("\x1b[{};{}R", self.cursor.y + 1, self.cursor.x + 1);
|
// Note that this is relative to scrolling region.
|
||||||
|
let offset = match self.scroll_region {
|
||||||
|
Some((scroll_region_top, _scroll_region_bottom)) => scroll_region_top,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
let position_report = format!(
|
||||||
|
"\u{1b}[{};{}R",
|
||||||
|
self.cursor.y + 1 - offset,
|
||||||
|
self.cursor.x + 1
|
||||||
|
);
|
||||||
self.pending_messages_to_pty
|
self.pending_messages_to_pty
|
||||||
.push(position_report.as_bytes().to_vec());
|
.push(position_report.as_bytes().to_vec());
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
} else if c == 'x' {
|
||||||
|
// DECREQTPARM - Request Terminal Parameters
|
||||||
|
// https://vt100.net/docs/vt100-ug/chapter3.html#DECREQTPARM
|
||||||
|
//
|
||||||
|
// Respond with (same as xterm): Parity NONE, 8 bits,
|
||||||
|
// xmitspeed 38400, recvspeed 38400. (CLoCk MULtiplier =
|
||||||
|
// 1, STP option flags = 0)
|
||||||
|
//
|
||||||
|
// (xterm used to respond to DECREQTPARM in all modes.
|
||||||
|
// Now it seems to only do so when explicitly in VT100 mode.)
|
||||||
|
let query = next_param_or(0);
|
||||||
|
match query {
|
||||||
|
0 | 1 => {
|
||||||
|
let response = format!("\u{1b}[{};1;1;128;128;1;0x", query + 2);
|
||||||
|
self.pending_messages_to_pty
|
||||||
|
.push(response.as_bytes().to_vec());
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
} else if c == 't' {
|
} else if c == 't' {
|
||||||
match next_param_or(1) as usize {
|
match next_param_or(1) as usize {
|
||||||
14 => {
|
14 => {
|
||||||
|
|
@ -2678,6 +2729,19 @@ impl Perform for Grid {
|
||||||
|
|
||||||
fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, byte: u8) {
|
fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, byte: u8) {
|
||||||
match (byte, intermediates.get(0)) {
|
match (byte, intermediates.get(0)) {
|
||||||
|
(b'A', charset_index_symbol) => {
|
||||||
|
let charset_index: CharsetIndex = match charset_index_symbol {
|
||||||
|
Some(b'(') => CharsetIndex::G0,
|
||||||
|
Some(b')') => CharsetIndex::G1,
|
||||||
|
Some(b'*') => CharsetIndex::G2,
|
||||||
|
Some(b'+') => CharsetIndex::G3,
|
||||||
|
_ => {
|
||||||
|
// invalid, silently do nothing
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.configure_charset(StandardCharset::UK, charset_index);
|
||||||
|
},
|
||||||
(b'B', charset_index_symbol) => {
|
(b'B', charset_index_symbol) => {
|
||||||
let charset_index: CharsetIndex = match charset_index_symbol {
|
let charset_index: CharsetIndex = match charset_index_symbol {
|
||||||
Some(b'(') => CharsetIndex::G0,
|
Some(b'(') => CharsetIndex::G0,
|
||||||
|
|
|
||||||
|
|
@ -586,6 +586,7 @@ impl Default for CharsetIndex {
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum StandardCharset {
|
pub enum StandardCharset {
|
||||||
Ascii,
|
Ascii,
|
||||||
|
UK,
|
||||||
SpecialCharacterAndLineDrawing,
|
SpecialCharacterAndLineDrawing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -602,6 +603,10 @@ impl StandardCharset {
|
||||||
pub fn map(self, c: char) -> char {
|
pub fn map(self, c: char) -> char {
|
||||||
match self {
|
match self {
|
||||||
StandardCharset::Ascii => c,
|
StandardCharset::Ascii => c,
|
||||||
|
StandardCharset::UK => match c {
|
||||||
|
'#' => '£',
|
||||||
|
_ => c,
|
||||||
|
},
|
||||||
StandardCharset::SpecialCharacterAndLineDrawing => match c {
|
StandardCharset::SpecialCharacterAndLineDrawing => match c {
|
||||||
'`' => '◆',
|
'`' => '◆',
|
||||||
'a' => '▒',
|
'a' => '▒',
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,12 @@ impl Pane for TerminalPane {
|
||||||
// needs to be adjusted.
|
// needs to be adjusted.
|
||||||
// here we match against those cases - if need be, we adjust the input and if not
|
// here we match against those cases - if need be, we adjust the input and if not
|
||||||
// we send back the original input
|
// we send back the original input
|
||||||
|
if self.grid.new_line_mode {
|
||||||
|
if let &[13] = input_bytes.as_slice() {
|
||||||
|
// LNM - carriage return is followed by linefeed
|
||||||
|
return "\u{0d}\u{0a}".as_bytes().to_vec();
|
||||||
|
};
|
||||||
|
}
|
||||||
if self.grid.cursor_key_mode {
|
if self.grid.cursor_key_mode {
|
||||||
match input_bytes.as_slice() {
|
match input_bytes.as_slice() {
|
||||||
LEFT_ARROW => {
|
LEFT_ARROW => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/panes/./unit/grid_tests.rs
|
source: zellij-server/src/panes/./unit/grid_tests.rs
|
||||||
assertion_line: 721
|
|
||||||
expression: "format!(\"{:?}\", grid.pending_messages_to_pty)"
|
expression: "format!(\"{:?}\", grid.pending_messages_to_pty)"
|
||||||
---
|
---
|
||||||
[[27, 91, 63, 54, 52, 59, 52, 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]]
|
[[27, 91, 63, 54, 50, 59, 52, 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]]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/panes/./unit/grid_tests.rs
|
source: zellij-server/src/panes/./unit/grid_tests.rs
|
||||||
expression: "format!(\"{:?}\", grid)"
|
expression: "format!(\"{:?}\", grid)"
|
||||||
|
|
||||||
---
|
---
|
||||||
00 (C): Selected as G0 (with SI) Selected as G1 (with SO)
|
00 (C): Selected as G0 (with SI) Selected as G1 (with SO)
|
||||||
01 (C):
|
01 (C):
|
||||||
|
|
@ -10,7 +9,7 @@ expression: "format!(\"{:?}\", grid)"
|
||||||
04 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
|
04 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
|
||||||
05 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~
|
05 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~
|
||||||
06 (C): Character set A (British)
|
06 (C): Character set A (British)
|
||||||
07 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>?
|
07 (C): !"£$%&'()*+,-./0123456789:;<=>? !"£$%&'()*+,-./0123456789:;<=>?
|
||||||
08 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
|
08 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
|
||||||
09 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~
|
09 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~
|
||||||
10 (C): Character set 0 (DEC Special graphics and line drawing)
|
10 (C): Character set 0 (DEC Special graphics and line drawing)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue