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, widgets::Widget};
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, style::Style, widgets::Widget};
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
pub(super) struct Folder<'a> {
|
pub(super) struct Folder<'a> {
|
||||||
|
|
@ -20,52 +19,24 @@ impl<'a> Folder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Folder<'a> {
|
impl<'a> Folder<'a> {
|
||||||
#[inline]
|
// fn highlighted_item<'b>(&'b self, file: &'b File) -> Vec<Span> {
|
||||||
fn icon(file: &File) -> &'static str {
|
// let short = short_path(file.url(), &self.folder.cwd);
|
||||||
THEME
|
//
|
||||||
.icons
|
// let v = self.is_find.then_some(()).and_then(|_| {
|
||||||
.iter()
|
// let finder = self.cx.manager.active().finder()?;
|
||||||
.find(|x| x.name.match_path(file.url(), Some(file.is_dir())))
|
// let (head, body, tail) = finder.explode(short.name)?;
|
||||||
.map(|x| x.display.as_ref())
|
//
|
||||||
.unwrap_or("")
|
// // TODO: to be configured by THEME?
|
||||||
}
|
// let style = Style::new().fg(Color::Rgb(255, 255,
|
||||||
|
// 50)).add_modifier(Modifier::ITALIC); Some(vec![
|
||||||
#[inline]
|
// Span::raw(short.prefix.join(head.as_ref()).display().to_string()),
|
||||||
fn item_style(&self, file: &File) -> Style {
|
// Span::styled(body, style),
|
||||||
let mime = self.cx.manager.mimetype.get(file.url());
|
// Span::raw(tail),
|
||||||
THEME
|
// ])
|
||||||
.filetypes
|
// });
|
||||||
.iter()
|
//
|
||||||
.find(|x| x.matches(file.url(), mime, file.is_dir()))
|
// v.unwrap_or_else(|| vec![Span::raw(format!("{}", short))])
|
||||||
.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))])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Widget for Folder<'a> {
|
impl<'a> Widget for Folder<'a> {
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,23 @@ function Folder:parent(area)
|
||||||
return ui.Paragraph(area, ui.Line {})
|
return ui.Paragraph(area, ui.Line {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local hovered = nil
|
||||||
|
if parent.hovered ~= nil then
|
||||||
|
hovered = parent.hovered.url
|
||||||
|
end
|
||||||
|
|
||||||
local lines = {}
|
local lines = {}
|
||||||
for _, f in pairs(parent.files) do
|
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
|
end
|
||||||
|
|
||||||
return { ui.Paragraph(area, lines) }
|
return { ui.Paragraph(area, lines) }
|
||||||
|
|
@ -22,10 +36,15 @@ function Folder:current(area)
|
||||||
|
|
||||||
local lines = {}
|
local lines = {}
|
||||||
for _, f in pairs(cx.manager.current.files) do
|
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
|
if f.url == hovered then
|
||||||
line = line:style(THEME.selection.hovered)
|
line = line:style(THEME.selection.hovered)
|
||||||
|
else
|
||||||
|
line = line:style(f.style)
|
||||||
end
|
end
|
||||||
|
|
||||||
lines[#lines + 1] = line
|
lines[#lines + 1] = line
|
||||||
end
|
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 super::Url;
|
||||||
use crate::LUA;
|
use crate::{layout::Style, LUA};
|
||||||
|
|
||||||
pub struct Manager;
|
pub struct Manager;
|
||||||
|
|
||||||
|
|
@ -46,6 +47,13 @@ impl Manager {
|
||||||
reg.add_field_method_get("name", |_, me| {
|
reg.add_field_method_get("name", |_, me| {
|
||||||
Ok(me.url().file_name().map(|n| n.to_string_lossy().to_string()))
|
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("url", |_, me| Ok(Url::from(me.url())));
|
||||||
reg.add_field_method_get("length", |_, me| Ok(me.length()));
|
reg.add_field_method_get("length", |_, me| Ok(me.length()));
|
||||||
reg.add_field_method_get("link_to", |_, me| {
|
reg.add_field_method_get("link_to", |_, me| {
|
||||||
|
|
@ -72,22 +80,26 @@ impl Manager {
|
||||||
inner: &'a core::manager::Manager,
|
inner: &'a core::manager::Manager,
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> mlua::Result<AnyUserData<'a>> {
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
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(
|
||||||
ud.set_named_user_value("current", Self::folder(scope, inner.current())?)?;
|
"parent",
|
||||||
ud.set_named_user_value("preview", Self::preview(scope, inner.active())?)?;
|
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)
|
Ok(ud)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn folder<'a>(
|
pub(crate) fn folder<'a>(
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
scope: &mlua::Scope<'a, 'a>,
|
||||||
|
manager: &'a core::manager::Manager,
|
||||||
inner: &'a core::manager::Folder,
|
inner: &'a core::manager::Folder,
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> mlua::Result<AnyUserData<'a>> {
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
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(
|
ud.set_named_user_value(
|
||||||
"hovered",
|
"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)
|
Ok(ud)
|
||||||
|
|
@ -95,12 +107,13 @@ impl Manager {
|
||||||
|
|
||||||
fn files<'a>(
|
fn files<'a>(
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
scope: &mlua::Scope<'a, 'a>,
|
||||||
|
manager: &'a core::manager::Manager,
|
||||||
inner: &'a core::files::Files,
|
inner: &'a core::files::Files,
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> mlua::Result<AnyUserData<'a>> {
|
||||||
let ud = scope.create_any_userdata_ref(inner)?;
|
let ud = scope.create_any_userdata_ref(inner)?;
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value(
|
||||||
"items",
|
"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)
|
Ok(ud)
|
||||||
|
|
@ -108,13 +121,44 @@ impl Manager {
|
||||||
|
|
||||||
fn file<'a>(
|
fn file<'a>(
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
scope: &mlua::Scope<'a, 'a>,
|
||||||
|
manager: &'a core::manager::Manager,
|
||||||
inner: &'a core::files::File,
|
inner: &'a core::files::File,
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> 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>(
|
fn preview<'a>(
|
||||||
scope: &mlua::Scope<'a, 'a>,
|
scope: &mlua::Scope<'a, 'a>,
|
||||||
|
manager: &'a core::manager::Manager,
|
||||||
tab: &'a core::manager::Tab,
|
tab: &'a core::manager::Tab,
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> mlua::Result<AnyUserData<'a>> {
|
||||||
let inner = tab.preview();
|
let inner = tab.preview();
|
||||||
|
|
@ -127,7 +171,7 @@ impl Manager {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.filter(|l| l.is_folder())
|
.filter(|l| l.is_folder())
|
||||||
.and_then(|l| tab.history(&l.url))
|
.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)
|
Ok(ud)
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,15 @@ impl<'lua> FromLua<'lua> for Line {
|
||||||
|
|
||||||
impl UserData for Line {
|
impl UserData for Line {
|
||||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
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>()?;
|
let mut me = ud.borrow_mut::<Self>()?;
|
||||||
me.0.reset_style();
|
match value {
|
||||||
me.0.patch_style(style.0);
|
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)
|
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 {
|
impl<'a> From<Table<'a>> for Style {
|
||||||
fn from(value: Table) -> Self {
|
fn from(value: Table) -> Self {
|
||||||
let mut style = ratatui::style::Style::default();
|
let mut style = ratatui::style::Style::default();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue