fix: use a less intrusive DSR instead of DA1 workaround to forward terminal responses twice in tmux (#2058)

This commit is contained in:
三咲雅 · Misaki Masa 2024-12-16 21:59:28 +08:00 committed by GitHub
parent c96b1d3aa1
commit 63ad28930f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 1 deletions

View file

@ -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<u8> = 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<Self> {
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),

View file

@ -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}"])

View file

@ -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(