aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-05 21:55:56 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-06 01:17:49 -0500
commit37f25e563499399c7645bcffb6f4e47bba749514 (patch)
tree3b72a70b96e463036672069cf2103cb9b17654d5 /examples
parent2e7a43fd0f68f4469927a032f5f77a52b664d276 (diff)
downloadvt100-rust-37f25e563499399c7645bcffb6f4e47bba749514.tar.gz
vt100-rust-37f25e563499399c7645bcffb6f4e47bba749514.zip
add a binary to test vt100 state against a real terminal
Diffstat (limited to 'examples')
-rw-r--r--examples/real_terminal_compare.rs134
1 files changed, 134 insertions, 0 deletions
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<u16> = None;
+ let col: Option<u16>;
+ 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);
+ }
+ }
+ }
+}