diff --git a/yazi-tty/src/tty.rs b/yazi-tty/src/tty.rs index d55f5118..91dfa582 100644 --- a/yazi-tty/src/tty.rs +++ b/yazi-tty/src/tty.rs @@ -58,4 +58,32 @@ impl Tty { let result = read(); (buf, result) } + + pub fn drain_until_quiet(&self, timeout: Duration, quiet: Duration) -> std::io::Result { + let mut drained = 0; + let until = Instant::now() + timeout; + let mut stdin = self.stdin.lock(); + + while Instant::now() < until { + match stdin.poll(quiet) { + Ok(true) => {} + Ok(false) => break, + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + } + + let mut b = [0u8]; + loop { + match stdin.read_exact(&mut b) { + Ok(()) => { + drained += 1; + break; + } + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + } + } + } + Ok(drained) + } } diff --git a/yazi-tui/src/raterm.rs b/yazi-tui/src/raterm.rs index 1fd82217..af4fe176 100644 --- a/yazi-tui/src/raterm.rs +++ b/yazi-tui/src/raterm.rs @@ -1,4 +1,4 @@ -use std::{io::{self, Write}, ops::Deref}; +use std::{io::{self, Write}, ops::Deref, time::Duration}; use anyhow::Result; use ratatui::{CompletedFrame, Frame, Terminal, buffer::Buffer, layout::Rect}; @@ -63,7 +63,15 @@ impl Raterm { let mut term = Self { inner: Terminal::new(RatermBackend::new(TTY.writer()))?, - stream: EventStream::from(&*TERM), + stream: { + if TMUX.get() { + // tmux passthrough can deliver terminal query replies out of order. + // Keep them out of EventStream, where DCS/CSI payload bytes + // such as `r`, `f`, or `z` are indistinguishable from keys. + let _ = TTY.drain_until_quiet(Duration::from_millis(1000), Duration::from_millis(100)); + } + EventStream::from(&*TERM) + }, last_area: Default::default(), last_buffer: Default::default(), };