This commit is contained in:
sxyazi 2024-04-19 07:50:29 +08:00
parent 7a8dbe68d8
commit 79d61248dd
No known key found for this signature in database
41 changed files with 173 additions and 140 deletions

View file

@ -19,9 +19,9 @@ impl From<Cmd> for Opt {
// cache: mem::take(&mut c.args),
// TODO: Fix this
cache: vec![],
cache_name: c.take_name_str("cache-name").unwrap_or_default(),
word: c.take_name_str("word").unwrap_or_default(),
ticket: c.take_name_str("ticket").and_then(|v| v.parse().ok()).unwrap_or(0),
cache_name: c.take_str("cache-name").unwrap_or_default(),
word: c.take_str("word").unwrap_or_default(),
ticket: c.take_str("ticket").and_then(|v| v.parse().ok()).unwrap_or(0),
}
}
}

View file

@ -20,7 +20,7 @@ impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
word: c.take_first_str().unwrap_or_default(),
ticket: c.take_name_str("ticket").and_then(|s| s.parse().ok()).unwrap_or(0),
ticket: c.take_str("ticket").and_then(|s| s.parse().ok()).unwrap_or(0),
}
}
}

View file

@ -19,7 +19,7 @@ impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
word: c.take_first_str().unwrap_or_default(),
ticket: c.take_name_str("ticket").and_then(|s| s.parse().ok()).unwrap_or(0),
ticket: c.take_str("ticket").and_then(|s| s.parse().ok()).unwrap_or(0),
}
}
}

View file

@ -15,7 +15,7 @@ impl From<Cmd> for Opt {
Self {
skip: c.take_first_str().and_then(|s| s.parse().ok()),
force: c.get_bool("force"),
only_if: c.take_name_str("only-if").map(Url::from),
only_if: c.take_str("only-if").map(Url::from),
upper_bound: c.get_bool("upper-bound"),
}
}

View file

@ -15,7 +15,7 @@ impl From<Cmd> for Opt {
Self {
force: c.get_bool("force"),
permanently: c.get_bool("permanently"),
targets: c.take_data().unwrap_or_default(),
targets: c.take_any("targets").unwrap_or_default(),
}
}
}

View file

@ -19,8 +19,8 @@ impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
force: c.get_bool("force"),
empty: c.take_name_str("empty").unwrap_or_default(),
cursor: c.take_name_str("cursor").unwrap_or_default(),
empty: c.take_str("empty").unwrap_or_default(),
cursor: c.take_str("cursor").unwrap_or_default(),
}
}
}

View file

@ -12,7 +12,9 @@ pub struct Opt {
impl TryFrom<Cmd> for Opt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { Ok(Self { op: c.take_data().ok_or(())? }) }
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self { op: c.take_any("op").ok_or(())? })
}
}
impl Manager {

View file

@ -1,18 +1,18 @@
use std::collections::HashMap;
use yazi_shared::{event::{Cmd, Data}, fs::Url, render};
use yazi_shared::{event::Cmd, fs::Url, render};
use crate::{manager::{Manager, LINKED}, tasks::Tasks};
pub struct Opt {
data: Data,
updates: HashMap<String, String>,
}
impl TryFrom<Cmd> for Opt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self { data: c.take_data().ok_or(())? })
Ok(Self { updates: c.take_data("updates").ok_or(())?.into_table_string() })
}
}
@ -24,8 +24,7 @@ impl Manager {
let linked = LINKED.read();
let updates = opt
.data
.into_table_string()
.updates
.into_iter()
.map(|(url, mime)| (Url::from(url), mime))
.filter(|(url, mime)| self.mimetype.get(url) != Some(mime))

View file

@ -12,7 +12,7 @@ impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
page: c.take_first_str().and_then(|s| s.parse().ok()),
only_if: c.take_name_str("only-if").map(Url::from),
only_if: c.take_str("only-if").map(Url::from),
}
}
}

