From b92b576ce17c6e475e2c231c2ae9cbaf70de41bd Mon Sep 17 00:00:00 2001 From: Yashank <37672190+stickyburn@users.noreply.github.com> Date: Tue, 3 Mar 2026 07:18:55 -0500 Subject: [PATCH] feat: new `hovered` condition specifying different icons for hovered files (#3728) Co-authored-by: sxyazi --- .github/workflows/draft.yml | 14 +++++++------- .github/workflows/publish.yml | 4 ++-- CHANGELOG.md | 2 ++ yazi-actor/src/lives/file.rs | 10 +++++++++- yazi-binding/src/file.rs | 6 ++++++ yazi-binding/src/macros.rs | 6 ------ yazi-codegen/src/lib.rs | 2 -- yazi-config/preset/theme-dark.toml | 1 + yazi-config/preset/theme-light.toml | 1 + yazi-config/src/theme/icon.rs | 3 ++- 10 files changed, 30 insertions(+), 19 deletions(-) diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index 4df42b5b..f518914e 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -59,7 +59,7 @@ jobs: run: ./scripts/build.sh ${{ matrix.target }} - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.target }} path: | @@ -105,7 +105,7 @@ jobs: Compress-Archive -Path ${env:TARGET_NAME} -DestinationPath "${env:TARGET_NAME}.zip" - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.target }} path: yazi-${{ matrix.target }}.zip @@ -133,7 +133,7 @@ jobs: run: ./scripts/build.sh ${{ matrix.target }} - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.target }} path: | @@ -167,7 +167,7 @@ jobs: run: mv yazi_*.snap yazi-${{ matrix.arch }}.snap - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: snap-${{ matrix.arch }} path: yazi-${{ matrix.arch }}.snap @@ -176,7 +176,7 @@ jobs: runs-on: ubuntu-latest needs: [build-snap] steps: - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: pattern: snap-* merge-multiple: true @@ -205,7 +205,7 @@ jobs: runs-on: ubuntu-latest needs: [build-unix, build-windows, build-musl, build-snap] steps: - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: merge-multiple: true @@ -235,7 +235,7 @@ jobs: - uses: actions/checkout@v6 - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: merge-multiple: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 624175c0..523ef441 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,7 +11,7 @@ jobs: winget: runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: merge-multiple: true @@ -25,7 +25,7 @@ jobs: snapcraft: runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: merge-multiple: true diff --git a/CHANGELOG.md b/CHANGELOG.md index e388e351..ecc6e586 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Custom tab name ([#3666]) - New `--in` for `search` action to set search directory ([#3696]) +- New `hovered` condition specifying different icons for hovered files ([#3728]) - Allow using `ps.sub()` in `init.lua` directly without a plugin ([#3638]) - New `sort_fallback` option to control fallback sorting behavior ([#3077]) - New `fs.access()` API to access the filesystem ([#3668]) @@ -1670,3 +1671,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): [#3696]: https://github.com/sxyazi/yazi/pull/3696 [#3708]: https://github.com/sxyazi/yazi/pull/3708 [#3725]: https://github.com/sxyazi/yazi/pull/3725 +[#3728]: https://github.com/sxyazi/yazi/pull/3728 diff --git a/yazi-actor/src/lives/file.rs b/yazi-actor/src/lives/file.rs index ac439541..578c384c 100644 --- a/yazi-actor/src/lives/file.rs +++ b/yazi-actor/src/lives/file.rs @@ -65,6 +65,9 @@ impl File { } }) } + + #[inline] + fn is_hovered(&self) -> bool { self.idx == self.folder.cursor } } impl UserData for File { @@ -73,7 +76,7 @@ impl UserData for File { cached_field!(fields, bare, |_, me| Ok(yazi_binding::File::new(&**me))); fields.add_field_method_get("idx", |_, me| Ok(me.idx + 1)); - fields.add_field_method_get("is_hovered", |_, me| Ok(me.idx == me.folder.cursor)); + fields.add_field_method_get("is_hovered", |_, me| Ok(me.is_hovered())); fields.add_field_method_get("in_current", |_, me| Ok(ptr::eq(&*me.folder, &me.tab.current))); fields.add_field_method_get("in_preview", |_, me| { Ok(me.idx == me.folder.cursor && me.tab.hovered().is_some_and(|f| f.url == me.folder.url)) @@ -83,6 +86,11 @@ impl UserData for File { fn add_methods>(methods: &mut M) { yazi_binding::impl_file_methods!(methods); + methods.add_method("icon", |_, me, ()| { + use yazi_binding::Icon; + // TODO: use a cache + Ok(yazi_config::THEME.icon.matches(me, me.is_hovered()).map(Icon::from)) + }); methods.add_method("size", |_, me, ()| { Ok(if me.is_dir() { me.folder.files.sizes.get(&me.urn()).copied() } else { Some(me.len) }) }); diff --git a/yazi-binding/src/file.rs b/yazi-binding/src/file.rs index 19eed92b..62d1c5c4 100644 --- a/yazi-binding/src/file.rs +++ b/yazi-binding/src/file.rs @@ -90,5 +90,11 @@ impl UserData for File { fn add_methods>(methods: &mut M) { impl_file_methods!(methods); + + methods.add_method("icon", |_, me, ()| { + use crate::Icon; + // TODO: use a cache + Ok(yazi_config::THEME.icon.matches(me, false).map(Icon::from)) + }); } } diff --git a/yazi-binding/src/macros.rs b/yazi-binding/src/macros.rs index ac7eb742..4cb71fac 100644 --- a/yazi-binding/src/macros.rs +++ b/yazi-binding/src/macros.rs @@ -267,11 +267,5 @@ macro_rules! impl_file_methods { use yazi_fs::FsHash64; Ok(me.hash_u64()) }); - - $methods.add_method("icon", |_, me, ()| { - use $crate::Icon; - // TODO: use a cache - Ok(yazi_config::THEME.icon.matches(me).map(Icon::from)) - }); }; } diff --git a/yazi-codegen/src/lib.rs b/yazi-codegen/src/lib.rs index 47d9b99d..6fb82433 100644 --- a/yazi-codegen/src/lib.rs +++ b/yazi-codegen/src/lib.rs @@ -53,7 +53,6 @@ pub fn deserialize_over1(input: TokenStream) -> TokenStream { quote! { impl #ident { - #[inline] pub(crate) fn deserialize_over_with<'de>(mut self, table: toml::Spanned>) -> Result { use serde::{Deserialize, de::IntoDeserializer}; @@ -96,7 +95,6 @@ pub fn deserialize_over2(input: TokenStream) -> TokenStream { quote! { impl #ident { - #[inline] pub(crate) fn deserialize_over_with<'de>(mut self, table: toml::Spanned>) -> Result { use serde::{Deserialize, de::IntoDeserializer}; diff --git a/yazi-config/preset/theme-dark.toml b/yazi-config/preset/theme-dark.toml index 1d36e9d0..372e5f9c 100644 --- a/yazi-config/preset/theme-dark.toml +++ b/yazi-config/preset/theme-dark.toml @@ -997,6 +997,7 @@ conds = [ { if = "dummy", text = "", fg = "#f44336" }, # Fallback + { if = "dir & hovered", text = "", fg = "#03a9f4" }, { if = "dir", text = "", fg = "#03a9f4" }, { if = "exec", text = "", fg = "#8bc34a" }, { if = "!dir", text = "", fg = "#ffffff" }, diff --git a/yazi-config/preset/theme-light.toml b/yazi-config/preset/theme-light.toml index 0489b216..e68d8309 100644 --- a/yazi-config/preset/theme-light.toml +++ b/yazi-config/preset/theme-light.toml @@ -997,6 +997,7 @@ conds = [ { if = "dummy", text = "", fg = "#f44336" }, # Fallback + { if = "dir & hovered", text = "", fg = "#03a9f4" }, { if = "dir", text = "", fg = "#03a9f4" }, { if = "exec", text = "", fg = "#8bc34a" }, { if = "!dir", text = "", fg = "#000000" }, diff --git a/yazi-config/src/theme/icon.rs b/yazi-config/src/theme/icon.rs index e0b13699..cdbe9471 100644 --- a/yazi-config/src/theme/icon.rs +++ b/yazi-config/src/theme/icon.rs @@ -44,7 +44,7 @@ pub struct Icon { } impl Icon { - pub fn matches(&self, file: &File) -> Option<&I> { + pub fn matches(&self, file: &File, hovered: bool) -> Option<&I> { if let Some(i) = self.match_by_glob(file) { return Some(i); } @@ -65,6 +65,7 @@ impl Icon { "sock" => file.is_sock(), "exec" => file.is_exec(), "sticky" => file.is_sticky(), + "hovered" => hovered, _ => false, }; self.conds.iter().find(|(c, _)| c.eval(f) == Some(true)).map(|(_, i)| i)