use std::str::FromStr; use mlua::{ExternalError, ExternalResult, Lua, Table, Value}; use tokio::sync::mpsc; use yazi_config::keymap::{Control, Key}; use yazi_shared::{emit, event::Cmd, Layer}; use super::Utils; impl Utils { fn parse_keys(value: Value) -> mlua::Result> { Ok(match value { Value::String(s) => { vec![Key::from_str(s.to_str()?).into_lua_err()?] } Value::Table(t) => { let mut v = Vec::with_capacity(10); for s in t.sequence_values::() { v.push(Key::from_str(s?.to_str()?).into_lua_err()?); } v } _ => Err("invalid `on`".into_lua_err())?, }) } pub(super) fn layer(lua: &Lua, ya: &Table) -> mlua::Result<()> { ya.raw_set( "which", lua.create_async_function(|_, t: Table| async move { let (tx, mut rx) = mpsc::channel::(1); let mut cands = Vec::with_capacity(30); for (i, cand) in t.raw_get::<_, Table>("cands")?.sequence_values::().enumerate() { let cand = cand?; cands.push(Control { on: Self::parse_keys(cand.raw_get("on")?)?, exec: vec![Cmd::args("callback", vec![i.to_string()]).with_data(tx.clone())], desc: cand.raw_get("desc").ok(), }); } drop(tx); emit!(Call( Cmd::new("show") .with("layer", Layer::Which) .with_bool("silent", t.raw_get("silent").unwrap_or_default()) .with_data(cands), Layer::Which )); Ok(rx.recv().await.map(|idx| idx + 1)) })?, )?; Ok(()) } }