From 63ad28930fddfdf8784d250857a430faf406f8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Mon, 16 Dec 2024 21:59:28 +0800 Subject: [PATCH] fix: use a less intrusive `DSR` instead of `DA1` workaround to forward terminal responses twice in tmux (#2058) --- yazi-adapter/src/emulator.rs | 29 +++++++++++++++++++++++++++++ yazi-adapter/src/mux.rs | 11 ++++++++++- yazi-fm/src/term.rs | 2 ++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/yazi-adapter/src/emulator.rs b/yazi-adapter/src/emulator.rs index 5a80c0cf8..9f535a44e 100644 --- a/yazi-adapter/src/emulator.rs +++ b/yazi-adapter/src/emulator.rs @@ -47,6 +47,8 @@ impl Emulator { )?; let resp = futures::executor::block_on(Self::read_until_da1()); + Mux::tmux_drain()?; + let kind = if let Some(brand) = Brand::from_csi(&resp) { Either::Left(brand) } else { @@ -130,6 +132,31 @@ impl Emulator { String::from_utf8_lossy(&buf).into_owned() } + pub async fn read_until_dsr() -> String { + let mut buf: Vec = Vec::with_capacity(200); + let read = async { + let mut stdin = BufReader::new(tokio::io::stdin()); + loop { + let mut c = [0; 1]; + if stdin.read(&mut c).await? == 0 { + bail!("unexpected EOF"); + } + buf.push(c[0]); + if c[0] == b'n' && (buf.ends_with(b"\x1b[0n") || buf.ends_with(b"\x1b[3n")) { + break; + } + } + Ok(()) + }; + + match timeout(Duration::from_secs(10), read).await { + Err(e) => error!("read_until_dsr timed out: {buf:?}, error: {e:?}"), + Ok(Err(e)) => error!("read_until_dsr failed: {buf:?}, error: {e:?}"), + Ok(Ok(())) => debug!("read_until_dsr: {buf:?}"), + } + String::from_utf8_lossy(&buf).into_owned() + } + fn detect_base() -> Result { defer! { disable_raw_mode().ok(); } enable_raw_mode()?; @@ -142,6 +169,8 @@ impl Emulator { )?; let resp = futures::executor::block_on(Self::read_until_da1()); + Mux::tmux_drain()?; + Ok(Self { light: Self::light_bg(&resp).unwrap_or_default(), cell_size: Self::cell_size(&resp), diff --git a/yazi-adapter/src/mux.rs b/yazi-adapter/src/mux.rs index a8a1cdd55..3ebd1d517 100644 --- a/yazi-adapter/src/mux.rs +++ b/yazi-adapter/src/mux.rs @@ -1,7 +1,8 @@ +use anyhow::Result; use tracing::error; use yazi_shared::env_exists; -use crate::{CLOSE, ESCAPE, NVIM, START, TMUX}; +use crate::{CLOSE, ESCAPE, Emulator, NVIM, START, TMUX}; pub struct Mux; @@ -47,6 +48,14 @@ impl Mux { 1 } + pub fn tmux_drain() -> Result<()> { + if *TMUX == 2 && !*NVIM { + crossterm::execute!(std::io::stderr(), crossterm::style::Print(Mux::csi("\x1b[5n")))?; + _ = futures::executor::block_on(Emulator::read_until_dsr()); + } + Ok(()) + } + pub fn tmux_sixel_flag() -> &'static str { let stdout = std::process::Command::new("tmux") .args(["-LwU0dju1is5", "-f/dev/null", "start", ";", "display", "-p", "#{sixel_support}"]) diff --git a/yazi-fm/src/term.rs b/yazi-fm/src/term.rs index 81f0fa547..8598ad619 100644 --- a/yazi-fm/src/term.rs +++ b/yazi-fm/src/term.rs @@ -42,6 +42,8 @@ impl Term { )?; let da = futures::executor::block_on(Emulator::read_until_da1()); + Mux::tmux_drain()?; + CSI_U.store(da.contains("\x1b[?0u"), Ordering::Relaxed); BLINK.store(da.contains("\x1b[?12;1$y"), Ordering::Relaxed); SHAPE.store(