This commit is contained in:
sxyazi 2024-03-02 19:35:39 +08:00
parent 9e05099a50
commit 6e1d88c3fa
No known key found for this signature in database
8 changed files with 150 additions and 20 deletions

1
Cargo.lock generated
View file

@ -2803,6 +2803,7 @@ dependencies = [
"yazi-boot",
"yazi-config",
"yazi-prebuild",
"yazi-proxy",
"yazi-shared",
]

View file

@ -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<Self, Self::Err> {
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<String> for Origin {
type Error = anyhow::Error;
fn try_from(value: String) -> Result<Self, Self::Error> { 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",
})
}
}

View file

@ -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}"),
})
}
}

View file

@ -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

View file

@ -0,0 +1,27 @@
use mlua::{prelude::LuaUserDataMethods, UserData};
use tokio::sync::mpsc::UnboundedReceiver;
use yazi_shared::InputError;
pub struct InputRx {
inner: UnboundedReceiver<Result<String, InputError>>,
}
impl InputRx {
pub fn new(inner: UnboundedReceiver<Result<String, InputError>>) -> 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),
})
});
}
}

View file

@ -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::*;

View file

@ -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<Position> for yazi_config::popup::Position {
fn from(value: Position) -> Self { value.0 }
}
impl<'a> TryFrom<mlua::Table<'a>> for Position {
type Error = mlua::Error;
fn try_from(t: mlua::Table<'a>) -> Result<Self, Self::Error> {
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<mlua::Value> {
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)
}
}

View file

@ -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<Vec<Key>> {
@ -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<usize>,
// 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)?)
})
})?,
)?;