diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index 13c11e93..df8a36df 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -4,8 +4,6 @@ on: push: branches: [main] tags: ["v[0-9]+.[0-9]+.[0-9]+"] - schedule: - - cron: "0 */6 * * *" workflow_dispatch: env: diff --git a/Cargo.lock b/Cargo.lock index 2e9b225e..38287a6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arbitrary" @@ -366,9 +366,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -376,9 +376,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -429,9 +429,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -777,9 +777,9 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -2562,9 +2562,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -2585,9 +2585,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -2605,9 +2605,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -2634,9 +2634,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -2645,9 +2645,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", diff --git a/Cargo.toml b/Cargo.toml index fdcfbbff..ac6ad943 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,10 @@ strip = true [workspace.dependencies] ansi-to-tui = "7.0.0" -anyhow = "1.0.93" +anyhow = "1.0.94" base64 = "0.22.1" bitflags = "2.6.0" -clap = { version = "4.5.21", features = [ "derive" ] } +clap = { version = "4.5.23", features = [ "derive" ] } crossterm = { version = "0.28.1", features = [ "event-stream" ] } dirs = "5.0.1" futures = "0.3.31" @@ -29,9 +29,9 @@ scopeguard = "1.2.0" serde = { version = "1.0.215", features = [ "derive" ] } serde_json = "1.0.133" shell-words = "1.1.0" -tokio = { version = "1.41.1", features = [ "full" ] } -tokio-stream = "0.1.16" -tokio-util = "0.7.12" +tokio = { version = "1.42.0", features = [ "full" ] } +tokio-stream = "0.1.17" +tokio-util = "0.7.13" tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] } unicode-width = "0.2.0" uzers = "0.12.1" diff --git a/yazi-adapter/src/dimension.rs b/yazi-adapter/src/dimension.rs index 837fc8a2..57d52037 100644 --- a/yazi-adapter/src/dimension.rs +++ b/yazi-adapter/src/dimension.rs @@ -2,6 +2,8 @@ use std::mem; use crossterm::terminal::WindowSize; +use crate::EMULATOR; + pub struct Dimension; impl Dimension { @@ -27,9 +29,10 @@ impl Dimension { #[inline] pub fn ratio() -> Option<(f64, f64)> { let s = Self::available(); - if s.width == 0 || s.height == 0 { - return None; - } - Some((f64::from(s.width) / f64::from(s.columns), f64::from(s.height) / f64::from(s.rows))) + Some(if s.width == 0 || s.height == 0 { + (EMULATOR.cell_size?.0 as f64, EMULATOR.cell_size?.1 as f64) + } else { + (f64::from(s.width) / f64::from(s.columns), f64::from(s.height) / f64::from(s.rows)) + }) } } diff --git a/yazi-adapter/src/emulator.rs b/yazi-adapter/src/emulator.rs index d6fca8ca..1db370d2 100644 --- a/yazi-adapter/src/emulator.rs +++ b/yazi-adapter/src/emulator.rs @@ -11,18 +11,21 @@ use crate::{Adapter, Brand, Mux, TMUX, Unknown}; #[derive(Clone, Copy, Debug)] pub struct Emulator { - pub kind: Either, - pub light: bool, + pub kind: Either, + pub light: bool, + pub cell_size: Option<(u16, u16)>, } impl Default for Emulator { - fn default() -> Self { Self { kind: Either::Right(Unknown::default()), light: false } } + fn default() -> Self { + Self { kind: Either::Right(Unknown::default()), light: false, cell_size: None } + } } impl Emulator { pub fn detect() -> Self { if let Some(brand) = Brand::from_env() { - Self { kind: Either::Left(brand), light: Self::detect_base().unwrap_or_default().light } + Self { kind: Either::Left(brand), ..Self::detect_base().unwrap_or_default() } } else { Self::detect_full().unwrap_or_default() } @@ -37,6 +40,7 @@ impl Emulator { SavePosition, Print(Mux::csi("\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\")), // Detect KGP Print(Mux::csi("\x1b[>q")), // Request terminal version + Print("\x1b[16t"), // Request cell size Print("\x1b]11;?\x07"), // Request background color Print(Mux::csi("\x1b[0c")), // Request device attributes RestorePosition @@ -52,7 +56,11 @@ impl Emulator { }) }; - Ok(Self { kind, light: Self::light_bg(&resp).unwrap_or_default() }) + Ok(Self { + kind, + light: Self::light_bg(&resp).unwrap_or_default(), + cell_size: Self::cell_size(&resp), + }) } pub fn adapters(self) -> &'static [Adapter] { @@ -117,7 +125,7 @@ impl Emulator { match timeout(Duration::from_secs(10), read).await { Err(e) => error!("read_until_da1 timed out: {buf:?}, error: {e:?}"), Ok(Err(e)) => error!("read_until_da1 failed: {buf:?}, error: {e:?}"), - Ok(Ok(())) => {} + Ok(Ok(())) => debug!("read_until_da1: {buf:?}"), } String::from_utf8_lossy(&buf).into_owned() } @@ -128,12 +136,30 @@ impl Emulator { execute!( LineWriter::new(stderr()), + Print("\x1b[16t"), // Request cell size Print("\x1b]11;?\x07"), // Request background color Print(Mux::csi("\x1b[0c")), // Request device attributes )?; let resp = futures::executor::block_on(Self::read_until_da1()); - Ok(Self { light: Self::light_bg(&resp).unwrap_or_default(), ..Default::default() }) + Ok(Self { + light: Self::light_bg(&resp).unwrap_or_default(), + cell_size: Self::cell_size(&resp), + ..Default::default() + }) + } + + fn cell_size(resp: &str) -> Option<(u16, u16)> { + let b = resp.split_at(resp.find("\x1b[6;")? + 4).1.as_bytes(); + + let h: Vec<_> = b.iter().copied().take_while(|&c| c.is_ascii_digit()).collect(); + b.get(h.len()).filter(|&&c| c == b';')?; + + let w: Vec<_> = b[h.len() + 1..].iter().copied().take_while(|&c| c.is_ascii_digit()).collect(); + b.get(h.len() + 1 + w.len()).filter(|&&c| c == b't')?; + + let (w, h) = unsafe { (String::from_utf8_unchecked(w), String::from_utf8_unchecked(h)) }; + Some((w.parse().ok()?, h.parse().ok()?)) } fn light_bg(resp: &str) -> Result {