From 37f25e563499399c7645bcffb6f4e47bba749514 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 5 Dec 2021 21:55:56 -0500 Subject: add a binary to test vt100 state against a real terminal --- examples/real_terminal_compare.rs | 134 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 examples/real_terminal_compare.rs (limited to 'examples') diff --git a/examples/real_terminal_compare.rs b/examples/real_terminal_compare.rs new file mode 100644 index 0000000..e9ac92b --- /dev/null +++ b/examples/real_terminal_compare.rs @@ -0,0 +1,134 @@ +use std::io::{Read as _, Write as _}; +use std::os::unix::io::AsRawFd as _; + +#[path = "../tests/helpers/mod.rs"] +mod helpers; + +fn main() { + unsafe { helpers::QUIET = true } + + let mut stdin = std::io::stdin(); + let mut stdout = std::io::stdout(); + + let stdin_fd = std::io::stdin().as_raw_fd(); + let mut termios = nix::sys::termios::tcgetattr(stdin_fd).unwrap(); + nix::sys::termios::cfmakeraw(&mut termios); + nix::sys::termios::tcsetattr( + stdin_fd, + nix::sys::termios::SetArg::TCSANOW, + &termios, + ) + .unwrap(); + + let size = terminal_size::terminal_size().map_or( + (24, 80), + |(terminal_size::Width(w), terminal_size::Height(h))| (h, w), + ); + + let file = std::env::args_os().nth(1).unwrap(); + let mut fh = std::fs::File::open(file).unwrap(); + + let mut log = std::fs::File::create("compare.log").unwrap(); + macro_rules! log { + ($out:expr) => { + log.write_all($out).unwrap(); + log.flush().unwrap(); + }; + } + + stdout.write_all(b"\x1b[H\x1b[J").unwrap(); + stdout.flush().unwrap(); + + let mut parser = vt100::Parser::new(size.0, size.1, 0); + let mut buf = [0u8; 4096]; + let mut screen = parser.screen().clone(); + let mut idx = 0; + loop { + match fh.read(&mut buf) { + Ok(0) => break, + Ok(bytes) => { + for byte in &buf[..bytes] { + parser.process(&[*byte]); + let mut pos = parser.screen().cursor_position(); + if pos.1 == size.1 { + pos.1 -= 1; + } + if helpers::compare_screens(parser.screen(), &screen) { + log!(format!( + "{}: {}: ({}, {})\n", + idx, byte, pos.0, pos.1, + ) + .as_bytes()); + } else { + let diff = parser.screen().state_diff(&screen); + stdout.write_all(&diff).unwrap(); + stdout.write_all(b"\x1b[6n").unwrap(); + stdout.flush().unwrap(); + + let mut buf = [0u8; 1]; + let mut n = 0; + let mut row: Option = None; + let col: Option; + loop { + match stdin.read(&mut buf) { + Ok(0) => panic!("stdin closed"), + Ok(1) => match buf[0] { + b'\x1b' | b'[' => {} + b'0'..=b'9' => { + let digit = (buf[0] - b'0') as u16; + n = n * 10 + digit; + } + b';' => { + row = Some(n - 1); + n = 0; + } + b'R' => { + col = Some(n - 1); + break; + } + _ => panic!("unexpected char {}", buf[0]), + }, + Ok(_) => unreachable!(), + Err(e) => panic!("{}", e), + } + } + + let row = row.unwrap(); + let mut col = col.unwrap(); + if col == size.1 { + col -= 1; + } + + log!(format!( + "{}: {}: ({}, {}): wrote '{}', got ({}, {})\n", + idx, + byte, + pos.0, + pos.1, + helpers::format_bytes(&diff), + row, + col, + ) + .as_bytes()); + + if row != pos.0 || col != pos.1 { + panic!( + "unexpected cursor position at idx {} ({}): \ + vt100 was at ({}, {}) but the real terminal \ + was at ({}, {})", + idx, byte, pos.0, pos.1, row, col, + ); + } + + screen = parser.screen().clone(); + } + idx += 1; + } + } + Err(e) => { + eprintln!("{}", e); + std::process::exit(1); + } + } + } +} -- cgit v1.2.3-54-g00ecf