mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
f3b82274b6
commit
2616419858
5 changed files with 106 additions and 64 deletions
|
|
@ -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<Span> {
|
||||
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<Span> {
|
||||
// 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> {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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::<Function>("icon")?.call::<_, String>(())
|
||||
});
|
||||
reg.add_field_function_get("style", |_, me| {
|
||||
me.named_user_value::<Function>("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<AnyUserData<'a>> {
|
||||
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<AnyUserData<'a>> {
|
||||
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<AnyUserData<'a>> {
|
||||
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::<Vec<_>>(),
|
||||
inner.iter().filter_map(|f| Self::file(scope, manager, f).ok()).collect::<Vec<_>>(),
|
||||
)?;
|
||||
|
||||
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<AnyUserData<'a>> {
|
||||
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<AnyUserData<'a>> {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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::<Self>()?;
|
||||
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::<Style>()?.0),
|
||||
_ => return Err(mlua::Error::external("expected a Style or Table or nil")),
|
||||
};
|
||||
}
|
||||
Ok(ud)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ impl Style {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<config::theme::Style> for Style {
|
||||
fn from(value: config::theme::Style) -> Self { Self(value.into()) }
|
||||
}
|
||||
|
||||
impl<'a> From<Table<'a>> for Style {
|
||||
fn from(value: Table) -> Self {
|
||||
let mut style = ratatui::style::Style::default();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue