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:
三咲雅 · Misaki Masa 2024-04-02 20:50:36 +08:00 committed by GitHub
parent b51babde1c
commit ec83c5dc5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
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
anyhow = "1.0.81"
arc-swap = "1.7.0"
arc-swap = "1.7.1"
base64 = "0.22.0"
color_quant = "1.1.0"
crossterm = "0.27.0"
image = "0.24.9"
futures = "0.3.30"
image = "0.25.1"
imagesize = "0.12.0"
kamadak-exif = "0.5.5"
ratatui = "0.26.1"
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" ] }

View File

@ -1,9 +1,9 @@
use std::{env, io::{stderr, LineWriter, Read}};
use std::{env, io::{stderr, LineWriter}};
use anyhow::{anyhow, Result};
use crossterm::{cursor::{RestorePosition, SavePosition}, execute, style::Print, terminal::{disable_raw_mode, enable_raw_mode}};
use tracing::warn;
use yazi_shared::env_exists;
use yazi_shared::{env_exists, term::Term};
use crate::{Adaptor, TMUX};
@ -120,20 +120,9 @@ impl Emulator {
RestorePosition
)?;
let mut stdin = std::io::stdin().lock();
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);
}
let resp = futures::executor::block_on(Term::read_until_da1())?;
disable_raw_mode().ok();
let names = [
("kitty", Self::Kitty),
("Konsole", Self::Konsole),
@ -144,16 +133,16 @@ impl Emulator {
];
for (name, emulator) in names.iter() {
if buf.contains(name) {
if resp.contains(name) {
return Ok(emulator.clone());
}
}
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);
}
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);
}

View File

@ -39,7 +39,7 @@ impl Image {
img.as_bytes(),
img.width(),
img.height(),
img.color(),
img.color().into(),
)?;
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" }
# External dependencies
clap = { version = "4.5.3", features = [ "derive" ] }
clap = { version = "4.5.4", features = [ "derive" ] }
serde = { version = "1.0.197", features = [ "derive" ] }
[build-dependencies]
clap = { version = "4.5.3", features = [ "derive" ] }
clap = { version = "4.5.4", features = [ "derive" ] }
clap_complete = "4.5.1"
clap_complete_nushell = "4.5.1"
clap_complete_fig = "4.5.0"

View File

@ -13,14 +13,14 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
# External dependencies
anyhow = "1.0.81"
arc-swap = "1.7.0"
arc-swap = "1.7.1"
crossterm = "0.27.0"
futures = "0.3.30"
glob = "0.3.1"
indexmap = "2.2.5"
indexmap = "2.2.6"
md-5 = "0.10.6"
ratatui = "0.26.1"
serde = { version = "1.0.197", features = [ "derive" ] }
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" ] }

View File

@ -21,16 +21,16 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
# External dependencies
anyhow = "1.0.81"
base64 = "0.22.0"
bitflags = "2.4.2"
bitflags = "2.5.0"
crossterm = "0.27.0"
futures = "0.3.30"
indexmap = "2.2.5"
indexmap = "2.2.6"
notify = { version = "6.1.1", default-features = false, features = [ "macos_fsevent" ] }
parking_lot = "0.12.1"
ratatui = "0.26.1"
regex = "1.10.3"
regex = "1.10.4"
serde = "1.0.197"
tokio = { version = "1.36.0", features = [ "full" ] }
tokio = { version = "1.37.0", features = [ "full" ] }
tokio-stream = "0.1.15"
tokio-util = "0.7.10"
unicode-width = "0.1.11"

View File

@ -17,8 +17,8 @@ anyhow = "1.0.81"
mlua = { version = "0.9.6", features = [ "lua54", "vendored" ] }
parking_lot = "0.12.1"
serde = { version = "1.0.197", features = [ "derive" ] }
serde_json = "1.0.114"
tokio = { version = "1.36.0", features = [ "full" ] }
serde_json = "1.0.115"
tokio = { version = "1.37.0", features = [ "full" ] }
# Logging
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" ] }
ratatui = "0.26.1"
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"
unicode-width = "0.1.11"

View File

@ -19,7 +19,7 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
# External dependencies
ansi-to-tui = "3.1.0"
anyhow = "1.0.81"
arc-swap = "1.7.0"
arc-swap = "1.7.1"
crossterm = "0.27.0"
futures = "0.3.30"
md-5 = "0.10.6"
@ -27,15 +27,17 @@ mlua = { version = "0.9.6", features = [ "lua54", "vendored", "serializ
parking_lot = "0.12.1"
ratatui = "0.26.1"
serde = "1.0.197"
serde_json = "1.0.114"
serde_json = "1.0.115"
shell-escape = "0.1.5"
shell-words = "1.1.0"
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"
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
unicode-width = "0.1.11"
yazi-prebuild = "0.1.2"
# Logging
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }
[target."cfg(unix)".dependencies]
uzers = "0.11.3"

View File

@ -15,4 +15,4 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.4" }
# External dependencies
anyhow = "1.0.81"
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"
futures = "0.3.30"
parking_lot = "0.12.1"
regex = "1.10.3"
tokio = { version = "1.36.0", features = [ "full" ] }
regex = "1.10.4"
tokio = { version = "1.37.0", features = [ "full" ] }
tokio-stream = "0.1.15"
# Logging
@ -34,4 +34,4 @@ tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_lev
libc = "0.2.153"
[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]
anyhow = "1.0.81"
bitflags = "2.4.2"
bitflags = "2.5.0"
crossterm = "0.27.0"
dirs = "5.0.1"
futures = "0.3.30"
parking_lot = "0.12.1"
percent-encoding = "2.3.1"
ratatui = "0.26.1"
regex = "1.10.3"
regex = "1.10.4"
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]
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)]
mod csi_u;
mod cursor;
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 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};
static CSI_U: AtomicBool = AtomicBool::new(false);
@ -21,9 +21,18 @@ impl Term {
};
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!(
stderr(),
PushKeyboardEnhancementFlags(