From 55da9e342c5d4de919bc3bd05a731fd2284e32da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sat, 20 Apr 2024 15:43:08 +0800 Subject: [PATCH] perf: cache each file's icon to avoid redundant calculations at rendering (#931) --- yazi-config/src/theme/filetype.rs | 4 +-- yazi-config/src/theme/icon.rs | 28 ++++++++++++------- yazi-config/src/theme/mod.rs | 4 --- yazi-config/src/theme/theme.rs | 4 +-- yazi-fm/src/lives/file.rs | 12 +++++++- yazi-plugin/src/bindings/icon.rs | 6 ++-- yazi-plugin/src/elements/span.rs | 2 +- yazi-plugin/src/elements/style.rs | 6 ++-- yazi-shared/src/fs/file.rs | 7 +++-- yazi-shared/src/lib.rs | 1 + .../src/theme/color.rs | 2 +- yazi-shared/src/theme/icon.rs | 15 ++++++++++ yazi-shared/src/theme/mod.rs | 7 +++++ .../src/theme/style.rs | 26 ++++++++--------- 14 files changed, 81 insertions(+), 43 deletions(-) rename {yazi-config => yazi-shared}/src/theme/color.rs (94%) create mode 100644 yazi-shared/src/theme/icon.rs create mode 100644 yazi-shared/src/theme/mod.rs rename {yazi-config => yazi-shared}/src/theme/style.rs (81%) diff --git a/yazi-config/src/theme/filetype.rs b/yazi-config/src/theme/filetype.rs index cac982d2..31528caf 100644 --- a/yazi-config/src/theme/filetype.rs +++ b/yazi-config/src/theme/filetype.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Deserializer}; -use yazi_shared::fs::File; +use yazi_shared::{fs::File, theme::{Color, Style, StyleShadow}}; -use super::{Color, Is, Style, StyleShadow}; +use super::Is; use crate::Pattern; pub struct Filetype { diff --git a/yazi-config/src/theme/icon.rs b/yazi-config/src/theme/icon.rs index c9b0f4db..05f20552 100644 --- a/yazi-config/src/theme/icon.rs +++ b/yazi-config/src/theme/icon.rs @@ -1,14 +1,20 @@ -use serde::{Deserialize, Deserializer}; -use yazi_shared::fs::File; +use std::ops::Deref; -use super::Style; -use crate::{preset::Preset, theme::{Color, Is, StyleShadow}, Pattern}; +use serde::{Deserialize, Deserializer}; +use yazi_shared::{fs::File, theme::{Color, StyleShadow}}; + +use crate::{preset::Preset, theme::Is, Pattern}; pub struct Icon { - pub is: Is, - pub name: Pattern, - pub text: String, - pub style: Style, + is: Is, + name: Pattern, + inner: yazi_shared::theme::Icon, +} + +impl Deref for Icon { + type Target = yazi_shared::theme::Icon; + + fn deref(&self) -> &Self::Target { &self.inner } } impl Icon { @@ -61,8 +67,10 @@ impl Icon { .map(|r| Icon { is: r.is, name: r.name, - text: r.text, - style: StyleShadow { fg: r.fg, ..Default::default() }.into(), + inner: yazi_shared::theme::Icon { + text: r.text, + style: StyleShadow { fg: r.fg, ..Default::default() }.into(), + }, }) .collect(), ) diff --git a/yazi-config/src/theme/mod.rs b/yazi-config/src/theme/mod.rs index f4fd0102..28051c97 100644 --- a/yazi-config/src/theme/mod.rs +++ b/yazi-config/src/theme/mod.rs @@ -1,15 +1,11 @@ -mod color; mod filetype; mod flavor; mod icon; mod is; -mod style; mod theme; -pub use color::*; pub use filetype::*; pub use flavor::*; pub use icon::*; pub use is::*; -pub use style::*; pub use theme::*; diff --git a/yazi-config/src/theme/theme.rs b/yazi-config/src/theme/theme.rs index 6cd96ca8..00508ded 100644 --- a/yazi-config/src/theme/theme.rs +++ b/yazi-config/src/theme/theme.rs @@ -2,9 +2,9 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; use validator::Validate; -use yazi_shared::{fs::expand_path, Xdg}; +use yazi_shared::{fs::expand_path, theme::Style, Xdg}; -use super::{Filetype, Flavor, Icon, Style}; +use super::{Filetype, Flavor, Icon}; use crate::{validation::check_validation, MERGED_THEME}; #[derive(Deserialize, Serialize)] diff --git a/yazi-fm/src/lives/file.rs b/yazi-fm/src/lives/file.rs index a257d3a7..8037fd22 100644 --- a/yazi-fm/src/lives/file.rs +++ b/yazi-fm/src/lives/file.rs @@ -58,7 +58,17 @@ impl File { Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose() }); reg.add_method("icon", |lua, me, ()| { - THEME.icons.iter().find(|&x| x.matches(me)).map(|x| Icon::cast(lua, x)).transpose() + use yazi_shared::theme::IconCache; + + match me.icon.get() { + IconCache::Missing => { + let matched = THEME.icons.iter().find(|&i| i.matches(me)); + me.icon.set(matched.map_or(IconCache::Undefined, |i| IconCache::Icon(i))); + matched.map(|i| Icon::cast(lua, i)).transpose() + } + IconCache::Undefined => Ok(None), + IconCache::Icon(cached) => Some(Icon::cast(lua, cached)).transpose(), + } }); reg.add_method("style", |lua, me, ()| { let cx = lua.named_registry_value::("cx")?; diff --git a/yazi-plugin/src/bindings/icon.rs b/yazi-plugin/src/bindings/icon.rs index 85674ff0..07382e0e 100644 --- a/yazi-plugin/src/bindings/icon.rs +++ b/yazi-plugin/src/bindings/icon.rs @@ -7,7 +7,7 @@ pub struct Icon; impl Icon { pub fn register(lua: &Lua) -> mlua::Result<()> { - lua.register_userdata_type::<&yazi_config::theme::Icon>(|reg| { + lua.register_userdata_type::<&yazi_shared::theme::Icon>(|reg| { reg.add_field_method_get("text", |lua, me| lua.create_string(&me.text)); reg.add_field_method_get("style", |_, me| Ok(Style::from(me.style))); })?; @@ -16,10 +16,10 @@ impl Icon { } } -impl Cast<&'static yazi_config::theme::Icon> for Icon { +impl Cast<&'static yazi_shared::theme::Icon> for Icon { fn cast<'lua>( lua: &'lua Lua, - data: &'static yazi_config::theme::Icon, + data: &'static yazi_shared::theme::Icon, ) -> mlua::Result> { lua.create_any_userdata(data) } diff --git a/yazi-plugin/src/elements/span.rs b/yazi-plugin/src/elements/span.rs index f7631118..96549f3c 100644 --- a/yazi-plugin/src/elements/span.rs +++ b/yazi-plugin/src/elements/span.rs @@ -1,5 +1,5 @@ use mlua::{AnyUserData, ExternalError, FromLua, Lua, Table, UserData, UserDataMethods, Value}; -use yazi_config::theme::Color; +use yazi_shared::theme::Color; use super::Style; diff --git a/yazi-plugin/src/elements/style.rs b/yazi-plugin/src/elements/style.rs index 051419b1..67070b99 100644 --- a/yazi-plugin/src/elements/style.rs +++ b/yazi-plugin/src/elements/style.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use mlua::{AnyUserData, ExternalError, ExternalResult, Lua, Table, UserData, UserDataMethods, Value}; -use yazi_config::theme::Color; +use yazi_shared::theme::Color; #[derive(Clone, Copy, Default)] pub struct Style(pub(super) ratatui::style::Style); @@ -17,8 +17,8 @@ impl Style { } } -impl From for Style { - fn from(value: yazi_config::theme::Style) -> Self { Self(value.into()) } +impl From for Style { + fn from(value: yazi_shared::theme::Style) -> Self { Self(value.into()) } } impl<'a> TryFrom> for Style { diff --git a/yazi-shared/src/fs/file.rs b/yazi-shared/src/fs/file.rs index 2683ea47..90841bf5 100644 --- a/yazi-shared/src/fs/file.rs +++ b/yazi-shared/src/fs/file.rs @@ -1,15 +1,16 @@ -use std::{ffi::OsStr, fs::Metadata, ops::Deref}; +use std::{cell::Cell, ffi::OsStr, fs::Metadata, ops::Deref}; use anyhow::Result; use tokio::fs; -use crate::fs::{Cha, ChaKind, Url}; +use crate::{fs::{Cha, ChaKind, Url}, theme::IconCache}; #[derive(Clone, Debug, Default)] pub struct File { pub url: Url, pub cha: Cha, pub link_to: Option, + pub icon: Cell, } impl Deref for File { @@ -53,7 +54,7 @@ impl File { } } - Self { url, cha: Cha::from(meta).with_kind(ck), link_to } + Self { url, cha: Cha::from(meta).with_kind(ck), link_to, icon: Default::default() } } #[inline] diff --git a/yazi-shared/src/lib.rs b/yazi-shared/src/lib.rs index 76494181..1a81d158 100644 --- a/yazi-shared/src/lib.rs +++ b/yazi-shared/src/lib.rs @@ -13,6 +13,7 @@ mod number; mod os; mod ro_cell; pub mod term; +pub mod theme; mod throttle; mod time; mod xdg; diff --git a/yazi-config/src/theme/color.rs b/yazi-shared/src/theme/color.rs similarity index 94% rename from yazi-config/src/theme/color.rs rename to yazi-shared/src/theme/color.rs index 71c212c8..5cde2172 100644 --- a/yazi-config/src/theme/color.rs +++ b/yazi-shared/src/theme/color.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use anyhow::Result; use serde::{Deserialize, Serialize}; -#[derive(Clone, Copy, Deserialize)] +#[derive(Clone, Copy, Debug, Deserialize)] #[serde(try_from = "String")] pub struct Color(ratatui::style::Color); diff --git a/yazi-shared/src/theme/icon.rs b/yazi-shared/src/theme/icon.rs new file mode 100644 index 00000000..721d8445 --- /dev/null +++ b/yazi-shared/src/theme/icon.rs @@ -0,0 +1,15 @@ +use super::Style; + +#[derive(Clone, Debug)] +pub struct Icon { + pub text: String, + pub style: Style, +} + +#[derive(Clone, Copy, Debug, Default)] +pub enum IconCache { + #[default] + Missing, + Undefined, + Icon(&'static Icon), +} diff --git a/yazi-shared/src/theme/mod.rs b/yazi-shared/src/theme/mod.rs new file mode 100644 index 00000000..97ccb2e1 --- /dev/null +++ b/yazi-shared/src/theme/mod.rs @@ -0,0 +1,7 @@ +mod color; +mod icon; +mod style; + +pub use color::*; +pub use icon::*; +pub use style::*; diff --git a/yazi-config/src/theme/style.rs b/yazi-shared/src/theme/style.rs similarity index 81% rename from yazi-config/src/theme/style.rs rename to yazi-shared/src/theme/style.rs index 39e0a069..8054d4a4 100644 --- a/yazi-config/src/theme/style.rs +++ b/yazi-shared/src/theme/style.rs @@ -3,7 +3,7 @@ use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer}; use super::Color; -#[derive(Clone, Copy, Deserialize)] +#[derive(Clone, Copy, Debug, Deserialize)] #[serde(from = "StyleShadow")] pub struct Style { pub fg: Option, @@ -37,29 +37,29 @@ impl From