View file

@ -11,7 +11,7 @@ impl TryFrom<Cmd> for Opt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self { lock: c.take_data().ok_or(())? })
Ok(Self { lock: c.take_any("lock").ok_or(())? })
}
}

View file

@ -13,8 +13,8 @@ pub struct Opt<'a> {
impl<'a> From<Cmd> for Opt<'a> {
fn from(mut c: Cmd) -> Self {
Self {
url: c.take_name_str("url").map(|s| Cow::Owned(Url::from(s))),
state: match c.take_name_str("state").as_deref() {
url: c.take_str("url").map(|s| Cow::Owned(Url::from(s))),
state: match c.take_str("state").as_deref() {
Some("true") => Some(true),
Some("false") => Some(false),
_ => None,

View file

@ -10,7 +10,7 @@ pub struct Opt {
impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
state: match c.take_name_str("state").as_deref() {
state: match c.take_str("state").as_deref() {
Some("true") => Some(true),
Some("false") => Some(false),
_ => None,

View file

@ -29,7 +29,7 @@ impl Tasks {
let new = TasksProgress::from(&*ongoing.lock());
if last != new {
last = new;
emit!(Call(Cmd::new("update_progress").with_data(new), Layer::App));
emit!(Call(Cmd::new("update_progress").with_any("progress", new), Layer::App));
}
}
});

View file

@ -14,7 +14,7 @@ impl TryFrom<Cmd> for Opt {
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self {
tx: c.take_data().ok_or(())?,
tx: c.take_any("tx").ok_or(())?,
idx: c.take_first_str().and_then(|s| s.parse().ok()).ok_or(())?,
})
}

View file

@ -16,8 +16,8 @@ impl TryFrom<Cmd> for Opt {
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self {
cands: c.take_data().unwrap_or_default(),
layer: Layer::from_str(&c.take_name_str("layer").unwrap_or_default())?,
cands: c.take_any("candidates").unwrap_or_default(),
layer: Layer::from_str(&c.take_str("layer").unwrap_or_default())?,
silent: c.get_bool("silent"),
})
}

View file

@ -67,7 +67,7 @@ impl Payload<'static> {
pub(super) fn emit(self) {
self.try_flush();
emit!(Call(Cmd::new("accept_payload").with_data(self), Layer::App));
emit!(Call(Cmd::new("accept_payload").with_any("payload", self), Layer::App));
}
}

View file

@ -8,7 +8,7 @@ use crate::{app::App, lives::Lives};
impl App {
pub(crate) fn accept_payload(&mut self, mut cmd: Cmd) {
let Some(payload) = cmd.take_data::<Payload>() else {
let Some(payload) = cmd.take_any::<Payload>("payload") else {
return;
};

View file

@ -4,7 +4,7 @@ use mlua::TableExt;
use scopeguard::defer;
use tracing::warn;
use yazi_dds::Sendable;
use yazi_plugin::{loader::LOADER, OptData, RtRef, LUA};
use yazi_plugin::{loader::LOADER, RtRef, LUA};
use yazi_shared::{emit, event::Cmd, Layer};
use crate::{app::App, lives::Lives};
@ -17,7 +17,7 @@ impl App {
};
if !opt.sync {
return self.cx.tasks.plugin_micro(opt.name, opt.data.args);
return self.cx.tasks.plugin_micro(opt.name, opt.args);
}
if LOADER.read().contains_key(&opt.name) {
@ -26,14 +26,15 @@ impl App {
tokio::spawn(async move {
if LOADER.ensure(&opt.name).await.is_ok() {
Self::_plugin_do(opt.name, opt.data);
Self::_plugin_do(opt);
}
});
}
#[inline]
pub(crate) fn _plugin_do(name: String, data: OptData) {
emit!(Call(Cmd::args("plugin_do", vec![name]).with_data(data), Layer::App));
pub(crate) fn _plugin_do(opt: yazi_plugin::Opt) {
let cmd: Cmd = opt.into();
emit!(Call(cmd.with_name("plugin_do"), Layer::App));
}
pub(crate) fn plugin_do(&mut self, opt: impl TryInto<yazi_plugin::Opt, Error = impl Display>) {
@ -54,10 +55,10 @@ impl App {
};
_ = Lives::scope(&self.cx, |_| {
if let Some(cb) = opt.data.cb {
if let Some(cb) = opt.cb {
cb(&LUA, plugin)
} else {
plugin.call_method("entry", Sendable::vec_to_table(&LUA, opt.data.args)?)
plugin.call_method("entry", Sendable::vec_to_table(&LUA, opt.args)?)
}
});
}

View file

@ -8,7 +8,7 @@ pub struct Opt {
}
impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self { Self { tx: c.take_data() } }
fn from(mut c: Cmd) -> Self { Self { tx: c.take_any("tx") } }
}
impl App {

View file

@ -12,7 +12,7 @@ impl TryFrom<Cmd> for Opt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self { progress: c.take_data().ok_or(())? })
Ok(Self { progress: c.take_any("progress").ok_or(())? })
}
}

View file

@ -22,18 +22,18 @@ function M:preload()
return 0
end
local mimes, last = {}, ya.time()
local updates, last = {}, ya.time()
local flush = function(force)
if not force and ya.time() - last < 0.3 then
return
end
if next(mimes) then
ya.manager_emit("update_mimetype", {}, mimes)
mimes, last = {}, ya.time()
if next(updates) then
ya.manager_emit("update_mimetype", { updates = updates })
updates, last = {}, ya.time()
end
end
local i, j, mime = 1, 0, nil
local i, j, valid = 1, 0, nil
repeat
local line, event = child:read_line_with { timeout = 300 }
if event == 3 then
@ -43,11 +43,11 @@ function M:preload()
break
end
mime = match_mimetype(line)
if mime and string.find(line, mime, 1, true) ~= 1 then
valid = match_mimetype(line)
if valid and string.find(line, valid, 1, true) ~= 1 then
goto continue
elseif mime then
j, mimes[urls[i]] = j + 1, mime
elseif valid then
j, updates[urls[i]] = j + 1, valid
flush(false)
end

View file

@ -6,7 +6,7 @@ use yazi_config::LAYOUT;
use yazi_shared::{emit, event::Cmd, Layer};
use super::slim_lua;
use crate::{bindings::{Cast, File, Window}, elements::Rect, loader::LOADER, OptData, LUA};
use crate::{bindings::{Cast, File, Window}, elements::Rect, loader::LOADER, Opt, OptCallback, LUA};
pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> CancellationToken {
let ct = CancellationToken::new();
@ -56,18 +56,16 @@ pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> Cancellation
}
pub fn peek_sync(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) {
let data = OptData {
cb: Some(Box::new(move |_, plugin| {
plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("skip", skip)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?;
plugin.raw_set("window", Window::default())?;
plugin.call_method("peek", ())
})),
..Default::default()
};
emit!(Call(
Cmd::args("plugin", vec![cmd.name.to_owned()]).with_bool("sync", true).with_data(data),
Layer::App
));
let cb: OptCallback = Box::new(move |_, plugin| {
plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("skip", skip)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?;
plugin.raw_set("window", Window::default())?;
plugin.call_method("peek", ())
});
let cmd: Cmd =
Opt { name: cmd.name.to_owned(), sync: true, cb: Some(cb), ..Default::default() }.into();
emit!(Call(cmd.with_name("plugin"), Layer::App));
}

View file

@ -2,19 +2,17 @@ use mlua::TableExt;
use yazi_config::LAYOUT;
use yazi_shared::{emit, event::Cmd, Layer};
use crate::{bindings::{Cast, File}, elements::Rect, OptData, LUA};
use crate::{bindings::{Cast, File}, elements::Rect, Opt, OptCallback, LUA};
pub fn seek_sync(cmd: &Cmd, file: yazi_shared::fs::File, units: i16) {
let data = OptData {
cb: Some(Box::new(move |_, plugin| {
plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?;
plugin.call_method("seek", units)
})),
..Default::default()
};
emit!(Call(
Cmd::args("plugin", vec![cmd.name.to_owned()]).with_bool("sync", true).with_data(data),
Layer::App
));
let cb: OptCallback = Box::new(move |_, plugin| {
plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?;
plugin.call_method("seek", units)
});
let cmd: Cmd =
Opt { name: cmd.name.to_owned(), sync: true, cb: Some(cb), ..Default::default() }.into();
emit!(Call(cmd.with_name("plugin"), Layer::App));
}

View file

@ -2,16 +2,14 @@ use anyhow::bail;
use mlua::{Lua, Table};
use yazi_shared::event::{Cmd, Data};
pub(super) type OptCallback = Box<dyn FnOnce(&Lua, Table) -> mlua::Result<()> + Send>;
#[derive(Default)]
pub struct Opt {
pub name: String,
pub sync: bool,
pub data: OptData,
}
#[derive(Default)]
pub struct OptData {
pub args: Vec<Data>,
pub cb: Option<Box<dyn FnOnce(&Lua, Table) -> mlua::Result<()> + Send>>,
pub cb: Option<OptCallback>,
}
impl TryFrom<Cmd> for Opt {
@ -22,12 +20,24 @@ impl TryFrom<Cmd> for Opt {
bail!("plugin name cannot be empty");
};
let mut data: OptData = c.take_data().unwrap_or_default();
let args = if let Some(s) = c.get_str("args") {
shell_words::split(s)?.into_iter().map(Data::String).collect()
} else {
c.take_any::<Vec<Data>>("args").unwrap_or_default()
};
if let Some(args) = c.get_str("args") {
data.args = shell_words::split(args)?.into_iter().map(Data::String).collect();
}
Ok(Self { name, sync: c.get_bool("sync"), data })
Ok(Self { name, sync: c.get_bool("sync"), args, cb: c.take_any::<OptCallback>("callback") })
}
}
impl From<Opt> for Cmd {
fn from(value: Opt) -> Self {
let mut cmd =
Cmd::args("", vec![value.name]).with_bool("sync", value.sync).with_any("args", value.args);
if let Some(cb) = value.cb {
cmd = cmd.with_any("callback", cb);
}
cmd
}
}

View file

@ -38,9 +38,9 @@ impl Utils {
}
#[inline]
fn create_cmd(name: String, table: Table, data: Option<Value>) -> mlua::Result<Cmd> {
fn create_cmd(name: String, args: Value) -> mlua::Result<Cmd> {
// TODO: Fix this
return Ok(Cmd { name, args: Default::default(), data: None });
return Ok(Cmd { name, args: Default::default() });
// let (args, named) = Self::parse_args(table)?;
// let mut cmd = Cmd { name, args, named, ..Default::default() };
@ -62,16 +62,16 @@ impl Utils {
ya.raw_set(
"app_emit",
lua.create_function(|_, (name, table, data): (String, Table, Option<Value>)| {
emit!(Call(Self::create_cmd(name, table, data)?, Layer::App));
lua.create_function(|_, (name, args): (String, Value)| {
emit!(Call(Self::create_cmd(name, args)?, Layer::App));
Ok(())
})?,
)?;
ya.raw_set(
"manager_emit",
lua.create_function(|_, (name, table, data): (String, Table, Option<Value>)| {
emit!(Call(Self::create_cmd(name, table, data)?, Layer::Manager));
lua.create_function(|_, (name, args): (String, Value)| {
emit!(Call(Self::create_cmd(name, args)?, Layer::Manager));
Ok(())
})?,
)?;

View file

@ -37,7 +37,7 @@ impl Utils {
let cand = cand?;
cands.push(Control {
on: Self::parse_keys(cand.raw_get("on")?)?,
run: vec![Cmd::args("callback", vec![i.to_string()]).with_data(tx.clone())],
run: vec![Cmd::args("callback", vec![i.to_string()]).with_any("tx", tx.clone())],
desc: cand.raw_get("desc").ok(),
});
}
@ -47,7 +47,7 @@ impl Utils {
Cmd::new("show")
.with("layer", Layer::Which)
.with_bool("silent", t.raw_get("silent").unwrap_or_default())
.with_data(cands),
.with_any("candidates", cands),
Layer::Which
));

View file

@ -44,7 +44,7 @@ impl Utils {
};
lock.data = vec![Box::new(Paragraph { area: *area, text, ..Default::default() })];
emit!(Call(Cmd::new("preview").with_data(lock), Layer::Manager));
emit!(Call(Cmd::new("preview").with_any("lock", lock), Layer::Manager));
(true, Value::Nil).into_lua_multi(lua)
})?,
)?;
@ -67,7 +67,7 @@ impl Utils {
..Default::default()
})];
emit!(Call(Cmd::new("preview").with_data(lock), Layer::Manager));
emit!(Call(Cmd::new("preview").with_any("lock", lock), Layer::Manager));
(true, Value::Nil).into_lua_multi(lua)
})?,
)?;
@ -78,7 +78,7 @@ impl Utils {
let mut lock = PreviewLock::try_from(t)?;
lock.data = widgets.into_iter().filter_map(cast_to_renderable).collect();
emit!(Call(Cmd::new("preview").with_data(lock), Layer::Manager));
emit!(Call(Cmd::new("preview").with_any("lock", lock), Layer::Manager));
Ok(())
})?,
)?;

View file

@ -4,7 +4,7 @@ use yazi_dds::Sendable;
use yazi_shared::{emit, event::{Cmd, Data}, Layer};
use super::Utils;
use crate::{loader::LOADER, runtime::RtRef, OptData};
use crate::{loader::LOADER, runtime::RtRef, OptCallback};
impl Utils {
pub(super) fn sync(lua: &'static Lua, ya: &Table) -> mlua::Result<()> {
@ -53,29 +53,28 @@ impl Utils {
let args = Sendable::variadic_to_vec(args)?;
let (tx, rx) = oneshot::channel::<Vec<Data>>();
let data = OptData {
cb: Some({
let name = name.clone();
Box::new(move |lua, plugin| {
let Some(block) = lua.named_registry_value::<RtRef>("rt")?.get_block(&name, calls) else {
return Err("sync block not found".into_lua_err());
};
let callback: OptCallback = {
let name = name.clone();
Box::new(move |lua, plugin| {
let Some(block) = lua.named_registry_value::<RtRef>("rt")?.get_block(&name, calls) else {
return Err("sync block not found".into_lua_err());
};
let mut self_args = Vec::with_capacity(args.len() + 1);
self_args.push(Value::Table(plugin));
for arg in args {
self_args.push(Sendable::data_to_value(lua, arg)?);
}
let mut self_args = Vec::with_capacity(args.len() + 1);
self_args.push(Value::Table(plugin));
for arg in args {
self_args.push(Sendable::data_to_value(lua, arg)?);
}
let values = Sendable::variadic_to_vec(block.call(Variadic::from_iter(self_args))?)?;
tx.send(values).map_err(|_| "send failed".into_lua_err())
})
}),
..Default::default()
let values = Sendable::variadic_to_vec(block.call(Variadic::from_iter(self_args))?)?;
tx.send(values).map_err(|_| "send failed".into_lua_err())
})
};
emit!(Call(
Cmd::args("plugin", vec![name.clone()]).with_bool("sync", true).with_data(data),
Cmd::args("plugin", vec![name.clone()])
.with_bool("sync", true)
.with_any("callback", callback),
Layer::App
));

View file

@ -11,7 +11,7 @@ impl AppProxy {
#[inline]
pub async fn stop() {
let (tx, rx) = oneshot::channel::<()>();
emit!(Call(Cmd::new("stop").with_data(tx), Layer::App));
emit!(Call(Cmd::new("stop").with_any("tx", tx), Layer::App));
rx.await.ok();
}
@ -22,13 +22,13 @@ impl AppProxy {
#[inline]
pub fn notify(opt: NotifyOpt) {
emit!(Call(Cmd::new("notify").with_data(opt), Layer::App));
emit!(Call(Cmd::new("notify").with_any("option", opt), Layer::App));
}
#[inline]
pub fn notify_warn(title: &str, content: &str) {
emit!(Call(
Cmd::new("notify").with_data(NotifyOpt {
Cmd::new("notify").with_any("option", NotifyOpt {
title: title.to_owned(),
content: content.to_owned(),
level: NotifyLevel::Warn,

View file

@ -10,7 +10,7 @@ impl InputProxy {
#[inline]
pub fn show(cfg: InputCfg) -> mpsc::UnboundedReceiver<Result<String, InputError>> {
let (tx, rx) = mpsc::unbounded_channel();
emit!(Call(Cmd::new("show").with_data(InputOpt { cfg, tx }), Layer::Input));
emit!(Call(Cmd::new("show").with_any("option", InputOpt { cfg, tx }), Layer::Input));
rx
}

View file

@ -25,13 +25,13 @@ impl ManagerProxy {
#[inline]
pub fn open_do(opt: OpenDoOpt) {
emit!(Call(Cmd::new("open_do").with_data(opt), Layer::Manager));
emit!(Call(Cmd::new("open_do").with_any("option", opt), Layer::Manager));
}
#[inline]
pub fn remove_do(targets: Vec<Url>, permanently: bool) {
emit!(Call(
Cmd::new("remove_do").with_bool("permanently", permanently).with_data(targets),
Cmd::new("remove_do").with_bool("permanently", permanently).with_any("targets", targets),
Layer::Manager
));
}

View file

@ -10,5 +10,5 @@ pub struct InputOpt {
impl TryFrom<Cmd> for InputOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}

View file

@ -14,7 +14,7 @@ pub struct NotifyOpt {
impl TryFrom<Cmd> for NotifyOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}
impl<'a> TryFrom<mlua::Table<'a>> for NotifyOpt {

View file

@ -12,7 +12,7 @@ pub struct OpenDoOpt {
}
impl From<Cmd> for OpenDoOpt {
fn from(mut c: Cmd) -> Self { c.take_data().unwrap_or_default() }
fn from(mut c: Cmd) -> Self { c.take_any("option").unwrap_or_default() }
}
// --- Open with
@ -24,5 +24,5 @@ pub struct OpenWithOpt {
impl TryFrom<Cmd> for OpenWithOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}

View file

@ -14,5 +14,5 @@ pub struct ProcessExecOpt {
impl TryFrom<Cmd> for ProcessExecOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}

View file

@ -10,5 +10,5 @@ pub struct SelectOpt {
impl TryFrom<Cmd> for SelectOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_data().ok_or(()) }
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}

View file

@ -10,7 +10,7 @@ impl SelectProxy {
#[inline]
pub async fn show(cfg: SelectCfg) -> anyhow::Result<usize> {
let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("show").with_data(SelectOpt { cfg, tx }), Layer::Select));
emit!(Call(Cmd::new("show").with_any("option", SelectOpt { cfg, tx }), Layer::Select));
rx.await?
}
}

View file

@ -11,14 +11,17 @@ pub struct TasksProxy;
impl TasksProxy {
#[inline]
pub fn open_with(targets: Vec<Url>, opener: Cow<'static, Opener>) {
emit!(Call(Cmd::new("open_with").with_data(OpenWithOpt { targets, opener }), Layer::Tasks));
emit!(Call(
Cmd::new("open_with").with_any("option", OpenWithOpt { targets, opener }),
Layer::Tasks
));
}
#[inline]
pub async fn process_exec(args: Vec<OsString>, opener: Cow<'static, Opener>) {
let (tx, rx) = oneshot::channel();
emit!(Call(
Cmd::new("process_exec").with_data(ProcessExecOpt { args, opener, done: tx }),
Cmd::new("process_exec").with_any("option", ProcessExecOpt { args, opener, done: tx }),
Layer::Tasks
));
rx.await.ok();

View file

@ -6,7 +6,6 @@ use super::Data;
pub struct Cmd {
pub name: String,
pub args: HashMap<String, Data>,
pub data: Option<Box<dyn Any + Send>>,
}
impl Cmd {
@ -18,7 +17,6 @@ impl Cmd {
Self {
name: name.to_owned(),
args: args.into_iter().enumerate().map(|(i, s)| (i.to_string(), Data::String(s))).collect(),
..Default::default()
}
}
@ -35,8 +33,14 @@ impl Cmd {
}
#[inline]
pub fn with_data(mut self, data: impl Any + Send) -> Self {
self.data = Some(Box::new(data));
pub fn with_any(mut self, name: impl ToString, data: impl Any + Send) -> Self {
self.args.insert(name.to_string(), Data::Any(Box::new(data)));
self
}
#[inline]
pub fn with_name(mut self, name: impl ToString) -> Self {
self.name = name.to_string();
self
}
@ -49,8 +53,11 @@ impl Cmd {
}
#[inline]
pub fn take_data<T: 'static>(&mut self) -> Option<T> {
self.data.take().and_then(|d| d.downcast::<T>().ok()).map(|d| *d)
pub fn take_data(&mut self, name: &str) -> Option<Data> { self.args.remove(name) }
#[inline]
pub fn take_str(&mut self, name: &str) -> Option<String> {
if let Some(Data::String(s)) = self.args.remove(name) { Some(s) } else { None }
}
#[inline]
@ -59,8 +66,8 @@ impl Cmd {
}
#[inline]
pub fn take_name_str(&mut self, name: &str) -> Option<String> {
if let Some(Data::String(s)) = self.args.remove(name) { Some(s) } else { None }
pub fn take_any<T: 'static>(&mut self, name: &str) -> Option<T> {
self.args.remove(name).and_then(|d| d.into_any())
}
pub fn shallow_clone(&self) -> Self {
@ -70,7 +77,7 @@ impl Cmd {
.filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), Data::String(s.to_owned()))))
.collect();
Self { name: self.name.clone(), args, data: None }
Self { name: self.name.clone(), args }
}
}

View file

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::{fs::Url, OrderedFloat};
// --- Arg
// --- Data
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Data {
@ -37,6 +37,22 @@ impl Data {
}
}
#[inline]
pub fn as_any<T: 'static>(&self) -> Option<&T> {
match self {
Self::Any(b) => b.downcast_ref::<T>(),
_ => None,
}
}
#[inline]
pub fn into_any<T: 'static>(self) -> Option<T> {
match self {
Data::Any(b) => b.downcast::<T>().ok().map(|b| *b),
_ => None,
}
}
pub fn into_table_string(self) -> HashMap<String, String> {
let Self::Table(table) = self else {
return Default::default();

View file

@ -38,7 +38,7 @@ impl FilesOp {
#[inline]
pub fn emit(self) {
emit!(Call(Cmd::new("update_files").with_data(self), Layer::Manager));
emit!(Call(Cmd::new("update_files").with_any("op", self), Layer::Manager));
}
pub fn prepare(url: &Url) -> u64 {