mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
99 lines
3.1 KiB
Rust
99 lines
3.1 KiB
Rust
use std::{collections::HashMap, ops::Deref};
|
|
|
|
use anyhow::{Context, Result};
|
|
use mlua::{ExternalError, Lua, Table};
|
|
use parking_lot::RwLock;
|
|
use tokio::fs;
|
|
use yazi_boot::BOOT;
|
|
use yazi_macro::plugin_preset as preset;
|
|
use yazi_shared::RoCell;
|
|
|
|
use super::Chunk;
|
|
|
|
pub static LOADER: RoCell<Loader> = RoCell::new();
|
|
|
|
pub struct Loader {
|
|
cache: RwLock<HashMap<String, Chunk>>,
|
|
}
|
|
|
|
impl Deref for Loader {
|
|
type Target = RwLock<HashMap<String, Chunk>>;
|
|
|
|
#[inline]
|
|
fn deref(&self) -> &Self::Target { &self.cache }
|
|
}
|
|
|
|
impl Default for Loader {
|
|
fn default() -> Self {
|
|
let cache = HashMap::from_iter([
|
|
("archive".to_owned(), preset!("plugins/archive").into()),
|
|
("code".to_owned(), preset!("plugins/code").into()),
|
|
("dds".to_owned(), preset!("plugins/dds").into()),
|
|
("empty".to_owned(), preset!("plugins/empty").into()),
|
|
("extract".to_owned(), preset!("plugins/extract").into()),
|
|
("file".to_owned(), preset!("plugins/file").into()),
|
|
("folder".to_owned(), preset!("plugins/folder").into()),
|
|
("font".to_owned(), preset!("plugins/font").into()),
|
|
("fzf".to_owned(), preset!("plugins/fzf").into()),
|
|
("image".to_owned(), preset!("plugins/image").into()),
|
|
("json".to_owned(), preset!("plugins/json").into()),
|
|
("magick".to_owned(), preset!("plugins/magick").into()),
|
|
("mime".to_owned(), preset!("plugins/mime").into()),
|
|
("noop".to_owned(), preset!("plugins/noop").into()),
|
|
("pdf".to_owned(), preset!("plugins/pdf").into()),
|
|
("session".to_owned(), preset!("plugins/session").into()),
|
|
("video".to_owned(), preset!("plugins/video").into()),
|
|
("zoxide".to_owned(), preset!("plugins/zoxide").into()),
|
|
]);
|
|
Self { cache: RwLock::new(cache) }
|
|
}
|
|
}
|
|
|
|
impl Loader {
|
|
pub async fn ensure(&self, name: &str) -> Result<()> {
|
|
if self.cache.read().contains_key(name) {
|
|
return Ok(());
|
|
}
|
|
|
|
let p = BOOT.plugin_dir.join(format!("{name}.yazi/init.lua"));
|
|
let chunk =
|
|
fs::read(&p).await.with_context(|| format!("failed to load plugin from {p:?}"))?.into();
|
|
|
|
self.cache.write().insert(name.to_owned(), chunk);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
|
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
|
|
if let Ok(t) = loaded.raw_get::<Table>(id) {
|
|
return Ok(t);
|
|
}
|
|
|
|
let t: Table = match self.read().get(id) {
|
|
Some(c) => lua.load(c.as_bytes()).set_name(id).call(())?,
|
|
None => Err(format!("plugin `{id}` not found").into_lua_err())?,
|
|
};
|
|
|
|
t.raw_set("_id", lua.create_string(id)?)?;
|
|
loaded.raw_set(id, t.clone())?;
|
|
Ok(t)
|
|
}
|
|
|
|
pub fn try_load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
|
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
|
|
loaded.raw_get(id)
|
|
}
|
|
|
|
pub fn load_with(&self, lua: &Lua, id: &str, chunk: &Chunk) -> mlua::Result<Table> {
|
|
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
|
|
if let Ok(t) = loaded.raw_get::<Table>(id) {
|
|
return Ok(t);
|
|
}
|
|
|
|
let t: Table = lua.load(chunk.as_bytes()).set_name(id).call(())?;
|
|
t.raw_set("_id", lua.create_string(id)?)?;
|
|
|
|
loaded.raw_set(id, t.clone())?;
|
|
Ok(t)
|
|
}
|
|
}
|