feat!: make ya.confirm() and ui.Pos() public API (#2921)

This commit is contained in:
三咲雅 misaki masa 2025-06-26 18:12:09 +08:00 committed by GitHub
parent 590d336716
commit 9d05946f4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 85 additions and 54 deletions

View file

@ -124,7 +124,7 @@ separator_style = { fg = "darkgray" }
[confirm]
border = { fg = "blue" }
title = { fg = "blue" }
content = {}
body = {}
list = {}
btn_yes = { reversed = true }
btn_no = {}

View file

@ -124,7 +124,7 @@ separator_style = { fg = "darkgray" }
[confirm]
border = { fg = "blue" }
title = { fg = "blue" }
content = {}
body = {}
list = {}
btn_yes = { reversed = true }
btn_no = {}

View file

@ -200,16 +200,16 @@ delete_origin = "center"
delete_offset = [ 0, 0, 70, 20 ]
# overwrite
overwrite_title = "Overwrite file?"
overwrite_content = "Will overwrite the following file:"
overwrite_origin = "center"
overwrite_offset = [ 0, 0, 50, 15 ]
overwrite_title = "Overwrite file?"
overwrite_body = "Will overwrite the following file:"
overwrite_origin = "center"
overwrite_offset = [ 0, 0, 50, 15 ]
# quit
quit_title = "Quit?"
quit_content = "The following tasks are still running, are you sure you want to quit?"
quit_origin = "center"
quit_offset = [ 0, 0, 50, 15 ]
quit_title = "Quit?"
quit_body = "The following tasks are still running, are you sure you want to quit?"
quit_origin = "center"
quit_offset = [ 0, 0, 50, 15 ]
[pick]
open_title = "Open with:"

View file

@ -16,16 +16,16 @@ pub struct Confirm {
pub delete_offset: Offset,
// overwrite
pub overwrite_title: String,
pub overwrite_content: String,
pub overwrite_origin: Origin,
pub overwrite_offset: Offset,
pub overwrite_title: String,
pub overwrite_body: String,
pub overwrite_origin: Origin,
pub overwrite_offset: Offset,
// quit
pub quit_title: String,
pub quit_content: String,
pub quit_origin: Origin,
pub quit_offset: Offset,
pub quit_title: String,
pub quit_body: String,
pub quit_origin: Origin,
pub quit_offset: Offset,
}
impl Confirm {

View file

@ -26,7 +26,7 @@ pub struct PickCfg {
pub struct ConfirmCfg {
pub position: Position,
pub title: Line<'static>,
pub content: Paragraph<'static>,
pub body: Paragraph<'static>,
pub list: Paragraph<'static>,
}
@ -107,13 +107,13 @@ impl ConfirmCfg {
fn new(
title: String,
(origin, offset): (Origin, Offset),
content: Option<Text<'static>>,
body: Option<Text<'static>>,
list: Option<Text<'static>>,
) -> Self {
Self {
position: Position::new(origin, offset),
title: Line::raw(title),
content: content.map(|c| Paragraph::new(c).wrap(Wrap { trim: false })).unwrap_or_default(),
body: body.map(|c| Paragraph::new(c).wrap(Wrap { trim: false })).unwrap_or_default(),
list: list.map(|l| Paragraph::new(l).wrap(Wrap { trim: false })).unwrap_or_default(),
}
}
@ -140,7 +140,7 @@ impl ConfirmCfg {
Self::new(
YAZI.confirm.overwrite_title.to_owned(),
(YAZI.confirm.overwrite_origin, YAZI.confirm.overwrite_offset),
Some(Text::raw(&YAZI.confirm.overwrite_content)),
Some(Text::raw(&YAZI.confirm.overwrite_body)),
Some(url.to_string().into()),
)
}
@ -149,7 +149,7 @@ impl ConfirmCfg {
Self::new(
Self::replace_number(&YAZI.confirm.quit_title, len),
(YAZI.confirm.quit_origin, YAZI.confirm.quit_offset),
Some(Text::raw(&YAZI.confirm.quit_content)),
Some(Text::raw(&YAZI.confirm.quit_body)),
Self::truncate_list(names.into_iter(), len, 10),
)
}

View file

@ -132,10 +132,10 @@ pub struct Which {
#[derive(Deserialize, DeserializeOver2)]
pub struct Confirm {
pub border: Style,
pub title: Style,
pub content: Style,
pub list: Style,
pub border: Style,
pub title: Style,
pub body: Style,
pub list: Style,
pub btn_yes: Style,
pub btn_no: Style,

View file

@ -26,7 +26,7 @@ impl Confirm {
self.close(false);
self.title = opt.cfg.title;
self.content = opt.cfg.content;
self.body = opt.cfg.body;
self.list = opt.cfg.list;
self.position = opt.cfg.position;

View file

@ -4,9 +4,9 @@ use yazi_config::popup::Position;
#[derive(Default)]
pub struct Confirm {
pub title: Line<'static>,
pub content: Paragraph<'static>,
pub list: Paragraph<'static>,
pub title: Line<'static>,
pub body: Paragraph<'static>,
pub list: Paragraph<'static>,
pub position: Position,
pub offset: usize,

View file

@ -3,20 +3,20 @@ use yazi_config::THEME;
use crate::Ctx;
pub(crate) struct Content<'a> {
pub(crate) struct Body<'a> {
cx: &'a Ctx,
border: bool,
}
impl<'a> Content<'a> {
impl<'a> Body<'a> {
pub(crate) fn new(cx: &'a Ctx, border: bool) -> Self { Self { cx, border } }
}
impl Widget for Content<'_> {
impl Widget for Body<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let confirm = &self.cx.confirm;
// Content area
// Inner area
let inner = area.inner(Margin::new(1, 0));
// Border
@ -27,11 +27,11 @@ impl Widget for Content<'_> {
};
confirm
.content
.body
.clone()
.alignment(ratatui::layout::Alignment::Center)
.block(block)
.style(THEME.confirm.content.derive(Styled::style(&confirm.content)))
.style(THEME.confirm.body.derive(Styled::style(&confirm.body)))
.render(inner, buf);
}
}

View file

@ -25,21 +25,21 @@ impl Widget for Confirm<'_> {
.title_alignment(Alignment::Center)
.render(area, buf);
let content_border = confirm.list.line_count(area.width) != 0;
let content_height = confirm.content.line_count(area.width) as u16;
let body_border = confirm.list.line_count(area.width) != 0;
let body_height = confirm.body.line_count(area.width) as u16;
let chunks = Layout::vertical([
Constraint::Length(if content_height == 0 {
Constraint::Length(if body_height == 0 {
0
} else {
content_height.saturating_add(content_border as u16)
body_height.saturating_add(body_border as u16)
}),
Constraint::Fill(1),
Constraint::Length(1),
])
.split(area.inner(Margin::new(0, 1)));
super::Content::new(self.cx, content_border).render(chunks[0], buf);
super::Body::new(self.cx, body_border).render(chunks[0], buf);
super::List::new(self.cx).render(chunks[1], buf);
super::Buttons.render(chunks[2], buf);
}

View file

@ -1 +1 @@
yazi_macro::mod_flat!(buttons confirm content list);
yazi_macro::mod_flat!(buttons confirm body list);

View file

@ -158,7 +158,7 @@ impl Theme {
match key {
b"border" => Style::from(t.border).into_lua(lua),
b"title" => Style::from(t.title).into_lua(lua),
b"content" => Style::from(t.content).into_lua(lua),
b"body" => Style::from(t.body).into_lua(lua),
b"list" => Style::from(t.list).into_lua(lua),
b"btn_yes" => Style::from(t.btn_yes).into_lua(lua),

View file

@ -1,9 +1,11 @@
use std::{ops::Deref, str::FromStr};
use mlua::{AnyUserData, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, Value};
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, Value};
use super::Pad;
const EXPECTED: &str = "expected a Pos";
#[derive(Clone, Copy, Default)]
pub struct Pos {
inner: yazi_config::popup::Position,
@ -45,6 +47,24 @@ impl TryFrom<mlua::Table> for Pos {
}
}
impl TryFrom<Value> for Pos {
type Error = mlua::Error;
fn try_from(value: Value) -> Result<Self, Self::Error> {
Ok(match value {
Value::Table(tbl) => Self::try_from(tbl)?,
Value::UserData(ud) => {
if let Ok(pos) = ud.borrow() {
*pos
} else {
Err(EXPECTED.into_lua_err())?
}
}
_ => Err(EXPECTED.into_lua_err())?,
})
}
}
impl Pos {
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
let new = lua.create_function(|_, (_, t): (Table, Table)| Self::try_from(t))?;
@ -55,8 +75,8 @@ impl Pos {
position.into_lua(lua)
}
pub fn new_input(t: mlua::Table) -> mlua::Result<Self> {
let mut p = Self::try_from(t)?;
pub fn new_input(v: Value) -> mlua::Result<Self> {
let mut p = Self::try_from(v)?;
p.inner.offset.height = 3;
Ok(p)
}

View file

@ -76,7 +76,7 @@ macro_rules! runtime_mut {
#[macro_export]
macro_rules! deprecate {
($lua:ident, $tt:tt) => {{
let id = match $lua.named_registry_value::<$crate::RtRef>("ir")?.current() {
let id = match $crate::runtime!($lua)?.current() {
Some(id) => &format!("`{id}.yazi` plugin"),
None => "`init.lua` config",
};

View file

@ -9,7 +9,7 @@ use yazi_proxy::{AppProxy, ConfirmProxy, InputProxy};
use yazi_shared::{Debounce, event::Cmd};
use super::Utils;
use crate::{bindings::InputRx, elements::{Line, Pos, Text}};
use crate::{bindings::InputRx, deprecate, elements::{Line, Pos, Text}};
impl Utils {
pub(super) fn which(lua: &Lua) -> mlua::Result<Function> {
@ -40,13 +40,24 @@ impl Utils {
pub(super) fn input(lua: &Lua) -> mlua::Result<Function> {
lua.create_async_function(|lua, t: Table| async move {
let mut pos = t.raw_get::<Value>("pos")?;
if pos.is_nil() {
pos = t.raw_get("position")?;
if !pos.is_nil() {
deprecate!(
lua,
"The `position` property of `ya.input()` is deprecated, use `pos` instead in your {}\nSee #2921 for more details: https://github.com/sxyazi/yazi/pull/2921"
);
}
}
let realtime = t.raw_get("realtime").unwrap_or_default();
let rx = UnboundedReceiverStream::new(InputProxy::show(InputCfg {
title: t.raw_get("title")?,
value: t.raw_get("value").unwrap_or_default(),
cursor: None, // TODO
obscure: t.raw_get("obscure").unwrap_or_default(),
position: Pos::new_input(t.raw_get::<Table>("position")?)?.into(),
position: Pos::new_input(pos)?.into(),
realtime,
completion: false,
}));
@ -67,8 +78,8 @@ impl Utils {
}
pub(super) fn confirm(lua: &Lua) -> mlua::Result<Function> {
fn content(t: &Table) -> mlua::Result<ratatui::widgets::Paragraph<'static>> {
Ok(match t.raw_get::<Value>("content")? {
fn body(t: &Table) -> mlua::Result<ratatui::widgets::Paragraph<'static>> {
Ok(match t.raw_get::<Value>("body")? {
Value::Nil => Default::default(),
v => Text::try_from(v)?.into(),
})
@ -76,9 +87,9 @@ impl Utils {
lua.create_async_function(|_, t: Table| async move {
let result = ConfirmProxy::show(ConfirmCfg {
position: Pos::try_from(t.raw_get::<Table>("pos")?)?.into(),
position: Pos::try_from(t.raw_get::<Value>("pos")?)?.into(),
title: Line::try_from(t.raw_get::<Value>("title")?)?.into(),
content: content(&t)?,
body: body(&t)?,
list: Default::default(), // TODO
});