mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Merge branch 'sxyazi:main' into main
This commit is contained in:
commit
36b3842a38
54 changed files with 486 additions and 314 deletions
152
Cargo.lock
generated
152
Cargo.lock
generated
|
|
@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
|
|
@ -126,9 +126,9 @@ checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
|||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.6.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||
checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f"
|
||||
|
||||
[[package]]
|
||||
name = "async-priority-channel"
|
||||
|
|
@ -166,6 +166,12 @@ version = "0.21.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||
|
||||
[[package]]
|
||||
name = "better-panic"
|
||||
version = "0.3.0"
|
||||
|
|
@ -263,9 +269,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
|
||||
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
|
@ -304,7 +310,7 @@ dependencies = [
|
|||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
"strsim 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -502,6 +508,41 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.10.0",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
|
@ -887,14 +928,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
|
|
@ -906,12 +943,6 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "if_chain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.24.9"
|
||||
|
|
@ -998,9 +1029,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.68"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
|
@ -1165,9 +1196,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
|
|
@ -1431,7 +1462,7 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"indexmap",
|
||||
"line-wrap",
|
||||
"quick-xml",
|
||||
|
|
@ -1592,9 +1623,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.5"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
|
@ -1840,6 +1871,12 @@ version = "1.0.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.0"
|
||||
|
|
@ -2240,7 +2277,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna 0.5.0",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
|
|
@ -2262,12 +2299,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "validator"
|
||||
version = "0.16.1"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd"
|
||||
checksum = "da339118f018cc70ebf01fafc103360528aad53717e4bf311db929cb01cb9345"
|
||||
dependencies = [
|
||||
"idna 0.4.0",
|
||||
"lazy_static",
|
||||
"idna",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
|
@ -2278,28 +2315,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "validator_derive"
|
||||
version = "0.16.0"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc44ca3088bb3ba384d9aecf40c6a23a676ce23e09bdaca2073d99c207f864af"
|
||||
checksum = "76e88ea23b8f5e59230bff8a2f03c0ee0054a61d5b8343a38946bcd406fe624c"
|
||||
dependencies = [
|
||||
"if_chain",
|
||||
"lazy_static",
|
||||
"darling",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 1.0.109",
|
||||
"validator_types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator_types"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2328,9 +2353,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
|
|
@ -2344,9 +2369,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
|
@ -2354,9 +2379,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
|
|
@ -2369,9 +2394,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
|
@ -2379,9 +2404,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -2392,9 +2417,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
|
|
@ -2668,7 +2693,7 @@ version = "0.2.3"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"base64",
|
||||
"base64 0.22.0",
|
||||
"color_quant",
|
||||
"crossterm",
|
||||
"image",
|
||||
|
|
@ -2719,7 +2744,7 @@ name = "yazi-core"
|
|||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"base64 0.22.0",
|
||||
"bitflags 2.4.2",
|
||||
"clipboard-win",
|
||||
"crossterm",
|
||||
|
|
@ -2818,6 +2843,7 @@ name = "yazi-proxy"
|
|||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mlua",
|
||||
"tokio",
|
||||
"yazi-config",
|
||||
"yazi-shared",
|
||||
|
|
@ -2829,7 +2855,7 @@ version = "0.2.3"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"async-priority-channel",
|
||||
"base64",
|
||||
"base64 0.22.0",
|
||||
"crossterm",
|
||||
"futures",
|
||||
"parking_lot",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use yazi_proxy::InputOpt;
|
||||
use yazi_proxy::options::InputOpt;
|
||||
use yazi_shared::render;
|
||||
|
||||
use crate::input::Input;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use tracing::error;
|
|||
use yazi_boot::ARGS;
|
||||
use yazi_config::{popup::SelectCfg, OPEN};
|
||||
use yazi_plugin::isolate;
|
||||
use yazi_proxy::{ManagerProxy, OpenDoOpt, TasksProxy};
|
||||
use yazi_proxy::{options::OpenDoOpt, ManagerProxy, TasksProxy};
|
||||
use yazi_shared::{emit, event::{Cmd, EventQuit}, fs::{File, Url}, MIME_DIR};
|
||||
|
||||
use crate::{folder::Folder, manager::Manager, tasks::Tasks};
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@ use yazi_shared::{emit, event::Cmd, Layer};
|
|||
use crate::notify::{Message, Notify};
|
||||
|
||||
impl Notify {
|
||||
pub fn push(&mut self, msg: impl TryInto<Message>) {
|
||||
let Ok(mut msg) = msg.try_into() else {
|
||||
return;
|
||||
};
|
||||
pub fn push(&mut self, msg: impl Into<Message>) {
|
||||
let mut msg = msg.into() as Message;
|
||||
|
||||
let instant = Instant::now();
|
||||
msg.timeout += instant - self.messages.first().map_or(instant, |m| m.instant);
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
pub enum Level {
|
||||
Info,
|
||||
Warn,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl FromStr for Level {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"info" => Self::Info,
|
||||
"warn" => Self::Warn,
|
||||
"error" => Self::Error,
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +1,31 @@
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use yazi_shared::event::Cmd;
|
||||
use yazi_proxy::options::{NotifyLevel, NotifyOpt};
|
||||
|
||||
use super::{Level, NOTIFY_BORDER};
|
||||
use super::NOTIFY_BORDER;
|
||||
|
||||
pub struct Message {
|
||||
pub title: String,
|
||||
pub content: String,
|
||||
pub level: Level,
|
||||
|
||||
pub instant: Instant,
|
||||
pub level: NotifyLevel,
|
||||
pub timeout: Duration,
|
||||
|
||||
pub instant: Instant,
|
||||
pub percent: u8,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for Message {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
|
||||
let timeout = c.take_name("timeout").and_then(|s| s.parse::<f64>().ok()).ok_or(())?;
|
||||
if timeout < 0.0 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let content = c.take_name("content").ok_or(())?;
|
||||
Ok(Self {
|
||||
title: c.take_name("title").ok_or(())?,
|
||||
content,
|
||||
level: c.take_name("level").ok_or(())?.parse()?,
|
||||
impl From<NotifyOpt> for Message {
|
||||
fn from(opt: NotifyOpt) -> Self {
|
||||
Self {
|
||||
title: opt.title,
|
||||
content: opt.content,
|
||||
level: opt.level,
|
||||
timeout: opt.timeout,
|
||||
|
||||
instant: Instant::now(),
|
||||
timeout: Duration::from_secs_f64(timeout),
|
||||
|
||||
percent: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
mod commands;
|
||||
mod level;
|
||||
mod message;
|
||||
mod notify;
|
||||
|
||||
pub use level::*;
|
||||
pub use message::*;
|
||||
pub use notify::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use yazi_proxy::SelectOpt;
|
||||
use yazi_proxy::options::SelectOpt;
|
||||
use yazi_shared::render;
|
||||
|
||||
use crate::select::Select;
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ impl Tab {
|
|||
if !select {
|
||||
self.selected.remove_many(&urls, same);
|
||||
} else if self.selected.add_many(&urls, same) != urls.len() {
|
||||
AppProxy::warn(
|
||||
AppProxy::notify_warn(
|
||||
"Escape visual mode",
|
||||
"Some files cannot be selected, due to path nesting conflict.",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ impl<'a> Tab {
|
|||
};
|
||||
|
||||
if !b {
|
||||
AppProxy::warn("Select one", "This file cannot be selected, due to path nesting conflict.");
|
||||
AppProxy::notify_warn(
|
||||
"Select one",
|
||||
"This file cannot be selected, due to path nesting conflict.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ impl Tab {
|
|||
render!(added > 0);
|
||||
|
||||
if added != addition.len() {
|
||||
AppProxy::warn("Select all", "Some files cannot be selected, due to path nesting conflict.");
|
||||
AppProxy::notify_warn(
|
||||
"Select all",
|
||||
"Some files cannot be selected, due to path nesting conflict.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use yazi_proxy::OpenWithOpt;
|
||||
use yazi_proxy::options::OpenWithOpt;
|
||||
|
||||
use crate::tasks::Tasks;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
use yazi_core::notify::Message;
|
||||
use yazi_proxy::options::NotifyOpt;
|
||||
|
||||
use crate::app::App;
|
||||
|
||||
impl App {
|
||||
pub(crate) fn notify(&mut self, msg: impl TryInto<Message>) { self.cx.notify.push(msg); }
|
||||
pub(crate) fn notify(&mut self, opt: impl TryInto<NotifyOpt>) {
|
||||
let Ok(opt) = opt.try_into() else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.cx.notify.push(opt);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::sync::atomic::Ordering;
|
||||
|
||||
use ratatui::{backend::{Backend, CrosstermBackend}, CompletedFrame};
|
||||
use yazi_plugin::elements::COLLISION;
|
||||
|
||||
use crate::{app::App, lives::Lives, root::{Root, COLLISION}};
|
||||
use crate::{app::App, lives::Lives, root::Root};
|
||||
|
||||
impl App {
|
||||
pub(crate) fn render(&mut self) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::path::MAIN_SEPARATOR;
|
|||
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, List, ListItem, Widget}};
|
||||
use yazi_config::{popup::{Offset, Position}, THEME};
|
||||
|
||||
use crate::{widgets, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
pub(crate) struct Completion<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -28,7 +28,7 @@ impl<'a> Widget for Completion<'a> {
|
|||
&THEME.completion.icon_file
|
||||
};
|
||||
|
||||
let mut item = ListItem::new(format!(" {} {}", icon, x));
|
||||
let mut item = ListItem::new(format!(" {icon} {x}"));
|
||||
if i == self.cx.completion.rel_cursor() {
|
||||
item = item.style(THEME.completion.active);
|
||||
} else {
|
||||
|
|
@ -54,7 +54,7 @@ impl<'a> Widget for Completion<'a> {
|
|||
area.height = rect.height.saturating_sub(area.y).min(area.height);
|
||||
}
|
||||
|
||||
widgets::Clear.render(area, buf);
|
||||
yazi_plugin::elements::Clear::default().render(area, buf);
|
||||
List::new(items)
|
||||
.block(
|
||||
Block::bordered().border_type(BorderType::Rounded).border_style(THEME.completion.border),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ratatui::{buffer::Buffer, layout::{self, Constraint, Rect}, text::Line, widg
|
|||
use yazi_config::THEME;
|
||||
|
||||
use super::Bindings;
|
||||
use crate::{widgets, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
pub(crate) struct Layout<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -15,7 +15,7 @@ impl<'a> Layout<'a> {
|
|||
impl<'a> Widget for Layout<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let help = &self.cx.help;
|
||||
widgets::Clear.render(area, buf);
|
||||
yazi_plugin::elements::Clear::default().render(area, buf);
|
||||
|
||||
let chunks = layout::Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).split(area);
|
||||
Line::styled(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use yazi_core::input::InputMode;
|
|||
use yazi_plugin::external::Highlighter;
|
||||
use yazi_shared::term::Term;
|
||||
|
||||
use crate::{widgets, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
pub(crate) struct Input<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -37,7 +37,7 @@ impl<'a> Widget for Input<'a> {
|
|||
let input = &self.cx.input;
|
||||
let area = self.cx.area(&input.position);
|
||||
|
||||
widgets::Clear.render(area, buf);
|
||||
yazi_plugin::elements::Clear::default().render(area, buf);
|
||||
Paragraph::new(self.highlighted_value().unwrap_or_else(|_| Line::from(input.value())))
|
||||
.block(
|
||||
Block::bordered()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{collections::{btree_set, BTreeSet}, ops::Deref};
|
||||
|
||||
use mlua::{AnyUserData, Lua, MetaMethod, UserDataMethods, UserDataRefMut};
|
||||
use mlua::{AnyUserData, IntoLuaMulti, Lua, MetaMethod, UserDataMethods, UserDataRefMut};
|
||||
use yazi_plugin::{bindings::Cast, url::Url};
|
||||
|
||||
use super::SCOPE;
|
||||
|
|
@ -28,7 +28,12 @@ impl Selected {
|
|||
|
||||
reg.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
|
||||
let iter = lua.create_function(|lua, mut iter: UserDataRefMut<SelectedIter>| {
|
||||
Ok(if let Some(url) = iter.0.next() { Some(Url::cast(lua, url.clone())?) } else { None })
|
||||
if let Some(url) = iter.inner.next() {
|
||||
iter.next += 1;
|
||||
(iter.next, Url::cast(lua, url.clone())?).into_lua_multi(lua)
|
||||
} else {
|
||||
().into_lua_multi(lua)
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok((iter, SelectedIter::make(me.inner())))
|
||||
|
|
@ -42,11 +47,14 @@ impl Selected {
|
|||
fn inner(&self) -> &'static BTreeSet<yazi_shared::fs::Url> { unsafe { &*self.inner } }
|
||||
}
|
||||
|
||||
struct SelectedIter(btree_set::Iter<'static, yazi_shared::fs::Url>);
|
||||
struct SelectedIter {
|
||||
next: usize,
|
||||
inner: btree_set::Iter<'static, yazi_shared::fs::Url>,
|
||||
}
|
||||
|
||||
impl SelectedIter {
|
||||
#[inline]
|
||||
fn make(selected: &'static BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
|
||||
SCOPE.create_any_userdata(Self(selected.iter()))
|
||||
SCOPE.create_any_userdata(Self { next: 0, inner: selected.iter() })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ mod select;
|
|||
mod signals;
|
||||
mod tasks;
|
||||
mod which;
|
||||
mod widgets;
|
||||
|
||||
use context::*;
|
||||
use executor::*;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ use std::rc::Rc;
|
|||
|
||||
use ratatui::{buffer::Buffer, layout::{self, Constraint, Offset, Rect}, widgets::{Block, BorderType, Paragraph, Widget, Wrap}};
|
||||
use yazi_config::THEME;
|
||||
use yazi_core::notify::{Level, Message};
|
||||
use yazi_core::notify::Message;
|
||||
use yazi_proxy::options::NotifyLevel;
|
||||
|
||||
use crate::{widgets::Clear, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
pub(crate) struct Layout<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -43,16 +44,16 @@ impl<'a> Widget for Layout<'a> {
|
|||
|
||||
for (i, m) in notify.messages.iter().enumerate().take(limit) {
|
||||
let (icon, style) = match m.level {
|
||||
Level::Info => (&THEME.notify.icon_info, THEME.notify.title_info),
|
||||
Level::Warn => (&THEME.notify.icon_warn, THEME.notify.title_warn),
|
||||
Level::Error => (&THEME.notify.icon_error, THEME.notify.title_error),
|
||||
NotifyLevel::Info => (&THEME.notify.icon_info, THEME.notify.title_info),
|
||||
NotifyLevel::Warn => (&THEME.notify.icon_warn, THEME.notify.title_warn),
|
||||
NotifyLevel::Error => (&THEME.notify.icon_error, THEME.notify.title_error),
|
||||
};
|
||||
|
||||
let mut rect =
|
||||
tile[i].offset(Offset { x: (100 - m.percent) as i32 * tile[i].width as i32 / 100, y: 0 });
|
||||
rect.width = area.width.saturating_sub(rect.x);
|
||||
|
||||
Clear.render(rect, buf);
|
||||
yazi_plugin::elements::Clear::default().render(rect, buf);
|
||||
Paragraph::new(m.content.as_str())
|
||||
.wrap(Wrap { trim: false })
|
||||
.block(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use ratatui::{buffer::Buffer, layout::{Constraint, Layout, Rect}, widgets::Widget};
|
||||
|
||||
use super::{completion, input, select, tasks, which};
|
||||
use crate::{components, help, Ctx};
|
||||
|
||||
pub(super) static COLLISION: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub(super) struct Root<'a> {
|
||||
cx: &'a Ctx,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, List, ListItem, Widget}};
|
||||
use yazi_config::THEME;
|
||||
|
||||
use crate::{widgets, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
pub(crate) struct Select<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -29,7 +29,7 @@ impl<'a> Widget for Select<'a> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
widgets::Clear.render(area, buf);
|
||||
yazi_plugin::elements::Clear::default().render(area, buf);
|
||||
List::new(items)
|
||||
.block(
|
||||
Block::bordered()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Rect}, text:
|
|||
use yazi_config::THEME;
|
||||
use yazi_core::tasks::TASKS_PERCENT;
|
||||
|
||||
use crate::{widgets, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
pub(crate) struct Layout<'a> {
|
||||
cx: &'a Ctx,
|
||||
|
|
@ -32,7 +32,7 @@ impl<'a> Widget for Layout<'a> {
|
|||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let area = Self::area(area);
|
||||
|
||||
widgets::Clear.render(area, buf);
|
||||
yazi_plugin::elements::Clear::default().render(area, buf);
|
||||
let block = Block::bordered()
|
||||
.title(Line::styled("Tasks", THEME.tasks.title))
|
||||
.title_alignment(Alignment::Center)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ratatui::{buffer::Buffer, layout, layout::{Constraint, Rect}, widgets::{Bloc
|
|||
use yazi_config::THEME;
|
||||
|
||||
use super::Cand;
|
||||
use crate::{widgets, Ctx};
|
||||
use crate::Ctx;
|
||||
|
||||
const PADDING_X: u16 = 1;
|
||||
const PADDING_Y: u16 = 1;
|
||||
|
|
@ -46,7 +46,7 @@ impl Widget for Which<'_> {
|
|||
.split(area)
|
||||
};
|
||||
|
||||
widgets::Clear.render(area, buf);
|
||||
yazi_plugin::elements::Clear::default().render(area, buf);
|
||||
Block::new().style(THEME.which.mask).render(area, buf);
|
||||
|
||||
for y in 0..area.height {
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
use std::sync::atomic::Ordering;
|
||||
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||
use yazi_adaptor::ADAPTOR;
|
||||
|
||||
use crate::root::COLLISION;
|
||||
|
||||
pub(crate) struct Clear;
|
||||
|
||||
#[inline]
|
||||
const fn is_overlapping(a: &Rect, b: &Rect) -> bool {
|
||||
a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y
|
||||
}
|
||||
|
||||
fn overlap(a: &Rect, b: &Rect) -> Option<Rect> {
|
||||
if !is_overlapping(a, b) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let x = a.x.max(b.x);
|
||||
let y = a.y.max(b.y);
|
||||
let width = (a.x + a.width).min(b.x + b.width) - x;
|
||||
let height = (a.y + a.height).min(b.y + b.height) - y;
|
||||
Some(Rect { x, y, width, height })
|
||||
}
|
||||
|
||||
impl Widget for Clear {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
ratatui::widgets::Clear.render(area, buf);
|
||||
|
||||
let Some(r) = ADAPTOR.shown_load().and_then(|r| overlap(&area, &r)) else {
|
||||
return;
|
||||
};
|
||||
|
||||
ADAPTOR.image_erase(r).ok();
|
||||
COLLISION.store(true, Ordering::Relaxed);
|
||||
for y in area.top()..area.bottom() {
|
||||
for x in area.left()..area.right() {
|
||||
buf.get_mut(x, y).set_skip(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
mod clear;
|
||||
|
||||
pub(super) use clear::*;
|
||||
|
|
@ -3,7 +3,9 @@ package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path
|
|||
local _require = require
|
||||
require = function(name)
|
||||
YAZI_PLUGIN_NAME, YAZI_SYNC_CALLS = name, 0
|
||||
return _require(name)
|
||||
local mod = _require(name)
|
||||
mod._name = name
|
||||
return mod
|
||||
end
|
||||
|
||||
YAZI_SYNC_BLOCKS = {}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ pub fn cast_to_renderable(ud: AnyUserData) -> Option<Box<dyn Renderable + Send>>
|
|||
Some(Box::new(c))
|
||||
} else if let Ok(c) = ud.take::<crate::elements::Bar>() {
|
||||
Some(Box::new(c))
|
||||
} else if let Ok(c) = ud.take::<crate::elements::Clear>() {
|
||||
Some(Box::new(c))
|
||||
} else if let Ok(c) = ud.take::<crate::elements::Border>() {
|
||||
Some(Box::new(c))
|
||||
} else if let Ok(c) = ud.take::<crate::elements::Gauge>() {
|
||||
|
|
@ -67,9 +69,10 @@ impl<'lua> IntoLua<'lua> for ValueSendable {
|
|||
ValueSendable::Number(n) => Ok(Value::Number(n)),
|
||||
ValueSendable::String(s) => Ok(Value::String(lua.create_string(s)?)),
|
||||
ValueSendable::Table(t) => {
|
||||
let table = lua.create_table()?;
|
||||
let seq_len = t.keys().filter(|&k| !k.is_numeric()).count();
|
||||
let table = lua.create_table_with_capacity(seq_len, t.len() - seq_len)?;
|
||||
for (k, v) in t {
|
||||
table.raw_set(k.into_lua(lua)?, v.into_lua(lua)?)?;
|
||||
table.raw_set(k, v)?;
|
||||
}
|
||||
Ok(Value::Table(table))
|
||||
}
|
||||
|
|
@ -113,6 +116,11 @@ pub enum ValueSendableKey {
|
|||
String(Vec<u8>),
|
||||
}
|
||||
|
||||
impl ValueSendableKey {
|
||||
#[inline]
|
||||
fn is_numeric(&self) -> bool { matches!(self, Self::Integer(_) | Self::Number(_)) }
|
||||
}
|
||||
|
||||
impl TryInto<ValueSendableKey> for ValueSendable {
|
||||
type Error = mlua::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, Table, UserData, Value};
|
||||
use mlua::{AnyUserData, ExternalError, Lua, Table, UserData, Value};
|
||||
use ratatui::widgets::Borders;
|
||||
|
||||
use super::{RectRef, Renderable, Style};
|
||||
|
|
@ -26,12 +26,12 @@ impl Bar {
|
|||
|
||||
let bar = lua.create_table_from([
|
||||
// Direction
|
||||
("NONE", Borders::NONE.bits().into_lua(lua)?),
|
||||
("TOP", Borders::TOP.bits().into_lua(lua)?),
|
||||
("RIGHT", Borders::RIGHT.bits().into_lua(lua)?),
|
||||
("BOTTOM", Borders::BOTTOM.bits().into_lua(lua)?),
|
||||
("LEFT", Borders::LEFT.bits().into_lua(lua)?),
|
||||
("ALL", Borders::ALL.bits().into_lua(lua)?),
|
||||
("NONE", Borders::NONE.bits()),
|
||||
("TOP", Borders::TOP.bits()),
|
||||
("RIGHT", Borders::RIGHT.bits()),
|
||||
("BOTTOM", Borders::BOTTOM.bits()),
|
||||
("LEFT", Borders::LEFT.bits()),
|
||||
("ALL", Borders::ALL.bits()),
|
||||
])?;
|
||||
|
||||
bar.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, Table, UserData, Value};
|
||||
use mlua::{AnyUserData, ExternalError, Lua, Table, UserData, Value};
|
||||
use ratatui::widgets::{Borders, Widget};
|
||||
|
||||
use super::{RectRef, Renderable, Style};
|
||||
|
|
@ -32,19 +32,19 @@ impl Border {
|
|||
|
||||
let border = lua.create_table_from([
|
||||
// Position
|
||||
("NONE", Borders::NONE.bits().into_lua(lua)?),
|
||||
("TOP", Borders::TOP.bits().into_lua(lua)?),
|
||||
("RIGHT", Borders::RIGHT.bits().into_lua(lua)?),
|
||||
("BOTTOM", Borders::BOTTOM.bits().into_lua(lua)?),
|
||||
("LEFT", Borders::LEFT.bits().into_lua(lua)?),
|
||||
("ALL", Borders::ALL.bits().into_lua(lua)?),
|
||||
("NONE", Borders::NONE.bits()),
|
||||
("TOP", Borders::TOP.bits()),
|
||||
("RIGHT", Borders::RIGHT.bits()),
|
||||
("BOTTOM", Borders::BOTTOM.bits()),
|
||||
("LEFT", Borders::LEFT.bits()),
|
||||
("ALL", Borders::ALL.bits()),
|
||||
// Type
|
||||
("PLAIN", PLAIN.into_lua(lua)?),
|
||||
("ROUNDED", ROUNDED.into_lua(lua)?),
|
||||
("DOUBLE", DOUBLE.into_lua(lua)?),
|
||||
("THICK", THICK.into_lua(lua)?),
|
||||
("QUADRANT_INSIDE", QUADRANT_INSIDE.into_lua(lua)?),
|
||||
("QUADRANT_OUTSIDE", QUADRANT_OUTSIDE.into_lua(lua)?),
|
||||
("PLAIN", PLAIN),
|
||||
("ROUNDED", ROUNDED),
|
||||
("DOUBLE", DOUBLE),
|
||||
("THICK", THICK),
|
||||
("QUADRANT_INSIDE", QUADRANT_INSIDE),
|
||||
("QUADRANT_OUTSIDE", QUADRANT_OUTSIDE),
|
||||
])?;
|
||||
|
||||
border.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
|
|
|||
75
yazi-plugin/src/elements/clear.rs
Normal file
75
yazi-plugin/src/elements/clear.rs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use mlua::{Lua, Table, UserData};
|
||||
use ratatui::layout::Rect;
|
||||
use yazi_adaptor::ADAPTOR;
|
||||
|
||||
use super::{RectRef, Renderable};
|
||||
|
||||
pub static COLLISION: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Clear {
|
||||
pub area: ratatui::layout::Rect,
|
||||
}
|
||||
|
||||
impl Clear {
|
||||
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
|
||||
let new = lua.create_function(|_, (_, area): (Table, RectRef)| Ok(Clear { area: *area }))?;
|
||||
|
||||
let clear = lua.create_table()?;
|
||||
clear.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
||||
ui.raw_set("Clear", clear)
|
||||
}
|
||||
}
|
||||
|
||||
impl ratatui::widgets::Widget for Clear {
|
||||
fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
ratatui::widgets::Clear.render(area, buf);
|
||||
|
||||
let Some(r) = ADAPTOR.shown_load().and_then(|r| overlap(&area, &r)) else {
|
||||
return;
|
||||
};
|
||||
|
||||
ADAPTOR.image_erase(r).ok();
|
||||
COLLISION.store(true, Ordering::Relaxed);
|
||||
for y in area.top()..area.bottom() {
|
||||
for x in area.left()..area.right() {
|
||||
buf.get_mut(x, y).set_skip(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderable for Clear {
|
||||
fn area(&self) -> ratatui::layout::Rect { self.area }
|
||||
|
||||
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
|
||||
<Self as ratatui::widgets::Widget>::render(Default::default(), self.area, buf);
|
||||
}
|
||||
|
||||
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(*self).render(buf); }
|
||||
}
|
||||
|
||||
impl UserData for Clear {}
|
||||
|
||||
#[inline]
|
||||
const fn is_overlapping(a: &Rect, b: &Rect) -> bool {
|
||||
a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y
|
||||
}
|
||||
|
||||
fn overlap(a: &Rect, b: &Rect) -> Option<Rect> {
|
||||
if !is_overlapping(a, b) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let x = a.x.max(b.x);
|
||||
let y = a.y.max(b.y);
|
||||
let width = (a.x + a.width).min(b.x + b.width) - x;
|
||||
let height = (a.y + a.height).min(b.y + b.height) - y;
|
||||
Some(Rect { x, y, width, height })
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ pub fn pour(lua: &Lua) -> mlua::Result<()> {
|
|||
// Install
|
||||
super::Bar::install(lua, &ui)?;
|
||||
super::Border::install(lua, &ui)?;
|
||||
super::Clear::install(lua, &ui)?;
|
||||
super::Constraint::install(lua, &ui)?;
|
||||
super::Gauge::install(lua, &ui)?;
|
||||
super::Layout::install(lua, &ui)?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{AnyUserData, IntoLua, Lua, Table, UserData, UserDataMethods};
|
||||
use mlua::{AnyUserData, Lua, Table, UserData, UserDataMethods};
|
||||
|
||||
use super::{Constraint, Rect, RectRef};
|
||||
use crate::bindings::Cast;
|
||||
|
|
@ -17,10 +17,7 @@ impl Layout {
|
|||
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
|
||||
let new = lua.create_function(|_, _: Table| Ok(Self::default()))?;
|
||||
|
||||
let layout = lua.create_table_from([
|
||||
("HORIZONTAL", HORIZONTAL.into_lua(lua)?),
|
||||
("VERTICAL", VERTICAL.into_lua(lua)?),
|
||||
])?;
|
||||
let layout = lua.create_table_from([("HORIZONTAL", HORIZONTAL), ("VERTICAL", VERTICAL)])?;
|
||||
|
||||
layout.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use mlua::{AnyUserData, ExternalError, FromLua, IntoLua, Lua, Table, UserData, UserDataMethods, Value};
|
||||
use std::mem;
|
||||
|
||||
use ansi_to_tui::IntoText;
|
||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, Table, UserData, UserDataMethods, Value};
|
||||
|
||||
use super::{Span, Style};
|
||||
|
||||
|
|
@ -39,7 +42,21 @@ impl Line {
|
|||
Err("expected a table of Spans or Lines".into_lua_err())
|
||||
})?;
|
||||
|
||||
let parse = lua.create_function(|_, code: mlua::String| {
|
||||
let Some(line) = code.as_bytes().split_inclusive(|&b| b == b'\n').next() else {
|
||||
return Ok(Line(Default::default()));
|
||||
};
|
||||
|
||||
let mut lines = line.into_text().into_lua_err()?.lines;
|
||||
if lines.is_empty() {
|
||||
return Ok(Line(Default::default()));
|
||||
}
|
||||
|
||||
Ok(Line(mem::take(&mut lines[0])))
|
||||
})?;
|
||||
|
||||
let line = lua.create_table_from([
|
||||
("parse", parse.into_lua(lua)?),
|
||||
// Alignment
|
||||
("LEFT", LEFT.into_lua(lua)?),
|
||||
("CENTER", CENTER.into_lua(lua)?),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
mod bar;
|
||||
mod border;
|
||||
mod clear;
|
||||
mod constraint;
|
||||
mod elements;
|
||||
mod gauge;
|
||||
|
|
@ -16,6 +17,7 @@ mod style;
|
|||
|
||||
pub use bar::*;
|
||||
pub use border::*;
|
||||
pub use clear::*;
|
||||
pub use constraint::*;
|
||||
pub use elements::*;
|
||||
pub use gauge::*;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{AnyUserData, IntoLua, Lua, Table, UserDataFields, UserDataMethods, UserDataRef};
|
||||
use mlua::{AnyUserData, Lua, Table, UserDataFields, UserDataMethods, UserDataRef};
|
||||
|
||||
use super::PaddingRef;
|
||||
use crate::bindings::Cast;
|
||||
|
|
@ -18,10 +18,7 @@ impl Rect {
|
|||
})
|
||||
})?;
|
||||
|
||||
let rect = lua.create_table_from([(
|
||||
"default",
|
||||
Rect::cast(lua, ratatui::layout::Rect::default())?.into_lua(lua)?,
|
||||
)])?;
|
||||
let rect = lua.create_table_from([("default", Rect::cast(lua, Default::default())?)])?;
|
||||
|
||||
rect.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{IntoLua, Lua, Value};
|
||||
use mlua::{IntoLuaMulti, Lua, Value};
|
||||
use tokio::fs;
|
||||
|
||||
use crate::{bindings::{Cast, Cha}, url::UrlRef};
|
||||
|
|
@ -10,28 +10,28 @@ pub fn install(lua: &Lua) -> mlua::Result<()> {
|
|||
(
|
||||
"write",
|
||||
lua.create_async_function(|lua, (url, data): (UrlRef, mlua::String)| async move {
|
||||
Ok(match fs::write(&*url, data).await {
|
||||
Ok(_) => (Value::Boolean(true), Value::Nil),
|
||||
Err(e) => (Value::Boolean(false), e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
match fs::write(&*url, data).await {
|
||||
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
})?,
|
||||
),
|
||||
(
|
||||
"cha",
|
||||
lua.create_async_function(|lua, url: UrlRef| async move {
|
||||
Ok(match fs::symlink_metadata(&*url).await {
|
||||
Ok(m) => (Cha::cast(lua, m)?.into_lua(lua)?, Value::Nil),
|
||||
Err(e) => (Value::Nil, e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
match fs::symlink_metadata(&*url).await {
|
||||
Ok(m) => (Cha::cast(lua, m)?, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
})?,
|
||||
),
|
||||
(
|
||||
"cha_follow",
|
||||
lua.create_async_function(|lua, url: UrlRef| async move {
|
||||
Ok(match fs::metadata(&*url).await {
|
||||
Ok(m) => (Cha::cast(lua, m)?.into_lua(lua)?, Value::Nil),
|
||||
Err(e) => (Value::Nil, e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
match fs::metadata(&*url).await {
|
||||
Ok(m) => (Cha::cast(lua, m)?, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
})?,
|
||||
),
|
||||
])?,
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ impl Loader {
|
|||
None => Err(format!("plugin `{name}` not found").into_lua_err())?,
|
||||
};
|
||||
|
||||
t.raw_set("_name", LUA.create_string(name)?)?;
|
||||
loaded.raw_set(name, t.clone())?;
|
||||
Ok(t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl TryFrom<Cmd> for Opt {
|
|||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
|
||||
let Some(name) = c.take_first().filter(|s| !s.is_empty()) else {
|
||||
bail!("invalid plugin name");
|
||||
bail!("plugin name cannot be empty");
|
||||
};
|
||||
|
||||
let mut data: OptData = c.take_data().unwrap_or_default();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use mlua::{IntoLua, Table, UserData, Value};
|
||||
use mlua::{IntoLuaMulti, Table, UserData, Value};
|
||||
use tokio::{io::{AsyncBufReadExt, AsyncReadExt, BufReader}, process::{ChildStderr, ChildStdin, ChildStdout}, select};
|
||||
|
||||
use super::Status;
|
||||
|
|
@ -68,16 +68,14 @@ impl UserData for Child {
|
|||
}
|
||||
});
|
||||
methods.add_async_method_mut("wait", |lua, me, ()| async move {
|
||||
Ok(match me.inner.wait().await {
|
||||
Ok(status) => (Status::new(status).into_lua(lua)?, Value::Nil),
|
||||
Err(e) => (Value::Nil, e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
match me.inner.wait().await {
|
||||
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
methods.add_method_mut("start_kill", |lua, me, ()| {
|
||||
Ok(match me.inner.start_kill() {
|
||||
Ok(_) => (true, Value::Nil),
|
||||
Err(e) => (false, e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
methods.add_method_mut("start_kill", |lua, me, ()| match me.inner.start_kill() {
|
||||
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::process::Stdio;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, Lua, Table, UserData, Value};
|
||||
use mlua::{AnyUserData, IntoLuaMulti, Lua, Table, UserData, Value};
|
||||
|
||||
use super::{output::Output, Child};
|
||||
|
||||
|
|
@ -23,9 +23,9 @@ impl Command {
|
|||
|
||||
let command = lua.create_table_from([
|
||||
// Stdio
|
||||
("NULL", NULL.into_lua(lua)?),
|
||||
("PIPED", PIPED.into_lua(lua)?),
|
||||
("INHERIT", INHERIT.into_lua(lua)?),
|
||||
("NULL", NULL),
|
||||
("PIPED", PIPED),
|
||||
("INHERIT", INHERIT),
|
||||
])?;
|
||||
|
||||
command.set_metatable(Some(lua.create_table_from([("__call", new)])?));
|
||||
|
|
@ -49,6 +49,10 @@ impl UserData for Command {
|
|||
}
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function(
|
||||
"env",
|
||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||
|
|
@ -82,17 +86,15 @@ impl UserData for Command {
|
|||
});
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_method_mut("spawn", |lua, me, ()| {
|
||||
Ok(match me.inner.spawn() {
|
||||
Ok(child) => (Child::new(child).into_lua(lua)?, Value::Nil),
|
||||
Err(e) => (Value::Nil, e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
methods.add_method_mut("spawn", |lua, me, ()| match me.inner.spawn() {
|
||||
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
});
|
||||
methods.add_async_method_mut("output", |lua, me, ()| async move {
|
||||
Ok(match me.inner.output().await {
|
||||
Ok(output) => (Output::new(output).into_lua(lua)?, Value::Nil),
|
||||
Err(e) => (Value::Nil, e.raw_os_error().into_lua(lua)?),
|
||||
})
|
||||
match me.inner.output().await {
|
||||
Ok(output) => (Output::new(output), Value::Nil).into_lua_multi(lua),
|
||||
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::str::FromStr;
|
|||
use mlua::{ExternalError, ExternalResult, IntoLuaMulti, Lua, Table, Value};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::{keymap::{Control, Key}, popup::InputCfg};
|
||||
use yazi_proxy::InputProxy;
|
||||
use yazi_proxy::{AppProxy, InputProxy};
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use super::Utils;
|
||||
|
|
@ -79,6 +79,14 @@ impl Utils {
|
|||
})?,
|
||||
)?;
|
||||
|
||||
ya.raw_set(
|
||||
"notify",
|
||||
lua.create_function(|_, t: Table| {
|
||||
AppProxy::notify(t.try_into()?);
|
||||
Ok(())
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.3" }
|
|||
|
||||
# External dependencies
|
||||
anyhow = "^1"
|
||||
mlua = { version = "^0", features = [ "lua54", "vendored" ] }
|
||||
tokio = { version = "^1", features = [ "parking_lot" ] }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use crate::options::{NotifyLevel, NotifyOpt};
|
||||
|
||||
pub struct AppProxy;
|
||||
|
||||
impl AppProxy {
|
||||
|
|
@ -16,14 +20,19 @@ impl AppProxy {
|
|||
emit!(Call(Cmd::new("resume"), Layer::App));
|
||||
}
|
||||
|
||||
pub fn notify(opt: NotifyOpt) {
|
||||
emit!(Call(Cmd::new("notify").with_data(opt), Layer::App));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn warn(title: &str, content: &str) {
|
||||
pub fn notify_warn(title: &str, content: &str) {
|
||||
emit!(Call(
|
||||
Cmd::new("notify")
|
||||
.with("title", title)
|
||||
.with("content", content)
|
||||
.with("level", "warn")
|
||||
.with("timeout", 5),
|
||||
Cmd::new("notify").with_data(NotifyOpt {
|
||||
title: title.to_owned(),
|
||||
content: content.to_owned(),
|
||||
level: NotifyLevel::Warn,
|
||||
timeout: Duration::from_secs(5),
|
||||
}),
|
||||
Layer::App
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,7 @@ use tokio::sync::mpsc;
|
|||
use yazi_config::popup::InputCfg;
|
||||
use yazi_shared::{emit, event::Cmd, InputError, Layer};
|
||||
|
||||
pub struct InputOpt {
|
||||
pub cfg: InputCfg,
|
||||
pub tx: mpsc::UnboundedSender<Result<String, InputError>>,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for InputOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
use crate::options::InputOpt;
|
||||
|
||||
pub struct InputProxy;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ mod app;
|
|||
mod completion;
|
||||
mod input;
|
||||
mod manager;
|
||||
pub mod options;
|
||||
mod select;
|
||||
mod tab;
|
||||
mod tasks;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
use yazi_shared::{emit, event::Cmd, fs::Url, Layer};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OpenDoOpt {
|
||||
pub hovered: Url,
|
||||
pub targets: Vec<(Url, String)>,
|
||||
pub interactive: bool,
|
||||
}
|
||||
|
||||
impl From<Cmd> for OpenDoOpt {
|
||||
fn from(mut c: Cmd) -> Self { c.take_data().unwrap_or_default() }
|
||||
}
|
||||
use crate::options::OpenDoOpt;
|
||||
|
||||
pub struct ManagerProxy;
|
||||
|
||||
|
|
|
|||
14
yazi-proxy/src/options/input.rs
Normal file
14
yazi-proxy/src/options/input.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use tokio::sync::mpsc;
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_shared::{event::Cmd, InputError};
|
||||
|
||||
pub struct InputOpt {
|
||||
pub cfg: InputCfg,
|
||||
pub tx: mpsc::UnboundedSender<Result<String, InputError>>,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for InputOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
9
yazi-proxy/src/options/mod.rs
Normal file
9
yazi-proxy/src/options/mod.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
mod input;
|
||||
mod notify;
|
||||
mod open;
|
||||
mod select;
|
||||
|
||||
pub use input::*;
|
||||
pub use notify::*;
|
||||
pub use open::*;
|
||||
pub use select::*;
|
||||
63
yazi-proxy/src/options/notify.rs
Normal file
63
yazi-proxy/src/options/notify.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use std::{str::FromStr, time::Duration};
|
||||
|
||||
use anyhow::bail;
|
||||
use mlua::{ExternalError, ExternalResult};
|
||||
use yazi_shared::event::Cmd;
|
||||
|
||||
pub struct NotifyOpt {
|
||||
pub title: String,
|
||||
pub content: String,
|
||||
pub level: NotifyLevel,
|
||||
pub timeout: Duration,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for NotifyOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<mlua::Table<'a>> for NotifyOpt {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(t: mlua::Table) -> Result<Self, Self::Error> {
|
||||
let timeout = t.raw_get::<_, f64>("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),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub enum NotifyLevel {
|
||||
#[default]
|
||||
Info,
|
||||
Warn,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl FromStr for NotifyLevel {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"info" => Self::Info,
|
||||
"warn" => Self::Warn,
|
||||
"error" => Self::Error,
|
||||
_ => bail!("Invalid notify level: {s}"),
|
||||
})
|
||||
}
|
||||
}
|
||||
26
yazi-proxy/src/options/open.rs
Normal file
26
yazi-proxy/src/options/open.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
use yazi_config::open::Opener;
|
||||
use yazi_shared::{event::Cmd, fs::Url};
|
||||
|
||||
// --- Open
|
||||
#[derive(Default)]
|
||||
pub struct OpenDoOpt {
|
||||
pub hovered: Url,
|
||||
pub targets: Vec<(Url, String)>,
|
||||
pub interactive: bool,
|
||||
}
|
||||
|
||||
impl From<Cmd> for OpenDoOpt {
|
||||
fn from(mut c: Cmd) -> Self { c.take_data().unwrap_or_default() }
|
||||
}
|
||||
|
||||
// --- Open with
|
||||
pub struct OpenWithOpt {
|
||||
pub targets: Vec<Url>,
|
||||
pub opener: Opener,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for OpenWithOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
14
yazi-proxy/src/options/select.rs
Normal file
14
yazi-proxy/src/options/select.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use tokio::sync::oneshot;
|
||||
use yazi_config::popup::SelectCfg;
|
||||
use yazi_shared::event::Cmd;
|
||||
|
||||
pub struct SelectOpt {
|
||||
pub cfg: SelectCfg,
|
||||
pub tx: oneshot::Sender<anyhow::Result<usize>>,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for SelectOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
|
|
@ -2,16 +2,7 @@ use tokio::sync::oneshot;
|
|||
use yazi_config::popup::SelectCfg;
|
||||
use yazi_shared::{emit, event::Cmd, term::Term, Layer};
|
||||
|
||||
pub struct SelectOpt {
|
||||
pub cfg: SelectCfg,
|
||||
pub tx: oneshot::Sender<anyhow::Result<usize>>,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for SelectOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
use crate::options::SelectOpt;
|
||||
|
||||
pub struct SelectProxy;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,10 @@
|
|||
use yazi_config::open::Opener;
|
||||
use yazi_shared::{emit, event::Cmd, fs::Url, Layer};
|
||||
|
||||
use crate::options::OpenWithOpt;
|
||||
|
||||
pub struct TasksProxy;
|
||||
|
||||
pub struct OpenWithOpt {
|
||||
pub targets: Vec<Url>,
|
||||
pub opener: Opener,
|
||||
}
|
||||
|
||||
impl TryFrom<Cmd> for OpenWithOpt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
|
||||
}
|
||||
|
||||
impl TasksProxy {
|
||||
#[inline]
|
||||
pub fn open_with(targets: Vec<Url>, opener: Opener) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue