mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41: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
|
### 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 `cx.which` API to access the which component state ([#3617])
|
||||||
- New `ind-which-activate` DDS event to change the which component behavior ([#3608])
|
- 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
|
[#3617]: https://github.com/sxyazi/yazi/pull/3617
|
||||||
[#3633]: https://github.com/sxyazi/yazi/pull/3633
|
[#3633]: https://github.com/sxyazi/yazi/pull/3633
|
||||||
[#3634]: https://github.com/sxyazi/yazi/pull/3634
|
[#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"
|
version = "26.1.22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi-to-tui",
|
"ansi-to-tui",
|
||||||
|
"anyhow",
|
||||||
"crossterm 0.29.0",
|
"crossterm 0.29.0",
|
||||||
"futures",
|
"futures",
|
||||||
"hashbrown 0.16.1",
|
"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.
|
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.
|
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()) {
|
if let Err(e) = cb.call::<()>(body.clone()) {
|
||||||
error!("Failed to run `{kind}` event handler in your `{id}` plugin: {e}");
|
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(())
|
Ok(())
|
||||||
})?);
|
})?);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ impl Preflight {
|
||||||
for (id, cb) in handlers {
|
for (id, cb) in handlers {
|
||||||
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
||||||
let result = cb.call::<Value>(&body);
|
let result = cb.call::<Value>(&body);
|
||||||
runtime_mut!(LUA)?.critical_pop(blocking);
|
runtime_mut!(LUA)?.critical_pop(blocking)?;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(Value::Nil) => {
|
Ok(Value::Nil) => {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ yazi-widgets = { path = "../yazi-widgets", version = "26.1.22" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
ansi-to-tui = { workspace = true }
|
ansi-to-tui = { workspace = true }
|
||||||
|
anyhow = { workspace = true }
|
||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
hashbrown = { workspace = true }
|
hashbrown = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{collections::VecDeque, mem};
|
use std::{collections::VecDeque, mem};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
use hashbrown::{HashMap, hash_map::EntryRef};
|
use hashbrown::{HashMap, hash_map::EntryRef};
|
||||||
use mlua::Function;
|
use mlua::Function;
|
||||||
|
|
||||||
|
|
@ -11,12 +12,12 @@ pub struct Runtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RuntimeFrame {
|
pub struct RuntimeFrame {
|
||||||
id: String,
|
id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runtime {
|
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 {
|
pub fn new_isolate(id: &str) -> Self {
|
||||||
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 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 {
|
pub fn critical_push(&mut self, id: &str, blocking: bool) -> bool {
|
||||||
self.push(id);
|
self.push(id);
|
||||||
mem::replace(&mut self.blocking, blocking)
|
mem::replace(&mut self.blocking, blocking)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn critical_pop(&mut self, blocking: bool) {
|
pub fn critical_pop(&mut self, blocking: bool) -> Result<RuntimeFrame> {
|
||||||
self.pop();
|
|
||||||
self.blocking = blocking;
|
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> {
|
pub fn get_block(&self, id: &str, calls: usize) -> Option<Function> {
|
||||||
self.blocks.get(id).and_then(|v| v.get(calls)).cloned()
|
self.blocks.get(id).and_then(|v| v.get(calls)).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put_block(&mut self, f: &Function) -> Option<usize> {
|
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) {
|
Some(match self.blocks.entry_ref(&cur.id) {
|
||||||
EntryRef::Occupied(mut oe) => {
|
EntryRef::Occupied(mut oe) => {
|
||||||
oe.get_mut().push(f.clone());
|
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()),
|
("font".to_owned(), preset!("plugins/font").into()),
|
||||||
("fzf".to_owned(), preset!("plugins/fzf").into()),
|
("fzf".to_owned(), preset!("plugins/fzf").into()),
|
||||||
("image".to_owned(), preset!("plugins/image").into()),
|
("image".to_owned(), preset!("plugins/image").into()),
|
||||||
|
("init".to_owned(), preset!("plugins/init").into()),
|
||||||
("json".to_owned(), preset!("plugins/json").into()),
|
("json".to_owned(), preset!("plugins/json").into()),
|
||||||
("magick".to_owned(), preset!("plugins/magick").into()),
|
("magick".to_owned(), preset!("plugins/magick").into()),
|
||||||
("mime".to_owned(), preset!("plugins/mime").into()),
|
("mime".to_owned(), preset!("plugins/mime").into()),
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl Require {
|
||||||
|
|
||||||
runtime_mut!(lua)?.push(&id);
|
runtime_mut!(lua)?.push(&id);
|
||||||
let mod_ = LOADER.load(&lua, &id).await;
|
let mod_ = LOADER.load(&lua, &id).await;
|
||||||
runtime_mut!(lua)?.pop();
|
runtime_mut!(lua)?.pop()?;
|
||||||
|
|
||||||
Self::create_mt(&lua, id.into_owned(), mod_?)
|
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)?;
|
let (r#mod, args) = Self::split_mod_and_args(&lua, &id, args)?;
|
||||||
runtime_mut!(lua)?.push(&id);
|
runtime_mut!(lua)?.push(&id);
|
||||||
let result = r#mod.call_async_function::<MultiValue>(&f, args).await;
|
let result = r#mod.call_async_function::<MultiValue>(&f, args).await;
|
||||||
runtime_mut!(lua)?.pop();
|
runtime_mut!(lua)?.pop()?;
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -90,10 +90,9 @@ impl Require {
|
||||||
|
|
||||||
fn absolute_id<'a>(lua: &Lua, id: &'a str) -> mlua::Result<Cow<'a, str>> {
|
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()) };
|
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()
|
let rt = runtime!(lua)?;
|
||||||
} else {
|
let cur = rt.current()?;
|
||||||
stripped.into()
|
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()?;
|
lua.load(preset!("compat")).set_name("compat.lua").exec()?;
|
||||||
|
|
||||||
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
|
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())?;
|
block_on(lua.load(b).set_name("init.lua").exec_async())?;
|
||||||
|
runtime_mut!(lua)?.critical_pop(blocking)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime_mut!(lua)?.blocking = false;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,7 @@ impl Pubsub {
|
||||||
pub(super) fn sub(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn sub(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||||
let rt = runtime!(lua)?;
|
let rt = runtime!(lua)?;
|
||||||
let Some(cur) = rt.current() else {
|
if !yazi_dds::Pubsub::sub(rt.current()?, &kind.to_str()?, f) {
|
||||||
return Err("`sub()` must be called in a sync plugin").into_lua_err();
|
|
||||||
};
|
|
||||||
if !yazi_dds::Pubsub::sub(cur, &kind.to_str()?, f) {
|
|
||||||
return Err("`sub()` called twice").into_lua_err();
|
return Err("`sub()` called twice").into_lua_err();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -34,10 +31,7 @@ impl Pubsub {
|
||||||
pub(super) fn sub_remote(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn sub_remote(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
|
||||||
let rt = runtime!(lua)?;
|
let rt = runtime!(lua)?;
|
||||||
let Some(cur) = rt.current() else {
|
if !yazi_dds::Pubsub::sub_remote(rt.current()?, &kind.to_str()?, f) {
|
||||||
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) {
|
|
||||||
return Err("`sub_remote()` called twice").into_lua_err();
|
return Err("`sub_remote()` called twice").into_lua_err();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -46,21 +40,15 @@ impl Pubsub {
|
||||||
|
|
||||||
pub(super) fn unsub(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn unsub(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_function(|lua, kind: mlua::String| {
|
lua.create_function(|lua, kind: mlua::String| {
|
||||||
if let Some(cur) = runtime!(lua)?.current() {
|
let rt = runtime!(lua)?;
|
||||||
Ok(yazi_dds::Pubsub::unsub(cur, &kind.to_str()?))
|
Ok(yazi_dds::Pubsub::unsub(rt.current()?, &kind.to_str()?))
|
||||||
} else {
|
|
||||||
Err("`unsub()` must be called in a sync plugin").into_lua_err()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unsub_remote(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn unsub_remote(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_function(|lua, kind: mlua::String| {
|
lua.create_function(|lua, kind: mlua::String| {
|
||||||
if let Some(cur) = runtime!(lua)?.current() {
|
let rt = runtime!(lua)?;
|
||||||
Ok(yazi_dds::Pubsub::unsub_remote(cur, &kind.to_str()?))
|
Ok(yazi_dds::Pubsub::unsub_remote(rt.current()?, &kind.to_str()?))
|
||||||
} else {
|
|
||||||
Err("`unsub_remote()` must be called in a sync plugin").into_lua_err()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Table, Value, Variadic};
|
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Table, Value, Variadic};
|
||||||
|
|
@ -16,27 +14,26 @@ use crate::loader::LOADER;
|
||||||
impl Utils {
|
impl Utils {
|
||||||
pub(super) fn sync(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn sync(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_function(|lua, f: 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();
|
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| {
|
lua.create_async_function(move |lua, mut args: MultiValue| {
|
||||||
let f = f.clone();
|
let (f, current) = (f.clone(), current.clone());
|
||||||
async move {
|
async move {
|
||||||
let rt = runtime!(lua)?;
|
let blocking = runtime!(lua)?.blocking;
|
||||||
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);
|
|
||||||
|
|
||||||
if 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)
|
f.call::<MultiValue>(args)
|
||||||
} else {
|
} else {
|
||||||
Self::retrieve(&lua, &cur, block, args)
|
Self::retrieve(&lua, ¤t, block, args)
|
||||||
.await
|
.await
|
||||||
.and_then(|data| Sendable::list_to_values(&lua, data))
|
.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()
|
.into_lua_err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -51,26 +48,18 @@ impl Utils {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
lua.create_function(|lua, (f, args): (Function, MultiValue)| {
|
lua.create_function(|lua, (f, args): (Function, MultiValue)| {
|
||||||
let name = runtime!(lua)?.current_owned();
|
let name = runtime!(lua)?.current_owned()?;
|
||||||
let lua = lua.clone();
|
let lua = lua.clone();
|
||||||
|
|
||||||
Ok(Handle::AsyncFn(LOCAL_SET.spawn_local(async move {
|
Ok(Handle::AsyncFn(LOCAL_SET.spawn_local(async move {
|
||||||
let blocking = mem::replace(&mut runtime_mut!(lua)?.blocking, false);
|
let blocking = runtime_mut!(lua)?.critical_push(&name, false);
|
||||||
if let Some(s) = &name {
|
|
||||||
runtime_mut!(lua)?.push(s); // make `current_owned` always return Some to eliminate the check
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = f.call_async::<MultiValue>(args).await;
|
let result = f.call_async::<MultiValue>(args).await;
|
||||||
|
runtime_mut!(lua)?.critical_pop(blocking)?;
|
||||||
runtime_mut!(lua)?.blocking = blocking;
|
|
||||||
if name.is_some() {
|
|
||||||
runtime_mut!(lua)?.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(ref e) = result {
|
if let Err(ref e) = result {
|
||||||
match name {
|
match name.as_str() {
|
||||||
Some(s) => tracing::error!("Failed to execute async block in `{s}` plugin: {e}"),
|
"init" => tracing::error!("Failed to execute async block in `init.lua`: {e}"),
|
||||||
None => tracing::error!("Failed to execute async block in `init.lua`: {e}"),
|
s => tracing::error!("Failed to execute async block in `{s}` plugin: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue