mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-23 07:41:03 +00:00
refactor: make command data cloneable (#3613)
This commit is contained in:
parent
face6aed40
commit
92880b844b
81 changed files with 297 additions and 203 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -1242,6 +1242,12 @@ dependencies = [
|
|||
"litrs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.9"
|
||||
|
|
@ -5726,6 +5732,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"bitflags 2.10.0",
|
||||
"crossterm 0.29.0",
|
||||
"dyn-clone",
|
||||
"hashbrown",
|
||||
"mlua",
|
||||
"ordered-float 5.1.0",
|
||||
|
|
@ -5844,6 +5851,7 @@ version = "26.1.22"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"crossterm 0.29.0",
|
||||
"dyn-clone",
|
||||
"foldhash",
|
||||
"futures",
|
||||
"hashbrown",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ clap = { version = "4.5.54", features = [ "derive" ] }
|
|||
core-foundation-sys = "0.8.7"
|
||||
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
|
||||
dirs = "6.0.0"
|
||||
dyn-clone = "1.0.20"
|
||||
foldhash = "0.2.0"
|
||||
futures = "0.3.31"
|
||||
globset = "0.4.18"
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@ impl Actor for Close {
|
|||
const NAME: &str = "close";
|
||||
|
||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
if let Some(cb) = cx.confirm.callback.take() {
|
||||
_ = cb.send(opt.submit);
|
||||
}
|
||||
|
||||
cx.confirm.token.complete(opt.submit);
|
||||
cx.confirm.visible = false;
|
||||
succ!(render!());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl Actor for Show {
|
|||
confirm.position = opt.cfg.position;
|
||||
confirm.offset = 0;
|
||||
|
||||
confirm.callback = Some(opt.tx);
|
||||
confirm.token = opt.token;
|
||||
confirm.visible = true;
|
||||
|
||||
succ!(render!());
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub(super) struct Core {
|
|||
c_tasks: Option<Value>,
|
||||
c_yanked: Option<Value>,
|
||||
c_layer: Option<Value>,
|
||||
c_which: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Core {
|
||||
|
|
@ -31,6 +32,7 @@ impl Core {
|
|||
c_tasks: None,
|
||||
c_yanked: None,
|
||||
c_layer: None,
|
||||
c_which: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +60,7 @@ impl UserData for Core {
|
|||
b"layer" => {
|
||||
reuse!(layer, Ok::<_, mlua::Error>(yazi_plugin::bindings::Layer::from(me.layer())))
|
||||
}
|
||||
b"which" => reuse!(which, super::Which::make(&me.which)),
|
||||
_ => Value::Nil,
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(core file files filter finder folder lives mode preference preview ptr selected tab tabs task tasks yanked);
|
||||
yazi_macro::mod_flat!(core file files filter finder folder lives mode preference preview ptr selected tab tabs task tasks which yanked);
|
||||
|
|
|
|||
25
yazi-actor/src/lives/which.rs
Normal file
25
yazi-actor/src/lives/which.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Which {
|
||||
inner: PtrCell<yazi_core::which::Which>,
|
||||
}
|
||||
|
||||
impl Deref for Which {
|
||||
type Target = yazi_core::which::Which;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Which {
|
||||
pub(super) fn make(inner: &yazi_core::which::Which) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Which {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {}
|
||||
}
|
||||
|
|
@ -22,7 +22,10 @@ impl Actor for Displace {
|
|||
let tab = cx.tab().id;
|
||||
let from = cx.cwd().to_owned();
|
||||
tokio::spawn(async move {
|
||||
MgrProxy::displace_do(tab, DisplaceDoOpt { to: provider::canonicalize(&from).await, from });
|
||||
MgrProxy::displace_do(tab, DisplaceDoOpt {
|
||||
to: provider::canonicalize(&from).await.map_err(Into::into),
|
||||
from,
|
||||
});
|
||||
});
|
||||
|
||||
succ!();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ impl Actor for DisplaceDo {
|
|||
|
||||
let to = match opt.to {
|
||||
Ok(url) => url,
|
||||
Err(e) => return act!(mgr:update_files, cx, FilesOp::IOErr(opt.from, e.into())),
|
||||
Err(e) => return act!(mgr:update_files, cx, FilesOp::IOErr(opt.from, e)),
|
||||
};
|
||||
|
||||
if !to.is_absolute() {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ impl Actor for OpenDo {
|
|||
let urls: Vec<_> =
|
||||
[UrlCow::default()].into_iter().chain(targets.into_iter().map(|(u, _)| u)).collect();
|
||||
tokio::spawn(async move {
|
||||
if let Ok(choice) = pick.await {
|
||||
if let Some(choice) = pick.await {
|
||||
TasksProxy::open_shell_compat(ProcessOpenOpt {
|
||||
cwd: opt.cwd,
|
||||
cmd: openers[choice].run.clone().into(),
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ impl Actor for Quit {
|
|||
|
||||
tokio::spawn(async move {
|
||||
let mut i = 0;
|
||||
let mut rx = ConfirmProxy::show_rx(ConfirmCfg::quit(left, left_names));
|
||||
let token = ConfirmProxy::show_sync(ConfirmCfg::quit(left, left_names));
|
||||
loop {
|
||||
select! {
|
||||
_ = time::sleep(Duration::from_millis(50)) => {
|
||||
|
|
@ -44,8 +44,8 @@ impl Actor for Quit {
|
|||
return;
|
||||
}
|
||||
}
|
||||
b = &mut rx => {
|
||||
if b.unwrap_or(false) {
|
||||
b = token.future() => {
|
||||
if b {
|
||||
emit!(Quit(event));
|
||||
}
|
||||
return;
|
||||
|
|
@ -53,7 +53,7 @@ impl Actor for Quit {
|
|||
}
|
||||
}
|
||||
|
||||
if rx.await.unwrap_or(false) {
|
||||
if token.future().await {
|
||||
emit!(Quit(event));
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{Result, anyhow};
|
||||
use anyhow::Result;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::pick::CloseOpt;
|
||||
use yazi_shared::data::Data;
|
||||
|
|
@ -15,7 +15,7 @@ impl Actor for Close {
|
|||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
let pick = &mut cx.pick;
|
||||
if let Some(cb) = pick.callback.take() {
|
||||
_ = cb.send(if opt.submit { Ok(pick.cursor) } else { Err(anyhow!("canceled")) });
|
||||
_ = cb.send(if opt.submit { Some(pick.cursor) } else { None });
|
||||
}
|
||||
|
||||
pick.cursor = 0;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl Actor for Callback {
|
|||
const NAME: &str = "callback";
|
||||
|
||||
fn act(_: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
opt.tx.try_send(opt.idx)?;
|
||||
opt.tx.send(opt.idx)?;
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use super::Key;
|
|||
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct Chord {
|
||||
#[serde(deserialize_with = "super::deserialize_on")]
|
||||
pub on: Vec<Key>,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use yazi_shared::event::CmdCow;
|
|||
|
||||
use super::Chord;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ChordCow {
|
||||
Owned(Chord),
|
||||
Borrowed(&'static Chord),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use yazi_shared::{scheme::Encode as EncodeScheme, strand::ToStrand, url::{Url, U
|
|||
use super::{Offset, Position};
|
||||
use crate::YAZI;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct InputCfg {
|
||||
pub title: String,
|
||||
pub value: String,
|
||||
|
|
@ -15,14 +15,14 @@ pub struct InputCfg {
|
|||
pub completion: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PickCfg {
|
||||
pub title: String,
|
||||
pub items: Vec<String>,
|
||||
pub position: Position,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ConfirmCfg {
|
||||
pub position: Position,
|
||||
pub title: Line<'static>,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ratatui::{text::Line, widgets::Paragraph};
|
||||
use tokio::sync::oneshot::Sender;
|
||||
use yazi_config::popup::Position;
|
||||
use yazi_shared::CompletionToken;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Confirm {
|
||||
|
|
@ -11,6 +11,6 @@ pub struct Confirm {
|
|||
pub position: Position,
|
||||
pub offset: usize,
|
||||
|
||||
pub callback: Option<Sender<bool>>,
|
||||
pub visible: bool,
|
||||
pub token: CompletionToken,
|
||||
pub visible: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use tokio::sync::oneshot::Sender;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use yazi_config::{YAZI, popup::Position};
|
||||
use yazi_widgets::Scrollable;
|
||||
|
||||
|
|
@ -11,7 +10,7 @@ pub struct Pick {
|
|||
|
||||
pub offset: usize,
|
||||
pub cursor: usize,
|
||||
pub callback: Option<Sender<Result<usize>>>,
|
||||
pub callback: Option<UnboundedSender<Option<usize>>>,
|
||||
|
||||
pub visible: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub struct Client {
|
|||
pub(super) abilities: HashSet<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Peer {
|
||||
pub(super) abilities: HashSet<String>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use yazi_shared::url::{Url, UrlCow};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberBulk<'a> {
|
||||
pub changes: HashMap<UrlCow<'a>, UrlCow<'a>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberBye;
|
||||
|
||||
impl EmberBye {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::{Id, url::UrlBuf};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberCd<'a> {
|
||||
pub tab: Id,
|
||||
pub url: Cow<'a, UrlBuf>,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use yazi_shared::data::Data;
|
|||
use super::Ember;
|
||||
use crate::Sendable;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EmberCustom {
|
||||
pub kind: String,
|
||||
pub data: Data,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::url::UrlBuf;
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberDelete<'a> {
|
||||
pub urls: Cow<'a, Vec<UrlBuf>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::url::UrlBuf;
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberDuplicate<'a> {
|
||||
pub items: Cow<'a, Vec<BodyDuplicateItem>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use yazi_shared::Id;
|
|||
use super::{EmberBulk, EmberBye, EmberCd, EmberCustom, EmberDelete, EmberDuplicate, EmberHey, EmberHi, EmberHover, EmberLoad, EmberMount, EmberMove, EmberRename, EmberTab, EmberTrash, EmberYank};
|
||||
use crate::Payload;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Ember<'a> {
|
||||
Hi(EmberHi<'a>),
|
||||
Hey(EmberHey),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use super::{Ember, EmberHi};
|
|||
use crate::Peer;
|
||||
|
||||
/// Server handshake
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberHey {
|
||||
pub peers: HashMap<Id, Peer>,
|
||||
pub version: SStr,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use yazi_shared::SStr;
|
|||
use super::Ember;
|
||||
|
||||
/// Client handshake
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberHi<'a> {
|
||||
/// Kinds of events the client can handle
|
||||
pub abilities: HashSet<Cow<'a, str>>,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::{Id, url::UrlBuf};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberHover<'a> {
|
||||
pub tab: Id,
|
||||
pub url: Option<Cow<'a, UrlBuf>>,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use yazi_shared::{Id, url::UrlBuf};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberLoad<'a> {
|
||||
pub tab: Id,
|
||||
pub url: Cow<'a, UrlBuf>,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberMount;
|
||||
|
||||
impl EmberMount {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::url::UrlBuf;
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberMove<'a> {
|
||||
pub items: Cow<'a, Vec<BodyMoveItem>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::{Id, url::UrlBuf};
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberRename<'a> {
|
||||
pub tab: Id,
|
||||
pub from: Cow<'a, UrlBuf>,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use yazi_shared::Id;
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberTab {
|
||||
pub id: Id,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use yazi_shared::url::UrlBuf;
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberTrash<'a> {
|
||||
pub urls: Cow<'a, Vec<UrlBuf>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use yazi_shared::url::UrlBufCov;
|
|||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberYank<'a>(UpdateYankedOpt<'a>);
|
||||
|
||||
impl<'a> EmberYank<'a> {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use yazi_shared::Id;
|
|||
|
||||
use crate::{ID, ember::Ember};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Payload<'a> {
|
||||
pub receiver: Id,
|
||||
pub sender: Id,
|
||||
|
|
|
|||
|
|
@ -84,14 +84,21 @@ impl Sendable {
|
|||
}
|
||||
Data::Url(u) => yazi_binding::Url::new(u).into_lua(lua)?,
|
||||
Data::Path(u) => yazi_binding::Path::new(u).into_lua(lua)?,
|
||||
Data::Any(a) => {
|
||||
if a.is::<yazi_fs::FilesOp>() {
|
||||
lua.create_any_userdata(*a.downcast::<yazi_fs::FilesOp>().unwrap())?.into_lua(lua)?
|
||||
} else if a.is::<yazi_parser::mgr::UpdateYankedOpt>() {
|
||||
a.downcast::<yazi_parser::mgr::UpdateYankedOpt>().unwrap().into_lua(lua)?
|
||||
} else {
|
||||
Err("unsupported Data::Any included".into_lua_err())?
|
||||
Data::Any(b) => {
|
||||
let mut b = b.into_any();
|
||||
macro_rules! try_cast {
|
||||
($f:expr) => {
|
||||
match b.downcast() {
|
||||
Ok(v) => return $f(*v)?.into_lua(lua),
|
||||
#[allow(unused_assignments)]
|
||||
Err(e) => b = e,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try_cast!(|v: yazi_fs::FilesOp| lua.create_any_userdata(v));
|
||||
try_cast!(|v: yazi_parser::mgr::UpdateYankedOpt| v.into_lua(lua));
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
}
|
||||
data => Self::data_to_value_ref(lua, &data)?,
|
||||
})
|
||||
|
|
@ -124,12 +131,12 @@ impl Sendable {
|
|||
Data::Path(u) => yazi_binding::Path::new(u).into_lua(lua)?,
|
||||
Data::Bytes(b) => Value::String(lua.create_string(b)?),
|
||||
Data::Any(a) => {
|
||||
if let Some(t) = a.downcast_ref::<yazi_fs::FilesOp>() {
|
||||
if let Some(t) = a.as_any().downcast_ref::<yazi_fs::FilesOp>() {
|
||||
lua.create_any_userdata(t.clone())?.into_lua(lua)?
|
||||
} else if let Some(t) = a.downcast_ref::<yazi_parser::mgr::UpdateYankedOpt>() {
|
||||
} else if let Some(t) = a.as_any().downcast_ref::<yazi_parser::mgr::UpdateYankedOpt>() {
|
||||
t.clone().into_lua(lua)?
|
||||
} else {
|
||||
Err("unsupported Data::Any included".into_lua_err())?
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl App {
|
|||
drop(loader);
|
||||
|
||||
let result = Lives::scope(&self.core, || {
|
||||
if let Some(cb) = opt.cb {
|
||||
if let Some(cb) = opt.callback {
|
||||
cb(&LUA, plugin)
|
||||
} else {
|
||||
let job = LUA.create_table_from([("args", Sendable::args_to_table(&LUA, opt.args)?)])?;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::VoidOpt;
|
||||
use yazi_parser::app::ResumeOpt;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Term, app::App};
|
||||
|
||||
impl App {
|
||||
pub(crate) fn resume(&mut self, _: VoidOpt) -> Result<Data> {
|
||||
pub(crate) fn resume(&mut self, opt: ResumeOpt) -> Result<Data> {
|
||||
self.core.active_mut().preview.reset();
|
||||
self.term = Some(Term::start().unwrap());
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ impl App {
|
|||
// We need to trigger a resize, and render the UI based on the resized area.
|
||||
act!(resize, self)?;
|
||||
|
||||
self.signals.resume(None);
|
||||
self.signals.resume(opt.token);
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl App {
|
|||
// while the app is being suspended.
|
||||
self.term = None;
|
||||
|
||||
self.signals.stop(opt.tx);
|
||||
self.signals.stop(opt.token);
|
||||
|
||||
succ!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use crossterm::event::{Event as CrosstermEvent, EventStream, KeyEvent, KeyEventKind};
|
||||
use futures::StreamExt;
|
||||
use tokio::{select, sync::{mpsc, oneshot}};
|
||||
use tokio::{select, sync::mpsc};
|
||||
use yazi_config::YAZI;
|
||||
use yazi_shared::event::Event;
|
||||
use yazi_shared::{CompletionToken, event::Event};
|
||||
|
||||
pub(super) struct Signals {
|
||||
tx: mpsc::UnboundedSender<(bool, Option<oneshot::Sender<()>>)>,
|
||||
tx: mpsc::UnboundedSender<(bool, CompletionToken)>,
|
||||
}
|
||||
|
||||
impl Signals {
|
||||
|
|
@ -17,11 +17,9 @@ impl Signals {
|
|||
Ok(Self { tx })
|
||||
}
|
||||
|
||||
pub(super) fn stop(&mut self, cb: Option<oneshot::Sender<()>>) { self.tx.send((false, cb)).ok(); }
|
||||
pub(super) fn stop(&mut self, token: CompletionToken) { self.tx.send((false, token)).ok(); }
|
||||
|
||||
pub(super) fn resume(&mut self, cb: Option<oneshot::Sender<()>>) {
|
||||
self.tx.send((true, cb)).ok();
|
||||
}
|
||||
pub(super) fn resume(&mut self, token: CompletionToken) { self.tx.send((true, token)).ok(); }
|
||||
|
||||
#[cfg(unix)]
|
||||
fn handle_sys(n: libc::c_int) -> bool {
|
||||
|
|
@ -71,7 +69,7 @@ impl Signals {
|
|||
}
|
||||
}
|
||||
|
||||
fn spawn(mut rx: mpsc::UnboundedReceiver<(bool, Option<oneshot::Sender<()>>)>) -> Result<()> {
|
||||
fn spawn(mut rx: mpsc::UnboundedReceiver<(bool, CompletionToken)>) -> Result<()> {
|
||||
#[cfg(unix)]
|
||||
use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP};
|
||||
|
||||
|
|
@ -96,9 +94,9 @@ impl Signals {
|
|||
if let Some(t) = &mut term {
|
||||
select! {
|
||||
biased;
|
||||
Some((state, mut callback)) = rx.recv() => {
|
||||
Some((state, token)) = rx.recv() => {
|
||||
term = term.filter(|_| state);
|
||||
callback.take().map(|cb| cb.send(()));
|
||||
token.complete(true);
|
||||
},
|
||||
Some(n) = sys.next() => if !Self::handle_sys(n) { return },
|
||||
Some(Ok(e)) = t.next() => Self::handle_term(e)
|
||||
|
|
@ -106,9 +104,9 @@ impl Signals {
|
|||
} else {
|
||||
select! {
|
||||
biased;
|
||||
Some((state, mut callback)) = rx.recv() => {
|
||||
Some((state, token)) = rx.recv() => {
|
||||
term = state.then(EventStream::new);
|
||||
callback.take().map(|cb| cb.send(()));
|
||||
token.complete(true);
|
||||
},
|
||||
Some(n) = sys.next() => if !Self::handle_sys(n) { return },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ yazi-vfs = { path = "../yazi-vfs", version = "26.1.22" }
|
|||
anyhow = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
dyn-clone = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
ordered-float = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use serde::Deserialize;
|
|||
use yazi_config::{Style, THEME};
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NotifyOpt {
|
||||
pub title: String,
|
||||
pub content: String,
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
use std::{borrow::Cow, fmt::Debug, str::FromStr};
|
||||
use std::{borrow::Cow, fmt::{self, Debug}, str::FromStr};
|
||||
|
||||
use anyhow::bail;
|
||||
use dyn_clone::DynClone;
|
||||
use hashbrown::HashMap;
|
||||
use mlua::{Lua, Table};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::{SStr, data::{Data, DataKey}, event::{Cmd, CmdCow}};
|
||||
|
||||
pub type PluginCallback = Box<dyn FnOnce(&Lua, Table) -> mlua::Result<()> + Send + Sync>;
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PluginOpt {
|
||||
pub id: SStr,
|
||||
pub args: HashMap<DataKey, Data>,
|
||||
pub mode: PluginMode,
|
||||
pub cb: Option<PluginCallback>,
|
||||
pub id: SStr,
|
||||
pub args: HashMap<DataKey, Data>,
|
||||
pub mode: PluginMode,
|
||||
pub callback: Option<Box<dyn PluginCallback>>,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for PluginOpt {
|
||||
|
|
@ -36,27 +35,16 @@ impl TryFrom<CmdCow> for PluginOpt {
|
|||
};
|
||||
|
||||
let mode = c.str("mode").parse().unwrap_or_default();
|
||||
Ok(Self { id: Self::normalize_id(id), args, mode, cb: c.take_any("callback") })
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for PluginOpt {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("PluginOpt")
|
||||
.field("id", &self.id)
|
||||
.field("args", &self.args)
|
||||
.field("mode", &self.mode)
|
||||
.field("cb", &self.cb.is_some())
|
||||
.finish()
|
||||
Ok(Self { id: Self::normalize_id(id), args, mode, callback: c.take_any("callback") })
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginOpt {
|
||||
pub fn new_callback(id: impl Into<SStr>, cb: PluginCallback) -> Self {
|
||||
pub fn new_callback(id: impl Into<SStr>, f: impl PluginCallback) -> Self {
|
||||
Self {
|
||||
id: Self::normalize_id(id.into()),
|
||||
mode: PluginMode::Sync,
|
||||
cb: Some(cb),
|
||||
callback: Some(Box::new(f)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -98,3 +86,24 @@ impl PluginMode {
|
|||
if sync { Self::Sync } else { Self::Async }
|
||||
}
|
||||
}
|
||||
|
||||
// --- Callback
|
||||
pub trait PluginCallback:
|
||||
FnOnce(&Lua, Table) -> mlua::Result<()> + Send + Sync + DynClone + 'static
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> PluginCallback for T where
|
||||
T: FnOnce(&Lua, Table) -> mlua::Result<()> + Send + Sync + DynClone + 'static
|
||||
{
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn PluginCallback> {
|
||||
fn clone(&self) -> Self { dyn_clone::clone_box(&**self) }
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn PluginCallback {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PluginCallback").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
use tokio::sync::oneshot;
|
||||
use yazi_shared::event::CmdCow;
|
||||
use anyhow::bail;
|
||||
use yazi_shared::{CompletionToken, event::CmdCow};
|
||||
|
||||
pub struct ResumeOpt {
|
||||
pub tx: Option<oneshot::Sender<()>>,
|
||||
pub token: CompletionToken,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for ResumeOpt {
|
||||
fn from(mut c: CmdCow) -> Self { Self { tx: c.take_any("tx") } }
|
||||
impl TryFrom<CmdCow> for ResumeOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(token) = c.take_any("token") else {
|
||||
bail!("Invalid 'token' in ResumeOpt");
|
||||
};
|
||||
|
||||
Ok(Self { token })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
use tokio::sync::oneshot;
|
||||
use yazi_shared::event::CmdCow;
|
||||
use anyhow::bail;
|
||||
use yazi_shared::{CompletionToken, event::CmdCow};
|
||||
|
||||
pub struct StopOpt {
|
||||
pub tx: Option<oneshot::Sender<()>>,
|
||||
pub token: CompletionToken,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for StopOpt {
|
||||
fn from(mut c: CmdCow) -> Self { Self { tx: c.take_any("tx") } }
|
||||
impl TryFrom<CmdCow> for StopOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(token) = c.take_any("token") else {
|
||||
bail!("Invalid 'token' in StopOpt");
|
||||
};
|
||||
|
||||
Ok(Self { token })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl TryFrom<CmdCow> for ArrowOpt {
|
|||
|
||||
fn try_from(c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Ok(step) = c.first() else {
|
||||
bail!("'step' is required for ArrowOpt");
|
||||
bail!("Invalid 'step' in ArrowOpt");
|
||||
};
|
||||
|
||||
Ok(Self { step })
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use anyhow::bail;
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_shared::{Id, event::CmdCow, path::PathBufDyn, strand::{StrandBuf, StrandLike}, url::UrlBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShowOpt {
|
||||
pub cache: Vec<CmpItem>,
|
||||
pub cache_name: UrlBuf,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use anyhow::bail;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_config::popup::ConfirmCfg;
|
||||
use yazi_shared::event::CmdCow;
|
||||
use yazi_shared::{CompletionToken, event::CmdCow};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShowOpt {
|
||||
pub cfg: ConfirmCfg,
|
||||
pub tx: oneshot::Sender<bool>,
|
||||
pub cfg: ConfirmCfg,
|
||||
pub token: CompletionToken,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for ShowOpt {
|
||||
|
|
@ -15,14 +14,14 @@ impl TryFrom<CmdCow> for ShowOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(cfg) = c.take_any("cfg") else {
|
||||
bail!("Invalid 'cfg' argument in ShowOpt");
|
||||
bail!("Invalid 'cfg' in ShowOpt");
|
||||
};
|
||||
|
||||
let Some(tx) = c.take_any("tx") else {
|
||||
bail!("Invalid 'tx' argument in ShowOpt");
|
||||
let Some(token) = c.take_any("token") else {
|
||||
bail!("Invalid 'token' in ShowOpt");
|
||||
};
|
||||
|
||||
Ok(Self { cfg, tx })
|
||||
Ok(Self { cfg, token })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ impl TryFrom<CmdCow> for ShowOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(cfg) = c.take_any("cfg") else {
|
||||
bail!("Invalid 'cfg' argument in ShowOpt");
|
||||
bail!("Invalid 'cfg' in ShowOpt");
|
||||
};
|
||||
|
||||
let Some(tx) = c.take_any("tx") else {
|
||||
bail!("Invalid 'tx' argument in ShowOpt");
|
||||
bail!("Invalid 'tx' in ShowOpt");
|
||||
};
|
||||
|
||||
Ok(Self { cfg, tx })
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ use anyhow::bail;
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_shared::{event::CmdCow, url::UrlBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DisplaceDoOpt {
|
||||
pub to: std::io::Result<UrlBuf>,
|
||||
pub to: Result<UrlBuf, yazi_fs::error::Error>,
|
||||
pub from: UrlBuf,
|
||||
}
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ impl TryFrom<CmdCow> for DisplaceDoOpt {
|
|||
if let Some(opt) = c.take_any2("opt") {
|
||||
opt
|
||||
} else {
|
||||
bail!("'opt' is required for DisplaceDoOpt");
|
||||
bail!("Invalid 'opt' in DisplaceDoOpt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
|||
use yazi_fs::FilterCase;
|
||||
use yazi_shared::{SStr, event::CmdCow};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct FilterOpt {
|
||||
pub query: SStr,
|
||||
pub case: FilterCase,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
|||
use yazi_fs::FilterCase;
|
||||
use yazi_shared::{SStr, event::CmdCow};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FindDoOpt {
|
||||
pub query: SStr,
|
||||
pub prev: bool,
|
||||
|
|
@ -19,7 +19,7 @@ impl TryFrom<CmdCow> for FindDoOpt {
|
|||
}
|
||||
|
||||
let Ok(query) = c.take_first() else {
|
||||
bail!("'query' is required for FindDoOpt");
|
||||
bail!("Invalid 'query' in FindDoOpt");
|
||||
};
|
||||
|
||||
Ok(Self { query, prev: c.bool("previous"), case: FilterCase::from(&*c) })
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_shared::{event::CmdCow, url::UrlCow};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOpt {
|
||||
pub cwd: Option<UrlCow<'static>>,
|
||||
pub targets: Vec<UrlCow<'static>>,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use anyhow::bail;
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_shared::{event::CmdCow, url::UrlCow};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct OpenDoOpt {
|
||||
pub cwd: UrlCow<'static>,
|
||||
pub targets: Vec<UrlCow<'static>>,
|
||||
|
|
@ -16,7 +16,7 @@ impl TryFrom<CmdCow> for OpenDoOpt {
|
|||
if let Some(opt) = c.take_any2("opt") {
|
||||
opt
|
||||
} else {
|
||||
bail!("'opt' is required for OpenDoOpt");
|
||||
bail!("Invalid 'opt' in OpenDoOpt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl TryFrom<CmdCow> for SearchOpt {
|
|||
};
|
||||
|
||||
let Ok(args) = yazi_shared::shell::unix::split(c.str("args"), false) else {
|
||||
bail!("Invalid 'args' argument in SearchOpt");
|
||||
bail!("Invalid 'args' in SearchOpt");
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl TryFrom<CmdCow> for UpdateFilesOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(op) = c.take_any("op") else {
|
||||
bail!("Invalid 'op' argument in UpdateFilesOpt");
|
||||
bail!("Invalid 'op' in UpdateFilesOpt");
|
||||
};
|
||||
|
||||
Ok(Self { op })
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl TryFrom<CmdCow> for UpdateMimesOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Ok(updates) = c.take("updates") else {
|
||||
bail!("Invalid 'updates' argument in UpdateMimesOpt");
|
||||
bail!("Invalid 'updates' in UpdateMimesOpt");
|
||||
};
|
||||
|
||||
Ok(Self { updates })
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value};
|
|||
use yazi_binding::{FileRef, elements::{Rect, Renderable}};
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UpdatePeekedOpt {
|
||||
pub lock: PreviewLock,
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ impl TryFrom<CmdCow> for UpdatePeekedOpt {
|
|||
}
|
||||
|
||||
let Some(lock) = c.take_any("lock") else {
|
||||
bail!("Invalid 'lock' argument in UpdatePeekedOpt");
|
||||
bail!("Invalid 'lock' in UpdatePeekedOpt");
|
||||
};
|
||||
|
||||
Ok(Self { lock })
|
||||
|
|
@ -33,7 +33,7 @@ impl IntoLua for UpdatePeekedOpt {
|
|||
}
|
||||
|
||||
// --- Lock
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PreviewLock {
|
||||
pub url: yazi_shared::url::UrlBuf,
|
||||
pub cha: yazi_fs::cha::Cha,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value};
|
|||
use yazi_binding::{FileRef, elements::Renderable};
|
||||
use yazi_shared::{Id, event::CmdCow};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UpdateSpottedOpt {
|
||||
pub lock: SpotLock,
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ impl TryFrom<CmdCow> for UpdateSpottedOpt {
|
|||
}
|
||||
|
||||
let Some(lock) = c.take_any("lock") else {
|
||||
bail!("Invalid 'lock' argument in UpdateSpottedOpt");
|
||||
bail!("Invalid 'lock' in UpdateSpottedOpt");
|
||||
};
|
||||
|
||||
Ok(Self { lock })
|
||||
|
|
@ -33,7 +33,7 @@ impl IntoLua for UpdateSpottedOpt {
|
|||
}
|
||||
|
||||
// --- Lock
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpotLock {
|
||||
pub url: yazi_shared::url::UrlBuf,
|
||||
pub cha: yazi_fs::cha::Cha,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl TryFrom<CmdCow> for UpdateYankedOpt<'_> {
|
|||
if let Some(opt) = c.take_any2("opt") {
|
||||
opt
|
||||
} else {
|
||||
bail!("'opt' is required for UpdateYankedOpt");
|
||||
bail!("Invalid 'opt' in UpdateYankedOpt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl TryFrom<CmdCow> for TickOpt {
|
|||
|
||||
fn try_from(c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Ok(interval) = c.first() else {
|
||||
bail!("Invalid 'interval' argument in TickOpt");
|
||||
bail!("Invalid 'interval' in TickOpt");
|
||||
};
|
||||
|
||||
if interval < 0.0 {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::bail;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::popup::PickCfg;
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShowOpt {
|
||||
pub cfg: PickCfg,
|
||||
pub tx: oneshot::Sender<anyhow::Result<usize>>,
|
||||
pub tx: mpsc::UnboundedSender<Option<usize>>,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for ShowOpt {
|
||||
|
|
@ -15,11 +15,11 @@ impl TryFrom<CmdCow> for ShowOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(cfg) = c.take_any("cfg") else {
|
||||
bail!("Missing 'cfg' argument in ShowOpt");
|
||||
bail!("Invalid 'cfg' in ShowOpt");
|
||||
};
|
||||
|
||||
let Some(tx) = c.take_any("tx") else {
|
||||
bail!("Missing 'tx' argument in ShowOpt");
|
||||
bail!("Invalid 'tx' in ShowOpt");
|
||||
};
|
||||
|
||||
Ok(Self { cfg, tx })
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
|||
use yazi_shared::{CompletionToken, event::CmdCow, url::UrlCow};
|
||||
|
||||
// --- Exec
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessOpenOpt {
|
||||
pub cwd: UrlCow<'static>,
|
||||
pub cmd: OsString,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl TryFrom<CmdCow> for UpdateSucceedOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(urls) = c.take_any("urls") else {
|
||||
bail!("Invalid 'urls' argument in UpdateSucceedOpt");
|
||||
bail!("Invalid 'urls' in UpdateSucceedOpt");
|
||||
};
|
||||
|
||||
Ok(Self { urls })
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use yazi_shared::event::CmdCow;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct CallbackOpt {
|
||||
pub tx: mpsc::Sender<usize>,
|
||||
pub tx: mpsc::UnboundedSender<usize>,
|
||||
pub idx: usize,
|
||||
}
|
||||
|
||||
|
|
@ -14,11 +14,11 @@ impl TryFrom<CmdCow> for CallbackOpt {
|
|||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(tx) = c.take_any("tx") else {
|
||||
bail!("Invalid 'tx' argument in CallbackOpt");
|
||||
bail!("Invalid 'tx' in CallbackOpt");
|
||||
};
|
||||
|
||||
let Ok(idx) = c.first() else {
|
||||
bail!("Invalid 'idx' argument in CallbackOpt");
|
||||
bail!("Invalid 'idx' in CallbackOpt");
|
||||
};
|
||||
|
||||
Ok(Self { tx, idx })
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value};
|
|||
use yazi_config::{KEYMAP, keymap::{ChordCow, Key}};
|
||||
use yazi_shared::{Layer, event::CmdCow};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShowOpt {
|
||||
pub cands: Vec<ChordCow>,
|
||||
pub silent: bool,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use mlua::{ExternalError, HookTriggers, IntoLua, ObjectLike, VmState};
|
||||
use mlua::{ExternalError, HookTriggers, IntoLua, Lua, ObjectLike, Table, VmState};
|
||||
use tokio::{runtime::Handle, select};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::error;
|
||||
use yazi_binding::{Error, File, elements::{Rect, Renderable}};
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_dds::Sendable;
|
||||
use yazi_parser::{app::{PluginCallback, PluginOpt}, mgr::{PreviewLock, UpdatePeekedOpt}};
|
||||
use yazi_parser::{app::PluginOpt, mgr::{PreviewLock, UpdatePeekedOpt}};
|
||||
use yazi_proxy::{AppProxy, MgrProxy};
|
||||
use yazi_shared::{event::Cmd, pool::Symbol};
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ pub fn peek(
|
|||
}
|
||||
|
||||
fn peek_sync(cmd: &'static Cmd, file: yazi_fs::File, mime: Symbol<str>, skip: usize) {
|
||||
let cb: PluginCallback = Box::new(move |lua, plugin| {
|
||||
let cb = move |lua: &Lua, plugin: Table| {
|
||||
let job = lua.create_table_from([
|
||||
("area", Rect::from(LAYOUT.get().preview).into_lua(lua)?),
|
||||
("args", Sendable::args_to_table_ref(lua, &cmd.args)?.into_lua(lua)?),
|
||||
|
|
@ -62,7 +62,7 @@ fn peek_sync(cmd: &'static Cmd, file: yazi_fs::File, mime: Symbol<str>, skip: us
|
|||
])?;
|
||||
|
||||
plugin.call_method("peek", job)
|
||||
});
|
||||
};
|
||||
|
||||
AppProxy::plugin(PluginOpt::new_callback(&*cmd.name, cb));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use mlua::{IntoLua, ObjectLike};
|
||||
use mlua::{IntoLua, Lua, ObjectLike, Table};
|
||||
use yazi_binding::{File, elements::Rect};
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_parser::app::{PluginCallback, PluginOpt};
|
||||
use yazi_parser::app::PluginOpt;
|
||||
use yazi_proxy::AppProxy;
|
||||
use yazi_shared::event::Cmd;
|
||||
|
||||
pub fn seek_sync(cmd: &'static Cmd, file: yazi_fs::File, units: i16) {
|
||||
let cb: PluginCallback = Box::new(move |lua, plugin| {
|
||||
let cb = move |lua: &Lua, plugin: Table| {
|
||||
let job = lua.create_table_from([
|
||||
("file", File::new(file).into_lua(lua)?),
|
||||
("area", Rect::from(LAYOUT.get().preview).into_lua(lua)?),
|
||||
|
|
@ -14,7 +14,7 @@ pub fn seek_sync(cmd: &'static Cmd, file: yazi_fs::File, units: i16) {
|
|||
])?;
|
||||
|
||||
plugin.call_method("seek", job)
|
||||
});
|
||||
};
|
||||
|
||||
AppProxy::plugin(PluginOpt::new_callback(&*cmd.name, cb));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ impl Utils {
|
|||
return Err("Cannot call `ya.which()` while main thread is blocked".into_lua_err());
|
||||
}
|
||||
|
||||
let (tx, mut rx) = mpsc::channel::<usize>(1);
|
||||
let (tx, mut rx) = mpsc::unbounded_channel::<usize>();
|
||||
let cands: Vec<_> = t
|
||||
.raw_get::<Table>("cands")?
|
||||
.sequence_values::<Table>()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use anyhow::Context;
|
||||
use futures::future::join_all;
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Value, Variadic};
|
||||
use tokio::sync::oneshot;
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Table, Value, Variadic};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_binding::{Handle, runtime, runtime_mut};
|
||||
use yazi_dds::Sendable;
|
||||
use yazi_parser::app::{PluginCallback, PluginOpt};
|
||||
use yazi_parser::app::PluginOpt;
|
||||
use yazi_proxy::AppProxy;
|
||||
use yazi_shared::{LOCAL_SET, data::Data};
|
||||
|
||||
|
|
@ -115,27 +115,25 @@ impl Utils {
|
|||
args: MultiValue,
|
||||
) -> mlua::Result<Vec<Data>> {
|
||||
let args = Sendable::values_to_list(lua, args)?;
|
||||
let (tx, rx) = oneshot::channel::<Vec<Data>>();
|
||||
let (tx, mut rx) = mpsc::channel::<Vec<Data>>(1);
|
||||
|
||||
let callback: PluginCallback = {
|
||||
let id = id.to_owned();
|
||||
Box::new(move |lua, plugin| {
|
||||
let Some(block) = runtime!(lua)?.get_block(&id, calls) else {
|
||||
return Err("sync block not found".into_lua_err());
|
||||
};
|
||||
let id_ = id.to_owned();
|
||||
let callback = move |lua: &Lua, plugin: Table| {
|
||||
let Some(block) = runtime!(lua)?.get_block(&id_, calls) else {
|
||||
return Err("sync block not found".into_lua_err());
|
||||
};
|
||||
|
||||
let args = [Ok(Value::Table(plugin))]
|
||||
.into_iter()
|
||||
.chain(args.into_iter().map(|d| Sendable::data_to_value(lua, d)))
|
||||
.collect::<mlua::Result<MultiValue>>()?;
|
||||
let args = [Ok(Value::Table(plugin))]
|
||||
.into_iter()
|
||||
.chain(args.into_iter().map(|d| Sendable::data_to_value(lua, d)))
|
||||
.collect::<mlua::Result<MultiValue>>()?;
|
||||
|
||||
let values = Sendable::values_to_list(lua, block.call(args)?)?;
|
||||
tx.send(values).map_err(|_| "send failed".into_lua_err())
|
||||
})
|
||||
let values = Sendable::values_to_list(lua, block.call(args)?)?;
|
||||
tx.try_send(values).map_err(|_| "send failed".into_lua_err())
|
||||
};
|
||||
|
||||
AppProxy::plugin(PluginOpt::new_callback(id.to_owned(), callback));
|
||||
|
||||
rx.await.into_lua_err()
|
||||
rx.recv().await.ok_or("recv failed").into_lua_err()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_parser::app::{NotifyLevel, NotifyOpt, PluginOpt, TaskSummary};
|
||||
use yazi_shared::CompletionToken;
|
||||
|
||||
pub struct AppProxy;
|
||||
|
||||
impl AppProxy {
|
||||
pub async fn stop() {
|
||||
let (tx, rx) = oneshot::channel::<()>();
|
||||
emit!(Call(relay!(app:stop).with_any("tx", tx)));
|
||||
rx.await.ok();
|
||||
let token = CompletionToken::default();
|
||||
emit!(Call(relay!(app:stop).with_any("token", token.clone())));
|
||||
token.future().await;
|
||||
}
|
||||
|
||||
pub async fn resume() {
|
||||
let (tx, rx) = oneshot::channel::<()>();
|
||||
emit!(Call(relay!(app:resume).with_any("tx", tx)));
|
||||
rx.await.ok();
|
||||
let token = CompletionToken::default();
|
||||
emit!(Call(relay!(app:resume).with_any("token", token.clone())));
|
||||
token.future().await;
|
||||
}
|
||||
|
||||
pub fn notify(opt: NotifyOpt) {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use tokio::sync::oneshot;
|
||||
use yazi_config::popup::ConfirmCfg;
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_shared::CompletionToken;
|
||||
|
||||
pub struct ConfirmProxy;
|
||||
|
||||
impl ConfirmProxy {
|
||||
pub async fn show(cfg: ConfirmCfg) -> bool { Self::show_rx(cfg).await.unwrap_or(false) }
|
||||
pub async fn show(cfg: ConfirmCfg) -> bool { Self::show_sync(cfg).future().await }
|
||||
|
||||
pub fn show_rx(cfg: ConfirmCfg) -> oneshot::Receiver<bool> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
emit!(Call(relay!(confirm:show).with_any("tx", tx).with_any("cfg", cfg)));
|
||||
rx
|
||||
pub fn show_sync(cfg: ConfirmCfg) -> CompletionToken {
|
||||
let token = CompletionToken::default();
|
||||
emit!(Call(relay!(confirm:show).with_any("cfg", cfg).with_any("token", token.clone())));
|
||||
token
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use tokio::sync::oneshot;
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::popup::PickCfg;
|
||||
use yazi_macro::{emit, relay};
|
||||
|
||||
pub struct PickProxy;
|
||||
|
||||
impl PickProxy {
|
||||
pub async fn show(cfg: PickCfg) -> anyhow::Result<usize> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
pub async fn show(cfg: PickCfg) -> Option<usize> {
|
||||
let (tx, mut rx) = mpsc::unbounded_channel::<Option<usize>>();
|
||||
emit!(Call(relay!(pick:show).with_any("tx", tx).with_any("cfg", cfg)));
|
||||
rx.await?
|
||||
rx.recv().await?
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ yazi-macro = { path = "../yazi-macro", version = "26.1.22" }
|
|||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
dyn-clone = { workspace = true }
|
||||
foldhash = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
|
|
|
|||
28
yazi-shared/src/data/any.rs
Normal file
28
yazi-shared/src/data/any.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
use std::{any::Any, fmt};
|
||||
|
||||
use dyn_clone::DynClone;
|
||||
|
||||
pub trait DataAny: Any + Send + Sync + DynClone {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
||||
}
|
||||
|
||||
impl<T> DataAny for T
|
||||
where
|
||||
T: Any + Send + Sync + DynClone,
|
||||
{
|
||||
fn as_any(&self) -> &dyn Any { self }
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> { self }
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn DataAny> {
|
||||
fn clone(&self) -> Self { dyn_clone::clone_box(&**self) }
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn DataAny {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("DataAny").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
use std::{any::Any, borrow::Cow};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Id, SStr, data::DataKey, path::PathBufDyn, url::{UrlBuf, UrlCow}};
|
||||
use crate::{Id, SStr, data::{DataAny, DataKey}, path::PathBufDyn, url::{UrlBuf, UrlCow}};
|
||||
|
||||
// --- Data
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Data {
|
||||
Nil,
|
||||
|
|
@ -25,7 +25,7 @@ pub enum Data {
|
|||
#[serde(skip)]
|
||||
Bytes(Vec<u8>),
|
||||
#[serde(skip)]
|
||||
Any(Box<dyn Any + Send + Sync>),
|
||||
Any(Box<dyn DataAny>),
|
||||
}
|
||||
|
||||
impl From<()> for Data {
|
||||
|
|
@ -199,7 +199,7 @@ impl Data {
|
|||
|
||||
pub fn into_any<T: 'static>(self) -> Option<T> {
|
||||
match self {
|
||||
Self::Any(b) => b.downcast::<T>().ok().map(|b| *b),
|
||||
Self::Any(b) => b.into_any().downcast::<T>().ok().map(|b| *b),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ impl Data {
|
|||
// FIXME: find a better name
|
||||
pub fn into_any2<T: 'static>(self) -> Result<T> {
|
||||
if let Self::Any(b) = self
|
||||
&& let Ok(t) = b.downcast::<T>()
|
||||
&& let Ok(t) = b.into_any().downcast::<T>()
|
||||
{
|
||||
Ok(*t)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize, de};
|
|||
|
||||
use crate::{Id, SStr, path::PathBufDyn, url::{UrlBuf, UrlCow}};
|
||||
|
||||
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum DataKey {
|
||||
Nil,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(data key);
|
||||
yazi_macro::mod_flat!(any data key);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use std::{any::Any, borrow::Cow, fmt::{self, Display}, mem, str::FromStr};
|
||||
use std::{borrow::Cow, fmt::{self, Display}, mem, str::FromStr};
|
||||
|
||||
use anyhow::{Result, anyhow, bail};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, de};
|
||||
|
||||
use crate::{Layer, SStr, Source, data::{Data, DataKey}};
|
||||
use crate::{Layer, SStr, Source, data::{Data, DataAny, DataKey}};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Cmd {
|
||||
pub name: SStr,
|
||||
pub args: HashMap<DataKey, Data>,
|
||||
|
|
@ -76,7 +76,7 @@ impl Cmd {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_any(mut self, name: impl Into<DataKey>, data: impl Any + Send + Sync) -> Self {
|
||||
pub fn with_any(mut self, name: impl Into<DataKey>, data: impl DataAny) -> Self {
|
||||
self.args.insert(name.into(), Data::Any(Box::new(data)));
|
||||
self
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue