Skip to content

Commit 63ad289

Browse files
authored
fix: use a less intrusive DSR instead of DA1 workaround to forward terminal responses twice in tmux (#2058)
1 parent c96b1d3 commit 63ad289

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

yazi-adapter/src/emulator.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ impl Emulator {
4747
)?;
4848

4949
let resp = futures::executor::block_on(Self::read_until_da1());
50+
Mux::tmux_drain()?;
51+
5052
let kind = if let Some(brand) = Brand::from_csi(&resp) {
5153
Either::Left(brand)
5254
} else {
@@ -130,6 +132,31 @@ impl Emulator {
130132
String::from_utf8_lossy(&buf).into_owned()
131133
}
132134

135+
pub async fn read_until_dsr() -> String {
136+
let mut buf: Vec<u8> = Vec::with_capacity(200);
137+
let read = async {
138+
let mut stdin = BufReader::new(tokio::io::stdin());
139+
loop {
140+
let mut c = [0; 1];
141+
if stdin.read(&mut c).await? == 0 {
142+
bail!("unexpected EOF");
143+
}
144+
buf.push(c[0]);
145+
if c[0] == b'n' && (buf.ends_with(b"\x1b[0n") || buf.ends_with(b"\x1b[3n")) {
146+
break;
147+
}
148+
}
149+
Ok(())
150+
};
151+
152+
match timeout(Duration::from_secs(10), read).await {
153+
Err(e) => error!("read_until_dsr timed out: {buf:?}, error: {e:?}"),
154+
Ok(Err(e)) => error!("read_until_dsr failed: {buf:?}, error: {e:?}"),
155+
Ok(Ok(())) => debug!("read_until_dsr: {buf:?}"),
156+
}
157+
String::from_utf8_lossy(&buf).into_owned()
158+
}
159+
133160
fn detect_base() -> Result<Self> {
134161
defer! { disable_raw_mode().ok(); }
135162
enable_raw_mode()?;
@@ -142,6 +169,8 @@ impl Emulator {
142169
)?;
143170

144171
let resp = futures::executor::block_on(Self::read_until_da1());
172+
Mux::tmux_drain()?;
173+
145174
Ok(Self {
146175
light: Self::light_bg(&resp).unwrap_or_default(),
147176
cell_size: Self::cell_size(&resp),

yazi-adapter/src/mux.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use anyhow::Result;
12
use tracing::error;
23
use yazi_shared::env_exists;
34

4-
use crate::{CLOSE, ESCAPE, NVIM, START, TMUX};
5+
use crate::{CLOSE, ESCAPE, Emulator, NVIM, START, TMUX};
56

67
pub struct Mux;
78

@@ -47,6 +48,14 @@ impl Mux {
4748
1
4849
}
4950

51+
pub fn tmux_drain() -> Result<()> {
52+
if *TMUX == 2 && !*NVIM {
53+
crossterm::execute!(std::io::stderr(), crossterm::style::Print(Mux::csi("\x1b[5n")))?;
54+
_ = futures::executor::block_on(Emulator::read_until_dsr());
55+
}
56+
Ok(())
57+
}
58+
5059
pub fn tmux_sixel_flag() -> &'static str {
5160
let stdout = std::process::Command::new("tmux")
5261
.args(["-LwU0dju1is5", "-f/dev/null", "start", ";", "display", "-p", "#{sixel_support}"])

yazi-fm/src/term.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ impl Term {
4242
)?;
4343

4444
let da = futures::executor::block_on(Emulator::read_until_da1());
45+
Mux::tmux_drain()?;
46+
4547
CSI_U.store(da.contains("\x1b[?0u"), Ordering::Relaxed);
4648
BLINK.store(da.contains("\x1b[?12;1$y"), Ordering::Relaxed);
4749
SHAPE.store(

0 commit comments

Comments
 (0)