From 2616419858dd22a0594f5acc729b8b117f84fb64 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Fri, 29 Sep 2023 11:54:06 +0800 Subject: [PATCH] .. --- app/src/manager/folder.rs | 69 +++++++++-------------------- plugin/preset/components/folder.lua | 23 +++++++++- plugin/src/bindings/manager.rs | 64 +++++++++++++++++++++----- plugin/src/layout/line.rs | 10 +++-- plugin/src/layout/style.rs | 4 ++ 5 files changed, 106 insertions(+), 64 deletions(-) diff --git a/app/src/manager/folder.rs b/app/src/manager/folder.rs index 5dc0b0b0..ae49842a 100644 --- a/app/src/manager/folder.rs +++ b/app/src/manager/folder.rs @@ -1,7 +1,6 @@ -use core::{files::File, Ctx}; +use core::Ctx; -use config::THEME; -use ratatui::{buffer::Buffer, layout::Rect, style::Style, widgets::Widget}; +use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use tracing::info; pub(super) struct Folder<'a> { @@ -20,52 +19,24 @@ impl<'a> Folder<'a> { } impl<'a> Folder<'a> { - #[inline] - fn icon(file: &File) -> &'static str { - THEME - .icons - .iter() - .find(|x| x.name.match_path(file.url(), Some(file.is_dir()))) - .map(|x| x.display.as_ref()) - .unwrap_or("") - } - - #[inline] - fn item_style(&self, file: &File) -> Style { - let mime = self.cx.manager.mimetype.get(file.url()); - THEME - .filetypes - .iter() - .find(|x| x.matches(file.url(), mime, file.is_dir())) - .map(|x| x.style.into()) - .unwrap_or_else(Style::new) - } - - fn highlighted_item<'b>(&'b self, file: &'b File) -> Vec { - let short = short_path(file.url(), &self.folder.cwd); - - let v = self.is_find.then_some(()).and_then(|_| { - let finder = self.cx.manager.active().finder()?; - #[cfg(target_os = "windows")] - let (head, body, tail) = finder.explode(short.name.to_string_lossy().as_bytes())?; - - #[cfg(not(target_os = "windows"))] - let (head, body, tail) = { - use std::os::unix::ffi::OsStrExt; - finder.explode(short.name.as_bytes())? - }; - - // TODO: to be configured by THEME? - let style = Style::new().fg(Color::Rgb(255, 255, 50)).add_modifier(Modifier::ITALIC); - Some(vec![ - Span::raw(short.prefix.join(head).display().to_string()), - Span::styled(body, style), - Span::raw(tail), - ]) - }); - - v.unwrap_or_else(|| vec![Span::raw(format!("{}", short))]) - } + // fn highlighted_item<'b>(&'b self, file: &'b File) -> Vec { + // let short = short_path(file.url(), &self.folder.cwd); + // + // let v = self.is_find.then_some(()).and_then(|_| { + // let finder = self.cx.manager.active().finder()?; + // let (head, body, tail) = finder.explode(short.name)?; + // + // // TODO: to be configured by THEME? + // let style = Style::new().fg(Color::Rgb(255, 255, + // 50)).add_modifier(Modifier::ITALIC); Some(vec![ + // Span::raw(short.prefix.join(head.as_ref()).display().to_string()), + // Span::styled(body, style), + // Span::raw(tail), + // ]) + // }); + // + // v.unwrap_or_else(|| vec![Span::raw(format!("{}", short))]) + // } } impl<'a> Widget for Folder<'a> { diff --git a/plugin/preset/components/folder.lua b/plugin/preset/components/folder.lua index 19c1bbff..ae444af4 100644 --- a/plugin/preset/components/folder.lua +++ b/plugin/preset/components/folder.lua @@ -6,9 +6,23 @@ function Folder:parent(area) return ui.Paragraph(area, ui.Line {}) end + local hovered = nil + if parent.hovered ~= nil then + hovered = parent.hovered.url + end + local lines = {} for _, f in pairs(parent.files) do - lines[#lines + 1] = ui.Line { ui.Span(f.name) } + local line = ui.Line { ui.Span(" " .. f.icon .. " " .. f.name .. " ") } + + -- TODO: preview hovered + if f.url == hovered then + line = line:style(THEME.selection.hovered) + else + line = line:style(f.style) + end + + lines[#lines + 1] = line end return { ui.Paragraph(area, lines) } @@ -22,10 +36,15 @@ function Folder:current(area) local lines = {} for _, f in pairs(cx.manager.current.files) do - local line = ui.Line { ui.Span(f.name) } + local line = ui.Line { ui.Span(" " .. f.icon .. " " .. f.name .. " ") } + + -- TODO: preview hovered if f.url == hovered then line = line:style(THEME.selection.hovered) + else + line = line:style(f.style) end + lines[#lines + 1] = line end diff --git a/plugin/src/bindings/manager.rs b/plugin/src/bindings/manager.rs index 2bb39851..474e433a 100644 --- a/plugin/src/bindings/manager.rs +++ b/plugin/src/bindings/manager.rs @@ -1,7 +1,8 @@ -use mlua::{AnyUserData, IntoLua, MetaMethod, UserDataFields, UserDataMethods}; +use config::THEME; +use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserDataFields, UserDataMethods}; use super::Url; -use crate::LUA; +use crate::{layout::Style, LUA}; pub struct Manager; @@ -46,6 +47,13 @@ impl Manager { reg.add_field_method_get("name", |_, me| { Ok(me.url().file_name().map(|n| n.to_string_lossy().to_string())) }); + reg.add_field_function_get("icon", |_, me| { + me.named_user_value::("icon")?.call::<_, String>(()) + }); + reg.add_field_function_get("style", |_, me| { + me.named_user_value::("style")?.call::<_, Style>(()) + }); + reg.add_field_method_get("url", |_, me| Ok(Url::from(me.url()))); reg.add_field_method_get("length", |_, me| Ok(me.length())); reg.add_field_method_get("link_to", |_, me| { @@ -72,22 +80,26 @@ impl Manager { inner: &'a core::manager::Manager, ) -> mlua::Result> { let ud = scope.create_any_userdata_ref(inner)?; - ud.set_named_user_value("parent", inner.parent().and_then(|p| Self::folder(scope, p).ok()))?; - ud.set_named_user_value("current", Self::folder(scope, inner.current())?)?; - ud.set_named_user_value("preview", Self::preview(scope, inner.active())?)?; + ud.set_named_user_value( + "parent", + inner.parent().and_then(|p| Self::folder(scope, inner, p).ok()), + )?; + ud.set_named_user_value("current", Self::folder(scope, inner, inner.current())?)?; + ud.set_named_user_value("preview", Self::preview(scope, inner, inner.active())?)?; Ok(ud) } pub(crate) fn folder<'a>( scope: &mlua::Scope<'a, 'a>, + manager: &'a core::manager::Manager, inner: &'a core::manager::Folder, ) -> mlua::Result> { let ud = scope.create_any_userdata_ref(inner)?; - ud.set_named_user_value("files", Self::files(scope, &inner.files)?)?; + ud.set_named_user_value("files", Self::files(scope, manager, &inner.files)?)?; ud.set_named_user_value( "hovered", - inner.hovered.as_ref().and_then(|h| Self::file(scope, h).ok()), + inner.hovered.as_ref().and_then(|h| Self::file(scope, manager, h).ok()), )?; Ok(ud) @@ -95,12 +107,13 @@ impl Manager { fn files<'a>( scope: &mlua::Scope<'a, 'a>, + manager: &'a core::manager::Manager, inner: &'a core::files::Files, ) -> mlua::Result> { let ud = scope.create_any_userdata_ref(inner)?; ud.set_named_user_value( "items", - inner.iter().filter_map(|f| Self::file(scope, f).ok()).collect::>(), + inner.iter().filter_map(|f| Self::file(scope, manager, f).ok()).collect::>(), )?; Ok(ud) @@ -108,13 +121,44 @@ impl Manager { fn file<'a>( scope: &mlua::Scope<'a, 'a>, + manager: &'a core::manager::Manager, inner: &'a core::files::File, ) -> mlua::Result> { - scope.create_any_userdata_ref(inner) + let ud = scope.create_any_userdata_ref(inner)?; + + ud.set_named_user_value( + "icon", + scope.create_function(|_, ()| { + Ok( + THEME + .icons + .iter() + .find(|&x| x.name.match_path(inner.url(), Some(inner.is_dir()))) + .map(|x| x.display.to_string()), + ) + })?, + )?; + + ud.set_named_user_value( + "style", + scope.create_function(|_, ()| { + let mime = manager.mimetype.get(inner.url()); + Ok( + THEME + .filetypes + .iter() + .find(|&x| x.matches(inner.url(), mime, inner.is_dir())) + .map(|x| Style::from(x.style)), + ) + })?, + )?; + + Ok(ud) } fn preview<'a>( scope: &mlua::Scope<'a, 'a>, + manager: &'a core::manager::Manager, tab: &'a core::manager::Tab, ) -> mlua::Result> { let inner = tab.preview(); @@ -127,7 +171,7 @@ impl Manager { .as_ref() .filter(|l| l.is_folder()) .and_then(|l| tab.history(&l.url)) - .and_then(|f| Self::folder(scope, f).ok()), + .and_then(|f| Self::folder(scope, manager, f).ok()), )?; Ok(ud) diff --git a/plugin/src/layout/line.rs b/plugin/src/layout/line.rs index 37bdcc43..4b04b6cc 100644 --- a/plugin/src/layout/line.rs +++ b/plugin/src/layout/line.rs @@ -50,11 +50,15 @@ impl<'lua> FromLua<'lua> for Line { impl UserData for Line { fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_function("style", |_, (ud, style): (AnyUserData, Style)| { + methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| { { let mut me = ud.borrow_mut::()?; - me.0.reset_style(); - me.0.patch_style(style.0); + match value { + Value::Nil => me.0.reset_style(), + Value::Table(tbl) => me.0.patch_style(Style::from(tbl).0), + Value::UserData(ud) => me.0.patch_style(ud.borrow::