mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
perf: port require() and ya.sync() to Rust to avoid plugin information initialization process (#853)
This commit is contained in:
parent
903f3da7e5
commit
c240602046
23 changed files with 310 additions and 152 deletions
|
|
@ -1 +1 @@
|
|||
{"version":"0.2","language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub"]}
|
||||
{"version":"0.2","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers"],"language":"en","flagWords":[]}
|
||||
|
|
@ -48,11 +48,11 @@ pub struct BodyBulkIter {
|
|||
}
|
||||
|
||||
impl UserData for BodyBulkIter {
|
||||
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
|
||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("tab", |_, me| Ok(me.tab));
|
||||
}
|
||||
|
||||
fn add_methods<'a, M: mlua::UserDataMethods<'a, Self>>(methods: &mut M) {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.inner.len()));
|
||||
|
||||
methods.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub struct BodyTabsItem<'a> {
|
|||
}
|
||||
|
||||
impl UserData for BodyTabsItem<'static> {
|
||||
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
|
||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("url", |lua, me| lua.create_any_userdata(me.url.clone()));
|
||||
}
|
||||
}
|
||||
|
|
@ -69,11 +69,11 @@ impl From<BodyTabs<'static>> for BodyTabsIter {
|
|||
}
|
||||
|
||||
impl UserData for BodyTabsIter {
|
||||
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
|
||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
|
||||
}
|
||||
|
||||
fn add_methods<'a, M: mlua::UserDataMethods<'a, Self>>(methods: &mut M) {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.items.len()));
|
||||
|
||||
methods.add_meta_method(MetaMethod::Index, |_, me, idx: usize| {
|
||||
|
|
|
|||
|
|
@ -54,11 +54,11 @@ impl From<BodyYank<'static>> for BodyYankIter {
|
|||
}
|
||||
|
||||
impl UserData for BodyYankIter {
|
||||
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
|
||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("is_cut", |_, me| Ok(me.cut));
|
||||
}
|
||||
|
||||
fn add_methods<'a, M: mlua::UserDataMethods<'a, Self>>(methods: &mut M) {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.urls.len()));
|
||||
|
||||
methods.add_meta_method(MetaMethod::Index, |lua, me, idx: usize| {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
|||
|
||||
use mlua::TableExt;
|
||||
use tracing::warn;
|
||||
use yazi_plugin::{OptData, LOADER, LUA};
|
||||
use yazi_plugin::{loader::LOADER, OptData, RtRef, LUA};
|
||||
use yazi_shared::{emit, event::Cmd, Defer, Layer};
|
||||
|
||||
use crate::{app::App, lives::Lives};
|
||||
|
|
@ -40,9 +40,12 @@ impl App {
|
|||
Err(e) => return warn!("{e}"),
|
||||
};
|
||||
|
||||
LOADER.set_running(Some(&opt.name));
|
||||
let _defer = Defer::new(|| LOADER.set_running(None));
|
||||
match LUA.named_registry_value::<RtRef>("rt") {
|
||||
Ok(mut r) => r.swap(&opt.name),
|
||||
Err(e) => return warn!("{e}"),
|
||||
}
|
||||
|
||||
let _defer = Defer::new(|| LUA.named_registry_value::<RtRef>("rt").map(|mut r| r.reset()));
|
||||
let plugin = match LOADER.load(&opt.name) {
|
||||
Ok(plugin) => plugin,
|
||||
Err(e) => return warn!("{e}"),
|
||||
|
|
|
|||
|
|
@ -1,11 +1 @@
|
|||
package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path
|
||||
|
||||
local _require = require
|
||||
require = function(name)
|
||||
YAZI_PLUGIN_NAME, YAZI_SYNC_CALLS = name, 0
|
||||
local mod = _require(name)
|
||||
mod._name = name
|
||||
return mod
|
||||
end
|
||||
|
||||
YAZI_SYNC_BLOCKS = {}
|
||||
|
|
|
|||
|
|
@ -28,19 +28,6 @@ function ya.flat(t)
|
|||
return r
|
||||
end
|
||||
|
||||
function ya.sync(f)
|
||||
YAZI_SYNC_CALLS = YAZI_SYNC_CALLS + 1
|
||||
|
||||
local name, calls = YAZI_PLUGIN_NAME, YAZI_SYNC_CALLS
|
||||
if not YAZI_SYNC_BLOCKS then
|
||||
return function(...) return ya.plugin_retrieve(name, calls, ...) end
|
||||
end
|
||||
|
||||
YAZI_SYNC_BLOCKS[name] = YAZI_SYNC_BLOCKS[name] or {}
|
||||
YAZI_SYNC_BLOCKS[name][calls] = f
|
||||
return function(...) return f(package.loaded[name], ...) end
|
||||
end
|
||||
|
||||
function ya.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end
|
||||
|
||||
function ya.readable_size(size)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use tokio::runtime::Handle;
|
|||
use yazi_dds::ValueSendable;
|
||||
|
||||
use super::slim_lua;
|
||||
use crate::LOADER;
|
||||
use crate::loader::LOADER;
|
||||
|
||||
pub async fn entry(name: String, args: Vec<ValueSendable>) -> mlua::Result<()> {
|
||||
LOADER.ensure(&name).await.into_lua_err()?;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use mlua::Lua;
|
||||
|
||||
use crate::{bindings, elements};
|
||||
use crate::{bindings, elements, runtime::Runtime};
|
||||
|
||||
pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
||||
let lua = Lua::new();
|
||||
lua.set_named_registry_value("rt", Runtime::new(name))?;
|
||||
|
||||
// Base
|
||||
bindings::Cha::register(&lua)?;
|
||||
|
|
@ -12,7 +13,7 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
|||
|
||||
crate::fs::install(&lua)?;
|
||||
crate::process::install(&lua)?;
|
||||
crate::utils::install(&lua)?;
|
||||
crate::utils::install_isolate(&lua)?;
|
||||
crate::Config::new(&lua).install_preview()?;
|
||||
lua.load(include_str!("../../preset/ya.lua")).exec()?;
|
||||
|
||||
|
|
@ -24,12 +25,6 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
|||
elements::Rect::install(&lua, &ui)?;
|
||||
elements::Span::install(&lua, &ui)?;
|
||||
|
||||
{
|
||||
let globals = lua.globals();
|
||||
globals.raw_set("ui", ui)?;
|
||||
globals.raw_set("YAZI_PLUGIN_NAME", lua.create_string(name)?)?;
|
||||
globals.raw_set("YAZI_SYNC_CALLS", 0)?;
|
||||
}
|
||||
|
||||
lua.globals().raw_set("ui", ui)?;
|
||||
Ok(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, OptData, LOADER, LUA};
|
||||
use crate::{bindings::{Cast, File, Window}, elements::Rect, loader::LOADER, OptData, LUA};
|
||||
|
||||
pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> CancellationToken {
|
||||
let ct = CancellationToken::new();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use tokio::runtime::Handle;
|
|||
use yazi_config::LAYOUT;
|
||||
|
||||
use super::slim_lua;
|
||||
use crate::{bindings::{Cast, File}, elements::Rect, LOADER};
|
||||
use crate::{bindings::{Cast, File}, elements::Rect, loader::LOADER};
|
||||
|
||||
pub async fn preload(
|
||||
name: &str,
|
||||
|
|
|
|||
|
|
@ -7,18 +7,22 @@ pub mod elements;
|
|||
pub mod external;
|
||||
pub mod fs;
|
||||
pub mod isolate;
|
||||
mod loader;
|
||||
pub mod loader;
|
||||
mod lua;
|
||||
mod opt;
|
||||
pub mod process;
|
||||
pub mod pubsub;
|
||||
mod runtime;
|
||||
pub mod url;
|
||||
pub mod utils;
|
||||
|
||||
pub use cast::*;
|
||||
pub use config::*;
|
||||
pub use loader::*;
|
||||
pub use lua::*;
|
||||
pub use opt::*;
|
||||
pub use runtime::*;
|
||||
|
||||
pub fn init() { crate::init_lua(); }
|
||||
pub fn init() {
|
||||
crate::init_lua();
|
||||
crate::loader::init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{borrow::Cow, collections::HashMap, ops::Deref, sync::Arc};
|
||||
use std::{borrow::Cow, collections::HashMap, ops::Deref};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use mlua::{ExternalError, Table};
|
||||
|
|
@ -11,20 +11,12 @@ use crate::LUA;
|
|||
|
||||
pub static LOADER: RoCell<Loader> = RoCell::new();
|
||||
|
||||
pub(super) static RUNNING: RoCell<arc_swap::ArcSwapOption<String>> = RoCell::new();
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Loader {
|
||||
cache: RwLock<HashMap<String, Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl Loader {
|
||||
#[inline]
|
||||
pub(super) fn init() {
|
||||
LOADER.with(Default::default);
|
||||
RUNNING.with(Default::default);
|
||||
}
|
||||
|
||||
pub async fn ensure(&self, name: &str) -> Result<()> {
|
||||
if self.cache.read().contains_key(name) {
|
||||
return Ok(());
|
||||
|
|
@ -33,16 +25,16 @@ impl Loader {
|
|||
let path = BOOT.plugin_dir.join(format!("{name}.yazi/init.lua"));
|
||||
let b = fs::read(path).await.map(|v| v.into()).or_else(|_| {
|
||||
Ok(Cow::from(match name {
|
||||
"archive" => include_bytes!("../preset/plugins/archive.lua") as &[u8],
|
||||
"code" => include_bytes!("../preset/plugins/code.lua"),
|
||||
"file" => include_bytes!("../preset/plugins/file.lua"),
|
||||
"folder" => include_bytes!("../preset/plugins/folder.lua"),
|
||||
"image" => include_bytes!("../preset/plugins/image.lua"),
|
||||
"json" => include_bytes!("../preset/plugins/json.lua"),
|
||||
"mime" => include_bytes!("../preset/plugins/mime.lua"),
|
||||
"noop" => include_bytes!("../preset/plugins/noop.lua"),
|
||||
"pdf" => include_bytes!("../preset/plugins/pdf.lua"),
|
||||
"video" => include_bytes!("../preset/plugins/video.lua"),
|
||||
"archive" => include_bytes!("../../preset/plugins/archive.lua") as &[_],
|
||||
"code" => include_bytes!("../../preset/plugins/code.lua"),
|
||||
"file" => include_bytes!("../../preset/plugins/file.lua"),
|
||||
"folder" => include_bytes!("../../preset/plugins/folder.lua"),
|
||||
"image" => include_bytes!("../../preset/plugins/image.lua"),
|
||||
"json" => include_bytes!("../../preset/plugins/json.lua"),
|
||||
"mime" => include_bytes!("../../preset/plugins/mime.lua"),
|
||||
"noop" => include_bytes!("../../preset/plugins/noop.lua"),
|
||||
"pdf" => include_bytes!("../../preset/plugins/pdf.lua"),
|
||||
"video" => include_bytes!("../../preset/plugins/video.lua"),
|
||||
_ => bail!("plugin not found: {name}"),
|
||||
}))
|
||||
})?;
|
||||
|
|
@ -58,8 +50,6 @@ impl Loader {
|
|||
return Ok(t);
|
||||
}
|
||||
|
||||
globals.raw_set("YAZI_PLUGIN_NAME", LUA.create_string(name)?)?;
|
||||
globals.raw_set("YAZI_SYNC_CALLS", 0)?;
|
||||
let t: Table = match self.read().get(name) {
|
||||
Some(b) => LUA.load(b).call(())?,
|
||||
None => Err(format!("plugin `{name}` not found").into_lua_err())?,
|
||||
|
|
@ -69,14 +59,6 @@ impl Loader {
|
|||
loaded.raw_set(name, t.clone())?;
|
||||
Ok(t)
|
||||
}
|
||||
|
||||
pub fn set_running(&self, name: Option<&str>) {
|
||||
if let Some(s) = name {
|
||||
RUNNING.store(Some(Arc::new(s.to_owned())));
|
||||
} else {
|
||||
RUNNING.store(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Loader {
|
||||
15
yazi-plugin/src/loader/mod.rs
Normal file
15
yazi-plugin/src/loader/mod.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
mod loader;
|
||||
mod require;
|
||||
|
||||
pub use loader::*;
|
||||
use require::*;
|
||||
|
||||
pub(super) fn init() { LOADER.with(Default::default); }
|
||||
|
||||
pub(super) fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
|
||||
Require::install(lua)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
66
yazi-plugin/src/loader/require.rs
Normal file
66
yazi-plugin/src/loader/require.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use mlua::{ExternalResult, Function, IntoLua, Lua, MetaMethod, Table, TableExt, UserData, Value, Variadic};
|
||||
|
||||
use crate::RtRef;
|
||||
|
||||
pub(super) struct Require;
|
||||
|
||||
impl Require {
|
||||
pub(super) fn install(lua: &'static Lua) -> mlua::Result<()> {
|
||||
let globals = lua.globals();
|
||||
|
||||
let require = globals.raw_get::<_, Function>("require")?;
|
||||
globals.raw_set(
|
||||
"require",
|
||||
lua.create_function(move |lua, name: mlua::String| {
|
||||
lua.named_registry_value::<RtRef>("rt")?.swap(name.to_str()?);
|
||||
let module: Table = require.call(&name)?;
|
||||
lua.named_registry_value::<RtRef>("rt")?.reset();
|
||||
|
||||
module.raw_set("_name", &name)?;
|
||||
Self::create_mt(lua, name, module)
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_mt(
|
||||
lua: &'static Lua,
|
||||
name: mlua::String<'static>,
|
||||
module: Table<'static>,
|
||||
) -> mlua::Result<Table<'static>> {
|
||||
let ts =
|
||||
lua.create_table_from([("name", name.into_lua(lua)?), ("module", module.into_lua(lua)?)])?;
|
||||
|
||||
let mt = lua.create_table()?;
|
||||
mt.raw_set(
|
||||
"__index",
|
||||
lua.create_function(|_, (ts, key): (Table, mlua::String)| {
|
||||
if key.to_str()? == "setup" {
|
||||
Ok(RequireSetup { name: ts.raw_get("name")?, module: ts.raw_get("module")? })
|
||||
} else {
|
||||
Err("Only `require():setup()` is supported").into_lua_err()
|
||||
}
|
||||
})?,
|
||||
)?;
|
||||
|
||||
ts.set_metatable(Some(mt));
|
||||
Ok(ts)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct RequireSetup {
|
||||
name: mlua::String<'static>,
|
||||
module: Table<'static>,
|
||||
}
|
||||
|
||||
impl UserData for RequireSetup {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Call, |lua, me, args: Variadic<Value>| {
|
||||
lua.named_registry_value::<RtRef>("rt")?.swap(me.name.to_str()?);
|
||||
let result = me.module.call_method::<_, Variadic<Value>>("setup", args);
|
||||
lua.named_registry_value::<RtRef>("rt")?.reset();
|
||||
result
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -3,28 +3,31 @@ use mlua::Lua;
|
|||
use yazi_boot::BOOT;
|
||||
use yazi_shared::RoCell;
|
||||
|
||||
use crate::runtime::Runtime;
|
||||
|
||||
pub static LUA: RoCell<Lua> = RoCell::new();
|
||||
|
||||
pub(super) fn init_lua() {
|
||||
LUA.init(Lua::new());
|
||||
|
||||
stage_1(&LUA).expect("failed to initialize Lua");
|
||||
stage_2(&LUA);
|
||||
stage_1(&LUA).expect("Lua setup failed");
|
||||
stage_2(&LUA).expect("Lua runtime failed");
|
||||
}
|
||||
|
||||
fn stage_1(lua: &'static Lua) -> Result<()> {
|
||||
crate::Loader::init();
|
||||
crate::Config::new(lua).install_boot()?.install_manager()?.install_theme()?;
|
||||
crate::utils::init();
|
||||
crate::utils::install(lua)?;
|
||||
|
||||
// Base
|
||||
lua.set_named_registry_value("rt", Runtime::default())?;
|
||||
lua.load(include_str!("../preset/ya.lua")).exec()?;
|
||||
crate::bindings::Cha::register(lua)?;
|
||||
crate::bindings::File::register(lua)?;
|
||||
crate::bindings::Icon::register(lua)?;
|
||||
crate::elements::pour(lua)?;
|
||||
crate::pubsub::Pubsub::install(lua)?;
|
||||
crate::loader::install(lua)?;
|
||||
crate::pubsub::install(lua)?;
|
||||
crate::url::pour(lua)?;
|
||||
|
||||
// Components
|
||||
|
|
@ -41,10 +44,12 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn stage_2(lua: &'static Lua) {
|
||||
lua.load(include_str!("../preset/setup.lua")).exec().unwrap();
|
||||
fn stage_2(lua: &'static Lua) -> mlua::Result<()> {
|
||||
lua.load(include_str!("../preset/setup.lua")).exec()?;
|
||||
|
||||
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
|
||||
lua.load(b).exec().unwrap();
|
||||
lua.load(b).exec()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,9 @@
|
|||
mod pubsub;
|
||||
|
||||
pub use pubsub::*;
|
||||
|
||||
pub(super) fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
|
||||
Pubsub::install(lua)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use mlua::{ExternalResult, Function, Lua, Value};
|
||||
use yazi_dds::body::Body;
|
||||
|
||||
use crate::RUNNING;
|
||||
use crate::runtime::RtRef;
|
||||
|
||||
pub struct Pubsub;
|
||||
|
||||
impl Pubsub {
|
||||
pub fn install(lua: &'static Lua) -> mlua::Result<()> {
|
||||
pub(super) fn install(lua: &'static Lua) -> mlua::Result<()> {
|
||||
let ps = lua.create_table()?;
|
||||
|
||||
ps.raw_set(
|
||||
|
|
@ -42,11 +42,11 @@ impl Pubsub {
|
|||
|
||||
ps.raw_set(
|
||||
"sub",
|
||||
lua.create_function(|_, (kind, f): (mlua::String, Function)| {
|
||||
let Some(name) = &*RUNNING.load() else {
|
||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||
let Some(ref cur) = lua.named_registry_value::<RtRef>("rt")?.current else {
|
||||
return Err("`sub()` must be called in a sync plugin").into_lua_err();
|
||||
};
|
||||
if !yazi_dds::Pubsub::sub(name, kind.to_str()?, f) {
|
||||
if !yazi_dds::Pubsub::sub(cur, kind.to_str()?, f) {
|
||||
return Err("`sub()` called twice").into_lua_err();
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -56,10 +56,10 @@ impl Pubsub {
|
|||
ps.raw_set(
|
||||
"sub_remote",
|
||||
lua.create_function(|_, (kind, f): (mlua::String, Function)| {
|
||||
let Some(name) = &*RUNNING.load() else {
|
||||
let Some(ref cur) = lua.named_registry_value::<RtRef>("rt")?.current else {
|
||||
return Err("`sub_remote()` must be called in a sync plugin").into_lua_err();
|
||||
};
|
||||
if !yazi_dds::Pubsub::sub_remote(name, kind.to_str()?, f) {
|
||||
if !yazi_dds::Pubsub::sub_remote(cur, kind.to_str()?, f) {
|
||||
return Err("`sub_remote()` called twice").into_lua_err();
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -69,8 +69,8 @@ impl Pubsub {
|
|||
ps.raw_set(
|
||||
"unsub",
|
||||
lua.create_function(|_, kind: mlua::String| {
|
||||
if let Some(name) = &*RUNNING.load() {
|
||||
Ok(yazi_dds::Pubsub::unsub(name, kind.to_str()?))
|
||||
if let Some(ref cur) = lua.named_registry_value::<RtRef>("rt")?.current {
|
||||
Ok(yazi_dds::Pubsub::unsub(cur, kind.to_str()?))
|
||||
} else {
|
||||
Err("`unsub()` must be called in a sync plugin").into_lua_err()
|
||||
}
|
||||
|
|
@ -80,8 +80,8 @@ impl Pubsub {
|
|||
ps.raw_set(
|
||||
"unsub_remote",
|
||||
lua.create_function(|_, kind: mlua::String| {
|
||||
if let Some(name) = &*RUNNING.load() {
|
||||
Ok(yazi_dds::Pubsub::unsub_remote(name, kind.to_str()?))
|
||||
if let Some(ref cur) = lua.named_registry_value::<RtRef>("rt")?.current {
|
||||
Ok(yazi_dds::Pubsub::unsub_remote(cur, kind.to_str()?))
|
||||
} else {
|
||||
Err("`unsub_remote()` must be called in a sync plugin").into_lua_err()
|
||||
}
|
||||
|
|
|
|||
52
yazi-plugin/src/runtime.rs
Normal file
52
yazi-plugin/src/runtime.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use mlua::{Function, UserData};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Runtime {
|
||||
pub current: Option<String>,
|
||||
pub calls: usize,
|
||||
pub blocks: HashMap<String, Vec<Function<'static>>>,
|
||||
}
|
||||
|
||||
pub type RtRef<'lua> = mlua::UserDataRefMut<'lua, Runtime>;
|
||||
|
||||
impl Runtime {
|
||||
pub fn new(current: &str) -> Self {
|
||||
Self { current: Some(current.to_owned()), ..Default::default() }
|
||||
}
|
||||
|
||||
pub fn swap(&mut self, name: &str) {
|
||||
self.current = Some(name.to_owned());
|
||||
self.calls = 0;
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.current = None;
|
||||
self.calls = 0;
|
||||
}
|
||||
|
||||
pub fn next_block(&mut self) -> usize {
|
||||
self.calls += 1;
|
||||
self.calls - 1
|
||||
}
|
||||
|
||||
pub fn get_block(&self, name: &str, calls: usize) -> Option<Function<'static>> {
|
||||
self.blocks.get(name).and_then(|v| v.get(calls)).cloned()
|
||||
}
|
||||
|
||||
pub fn push_block(&mut self, f: Function<'static>) -> bool {
|
||||
let Some(ref cur) = self.current else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if let Some(vec) = self.blocks.get_mut(cur) {
|
||||
vec.push(f);
|
||||
} else {
|
||||
self.blocks.insert(cur.clone(), vec![f]);
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Runtime {}
|
||||
|
|
@ -6,8 +6,8 @@ mod call;
|
|||
mod image;
|
||||
mod layer;
|
||||
mod log;
|
||||
mod plugin;
|
||||
mod preview;
|
||||
mod sync;
|
||||
mod target;
|
||||
mod text;
|
||||
mod time;
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
use mlua::{ExternalError, Function, IntoLua, Lua, Table, Value, Variadic};
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_dds::ValueSendable;
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use super::Utils;
|
||||
use crate::OptData;
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn plugin(lua: &Lua, ya: &Table) -> mlua::Result<()> {
|
||||
ya.raw_set(
|
||||
"plugin_retrieve",
|
||||
lua.create_async_function(
|
||||
|_, (name, calls, args): (String, usize, Variadic<Value>)| async move {
|
||||
let args = ValueSendable::try_from_variadic(args)?;
|
||||
let (tx, rx) = oneshot::channel::<Vec<ValueSendable>>();
|
||||
|
||||
let data = OptData {
|
||||
cb: Some({
|
||||
let name = name.clone();
|
||||
Box::new(move |lua, plugin| {
|
||||
let blocks = lua.globals().raw_get::<_, Table>("YAZI_SYNC_BLOCKS")?;
|
||||
let block = blocks.raw_get::<_, Table>(name)?.raw_get::<_, Function>(calls)?;
|
||||
|
||||
let mut self_args = Vec::with_capacity(args.len() + 1);
|
||||
self_args.push(Value::Table(plugin));
|
||||
for arg in args {
|
||||
self_args.push(arg.into_lua(lua)?);
|
||||
}
|
||||
|
||||
let values =
|
||||
ValueSendable::try_from_variadic(block.call(Variadic::from_iter(self_args))?)?;
|
||||
tx.send(values).map_err(|_| "send failed".into_lua_err())
|
||||
})
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
emit!(Call(
|
||||
Cmd::args("plugin", vec![name.clone()]).with_bool("sync", true).with_data(data),
|
||||
Layer::App
|
||||
));
|
||||
|
||||
Ok(Variadic::from_iter(rx.await.map_err(|_| {
|
||||
format!("Failed to execute sync block-{calls} in `{name}` plugin").into_lua_err()
|
||||
})?))
|
||||
},
|
||||
)?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
87
yazi-plugin/src/utils/sync.rs
Normal file
87
yazi-plugin/src/utils/sync.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use mlua::{ExternalError, ExternalResult, Function, IntoLua, Lua, Table, Value, Variadic};
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_dds::ValueSendable;
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use super::Utils;
|
||||
use crate::{loader::LOADER, runtime::RtRef, OptData};
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn sync(lua: &'static Lua, ya: &Table) -> mlua::Result<()> {
|
||||
ya.raw_set(
|
||||
"sync",
|
||||
lua.create_function(|lua, f: Function<'static>| {
|
||||
let mut rt = lua.named_registry_value::<RtRef>("rt")?;
|
||||
if !rt.push_block(f.clone()) {
|
||||
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
|
||||
}
|
||||
|
||||
let cur = rt.current.clone().unwrap();
|
||||
lua.create_function(move |lua, mut args: Variadic<Value>| {
|
||||
args.insert(0, LOADER.load(&cur)?.into_lua(lua)?);
|
||||
f.call::<_, Variadic<Value>>(args)
|
||||
})
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn sync_isolate(lua: &Lua, ya: &Table) -> mlua::Result<()> {
|
||||
ya.raw_set(
|
||||
"sync",
|
||||
lua.create_function(|lua, ()| {
|
||||
let block = lua.named_registry_value::<RtRef>("rt")?.next_block();
|
||||
lua.create_async_function(move |lua, args: Variadic<Value>| async move {
|
||||
let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current.clone() else {
|
||||
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
|
||||
};
|
||||
|
||||
Self::retrieve(cur, block, args).await
|
||||
})
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn retrieve(
|
||||
name: String,
|
||||
calls: usize,
|
||||
args: Variadic<Value<'_>>,
|
||||
) -> mlua::Result<mlua::Variadic<ValueSendable>> {
|
||||
let args = ValueSendable::try_from_variadic(args)?;
|
||||
let (tx, rx) = oneshot::channel::<Vec<ValueSendable>>();
|
||||
|
||||
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 mut self_args = Vec::with_capacity(args.len() + 1);
|
||||
self_args.push(Value::Table(plugin));
|
||||
for arg in args {
|
||||
self_args.push(arg.into_lua(lua)?);
|
||||
}
|
||||
|
||||
let values =
|
||||
ValueSendable::try_from_variadic(block.call(Variadic::from_iter(self_args))?)?;
|
||||
tx.send(values).map_err(|_| "send failed".into_lua_err())
|
||||
})
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
emit!(Call(
|
||||
Cmd::args("plugin", vec![name.clone()]).with_bool("sync", true).with_data(data),
|
||||
Layer::App
|
||||
));
|
||||
|
||||
Ok(Variadic::from_iter(rx.await.map_err(|_| {
|
||||
format!("Failed to execute sync block-{calls} in `{name}` plugin").into_lua_err()
|
||||
})?))
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ pub(super) static HOSTNAME_CACHE: std::sync::OnceLock<Option<String>> = std::syn
|
|||
|
||||
pub(super) struct Utils;
|
||||
|
||||
pub fn install(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
pub fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
|
||||
let ya = lua.create_table()?;
|
||||
|
||||
Utils::app(lua, &ya)?;
|
||||
|
|
@ -15,8 +15,27 @@ pub fn install(lua: &mlua::Lua) -> mlua::Result<()> {
|
|||
Utils::image(lua, &ya)?;
|
||||
Utils::layer(lua, &ya)?;
|
||||
Utils::log(lua, &ya)?;
|
||||
Utils::plugin(lua, &ya)?;
|
||||
Utils::preview(lua, &ya)?;
|
||||
Utils::sync(lua, &ya)?;
|
||||
Utils::target(lua, &ya)?;
|
||||
Utils::text(lua, &ya)?;
|
||||
Utils::time(lua, &ya)?;
|
||||
Utils::user(lua, &ya)?;
|
||||
|
||||
lua.globals().raw_set("ya", ya)
|
||||
}
|
||||
|
||||
pub fn install_isolate(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
let ya = lua.create_table()?;
|
||||
|
||||
Utils::app(lua, &ya)?;
|
||||
Utils::cache(lua, &ya)?;
|
||||
Utils::call(lua, &ya)?;
|
||||
Utils::image(lua, &ya)?;
|
||||
Utils::layer(lua, &ya)?;
|
||||
Utils::log(lua, &ya)?;
|
||||
Utils::preview(lua, &ya)?;
|
||||
Utils::sync_isolate(lua, &ya)?;
|
||||
Utils::target(lua, &ya)?;
|
||||
Utils::text(lua, &ya)?;
|
||||
Utils::time(lua, &ya)?;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue