mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: allow using ps.sub() in init.lua directly without a plugin (#3638)
This commit is contained in:
parent
1ea0ea072c
commit
dfdb235d74
13 changed files with 52 additions and 65 deletions
|
|
@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
|
||||
### Added
|
||||
|
||||
- Allow using `ps.sub()` in `init.lua` directly without a plugin ([#3638])
|
||||
- New `cx.which` API to access the which component state ([#3617])
|
||||
- New `ind-which-activate` DDS event to change the which component behavior ([#3608])
|
||||
|
||||
|
|
@ -1634,3 +1635,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#3617]: https://github.com/sxyazi/yazi/pull/3617
|
||||
[#3633]: https://github.com/sxyazi/yazi/pull/3633
|
||||
[#3634]: https://github.com/sxyazi/yazi/pull/3634
|
||||
[#3638]: https://github.com/sxyazi/yazi/pull/3638
|
||||
|
|
|
|||
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -5596,6 +5596,7 @@ name = "yazi-binding"
|
|||
version = "26.1.22"
|
||||
dependencies = [
|
||||
"ansi-to-tui",
|
||||
"anyhow",
|
||||
"crossterm 0.29.0",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ I noticed that you did not correctly follow the issue template. Please ensure th
|
|||
|
||||
Issues with \`${LABEL_NAME}\` will be marked ready once edited with the proper content, or closed after 2 days of inactivity.
|
||||
|
||||
Our maintainers work on Yazi in their free time, this helps them work efficiently, understand your setup quickly, and find a more appropriate solution. Thanks for your understanding!
|
||||
Our maintainers work on Yazi in their free time, this helps them work efficiently, understand your setup quickly, and find a more appropriate solution. Thanks for your understanding! 🙏
|
||||
`
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ I noticed that you did not correctly follow the issue template. Please ensure th
|
|||
|
||||
Issues with \`${LABEL_NAME}\` will be marked ready once edited with the proper content, or closed after 2 days of inactivity.
|
||||
|
||||
Our maintainers work on Yazi in their free time, this helps them work efficiently, understand your setup quickly, and find a more appropriate solution. Thanks for your understanding!
|
||||
Our maintainers work on Yazi in their free time, this helps them work efficiently, understand your setup quickly, and find a more appropriate solution. Thanks for your understanding! 🙏
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl Actor for AcceptPayload {
|
|||
if let Err(e) = cb.call::<()>(body.clone()) {
|
||||
error!("Failed to run `{kind}` event handler in your `{id}` plugin: {e}");
|
||||
}
|
||||
runtime_mut!(LUA)?.critical_pop(blocking);
|
||||
runtime_mut!(LUA)?.critical_pop(blocking)?;
|
||||
}
|
||||
Ok(())
|
||||
})?);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ impl Preflight {
|
|||
for (id, cb) in handlers {
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
||||
let result = cb.call::<Value>(&body);
|
||||
runtime_mut!(LUA)?.critical_pop(blocking);
|
||||
runtime_mut!(LUA)?.critical_pop(blocking)?;
|
||||
|
||||
match result {
|
||||
Ok(Value::Nil) => {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ yazi-widgets = { path = "../yazi-widgets", version = "26.1.22" }
|
|||
|
||||
# External dependencies
|
||||
ansi-to-tui = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::{collections::VecDeque, mem};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use hashbrown::{HashMap, hash_map::EntryRef};
|
||||
use mlua::Function;
|
||||
|
||||
|
|
@ -11,12 +12,12 @@ pub struct Runtime {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RuntimeFrame {
|
||||
pub struct RuntimeFrame {
|
||||
id: String,
|
||||
}
|
||||
|
||||
impl Runtime {
|
||||
pub fn new() -> Self { Self { frames: <_>::default(), blocks: <_>::default(), blocking: true } }
|
||||
pub fn new() -> Self { Self { frames: <_>::default(), blocks: <_>::default(), blocking: false } }
|
||||
|
||||
pub fn new_isolate(id: &str) -> Self {
|
||||
Self {
|
||||
|
|
@ -28,28 +29,32 @@ impl Runtime {
|
|||
|
||||
pub fn push(&mut self, id: &str) { self.frames.push_back(RuntimeFrame { id: id.to_owned() }); }
|
||||
|
||||
pub fn pop(&mut self) { self.frames.pop_back(); }
|
||||
pub fn pop(&mut self) -> Result<RuntimeFrame> {
|
||||
self.frames.pop_back().context("Runtime stack underflow")
|
||||
}
|
||||
|
||||
pub fn critical_push(&mut self, id: &str, blocking: bool) -> bool {
|
||||
self.push(id);
|
||||
mem::replace(&mut self.blocking, blocking)
|
||||
}
|
||||
|
||||
pub fn critical_pop(&mut self, blocking: bool) {
|
||||
self.pop();
|
||||
pub fn critical_pop(&mut self, blocking: bool) -> Result<RuntimeFrame> {
|
||||
self.blocking = blocking;
|
||||
self.pop()
|
||||
}
|
||||
|
||||
pub fn current(&self) -> Option<&str> { self.frames.back().map(|f| f.id.as_str()) }
|
||||
pub fn current(&self) -> Result<&str> {
|
||||
self.frames.back().map(|f| f.id.as_str()).context("No current runtime frame")
|
||||
}
|
||||
|
||||
pub fn current_owned(&self) -> Option<String> { self.current().map(ToOwned::to_owned) }
|
||||
pub fn current_owned(&self) -> Result<String> { self.current().map(ToOwned::to_owned) }
|
||||
|
||||
pub fn get_block(&self, id: &str, calls: usize) -> Option<Function> {
|
||||
self.blocks.get(id).and_then(|v| v.get(calls)).cloned()
|
||||
}
|
||||
|
||||
pub fn put_block(&mut self, f: &Function) -> Option<usize> {
|
||||
let Some(cur) = self.frames.back() else { return None };
|
||||
let Some(cur) = self.frames.back().filter(|f| f.id != "init") else { return None };
|
||||
Some(match self.blocks.entry_ref(&cur.id) {
|
||||
EntryRef::Occupied(mut oe) => {
|
||||
oe.get_mut().push(f.clone());
|
||||
|
|
|
|||
0
yazi-plugin/preset/plugins/init.lua
Normal file
0
yazi-plugin/preset/plugins/init.lua
Normal file
|
|
@ -36,6 +36,7 @@ impl Default for Loader {
|
|||
("font".to_owned(), preset!("plugins/font").into()),
|
||||
("fzf".to_owned(), preset!("plugins/fzf").into()),
|
||||
("image".to_owned(), preset!("plugins/image").into()),
|
||||
("init".to_owned(), preset!("plugins/init").into()),
|
||||
("json".to_owned(), preset!("plugins/json").into()),
|
||||
("magick".to_owned(), preset!("plugins/magick").into()),
|
||||
("mime".to_owned(), preset!("plugins/mime").into()),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl Require {
|
|||
|
||||
runtime_mut!(lua)?.push(&id);
|
||||
let mod_ = LOADER.load(&lua, &id).await;
|
||||
runtime_mut!(lua)?.pop();
|
||||
runtime_mut!(lua)?.pop()?;
|
||||
|
||||
Self::create_mt(&lua, id.into_owned(), mod_?)
|
||||
})?,
|
||||
|
|
@ -61,7 +61,7 @@ impl Require {
|
|||
let (r#mod, args) = Self::split_mod_and_args(&lua, &id, args)?;
|
||||
runtime_mut!(lua)?.push(&id);
|
||||
let result = r#mod.call_async_function::<MultiValue>(&f, args).await;
|
||||
runtime_mut!(lua)?.pop();
|
||||
runtime_mut!(lua)?.pop()?;
|
||||
result
|
||||
}
|
||||
})
|
||||
|
|
@ -90,10 +90,9 @@ impl Require {
|
|||
|
||||
fn absolute_id<'a>(lua: &Lua, id: &'a str) -> mlua::Result<Cow<'a, str>> {
|
||||
let Some(stripped) = id.strip_prefix('.') else { return Ok(id.into()) };
|
||||
Ok(if let Some(cur) = runtime!(lua)?.current() {
|
||||
format!("{}.{stripped}", cur.split('.').next().unwrap_or(cur)).into()
|
||||
} else {
|
||||
stripped.into()
|
||||
})
|
||||
|
||||
let rt = runtime!(lua)?;
|
||||
let cur = rt.current()?;
|
||||
Ok(format!("{}.{stripped}", cur.split('.').next().unwrap_or(cur)).into())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ fn stage_2(lua: &'static Lua) -> mlua::Result<()> {
|
|||
lua.load(preset!("compat")).set_name("compat.lua").exec()?;
|
||||
|
||||
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
|
||||
let blocking = runtime_mut!(lua)?.critical_push("init", true);
|
||||
block_on(lua.load(b).set_name("init.lua").exec_async())?;
|
||||
runtime_mut!(lua)?.critical_pop(blocking)?;
|
||||
}
|
||||
|
||||
runtime_mut!(lua)?.blocking = false;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,7 @@ impl Pubsub {
|
|||
pub(super) fn sub(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||
let rt = runtime!(lua)?;
|
||||
let Some(cur) = rt.current() else {
|
||||
return Err("`sub()` must be called in a sync plugin").into_lua_err();
|
||||
};
|
||||
if !yazi_dds::Pubsub::sub(cur, &kind.to_str()?, f) {
|
||||
if !yazi_dds::Pubsub::sub(rt.current()?, &kind.to_str()?, f) {
|
||||
return Err("`sub()` called twice").into_lua_err();
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -34,10 +31,7 @@ impl Pubsub {
|
|||
pub(super) fn sub_remote(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||
let rt = runtime!(lua)?;
|
||||
let Some(cur) = rt.current() else {
|
||||
return Err("`sub_remote()` must be called in a sync plugin").into_lua_err();
|
||||
};
|
||||
if !yazi_dds::Pubsub::sub_remote(cur, &kind.to_str()?, f) {
|
||||
if !yazi_dds::Pubsub::sub_remote(rt.current()?, &kind.to_str()?, f) {
|
||||
return Err("`sub_remote()` called twice").into_lua_err();
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -46,21 +40,15 @@ impl Pubsub {
|
|||
|
||||
pub(super) fn unsub(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, kind: mlua::String| {
|
||||
if let Some(cur) = runtime!(lua)?.current() {
|
||||
Ok(yazi_dds::Pubsub::unsub(cur, &kind.to_str()?))
|
||||
} else {
|
||||
Err("`unsub()` must be called in a sync plugin").into_lua_err()
|
||||
}
|
||||
let rt = runtime!(lua)?;
|
||||
Ok(yazi_dds::Pubsub::unsub(rt.current()?, &kind.to_str()?))
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn unsub_remote(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, kind: mlua::String| {
|
||||
if let Some(cur) = runtime!(lua)?.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()
|
||||
}
|
||||
let rt = runtime!(lua)?;
|
||||
Ok(yazi_dds::Pubsub::unsub_remote(rt.current()?, &kind.to_str()?))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use std::mem;
|
||||
|
||||
use anyhow::Context;
|
||||
use futures::future::join_all;
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Table, Value, Variadic};
|
||||
|
|
@ -16,27 +14,26 @@ use crate::loader::LOADER;
|
|||
impl Utils {
|
||||
pub(super) fn sync(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, f: Function| {
|
||||
let Some(block) = runtime_mut!(lua)?.put_block(&f) else {
|
||||
let mut rt = runtime_mut!(lua)?;
|
||||
let Some(block) = rt.put_block(&f) else {
|
||||
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
|
||||
};
|
||||
|
||||
let current = rt.current_owned()?;
|
||||
lua.create_async_function(move |lua, mut args: MultiValue| {
|
||||
let f = f.clone();
|
||||
let (f, current) = (f.clone(), current.clone());
|
||||
async move {
|
||||
let rt = runtime!(lua)?;
|
||||
let (Some(cur), blocking) = (rt.current_owned(), rt.blocking) else {
|
||||
return Err("`ya.sync()` block must be used within a plugin").into_lua_err();
|
||||
};
|
||||
drop(rt);
|
||||
|
||||
let blocking = runtime!(lua)?.blocking;
|
||||
if blocking {
|
||||
args.push_front(Value::Table(LOADER.try_load(&lua, &cur)?));
|
||||
args.push_front(Value::Table(LOADER.try_load(&lua, ¤t)?));
|
||||
f.call::<MultiValue>(args)
|
||||
} else {
|
||||
Self::retrieve(&lua, &cur, block, args)
|
||||
Self::retrieve(&lua, ¤t, block, args)
|
||||
.await
|
||||
.and_then(|data| Sendable::list_to_values(&lua, data))
|
||||
.with_context(|| format!("Failed to execute sync block-{block} in `{cur}` plugin"))
|
||||
.with_context(|| {
|
||||
format!("Failed to execute sync block-{block} in `{current}` plugin")
|
||||
})
|
||||
.into_lua_err()
|
||||
}
|
||||
}
|
||||
|
|
@ -51,26 +48,18 @@ impl Utils {
|
|||
})
|
||||
} else {
|
||||
lua.create_function(|lua, (f, args): (Function, MultiValue)| {
|
||||
let name = runtime!(lua)?.current_owned();
|
||||
let name = runtime!(lua)?.current_owned()?;
|
||||
let lua = lua.clone();
|
||||
|
||||
Ok(Handle::AsyncFn(LOCAL_SET.spawn_local(async move {
|
||||
let blocking = mem::replace(&mut runtime_mut!(lua)?.blocking, false);
|
||||
if let Some(s) = &name {
|
||||
runtime_mut!(lua)?.push(s); // make `current_owned` always return Some to eliminate the check
|
||||
}
|
||||
|
||||
let blocking = runtime_mut!(lua)?.critical_push(&name, false);
|
||||
let result = f.call_async::<MultiValue>(args).await;
|
||||
|
||||
runtime_mut!(lua)?.blocking = blocking;
|
||||
if name.is_some() {
|
||||
runtime_mut!(lua)?.pop();
|
||||
}
|
||||
runtime_mut!(lua)?.critical_pop(blocking)?;
|
||||
|
||||
if let Err(ref e) = result {
|
||||
match name {
|
||||
Some(s) => tracing::error!("Failed to execute async block in `{s}` plugin: {e}"),
|
||||
None => tracing::error!("Failed to execute async block in `init.lua`: {e}"),
|
||||
match name.as_str() {
|
||||
"init" => tracing::error!("Failed to execute async block in `init.lua`: {e}"),
|
||||
s => tracing::error!("Failed to execute async block in `{s}` plugin: {e}"),
|
||||
}
|
||||
}
|
||||
result
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue