From ac196f211e6d5c28bb0967e177406d01118eeb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sat, 21 Sep 2024 00:23:46 +0800 Subject: [PATCH] feat: support calling methods in builtin plugins with arbitrary types of arguments (`self` can now be omitted) (#1666) --- yazi-plugin/preset/plugins/json.lua | 15 ++---------- yazi-plugin/src/loader/require.rs | 38 ++++++++++++++++++++++------- yazi-plugin/src/utils/sync.rs | 9 +++---- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/yazi-plugin/preset/plugins/json.lua b/yazi-plugin/preset/plugins/json.lua index 20c5cf1b..d58475b7 100644 --- a/yazi-plugin/preset/plugins/json.lua +++ b/yazi-plugin/preset/plugins/json.lua @@ -13,7 +13,7 @@ function M:peek() :spawn() if not child then - return self:fallback_to_builtin() + return require("code").peek(self) end local limit = self.area.h @@ -21,7 +21,7 @@ function M:peek() repeat local next, event = child:read_line() if event == 1 then - return self:fallback_to_builtin() + return require("code").peek(self) elseif event ~= 0 then break end @@ -52,15 +52,4 @@ function M:seek(units) end end -function M:fallback_to_builtin() - local err, bound = ya.preview_code(self) - if bound then - ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true }) - elseif err and not err:find("cancelled", 1, true) then - ya.preview_widgets(self, { - ui.Paragraph(self.area, { ui.Line(err):reverse() }), - }) - end -end - return M diff --git a/yazi-plugin/src/loader/require.rs b/yazi-plugin/src/loader/require.rs index d9cbd4e0..c5869a78 100644 --- a/yazi-plugin/src/loader/require.rs +++ b/yazi-plugin/src/loader/require.rs @@ -41,13 +41,11 @@ impl Require { } fn create_mt<'a>(lua: &'a Lua, id: &str, mod_: Table<'a>, sync: bool) -> mlua::Result> { - let ts = lua.create_table_from([("_mod", mod_.into_lua(lua)?)])?; - let id: Arc = Arc::from(id); let mt = lua.create_table_from([( "__index", lua.create_function(move |lua, (ts, key): (Table, mlua::String)| { - match ts.raw_get::<_, Table>("_mod")?.raw_get::<_, Value>(&key)? { + match ts.raw_get::<_, Table>("__mod")?.raw_get::<_, Value>(&key)? { Value::Function(_) => { Self::create_wrapper(lua, id.clone(), key.to_str()?, sync)?.into_lua(lua) } @@ -56,6 +54,7 @@ impl Require { })?, )])?; + let ts = lua.create_table_from([("__mod", mod_)])?; ts.set_metatable(Some(mt)); Ok(ts) } @@ -69,24 +68,45 @@ impl Require { let f: Arc = Arc::from(f); if sync { - lua.create_function(move |lua, (ts, args): (Table, MultiValue)| { - let mod_: Table = ts.raw_get::<_, Table>("_mod")?; + lua.create_function(move |lua, args: MultiValue| { + let (mod_, args) = Self::split_mod_and_args(lua, &id, args)?; lua.named_registry_value::("rt")?.push(&id); - let result = mod_.call_method::<_, MultiValue>(&f, args); + let result = mod_.call_function::<_, MultiValue>(&f, args); lua.named_registry_value::("rt")?.pop(); result }) } else { - lua.create_async_function(move |lua, (ts, args): (Table, MultiValue)| { + lua.create_async_function(move |lua, args: MultiValue| { let (id, f) = (id.clone(), f.clone()); async move { - let mod_: Table = ts.raw_get::<_, Table>("_mod")?; + let (mod_, args) = Self::split_mod_and_args(lua, &id, args)?; lua.named_registry_value::("rt")?.push(&id); - let result = mod_.call_async_method::<_, MultiValue>(&f, args).await; + let result = mod_.call_async_function::<_, MultiValue>(&f, args).await; lua.named_registry_value::("rt")?.pop(); result } }) } } + + fn split_mod_and_args<'a>( + lua: &'a Lua, + id: &str, + mut args: MultiValue<'a>, + ) -> mlua::Result<(Table<'a>, MultiValue<'a>)> { + let Some(front) = args.pop_front() else { + return Ok((LOADER.load(lua, id)?, args)); + }; + let Value::Table(tbl) = front else { + args.push_front(front); + return Ok((LOADER.load(lua, id)?, args)); + }; + Ok(if let Ok(mod_) = tbl.raw_get::<_, Table>("__mod") { + args.push_front(Value::Table(mod_.clone())); + (mod_, args) + } else { + args.push_front(Value::Table(tbl)); + (LOADER.load(lua, id)?, args) + }) + } } diff --git a/yazi-plugin/src/utils/sync.rs b/yazi-plugin/src/utils/sync.rs index b67941e3..2322b6df 100644 --- a/yazi-plugin/src/utils/sync.rs +++ b/yazi-plugin/src/utils/sync.rs @@ -1,4 +1,4 @@ -use mlua::{ExternalError, ExternalResult, Function, IntoLua, Lua, MultiValue, Table, Value}; +use mlua::{ExternalError, ExternalResult, Function, Lua, MultiValue, Table, Value}; use tokio::sync::oneshot; use yazi_dds::Sendable; use yazi_shared::{emit, event::{Cmd, Data}, Layer}; @@ -17,10 +17,9 @@ impl Utils { } let cur = rt.current().unwrap().to_owned(); - lua.create_function(move |lua, args: MultiValue| { - f.call::<_, MultiValue>(MultiValue::from_iter( - [LOADER.load(lua, &cur)?.into_lua(lua)?].into_iter().chain(args), - )) + lua.create_function(move |lua, mut args: MultiValue| { + args.push_front(Value::Table(LOADER.load(lua, &cur)?)); + f.call::<_, MultiValue>(args) }) })?, )?;