From 6e1d88c3fab1cf20e7261c6024169c23aaf53910 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 2 Mar 2024 19:35:39 +0800 Subject: [PATCH] .. --- Cargo.lock | 1 + yazi-config/src/popup/origin.rs | 55 ++++++++++++++++++++++++---- yazi-config/src/which/sorting.rs | 2 +- yazi-plugin/Cargo.toml | 1 + yazi-plugin/src/bindings/input.rs | 27 ++++++++++++++ yazi-plugin/src/bindings/mod.rs | 4 ++ yazi-plugin/src/bindings/position.rs | 47 ++++++++++++++++++++++++ yazi-plugin/src/utils/layer.rs | 33 +++++++++++------ 8 files changed, 150 insertions(+), 20 deletions(-) create mode 100644 yazi-plugin/src/bindings/input.rs create mode 100644 yazi-plugin/src/bindings/position.rs diff --git a/Cargo.lock b/Cargo.lock index eb1dbe32..c1dd3431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2803,6 +2803,7 @@ dependencies = [ "yazi-boot", "yazi-config", "yazi-prebuild", + "yazi-proxy", "yazi-shared", ] diff --git a/yazi-config/src/popup/origin.rs b/yazi-config/src/popup/origin.rs index ac997ecf..70231c88 100644 --- a/yazi-config/src/popup/origin.rs +++ b/yazi-config/src/popup/origin.rs @@ -1,24 +1,63 @@ +use std::{fmt::Display, str::FromStr}; + +use anyhow::bail; use serde::Deserialize; #[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq)] +#[serde(try_from = "String")] pub enum Origin { #[default] - #[serde(rename = "top-left")] TopLeft, - #[serde(rename = "top-center")] TopCenter, - #[serde(rename = "top-right")] TopRight, - #[serde(rename = "bottom-left")] BottomLeft, - #[serde(rename = "bottom-center")] BottomCenter, - #[serde(rename = "bottom-right")] BottomRight, - #[serde(rename = "center")] Center, - #[serde(rename = "hovered")] Hovered, } + +impl FromStr for Origin { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(match s { + "top-left" => Self::TopLeft, + "top-center" => Self::TopCenter, + "top-right" => Self::TopRight, + + "bottom-left" => Self::BottomLeft, + "bottom-center" => Self::BottomCenter, + "bottom-right" => Self::BottomRight, + + "center" => Self::Center, + "hovered" => Self::Hovered, + _ => bail!("Invalid `origin` value: {s}"), + }) + } +} + +impl TryFrom for Origin { + type Error = anyhow::Error; + + fn try_from(value: String) -> Result { Self::from_str(&value) } +} + +impl Display for Origin { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::TopLeft => "top-left", + Self::TopCenter => "top-center", + Self::TopRight => "top-right", + + Self::BottomLeft => "bottom-left", + Self::BottomCenter => "bottom-center", + Self::BottomRight => "bottom-right", + + Self::Center => "center", + Self::Hovered => "hovered", + }) + } +} diff --git a/yazi-config/src/which/sorting.rs b/yazi-config/src/which/sorting.rs index cb38e803..73939d58 100644 --- a/yazi-config/src/which/sorting.rs +++ b/yazi-config/src/which/sorting.rs @@ -20,7 +20,7 @@ impl FromStr for SortBy { "none" => Self::None, "key" => Self::Key, "desc" => Self::Desc, - _ => bail!("Invalid sort option: {s}"), + _ => bail!("Invalid `sort_by` value: {s}"), }) } } diff --git a/yazi-plugin/Cargo.toml b/yazi-plugin/Cargo.toml index dd8d2fa6..3168c6cf 100644 --- a/yazi-plugin/Cargo.toml +++ b/yazi-plugin/Cargo.toml @@ -12,6 +12,7 @@ repository = "https://github.com/sxyazi/yazi" yazi-adaptor = { path = "../yazi-adaptor", version = "0.2.3" } yazi-boot = { path = "../yazi-boot", version = "0.2.3" } yazi-config = { path = "../yazi-config", version = "0.2.3" } +yazi-proxy = { path = "../yazi-proxy", version = "0.2.3" } yazi-shared = { path = "../yazi-shared", version = "0.2.3" } # External dependencies diff --git a/yazi-plugin/src/bindings/input.rs b/yazi-plugin/src/bindings/input.rs new file mode 100644 index 00000000..65eca5ef --- /dev/null +++ b/yazi-plugin/src/bindings/input.rs @@ -0,0 +1,27 @@ +use mlua::{prelude::LuaUserDataMethods, UserData}; +use tokio::sync::mpsc::UnboundedReceiver; +use yazi_shared::InputError; + +pub struct InputRx { + inner: UnboundedReceiver>, +} + +impl InputRx { + pub fn new(inner: UnboundedReceiver>) -> Self { Self { inner } } +} + +impl UserData for InputRx { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method_mut("recv", |_, me, ()| async move { + let Some(res) = me.inner.recv().await else { + return Ok((None, 0)); + }; + + Ok(match res { + Ok(s) => (Some(s), 1), + Err(InputError::Typed(s)) => (Some(s), 2), + _ => (None, 0), + }) + }); + } +} diff --git a/yazi-plugin/src/bindings/mod.rs b/yazi-plugin/src/bindings/mod.rs index cba217e6..57e87ef7 100644 --- a/yazi-plugin/src/bindings/mod.rs +++ b/yazi-plugin/src/bindings/mod.rs @@ -4,6 +4,8 @@ mod bindings; mod cha; mod file; mod icon; +mod input; +mod position; mod range; mod window; @@ -11,5 +13,7 @@ pub use bindings::*; pub use cha::*; pub use file::*; pub use icon::*; +pub use input::*; +pub use position::*; pub use range::*; pub use window::*; diff --git a/yazi-plugin/src/bindings/position.rs b/yazi-plugin/src/bindings/position.rs new file mode 100644 index 00000000..abe3206b --- /dev/null +++ b/yazi-plugin/src/bindings/position.rs @@ -0,0 +1,47 @@ +use std::{ops::Deref, str::FromStr}; + +use mlua::{ExternalResult, IntoLua}; + +pub struct Position(yazi_config::popup::Position); + +impl Deref for Position { + type Target = yazi_config::popup::Position; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl From for yazi_config::popup::Position { + fn from(value: Position) -> Self { value.0 } +} + +impl<'a> TryFrom> for Position { + type Error = mlua::Error; + + fn try_from(t: mlua::Table<'a>) -> Result { + use yazi_config::popup::{Offset, Origin, Position}; + + Ok(Self(Position { + origin: Origin::from_str(t.raw_get::<_, mlua::String>(1)?.to_str()?).into_lua_err()?, + offset: Offset { + x: t.raw_get("x").unwrap_or_default(), + y: t.raw_get("y").unwrap_or_default(), + width: t.raw_get("w").unwrap_or_default(), + height: 3, + }, + })) + } +} + +impl<'lua> IntoLua<'lua> for Position { + fn into_lua(self, lua: &'lua mlua::Lua) -> mlua::Result { + lua + .create_table_from([ + (1.into_lua(lua)?, self.origin.to_string().into_lua(lua)?), + ("x".into_lua(lua)?, self.offset.x.into_lua(lua)?), + ("y".into_lua(lua)?, self.offset.y.into_lua(lua)?), + ("w".into_lua(lua)?, self.offset.width.into_lua(lua)?), + ("h".into_lua(lua)?, self.offset.height.into_lua(lua)?), + ])? + .into_lua(lua) + } +} diff --git a/yazi-plugin/src/utils/layer.rs b/yazi-plugin/src/utils/layer.rs index a8917ebd..e33c1a57 100644 --- a/yazi-plugin/src/utils/layer.rs +++ b/yazi-plugin/src/utils/layer.rs @@ -1,11 +1,13 @@ use std::str::FromStr; -use mlua::{ExternalError, ExternalResult, Lua, Table, Value}; +use mlua::{ExternalError, ExternalResult, IntoLua, Lua, Table, Value}; use tokio::sync::mpsc; -use yazi_config::keymap::{Control, Key}; +use yazi_config::{keymap::{Control, Key}, popup::InputCfg}; +use yazi_proxy::InputProxy; use yazi_shared::{emit, event::Cmd, Layer}; use super::Utils; +use crate::bindings::{InputRx, Position}; impl Utils { fn parse_keys(value: Value) -> mlua::Result> { @@ -55,16 +57,25 @@ impl Utils { ya.raw_set( "input", - lua.create_async_function(|_, t: Table| async move { - // pub title: String, - // pub value: String, - // pub cursor: Option, - // pub position: Position, - // pub realtime: bool, - // pub completion: bool, - // pub highlight: bool, + lua.create_async_function(|lua, t: Table| async move { + let realtime = t.raw_get("realtime").unwrap_or_default(); + let mut rx = InputProxy::show(InputCfg { + title: t.raw_get("title")?, + value: t.raw_get("value").unwrap_or_default(), + cursor: None, // TODO + position: Position::try_from(t.raw_get::<_, Table>("position")?)?.into(), + realtime, + completion: false, + highlight: false, + }); - Ok(()) + Ok(if realtime { + (InputRx::new(rx).into_lua(lua)?, Value::Nil) + } else if let Some(Ok(res)) = rx.recv().await { + (res.into_lua(lua)?, 1.into_lua(lua)?) + } else { + (Value::Nil, 0.into_lua(lua)?) + }) })?, )?;