mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: detect CSI u through Stderr to allow using Stdout as the carrier of DDS payload without an ANSI sequence response timeout (#867)
This commit is contained in:
parent
b51babde1c
commit
ec83c5dc5c
16 changed files with 570 additions and 153 deletions
588
Cargo.lock
generated
588
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -14,15 +14,16 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
arc-swap = "1.7.0"
|
arc-swap = "1.7.1"
|
||||||
base64 = "0.22.0"
|
base64 = "0.22.0"
|
||||||
color_quant = "1.1.0"
|
color_quant = "1.1.0"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
image = "0.24.9"
|
futures = "0.3.30"
|
||||||
|
image = "0.25.1"
|
||||||
imagesize = "0.12.0"
|
imagesize = "0.12.0"
|
||||||
kamadak-exif = "0.5.5"
|
kamadak-exif = "0.5.5"
|
||||||
ratatui = "0.26.1"
|
ratatui = "0.26.1"
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::{env, io::{stderr, LineWriter, Read}};
|
use std::{env, io::{stderr, LineWriter}};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use crossterm::{cursor::{RestorePosition, SavePosition}, execute, style::Print, terminal::{disable_raw_mode, enable_raw_mode}};
|
use crossterm::{cursor::{RestorePosition, SavePosition}, execute, style::Print, terminal::{disable_raw_mode, enable_raw_mode}};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use yazi_shared::env_exists;
|
use yazi_shared::{env_exists, term::Term};
|
||||||
|
|
||||||
use crate::{Adaptor, TMUX};
|
use crate::{Adaptor, TMUX};
|
||||||
|
|
||||||
|
|
@ -120,20 +120,9 @@ impl Emulator {
|
||||||
RestorePosition
|
RestorePosition
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut stdin = std::io::stdin().lock();
|
let resp = futures::executor::block_on(Term::read_until_da1())?;
|
||||||
let mut buf = String::with_capacity(200);
|
|
||||||
loop {
|
|
||||||
let mut c = [0; 1];
|
|
||||||
if stdin.read(&mut c)? == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if c[0] == b'c' && buf.contains("\x1b[?") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf.push(c[0] as char);
|
|
||||||
}
|
|
||||||
|
|
||||||
disable_raw_mode().ok();
|
disable_raw_mode().ok();
|
||||||
|
|
||||||
let names = [
|
let names = [
|
||||||
("kitty", Self::Kitty),
|
("kitty", Self::Kitty),
|
||||||
("Konsole", Self::Konsole),
|
("Konsole", Self::Konsole),
|
||||||
|
|
@ -144,16 +133,16 @@ impl Emulator {
|
||||||
];
|
];
|
||||||
|
|
||||||
for (name, emulator) in names.iter() {
|
for (name, emulator) in names.iter() {
|
||||||
if buf.contains(name) {
|
if resp.contains(name) {
|
||||||
return Ok(emulator.clone());
|
return Ok(emulator.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut adapters = Vec::with_capacity(2);
|
let mut adapters = Vec::with_capacity(2);
|
||||||
if buf.contains("\x1b_Gi=31;OK") {
|
if resp.contains("\x1b_Gi=31;OK") {
|
||||||
adapters.push(Adaptor::KittyOld);
|
adapters.push(Adaptor::KittyOld);
|
||||||
}
|
}
|
||||||
if ["?4;", "?4c", ";4;", ";4c"].iter().any(|s| buf.contains(s)) {
|
if ["?4;", "?4c", ";4;", ";4c"].iter().any(|s| resp.contains(s)) {
|
||||||
adapters.push(Adaptor::Sixel);
|
adapters.push(Adaptor::Sixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ impl Image {
|
||||||
img.as_bytes(),
|
img.as_bytes(),
|
||||||
img.width(),
|
img.width(),
|
||||||
img.height(),
|
img.height(),
|
||||||
img.color(),
|
img.color().into(),
|
||||||
)?;
|
)?;
|
||||||
Ok::<_, anyhow::Error>(buf)
|
Ok::<_, anyhow::Error>(buf)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ yazi-config = { path = "../yazi-config", version = "0.2.4" }
|
||||||
yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
clap = { version = "4.5.3", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
serde = { version = "1.0.197", features = [ "derive" ] }
|
serde = { version = "1.0.197", features = [ "derive" ] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "4.5.3", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
clap_complete = "4.5.1"
|
clap_complete = "4.5.1"
|
||||||
clap_complete_nushell = "4.5.1"
|
clap_complete_nushell = "4.5.1"
|
||||||
clap_complete_fig = "4.5.0"
|
clap_complete_fig = "4.5.0"
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
arc-swap = "1.7.0"
|
arc-swap = "1.7.1"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
glob = "0.3.1"
|
glob = "0.3.1"
|
||||||
indexmap = "2.2.5"
|
indexmap = "2.2.6"
|
||||||
md-5 = "0.10.6"
|
md-5 = "0.10.6"
|
||||||
ratatui = "0.26.1"
|
ratatui = "0.26.1"
|
||||||
serde = { version = "1.0.197", features = [ "derive" ] }
|
serde = { version = "1.0.197", features = [ "derive" ] }
|
||||||
shell-words = "1.1.0"
|
shell-words = "1.1.0"
|
||||||
toml = { version = "0.8.11", features = [ "preserve_order" ] }
|
toml = { version = "0.8.12", features = [ "preserve_order" ] }
|
||||||
validator = { version = "0.17.0", features = [ "derive" ] }
|
validator = { version = "0.17.0", features = [ "derive" ] }
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,16 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
base64 = "0.22.0"
|
base64 = "0.22.0"
|
||||||
bitflags = "2.4.2"
|
bitflags = "2.5.0"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
indexmap = "2.2.5"
|
indexmap = "2.2.6"
|
||||||
notify = { version = "6.1.1", default-features = false, features = [ "macos_fsevent" ] }
|
notify = { version = "6.1.1", default-features = false, features = [ "macos_fsevent" ] }
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
ratatui = "0.26.1"
|
ratatui = "0.26.1"
|
||||||
regex = "1.10.3"
|
regex = "1.10.4"
|
||||||
serde = "1.0.197"
|
serde = "1.0.197"
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
tokio-stream = "0.1.15"
|
tokio-stream = "0.1.15"
|
||||||
tokio-util = "0.7.10"
|
tokio-util = "0.7.10"
|
||||||
unicode-width = "0.1.11"
|
unicode-width = "0.1.11"
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ anyhow = "1.0.81"
|
||||||
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
|
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
serde = { version = "1.0.197", features = [ "derive" ] }
|
serde = { version = "1.0.197", features = [ "derive" ] }
|
||||||
serde_json = "1.0.114"
|
serde_json = "1.0.115"
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ futures = "0.3.30"
|
||||||
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
|
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
|
||||||
ratatui = "0.26.1"
|
ratatui = "0.26.1"
|
||||||
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
tokio-util = "0.7.10"
|
tokio-util = "0.7.10"
|
||||||
unicode-width = "0.1.11"
|
unicode-width = "0.1.11"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
# External dependencies
|
# External dependencies
|
||||||
ansi-to-tui = "3.1.0"
|
ansi-to-tui = "3.1.0"
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
arc-swap = "1.7.0"
|
arc-swap = "1.7.1"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
md-5 = "0.10.6"
|
md-5 = "0.10.6"
|
||||||
|
|
@ -27,15 +27,17 @@ mlua = { version = "0.9.6", features = [ "lua54", "vendored", "serializ
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
ratatui = "0.26.1"
|
ratatui = "0.26.1"
|
||||||
serde = "1.0.197"
|
serde = "1.0.197"
|
||||||
serde_json = "1.0.114"
|
serde_json = "1.0.115"
|
||||||
shell-escape = "0.1.5"
|
shell-escape = "0.1.5"
|
||||||
shell-words = "1.1.0"
|
shell-words = "1.1.0"
|
||||||
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
tokio-util = "0.7.10"
|
tokio-util = "0.7.10"
|
||||||
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
|
||||||
unicode-width = "0.1.11"
|
unicode-width = "0.1.11"
|
||||||
yazi-prebuild = "0.1.2"
|
yazi-prebuild = "0.1.2"
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
uzers = "0.11.3"
|
uzers = "0.11.3"
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,4 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
|
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ base64 = "0.22.0"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
regex = "1.10.3"
|
regex = "1.10.4"
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
tokio-stream = "0.1.15"
|
tokio-stream = "0.1.15"
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
|
|
@ -34,4 +34,4 @@ tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_lev
|
||||||
libc = "0.2.153"
|
libc = "0.2.153"
|
||||||
|
|
||||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||||
trash = "4.0.0"
|
trash = "4.1.0"
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,19 @@ repository = "https://github.com/sxyazi/yazi"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
bitflags = "2.4.2"
|
bitflags = "2.5.0"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
percent-encoding = "2.3.1"
|
percent-encoding = "2.3.1"
|
||||||
ratatui = "0.26.1"
|
ratatui = "0.26.1"
|
||||||
regex = "1.10.3"
|
regex = "1.10.4"
|
||||||
serde = "1.0.197"
|
serde = "1.0.197"
|
||||||
tokio = { version = "1.36.0", features = [ "full" ] }
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
libc = "0.2.153"
|
libc = "0.2.153"
|
||||||
|
|
|
||||||
34
yazi-shared/src/term/csi_u.rs
Normal file
34
yazi-shared/src/term/csi_u.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use tokio::{io::{stdin, AsyncReadExt, BufReader}, time::timeout};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use super::Term;
|
||||||
|
|
||||||
|
impl Term {
|
||||||
|
pub async fn read_until_da1() -> Result<String> {
|
||||||
|
let read = async {
|
||||||
|
let mut stdin = BufReader::new(stdin());
|
||||||
|
let mut buf = String::with_capacity(200);
|
||||||
|
loop {
|
||||||
|
let mut c = [0; 1];
|
||||||
|
if stdin.read(&mut c).await? == 0 {
|
||||||
|
bail!("unexpected EOF");
|
||||||
|
}
|
||||||
|
if c[0] == b'c' && buf.contains("\x1b[?") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf.push(c[0] as char);
|
||||||
|
}
|
||||||
|
Ok(buf)
|
||||||
|
};
|
||||||
|
|
||||||
|
let timeout = timeout(Duration::from_secs(10), read).await;
|
||||||
|
if let Err(ref e) = timeout {
|
||||||
|
error!("read_until_da1: {e:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
|
mod csi_u;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod term;
|
mod term;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{io::{self, stderr, BufWriter, Stderr, Write}, mem, ops::{Deref, DerefMut}, sync::atomic::{AtomicBool, Ordering}};
|
use std::{io::{self, stderr, BufWriter, Stderr, Write}, mem, ops::{Deref, DerefMut}, sync::atomic::{AtomicBool, Ordering}};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use crossterm::{event::{DisableBracketedPaste, DisableFocusChange, EnableBracketedPaste, EnableFocusChange, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, execute, queue, terminal::{disable_raw_mode, enable_raw_mode, supports_keyboard_enhancement, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen, WindowSize}};
|
use crossterm::{cursor::{RestorePosition, SavePosition}, event::{DisableBracketedPaste, DisableFocusChange, EnableBracketedPaste, EnableFocusChange, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, execute, queue, style::Print, terminal::{disable_raw_mode, enable_raw_mode, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen, WindowSize}};
|
||||||
use ratatui::{backend::CrosstermBackend, buffer::Buffer, layout::Rect, CompletedFrame, Frame, Terminal};
|
use ratatui::{backend::CrosstermBackend, buffer::Buffer, layout::Rect, CompletedFrame, Frame, Terminal};
|
||||||
|
|
||||||
static CSI_U: AtomicBool = AtomicBool::new(false);
|
static CSI_U: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
@ -21,9 +21,18 @@ impl Term {
|
||||||
};
|
};
|
||||||
|
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
queue!(stderr(), EnterAlternateScreen, EnableBracketedPaste, EnableFocusChange)?;
|
execute!(
|
||||||
|
BufWriter::new(stderr()),
|
||||||
|
EnterAlternateScreen,
|
||||||
|
EnableBracketedPaste,
|
||||||
|
EnableFocusChange,
|
||||||
|
SavePosition,
|
||||||
|
Print("\x1b[?u\x1b[c"),
|
||||||
|
RestorePosition
|
||||||
|
)?;
|
||||||
|
|
||||||
if let Ok(true) = supports_keyboard_enhancement() {
|
let resp = futures::executor::block_on(Self::read_until_da1());
|
||||||
|
if resp.is_ok_and(|s| s.contains("\x1b[?0u")) {
|
||||||
queue!(
|
queue!(
|
||||||
stderr(),
|
stderr(),
|
||||||
PushKeyboardEnhancementFlags(
|
PushKeyboardEnhancementFlags(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue