mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: experimental module-level async support (#3594)
This commit is contained in:
parent
e6d995710f
commit
d17e7e14cd
13 changed files with 41 additions and 39 deletions
|
|
@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
||||||
- Tree view for the preset archive previewer ([#3525])
|
- Tree view for the preset archive previewer ([#3525])
|
||||||
- Support compressed tarballs (`.tar.gz`, `.tar.bz2`, etc.) in the preset archive previewer ([#3518])
|
- Support compressed tarballs (`.tar.gz`, `.tar.bz2`, etc.) in the preset archive previewer ([#3518])
|
||||||
- Check and refresh the file list when the terminal gains focus ([#3561])
|
- Check and refresh the file list when the terminal gains focus ([#3561])
|
||||||
|
- Experimental module-level async support ([#3594])
|
||||||
- Disable ANSI escape sequences in `ya pkg` when stdout is not a TTY ([#3566])
|
- Disable ANSI escape sequences in `ya pkg` when stdout is not a TTY ([#3566])
|
||||||
- New `Path.os()` API creates an OS-native `Path` ([#3541])
|
- New `Path.os()` API creates an OS-native `Path` ([#3541])
|
||||||
|
|
||||||
|
|
@ -1607,3 +1608,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
||||||
[#3561]: https://github.com/sxyazi/yazi/pull/3561
|
[#3561]: https://github.com/sxyazi/yazi/pull/3561
|
||||||
[#3566]: https://github.com/sxyazi/yazi/pull/3566
|
[#3566]: https://github.com/sxyazi/yazi/pull/3566
|
||||||
[#3582]: https://github.com/sxyazi/yazi/pull/3582
|
[#3582]: https://github.com/sxyazi/yazi/pull/3582
|
||||||
|
[#3594]: https://github.com/sxyazi/yazi/pull/3594
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ use mlua::Function;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Runtime {
|
pub struct Runtime {
|
||||||
frames: VecDeque<RuntimeFrame>,
|
frames: VecDeque<RuntimeFrame>,
|
||||||
blocks: HashMap<String, Vec<Function>>,
|
blocks: HashMap<String, Vec<Function>>,
|
||||||
pub initing: bool,
|
pub blocking: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -17,13 +17,13 @@ struct RuntimeFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runtime {
|
impl Runtime {
|
||||||
pub fn new() -> Self { Self { frames: <_>::default(), blocks: <_>::default(), initing: true } }
|
pub fn new() -> Self { Self { frames: <_>::default(), blocks: <_>::default(), blocking: true } }
|
||||||
|
|
||||||
pub fn new_isolate(id: &str) -> Self {
|
pub fn new_isolate(id: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]),
|
frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]),
|
||||||
blocks: <_>::default(),
|
blocks: <_>::default(),
|
||||||
initing: false,
|
blocking: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,12 +48,12 @@ impl Runtime {
|
||||||
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) -> bool {
|
pub fn put_block(&mut self, f: &Function) -> bool {
|
||||||
let Some(cur) = self.frames.back() else { return false };
|
let Some(cur) = self.frames.back() else { return false };
|
||||||
if let Some(v) = self.blocks.get_mut(&cur.id) {
|
if let Some(v) = self.blocks.get_mut(&cur.id) {
|
||||||
v.push(f);
|
v.push(f.clone());
|
||||||
} else {
|
} else {
|
||||||
self.blocks.insert(cur.id.clone(), vec![f]);
|
self.blocks.insert(cur.id.clone(), vec![f.clone()]);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ pub(super) fn area(lua: &Lua) -> mlua::Result<Value> {
|
||||||
|
|
||||||
pub(super) fn hide(lua: &Lua) -> mlua::Result<Value> {
|
pub(super) fn hide(lua: &Lua) -> mlua::Result<Value> {
|
||||||
let f = lua.create_async_function(|lua, ()| async move {
|
let f = lua.create_async_function(|lua, ()| async move {
|
||||||
if runtime!(lua)?.initing {
|
if runtime!(lua)?.blocking {
|
||||||
return Err("Cannot call `ui.hide()` during app initialization".into_lua_err());
|
return Err("Cannot call `ui.hide()` while main thread is blocked".into_lua_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
if lua.named_registry_value::<PermitRef>("HIDE_PERMIT").is_ok_and(|h| h.is_some()) {
|
if lua.named_registry_value::<PermitRef>("HIDE_PERMIT").is_ok_and(|h| h.is_some()) {
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ pub async fn entry(opt: PluginOpt) -> mlua::Result<()> {
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let lua = slim_lua(&opt.id)?;
|
let lua = slim_lua(&opt.id)?;
|
||||||
let plugin = LOADER.load_once(&lua, &opt.id)?;
|
|
||||||
|
|
||||||
let job = lua.create_table_from([("args", Sendable::args_to_table(&lua, opt.args)?)])?;
|
let job = lua.create_table_from([("args", Sendable::args_to_table(&lua, opt.args)?)])?;
|
||||||
Handle::current().block_on(plugin.call_async_method("entry", job))
|
|
||||||
|
Handle::current().block_on(async {
|
||||||
|
LOADER.load_once(&lua, &opt.id).await?.call_async_method("entry", job).await
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.into_lua_err()?
|
.into_lua_err()?
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,14 @@ pub async fn fetch(
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let lua = slim_lua(&cmd.name)?;
|
let lua = slim_lua(&cmd.name)?;
|
||||||
let plugin = LOADER.load_once(&lua, &cmd.name)?;
|
let job = lua.create_table_from([
|
||||||
|
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
||||||
|
("files", lua.create_sequence_from(files.into_iter().map(File::new))?.into_lua(&lua)?),
|
||||||
|
])?;
|
||||||
|
|
||||||
Handle::current().block_on(plugin.call_async_method(
|
Handle::current().block_on(async {
|
||||||
"fetch",
|
LOADER.load_once(&lua, &cmd.name).await?.call_async_method("fetch", job).await
|
||||||
lua.create_table_from([
|
})
|
||||||
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
|
||||||
("files", lua.create_sequence_from(files.into_iter().map(File::new))?.into_lua(&lua)?),
|
|
||||||
])?,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.into_lua_err()?
|
.into_lua_err()?
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ fn peek_async(
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let plugin = LOADER.load_once(&lua, &cmd.name)?;
|
let plugin = LOADER.load_once(&lua, &cmd.name).await?;
|
||||||
let job = lua.create_table_from([
|
let job = lua.create_table_from([
|
||||||
("area", Rect::from(LAYOUT.get().preview).into_lua(&lua)?),
|
("area", Rect::from(LAYOUT.get().preview).into_lua(&lua)?),
|
||||||
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ pub async fn preload(
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let plugin = LOADER.load_once(&lua, &cmd.name)?;
|
let plugin = LOADER.load_once(&lua, &cmd.name).await?;
|
||||||
let job = lua.create_table_from([
|
let job = lua.create_table_from([
|
||||||
("area", Rect::from(LAYOUT.get().preview).into_lua(&lua)?),
|
("area", Rect::from(LAYOUT.get().preview).into_lua(&lua)?),
|
||||||
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ pub fn spot(
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let plugin = LOADER.load_once(&lua, &cmd.name)?;
|
let plugin = LOADER.load_once(&lua, &cmd.name).await?;
|
||||||
let job = lua.create_table_from([
|
let job = lua.create_table_from([
|
||||||
("id", Id(IDS.next()).into_lua(&lua)?),
|
("id", Id(IDS.next()).into_lua(&lua)?),
|
||||||
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
("args", Sendable::args_to_table_ref(&lua, &cmd.args)?.into_lua(&lua)?),
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ impl Loader {
|
||||||
result.map(|_| inspect)
|
result.map(|_| inspect)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
pub async fn load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
||||||
let (id, ..) = Self::normalize_id(id)?;
|
let (id, ..) = Self::normalize_id(id)?;
|
||||||
|
|
||||||
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
|
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
|
||||||
|
|
@ -87,14 +87,14 @@ impl Loader {
|
||||||
return Ok(t);
|
return Ok(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
let t = self.load_once(lua, id)?;
|
let t = self.load_once(lua, id).await?;
|
||||||
t.raw_set("_id", lua.create_string(id)?)?;
|
t.raw_set("_id", lua.create_string(id)?)?;
|
||||||
|
|
||||||
loaded.raw_set(id, t.clone())?;
|
loaded.raw_set(id, t.clone())?;
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_once(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
pub async fn load_once(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
||||||
let (id, ..) = Self::normalize_id(id)?;
|
let (id, ..) = Self::normalize_id(id)?;
|
||||||
|
|
||||||
let mut mode = ChunkMode::Text;
|
let mut mode = ChunkMode::Text;
|
||||||
|
|
@ -114,7 +114,7 @@ impl Loader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.call(())
|
f.call_async(()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
pub fn try_load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ impl Require {
|
||||||
LOADER.ensure(&id, |_| ()).await.into_lua_err()?;
|
LOADER.ensure(&id, |_| ()).await.into_lua_err()?;
|
||||||
|
|
||||||
runtime_mut!(lua)?.push(&id);
|
runtime_mut!(lua)?.push(&id);
|
||||||
let mod_ = LOADER.load(&lua, &id);
|
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_?)
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,6 @@ fn stage_2(lua: &'static Lua) -> mlua::Result<()> {
|
||||||
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)?.initing = false;
|
runtime_mut!(lua)?.blocking = false;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ use crate::bindings::InputRx;
|
||||||
impl Utils {
|
impl Utils {
|
||||||
pub(super) fn which(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn which(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_async_function(|lua, t: Table| async move {
|
lua.create_async_function(|lua, t: Table| async move {
|
||||||
if runtime!(lua)?.initing {
|
if runtime!(lua)?.blocking {
|
||||||
return Err("Cannot call `ya.which()` during app initialization".into_lua_err());
|
return Err("Cannot call `ya.which()` while main thread is blocked".into_lua_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx, mut rx) = mpsc::channel::<usize>(1);
|
let (tx, mut rx) = mpsc::channel::<usize>(1);
|
||||||
|
|
@ -45,8 +45,8 @@ impl Utils {
|
||||||
|
|
||||||
pub(super) fn input(lua: &Lua) -> mlua::Result<Function> {
|
pub(super) fn input(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_async_function(|lua, t: Table| async move {
|
lua.create_async_function(|lua, t: Table| async move {
|
||||||
if runtime!(lua)?.initing {
|
if runtime!(lua)?.blocking {
|
||||||
return Err("Cannot call `ya.input()` during app initialization".into_lua_err());
|
return Err("Cannot call `ya.input()` while main thread is blocked".into_lua_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pos = t.raw_get::<Value>("pos")?;
|
let mut pos = t.raw_get::<Value>("pos")?;
|
||||||
|
|
@ -92,8 +92,8 @@ impl Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
lua.create_async_function(|lua, t: Table| async move {
|
lua.create_async_function(|lua, t: Table| async move {
|
||||||
if runtime!(lua)?.initing {
|
if runtime!(lua)?.blocking {
|
||||||
return Err("Cannot call `ya.confirm()` during app initialization".into_lua_err());
|
return Err("Cannot call `ya.confirm()` while main thread is blocked".into_lua_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = ConfirmProxy::show(ConfirmCfg {
|
let result = ConfirmProxy::show(ConfirmCfg {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ impl Utils {
|
||||||
} else {
|
} else {
|
||||||
lua.create_function(|lua, f: Function| {
|
lua.create_function(|lua, f: Function| {
|
||||||
let mut rt = runtime_mut!(lua)?;
|
let mut rt = runtime_mut!(lua)?;
|
||||||
if !rt.put_block(f.clone()) {
|
if !rt.put_block(&f) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue