refactor: new yazi-tty crate (#3623)

This commit is contained in:
三咲雅 misaki masa 2026-01-27 22:03:48 +08:00 committed by GitHub
parent 6150571738
commit e0911f2507
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 293 additions and 131 deletions

171
Cargo.lock generated
View file

@ -583,6 +583,7 @@ dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-link",
]
@ -1002,6 +1003,16 @@ dependencies = [
"darling_macro 0.20.11",
]
[[package]]
name = "darling"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
dependencies = [
"darling_core 0.21.3",
"darling_macro 0.21.3",
]
[[package]]
name = "darling"
version = "0.23.0"
@ -1026,6 +1037,20 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "darling_core"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.114",
]
[[package]]
name = "darling_core"
version = "0.23.0"
@ -1050,6 +1075,17 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "darling_macro"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core 0.21.3",
"quote",
"syn 2.0.114",
]
[[package]]
name = "darling_macro"
version = "0.23.0"
@ -1134,6 +1170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
dependencies = [
"powerfmt",
"serde_core",
]
[[package]]
@ -1759,6 +1796,12 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.16.1"
@ -1938,6 +1981,17 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8"
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
"serde",
]
[[package]]
name = "indexmap"
version = "2.13.0"
@ -1945,7 +1999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.16.1",
"serde",
"serde_core",
]
@ -2091,7 +2145,7 @@ version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b"
dependencies = [
"hashbrown",
"hashbrown 0.16.1",
"portable-atomic",
"thiserror 2.0.18",
]
@ -2292,7 +2346,7 @@ version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593"
dependencies = [
"hashbrown",
"hashbrown 0.16.1",
]
[[package]]
@ -3097,7 +3151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
dependencies = [
"base64",
"indexmap",
"indexmap 2.13.0",
"quick-xml",
"serde",
"time",
@ -3380,7 +3434,7 @@ checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293"
dependencies = [
"bitflags 2.10.0",
"compact_str",
"hashbrown",
"hashbrown 0.16.1",
"indoc",
"itertools",
"kasuari",
@ -3444,7 +3498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db"
dependencies = [
"bitflags 2.10.0",
"hashbrown",
"hashbrown 0.16.1",
"indoc",
"instability",
"itertools",
@ -3816,6 +3870,30 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schemars"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
dependencies = [
"dyn-clone",
"ref-cast",
"serde",
"serde_json",
]
[[package]]
name = "schemars"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2"
dependencies = [
"dyn-clone",
"ref-cast",
"serde",
"serde_json",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -3915,6 +3993,37 @@ dependencies = [
"serde_core",
]
[[package]]
name = "serde_with"
version = "3.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7"
dependencies = [
"base64",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.13.0",
"schemars 0.9.0",
"schemars 1.2.0",
"serde_core",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c"
dependencies = [
"darling 0.21.3",
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "serdect"
version = "0.4.2"
@ -4524,7 +4633,7 @@ version = "0.9.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
dependencies = [
"indexmap",
"indexmap 2.13.0",
"serde_core",
"serde_spanned",
"toml_datetime",
@ -5426,7 +5535,7 @@ dependencies = [
"anyhow",
"crossterm 0.29.0",
"futures",
"hashbrown",
"hashbrown 0.16.1",
"libc",
"mlua",
"paste",
@ -5447,6 +5556,7 @@ dependencies = [
"yazi-scheduler",
"yazi-shared",
"yazi-term",
"yazi-tty",
"yazi-vfs",
"yazi-watcher",
"yazi-widgets",
@ -5473,6 +5583,7 @@ dependencies = [
"yazi-macro",
"yazi-shared",
"yazi-term",
"yazi-tty",
]
[[package]]
@ -5481,7 +5592,7 @@ version = "26.1.22"
dependencies = [
"ansi-to-tui",
"futures",
"hashbrown",
"hashbrown 0.16.1",
"mlua",
"paste",
"ratatui",
@ -5506,7 +5617,7 @@ dependencies = [
"clap_complete_fig",
"clap_complete_nushell",
"futures",
"hashbrown",
"hashbrown 0.16.1",
"regex",
"vergen-gitcl",
"yazi-adapter",
@ -5522,6 +5633,7 @@ name = "yazi-build"
version = "26.1.22"
dependencies = [
"yazi-term",
"yazi-tty",
]
[[package]]
@ -5565,8 +5677,8 @@ dependencies = [
"crossterm 0.29.0",
"dirs",
"globset",
"hashbrown",
"indexmap",
"hashbrown 0.16.1",
"indexmap 2.13.0",
"ratatui",
"regex",
"serde",
@ -5578,6 +5690,7 @@ dependencies = [
"yazi-macro",
"yazi-shared",
"yazi-term",
"yazi-tty",
]
[[package]]
@ -5586,8 +5699,8 @@ version = "26.1.22"
dependencies = [
"anyhow",
"crossterm 0.29.0",
"hashbrown",
"indexmap",
"hashbrown 0.16.1",
"indexmap 2.13.0",
"parking_lot",
"ratatui",
"tokio",
@ -5615,7 +5728,7 @@ name = "yazi-dds"
version = "26.1.22"
dependencies = [
"anyhow",
"hashbrown",
"hashbrown 0.16.1",
"mlua",
"ordered-float 5.1.0",
"parking_lot",
@ -5681,6 +5794,7 @@ dependencies = [
"yazi-proxy",
"yazi-shared",
"yazi-term",
"yazi-tty",
"yazi-vfs",
"yazi-watcher",
"yazi-widgets",
@ -5696,7 +5810,7 @@ dependencies = [
"core-foundation-sys",
"dirs",
"foldhash",
"hashbrown",
"hashbrown 0.16.1",
"libc",
"objc2",
"parking_lot",
@ -5733,10 +5847,11 @@ dependencies = [
"bitflags 2.10.0",
"crossterm 0.29.0",
"dyn-clone",
"hashbrown",
"hashbrown 0.16.1",
"mlua",
"ordered-float 5.1.0",
"serde",
"serde_with",
"tokio",
"yazi-binding",
"yazi-boot",
@ -5754,7 +5869,7 @@ dependencies = [
"anyhow",
"crossterm 0.29.0",
"futures",
"hashbrown",
"hashbrown 0.16.1",
"libc",
"mlua",
"parking_lot",
@ -5811,7 +5926,7 @@ dependencies = [
"anyhow",
"async-priority-channel",
"foldhash",
"hashbrown",
"hashbrown 0.16.1",
"libc",
"lru",
"mlua",
@ -5854,7 +5969,7 @@ dependencies = [
"dyn-clone",
"foldhash",
"futures",
"hashbrown",
"hashbrown 0.16.1",
"libc",
"memchr",
"ordered-float 5.1.0",
@ -5882,6 +5997,17 @@ name = "yazi-term"
version = "26.1.22"
dependencies = [
"crossterm 0.29.0",
"libc",
"parking_lot",
"tracing",
"yazi-macro",
"yazi-shared",
]
[[package]]
name = "yazi-tty"
version = "26.1.22"
dependencies = [
"libc",
"parking_lot",
"tracing",
@ -5897,7 +6023,7 @@ dependencies = [
"anyhow",
"deadpool",
"futures",
"hashbrown",
"hashbrown 0.16.1",
"parking_lot",
"russh",
"tokio",
@ -5915,7 +6041,7 @@ name = "yazi-watcher"
version = "26.1.22"
dependencies = [
"anyhow",
"hashbrown",
"hashbrown 0.16.1",
"notify",
"parking_lot",
"percent-encoding",
@ -5950,6 +6076,7 @@ dependencies = [
"yazi-parser",
"yazi-shared",
"yazi-term",
"yazi-tty",
]
[[package]]

View file

@ -55,6 +55,7 @@ russh = { version = "0.57.0", default-features = false, features =
scopeguard = "1.2.0"
serde = { version = "1.0.228", features = [ "derive" ] }
serde_json = "1.0.149"
serde_with = "3.16.1"
syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
thiserror = "2.0.18"
tokio = { version = "1.49.0", features = [ "full" ] }

View file

@ -29,6 +29,7 @@ yazi-proxy = { path = "../yazi-proxy", version = "26.1.22" }
yazi-scheduler = { path = "../yazi-scheduler", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
yazi-term = { path = "../yazi-term", version = "26.1.22" }
yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
yazi-vfs = { path = "../yazi-vfs", version = "26.1.22" }
yazi-watcher = { path = "../yazi-watcher", version = "26.1.22" }
yazi-widgets = { path = "../yazi-widgets", version = "26.1.22" }

View file

@ -13,7 +13,7 @@ use yazi_macro::{err, succ};
use yazi_parser::VoidOpt;
use yazi_proxy::{AppProxy, HIDER, TasksProxy};
use yazi_shared::{data::Data, path::PathDyn, strand::{AsStrand, AsStrandJoin, Strand, StrandBuf, StrandLike}, terminal_clear, url::{AsUrl, UrlBuf, UrlCow, UrlLike}};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
use yazi_vfs::{VfsFile, maybe_exists, provider};
use yazi_watcher::WATCHER;

View file

@ -7,7 +7,7 @@ use yazi_macro::{act, succ};
use yazi_parser::VoidOpt;
use yazi_proxy::MgrProxy;
use yazi_shared::{data::Data, url::{UrlBuf, UrlLike}};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
use yazi_vfs::{VfsFiles, VfsFilesOp};
use crate::{Actor, Ctx};

View file

@ -9,7 +9,7 @@ use yazi_macro::succ;
use yazi_parser::VoidOpt;
use yazi_proxy::{AppProxy, HIDER};
use yazi_shared::{data::Data, terminal_clear};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
use crate::{Actor, Ctx};

View file

@ -17,6 +17,7 @@ yazi-fs = { path = "../yazi-fs", version = "26.1.22" }
yazi-macro = { path = "../yazi-macro", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
yazi-term = { path = "../yazi-term", version = "26.1.22" }
yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
# External dependencies
ansi-to-tui = { workspace = true }

View file

@ -5,7 +5,7 @@ use ratatui::layout::Rect;
use tracing::warn;
use yazi_shared::env_exists;
use crate::{Emulator, SHOWN, TMUX, drivers};
use crate::{Adapters, Emulator, SHOWN, TMUX, drivers};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Adapter {
@ -85,13 +85,13 @@ impl Adapter {
impl Adapter {
pub fn matches(emulator: &Emulator) -> Self {
let mut protocols = emulator.adapters().to_owned();
let mut adapters: Adapters = emulator.into();
if env_exists("ZELLIJ_SESSION_NAME") {
protocols.retain(|p| *p == Self::Sixel);
adapters.retain(|p| *p == Self::Sixel);
} else if TMUX.get() {
protocols.retain(|p| *p != Self::KgpOld);
adapters.retain(|p| *p != Self::KgpOld);
}
if let Some(p) = protocols.first() {
if let Some(p) = adapters.first() {
return *p;
}

View file

@ -0,0 +1,69 @@
use std::ops::{Deref, DerefMut};
use yazi_shared::Either;
use crate::{Adapter, Brand, Emulator, Unknown};
pub(super) struct Adapters(Vec<Adapter>);
impl Deref for Adapters {
type Target = Vec<Adapter>;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for Adapters {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl From<&Emulator> for Adapters {
fn from(value: &Emulator) -> Self {
match value.kind {
Either::Left(b) => b.into(),
Either::Right(u) => u.into(),
}
}
}
impl From<Brand> for Adapters {
fn from(value: Brand) -> Self {
use Brand as B;
use crate::Adapter as A;
Self(match value {
B::Kitty => vec![A::Kgp],
B::Konsole => vec![A::KgpOld],
B::Iterm2 => vec![A::Iip, A::Sixel],
B::WezTerm => vec![A::Iip, A::Sixel],
B::Foot => vec![A::Sixel],
B::Ghostty => vec![A::Kgp],
B::Microsoft => vec![A::Sixel],
B::Warp => vec![A::Iip, A::KgpOld],
B::Rio => vec![A::Iip, A::Sixel],
B::BlackBox => vec![A::Sixel],
B::VSCode => vec![A::Iip, A::Sixel],
B::Tabby => vec![A::Iip, A::Sixel],
B::Hyper => vec![A::Iip, A::Sixel],
B::Mintty => vec![A::Iip],
B::Tmux => vec![],
B::VTerm => vec![],
B::Apple => vec![],
B::Urxvt => vec![],
B::Bobcat => vec![A::Iip, A::Sixel],
})
}
}
impl From<Unknown> for Adapters {
fn from(value: Unknown) -> Self {
use Adapter as A;
Self(match (value.kgp, value.sixel) {
(true, true) => vec![A::Sixel, A::KgpOld],
(true, false) => vec![A::KgpOld],
(false, true) => vec![A::Sixel],
(false, false) => vec![],
})
}
}

View file

@ -88,32 +88,6 @@ impl Brand {
None
}
pub(super) fn adapters(self) -> &'static [crate::Adapter] {
use crate::Adapter as A;
match self {
Self::Kitty => &[A::Kgp],
Self::Konsole => &[A::KgpOld],
Self::Iterm2 => &[A::Iip, A::Sixel],
Self::WezTerm => &[A::Iip, A::Sixel],
Self::Foot => &[A::Sixel],
Self::Ghostty => &[A::Kgp],
Self::Microsoft => &[A::Sixel],
Self::Warp => &[A::Iip, A::KgpOld],
Self::Rio => &[A::Iip, A::Sixel],
Self::BlackBox => &[A::Sixel],
Self::VSCode => &[A::Iip, A::Sixel],
Self::Tabby => &[A::Iip, A::Sixel],
Self::Hyper => &[A::Iip, A::Sixel],
Self::Mintty => &[A::Iip],
Self::Tmux => &[],
Self::VTerm => &[],
Self::Apple => &[],
Self::Urxvt => &[],
Self::Bobcat => &[A::Iip, A::Sixel],
}
}
fn env() -> (String, String) {
let (term, program) = Mux::term_program();
(

View file

@ -5,7 +5,7 @@ use anyhow::Result;
use base64::{Engine, engine::general_purpose};
use image::DynamicImage;
use ratatui::layout::Rect;
use yazi_term::tty::TTY;
use yazi_tty::TTY;
use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter};

View file

@ -6,9 +6,9 @@ use scopeguard::defer;
use tokio::time::sleep;
use tracing::{debug, error, warn};
use yazi_shared::Either;
use yazi_term::tty::{Handle, TTY};
use yazi_tty::{Handle, TTY};
use crate::{Adapter, Brand, Dimension, Mux, TMUX, Unknown};
use crate::{Brand, Dimension, Mux, TMUX, Unknown};
#[derive(Clone, Debug)]
pub struct Emulator {
@ -76,13 +76,6 @@ impl Emulator {
})
}
pub fn adapters(&self) -> &'static [Adapter] {
match self.kind {
Either::Left(brand) => brand.adapters(),
Either::Right(unknown) => unknown.adapters(),
}
}
pub fn move_lock<F, T>((x, y): (u16, u16), cb: F) -> Result<T>
where
F: FnOnce(&mut BufWriter<Handle>) -> Result<T>,

View file

@ -1,6 +1,6 @@
yazi_macro::mod_pub!(drivers);
yazi_macro::mod_flat!(adapter brand dimension emulator icc image info mux unknown);
yazi_macro::mod_flat!(adapter adapters brand dimension emulator icc image info mux unknown);
use yazi_shared::{RoCell, SyncCell, in_wsl};

View file

@ -3,7 +3,7 @@ use std::borrow::Cow;
use anyhow::Result;
use tracing::error;
use yazi_macro::time;
use yazi_term::tty::TTY;
use yazi_tty::TTY;
use crate::{CLOSE, ESCAPE, Emulator, START, TMUX};

View file

@ -1,20 +1,5 @@
use crate::Adapter;
#[derive(Clone, Copy, Debug, Default)]
pub struct Unknown {
pub kgp: bool,
pub sixel: bool,
}
impl Unknown {
pub(super) fn adapters(self) -> &'static [Adapter] {
use Adapter as A;
match (self.kgp, self.sixel) {
(true, true) => &[A::Sixel, A::KgpOld],
(true, false) => &[A::KgpOld],
(false, true) => &[A::Sixel],
(false, false) => &[],
}
}
}

View file

@ -19,6 +19,7 @@ strip = true
[build-dependencies]
yazi-term = { path = "../yazi-term", version = "26.1.22" }
yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
[[bin]]
name = "yazi-build"

View file

@ -1,9 +1,9 @@
use std::{env, error::Error, io::{BufRead, BufReader, Read, Write}, process::{Command, Stdio}, thread};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
fn main() -> Result<(), Box<dyn Error>> {
yazi_term::init();
yazi_tty::init();
let manifest = env::var_os("CARGO_MANIFEST_DIR").unwrap().to_string_lossy().replace(r"\", "/");
let crates = if manifest.contains("/git/checkouts/yazi-") {

View file

@ -17,6 +17,7 @@ yazi-fs = { path = "../yazi-fs", version = "26.1.22" }
yazi-macro = { path = "../yazi-macro", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
yazi-term = { path = "../yazi-term", version = "26.1.22" }
yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
# External dependencies
anyhow = { workspace = true }

View file

@ -5,7 +5,7 @@ yazi_macro::mod_flat!(icon layout pattern platform preset priority style utils y
use std::io::{Read, Write};
use yazi_shared::{RoCell, SyncCell};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
pub static YAZI: RoCell<yazi::Yazi> = RoCell::new();
pub static KEYMAP: RoCell<keymap::Keymap> = RoCell::new();

View file

@ -40,6 +40,7 @@ yazi-plugin = { path = "../yazi-plugin", version = "26.1.22" }
yazi-proxy = { path = "../yazi-proxy", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
yazi-term = { path = "../yazi-term", version = "26.1.22" }
yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
yazi-vfs = { path = "../yazi-vfs", version = "26.1.22" }
yazi-watcher = { path = "../yazi-watcher", version = "26.1.22" }
yazi-widgets = { path = "../yazi-widgets", version = "26.1.22" }

View file

@ -8,7 +8,7 @@ use yazi_binding::elements::COLLISION;
use yazi_macro::{act, succ};
use yazi_parser::VoidOpt;
use yazi_shared::{data::Data, event::NEED_RENDER};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
use crate::{app::App, root::Root};

View file

@ -14,7 +14,7 @@ async fn main() -> anyhow::Result<()> {
Logs::start()?;
_ = fdlimit::raise_fd_limit();
yazi_term::init();
yazi_tty::init();
yazi_fs::init();

View file

@ -6,7 +6,7 @@ use ratatui::{CompletedFrame, Frame, Terminal, backend::CrosstermBackend, buffer
use yazi_adapter::{Emulator, Mux, TMUX};
use yazi_config::{THEME, YAZI};
use yazi_shared::SyncCell;
use yazi_term::tty::{TTY, TtyWriter};
use yazi_tty::{TTY, TtyWriter};
static CSI_U: AtomicBool = AtomicBool::new(false);

View file

@ -33,4 +33,5 @@ hashbrown = { workspace = true }
mlua = { workspace = true }
ordered-float = { workspace = true }
serde = { workspace = true }
serde_with = { workspace = true }
tokio = { workspace = true }

View file

@ -1,16 +1,19 @@
use std::{str::FromStr, time::Duration};
use anyhow::anyhow;
use mlua::{ExternalError, ExternalResult};
use serde::Deserialize;
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
use serde::{Deserialize, Serialize};
use serde_with::{DurationSeconds, serde_as};
use yazi_config::{Style, THEME};
use yazi_shared::event::CmdCow;
#[derive(Clone)]
#[serde_as]
#[derive(Clone, Deserialize, Serialize)]
pub struct NotifyOpt {
pub title: String,
pub content: String,
pub level: NotifyLevel,
#[serde_as(as = "DurationSeconds<f64>")] // FIXME
pub timeout: Duration,
}
@ -22,32 +25,16 @@ impl TryFrom<CmdCow> for NotifyOpt {
}
}
impl TryFrom<mlua::Table> for NotifyOpt {
type Error = mlua::Error;
impl FromLua for NotifyOpt {
fn from_lua(value: Value, lua: &Lua) -> mlua::Result<Self> { lua.from_value(value) }
}
fn try_from(t: mlua::Table) -> Result<Self, Self::Error> {
let timeout = t.raw_get("timeout")?;
if timeout < 0.0 {
return Err("timeout must be non-negative".into_lua_err());
}
let level = if let Ok(s) = t.raw_get::<mlua::String>("level") {
s.to_str()?.parse().into_lua_err()?
} else {
Default::default()
};
Ok(Self {
title: t.raw_get("title")?,
content: t.raw_get("content")?,
level,
timeout: Duration::from_secs_f64(timeout),
})
}
impl IntoLua for NotifyOpt {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { lua.to_value(&self) }
}
// --- Level
#[derive(Clone, Copy, Default, Deserialize, Eq, PartialEq)]
#[derive(Clone, Copy, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum NotifyLevel {
#[default]

View file

@ -6,7 +6,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
use yazi_binding::{elements::{Line, Pos, Text}, runtime};
use yazi_config::{keymap::{Chord, ChordCow, Key}, popup::{ConfirmCfg, InputCfg}};
use yazi_macro::relay;
use yazi_parser::which::ActivateOpt;
use yazi_parser::{app::NotifyOpt, which::ActivateOpt};
use yazi_proxy::{AppProxy, ConfirmProxy, InputProxy, WhichProxy};
use yazi_shared::Debounce;
@ -100,10 +100,7 @@ impl Utils {
}
pub(super) fn notify(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|_, t: Table| {
AppProxy::notify(t.try_into()?);
Ok(())
})
lua.create_function(|_, opt: NotifyOpt| Ok(AppProxy::notify(opt)))
}
fn parse_keys(value: Value) -> mlua::Result<Vec<Key>> {

View file

@ -15,18 +15,13 @@ workspace = true
yazi-macro = { path = "../yazi-macro", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
# Logging
tracing = { workspace = true }
# External dependencies
crossterm = { workspace = true }
parking_lot = { workspace = true }
tracing = { workspace = true }
[target."cfg(unix)".dependencies]
libc = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies]
crossterm = { workspace = true, features = [ "use-dev-tty", "libc" ] }
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61.2", features = [ "Win32_Globalization", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_Console", "Win32_System_Threading", "Win32_Security" ] }

View file

@ -1,5 +1 @@
yazi_macro::mod_pub!(tty);
yazi_macro::mod_flat!(background cursor r#if);
pub fn init() { tty::init(); }

26
yazi-tty/Cargo.toml Normal file
View file

@ -0,0 +1,26 @@
[package]
name = "yazi-tty"
version = "26.1.22"
edition = "2024"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
description = "Yazi TTY access layer"
homepage = "https://yazi-rs.github.io"
repository = "https://github.com/sxyazi/yazi"
[lints]
workspace = true
[dependencies]
yazi-macro = { path = "../yazi-macro", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
# External dependencies
parking_lot = { workspace = true }
tracing = { workspace = true }
[target."cfg(unix)".dependencies]
libc = { workspace = true }
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61.2", features = [ "Win32_Globalization", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_Console", "Win32_System_Threading", "Win32_Security" ] }

5
yazi-tty/README.md Normal file
View file

@ -0,0 +1,5 @@
# yazi-tty
This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API.
[source]: https://github.com/sxyazi/yazi

View file

@ -5,4 +5,4 @@ yazi_macro::mod_flat!(windows);
pub static TTY: yazi_shared::RoCell<Tty> = yazi_shared::RoCell::new();
pub(super) fn init() { TTY.with(<_>::default); }
pub fn init() { TTY.with(<_>::default); }

View file

@ -18,6 +18,7 @@ yazi-macro = { path = "../yazi-macro", version = "26.1.22" }
yazi-parser = { path = "../yazi-parser", version = "26.1.22" }
yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
yazi-term = { path = "../yazi-term", version = "26.1.22" }
yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
# External dependencies
anyhow = { workspace = true }

View file

@ -55,7 +55,7 @@ impl Clipboard {
use crossterm::execute;
use tokio::{io::AsyncWriteExt, process::Command};
use yazi_term::tty::TTY;
use yazi_tty::TTY;
s.as_ref().clone_into(&mut self.content.lock());
execute!(TTY.writer(), osc52::SetClipboard::new(s.as_ref())).ok();