feat: detect CSI u through Stderr to allow using Stdout as the carrier of DDS payload without an ANSI sequence response timeout

This commit is contained in:
sxyazi 2024-04-02 20:11:45 +08:00
parent b51babde1c
commit 67d3470fa3
No known key found for this signature in database
16 changed files with 570 additions and 153 deletions

588
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

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

View file

@ -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);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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?
}
}

View file

@ -1,5 +1,6 @@
#![allow(clippy::module_inception)] #![allow(clippy::module_inception)]
mod csi_u;
mod cursor; mod cursor;
mod term; mod term;

View file

@ -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()).unwrap_or_default();
if resp.contains("\x1b[?0u") {
queue!( queue!(
stderr(), stderr(),
PushKeyboardEnhancementFlags( PushKeyboardEnhancementFlags(