mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
perf: reuse previewed and spotted widgets when possible (#3765)
This commit is contained in:
parent
fa1ee46edc
commit
d22c96b69c
12 changed files with 197 additions and 55 deletions
|
|
@ -55,6 +55,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
### Improved
|
||||
|
||||
- Reduce memory allocations by using Lua 5.5 external strings ([#3634])
|
||||
- Reuse previewed and spotted widgets when possible ([#3765])
|
||||
|
||||
## [v26.1.22]
|
||||
|
||||
|
|
@ -1682,3 +1683,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#3744]: https://github.com/sxyazi/yazi/pull/3744
|
||||
[#3748]: https://github.com/sxyazi/yazi/pull/3748
|
||||
[#3757]: https://github.com/sxyazi/yazi/pull/3757
|
||||
[#3765]: https://github.com/sxyazi/yazi/pull/3765
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
||||
use ratatui::widgets::Borders;
|
||||
use ratatui::widgets::{Borders, Widget};
|
||||
|
||||
use super::{Area, Edge};
|
||||
|
||||
|
|
@ -21,8 +21,22 @@ impl Bar {
|
|||
bar.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?;
|
||||
bar.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
impl Widget for Bar {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
(&self).render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &Bar {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
if rect.area() == 0 {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,13 @@ impl Border {
|
|||
border.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?;
|
||||
border.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
impl Widget for Border {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let mut block = ratatui::widgets::Block::default()
|
||||
.borders(self.edge.0)
|
||||
.border_type(self.r#type)
|
||||
|
|
@ -51,8 +56,8 @@ impl Border {
|
|||
|
||||
for title in self.titles {
|
||||
block = match title {
|
||||
(ratatui::widgets::TitlePosition::Top, line) => block.title(line),
|
||||
(ratatui::widgets::TitlePosition::Bottom, line) => block.title(line),
|
||||
(ratatui::widgets::TitlePosition::Top, line) => block.title_top(line),
|
||||
(ratatui::widgets::TitlePosition::Bottom, line) => block.title_bottom(line),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +65,15 @@ impl Border {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for &Border {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.clone().render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Border {
|
||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_area_method!(methods);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,22 @@ impl Clear {
|
|||
|
||||
clear.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
impl Widget for Clear {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
(&self).render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &Clear {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
yazi_widgets::Clear.render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,13 @@ impl Gauge {
|
|||
|
||||
gauge.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
impl Widget for Gauge {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let mut gauge = ratatui::widgets::Gauge::default()
|
||||
.ratio(self.ratio)
|
||||
.style(self.style)
|
||||
|
|
@ -38,6 +43,15 @@ impl Gauge {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for &Gauge {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.clone().render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Gauge {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_area_method!(methods);
|
||||
|
|
|
|||
|
|
@ -49,10 +49,6 @@ impl Line {
|
|||
line.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?;
|
||||
line.into_lua(lua)
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
self.inner.render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Table> for Line {
|
||||
|
|
@ -84,6 +80,24 @@ impl From<Line> for ratatui::text::Line<'static> {
|
|||
fn from(value: Line) -> Self { value.inner }
|
||||
}
|
||||
|
||||
impl Widget for Line {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
(&self).render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &Line {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
(&self.inner).render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for Line {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
Ok(Self {
|
||||
|
|
|
|||
|
|
@ -22,9 +22,23 @@ impl List {
|
|||
|
||||
list.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
self.inner.render(rect, buf);
|
||||
impl Widget for List {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
(&self).render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &List {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
(&self.inner).render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::any::TypeId;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, FromLua, Lua, Value};
|
||||
use ratatui::widgets::Widget;
|
||||
|
||||
use super::{Bar, Border, Clear, Gauge, Line, List, Table, Text};
|
||||
use crate::{Error, elements::Area};
|
||||
|
|
@ -46,19 +47,6 @@ impl Renderable {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
match self {
|
||||
Self::Line(line) => line.render(rect, buf),
|
||||
Self::Text(text) => text.render(rect, buf),
|
||||
Self::List(list) => list.render(rect, buf),
|
||||
Self::Bar(bar) => bar.render(rect, buf),
|
||||
Self::Clear(clear) => clear.render(rect, buf),
|
||||
Self::Border(border) => border.render(rect, buf),
|
||||
Self::Gauge(gauge) => gauge.render(rect, buf),
|
||||
Self::Table(table) => table.render(rect, buf),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_with<T>(self, buf: &mut ratatui::buffer::Buffer, trans: T)
|
||||
where
|
||||
T: FnOnce(yazi_config::popup::Position) -> ratatui::layout::Rect,
|
||||
|
|
@ -96,6 +84,42 @@ impl From<Error> for Renderable {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for Renderable {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match self {
|
||||
Self::Line(line) => line.render(rect, buf),
|
||||
Self::Text(text) => text.render(rect, buf),
|
||||
Self::List(list) => list.render(rect, buf),
|
||||
Self::Bar(bar) => bar.render(rect, buf),
|
||||
Self::Clear(clear) => clear.render(rect, buf),
|
||||
Self::Border(border) => border.render(rect, buf),
|
||||
Self::Gauge(gauge) => gauge.render(rect, buf),
|
||||
Self::Table(table) => table.render(rect, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &Renderable {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match self {
|
||||
Renderable::Line(line) => line.render(rect, buf),
|
||||
Renderable::Text(text) => text.render(rect, buf),
|
||||
Renderable::List(list) => (&**list).render(rect, buf),
|
||||
Renderable::Bar(bar) => bar.render(rect, buf),
|
||||
Renderable::Clear(clear) => clear.render(rect, buf),
|
||||
Renderable::Border(border) => border.render(rect, buf),
|
||||
Renderable::Gauge(gauge) => (&**gauge).render(rect, buf),
|
||||
Renderable::Table(table) => (&**table).render(rect, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for Renderable {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, UserData, Value};
|
||||
use ratatui::widgets::StatefulWidget;
|
||||
use ratatui::widgets::{StatefulWidget, Widget};
|
||||
|
||||
use super::{Area, Row};
|
||||
use crate::{Style, elements::Constraint};
|
||||
|
|
@ -47,7 +47,30 @@ impl Table {
|
|||
if row.cells.is_empty() { None } else { Some(&row.cells[col.min(row.cells.len() - 1)].text) }
|
||||
}
|
||||
|
||||
pub(super) fn render(mut self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
pub fn len(&self) -> usize { self.rows.len() }
|
||||
|
||||
pub fn select(&mut self, idx: Option<usize>) {
|
||||
self
|
||||
.state
|
||||
.select(idx.map(|i| if self.rows.is_empty() { 0 } else { i.min(self.rows.len() - 1) }));
|
||||
}
|
||||
|
||||
pub fn selected(&self) -> Option<usize> {
|
||||
if self.rows.is_empty() { None } else { Some(self.state.selected()?.min(self.rows.len() - 1)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<AnyUserData> for Table {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: AnyUserData) -> Result<Self, Self::Error> { value.take() }
|
||||
}
|
||||
|
||||
impl Widget for Table {
|
||||
fn render(mut self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let mut table = ratatui::widgets::Table::new(self.rows, self.widths)
|
||||
.column_spacing(self.column_spacing)
|
||||
.style(self.style)
|
||||
|
|
@ -68,26 +91,17 @@ impl Table {
|
|||
table = table.block(block);
|
||||
}
|
||||
|
||||
table.render(rect, buf, &mut self.state);
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize { self.rows.len() }
|
||||
|
||||
pub fn select(&mut self, idx: Option<usize>) {
|
||||
self
|
||||
.state
|
||||
.select(idx.map(|i| if self.rows.is_empty() { 0 } else { i.min(self.rows.len() - 1) }));
|
||||
}
|
||||
|
||||
pub fn selected(&self) -> Option<usize> {
|
||||
if self.rows.is_empty() { None } else { Some(self.state.selected()?.min(self.rows.len() - 1)) }
|
||||
StatefulWidget::render(table, rect, buf, &mut self.state);
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<AnyUserData> for Table {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(value: AnyUserData) -> Result<Self, Self::Error> { value.take() }
|
||||
impl Widget for &Table {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.clone().render(rect, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Table {
|
||||
|
|
|
|||
|
|
@ -31,14 +31,6 @@ impl Text {
|
|||
text.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?;
|
||||
text.into_lua(lua)
|
||||
}
|
||||
|
||||
pub(super) fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
if self.wrap.is_none() && self.scroll == Default::default() {
|
||||
self.inner.render(rect, buf);
|
||||
} else {
|
||||
ratatui::widgets::Paragraph::from(self).render(rect, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Table> for Text {
|
||||
|
|
@ -82,6 +74,32 @@ impl From<Text> for ratatui::widgets::Paragraph<'static> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for Text {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
if self.wrap.is_none() && self.scroll == Default::default() {
|
||||
self.inner.render(rect, buf);
|
||||
} else {
|
||||
ratatui::widgets::Paragraph::from(self).render(rect, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &Text {
|
||||
fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
if self.wrap.is_none() && self.scroll == Default::default() {
|
||||
(&self.inner).render(rect, buf);
|
||||
} else {
|
||||
ratatui::widgets::Paragraph::from(self.clone()).render(rect, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for Text {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
let inner = match value {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ impl Widget for Preview<'_> {
|
|||
for w in &lock.data {
|
||||
let rect = w.area().transform(|p| self.core.mgr.area(p));
|
||||
if rect.intersection(win) == rect {
|
||||
w.clone().render(rect, buf);
|
||||
w.render(rect, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl Widget for Spot<'_> {
|
|||
for w in &lock.data {
|
||||
let rect = w.area().transform(|p| self.core.mgr.area(p));
|
||||
if rect.intersection(win) == rect {
|
||||
w.clone().render(rect, buf);
|
||||
w.render(rect, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue