use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value}; use tokio::sync::mpsc; use yazi_config::{KEYMAP, keymap::{ChordCow, Key}}; use yazi_shared::{Layer, event::ActionCow}; #[derive(Clone, Debug)] pub struct ActivateOpt { pub tx: Option>>, pub cands: Vec, pub silent: bool, pub times: usize, } impl TryFrom for ActivateOpt { type Error = anyhow::Error; fn try_from(mut a: ActionCow) -> Result { if let Some(opt) = a.take_any2("opt") { return opt; } Ok(Self { tx: a.take_any2("tx").transpose()?, cands: a.take_any_iter::().map(Into::into).collect(), silent: a.bool("silent"), times: a.get("times").unwrap_or(0), }) } } impl From<(Layer, Key)> for ActivateOpt { fn from((layer, key): (Layer, Key)) -> Self { Self { tx: None, cands: KEYMAP .get(layer) .iter() .filter(|c| c.on.len() > 1 && c.on[0] == key) .map(Into::into) .collect(), times: 1, silent: false, } } } impl FromLua for ActivateOpt { fn from_lua(value: Value, _: &Lua) -> mlua::Result { let Value::Table(t) = value else { return Err("expected a table".into_lua_err()); }; Ok(Self { tx: t.raw_get::>("tx").ok().map(|t| t.0), cands: t .raw_get::("cands")? .sequence_values::() .map(|c| c.map(Into::into)) .collect::>>()?, times: t.raw_get("times").unwrap_or_default(), silent: t.raw_get("silent")?, }) } } impl IntoLua for ActivateOpt { #[rustfmt::skip] fn into_lua(self, lua: &Lua) -> mlua::Result { lua .create_table_from([ ("tx", self.tx.map(yazi_binding::MpscUnboundedTx).into_lua(lua)?), ("cands", lua.create_sequence_from(self.cands.into_iter().map(yazi_binding::ChordCow))?.into_lua(lua)?), ("times", self.times.into_lua(lua)?), ("silent", self.silent.into_lua(lua)?), ])? .into_lua(lua) } }