This commit is contained in:
sxyazi 2023-10-20 14:12:04 +08:00
parent eac7b6fd8d
commit 4e2a06f221
No known key found for this signature in database
5 changed files with 44 additions and 27 deletions

View file

@ -8,7 +8,6 @@ use tokio::fs;
pub struct File { pub struct File {
pub url: Url, pub url: Url,
pub meta: Metadata, pub meta: Metadata,
pub length: u64,
pub(super) link_to: Option<Url>, pub(super) link_to: Option<Url>,
pub is_link: bool, pub is_link: bool,
pub is_hidden: bool, pub is_hidden: bool,
@ -30,9 +29,8 @@ impl File {
link_to = fs::read_link(&url).await.map(Url::from).ok(); link_to = fs::read_link(&url).await.map(Url::from).ok();
} }
let length = meta.len();
let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false); let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false);
Self { url, meta, length, link_to, is_link, is_hidden } Self { url, meta, link_to, is_link, is_hidden }
} }
#[inline] #[inline]

View file

@ -48,7 +48,7 @@ impl FilesSorter {
SortBy::Size => items.sort_unstable_by(|a, b| { SortBy::Size => items.sort_unstable_by(|a, b| {
let aa = if a.is_dir() { sizes.get(&a.url).copied() } else { None }; let aa = if a.is_dir() { sizes.get(&a.url).copied() } else { None };
let bb = if b.is_dir() { sizes.get(&b.url).copied() } else { None }; let bb = if b.is_dir() { sizes.get(&b.url).copied() } else { None };
self.cmp(aa.unwrap_or(a.length), bb.unwrap_or(b.length), self.promote(a, b)) self.cmp(aa.unwrap_or(a.meta.len()), bb.unwrap_or(b.meta.len()), self.promote(a, b))
}), }),
} }
true true
@ -75,7 +75,6 @@ impl FilesSorter {
let dummy = File { let dummy = File {
url: Default::default(), url: Default::default(),
meta: items[0].meta.clone(), meta: items[0].meta.clone(),
length: 0,
link_to: None, link_to: None,
is_link: false, is_link: false,
is_hidden: false, is_hidden: false,

View file

@ -53,9 +53,9 @@ function Folder:labels(area)
if linemode == "size" then if linemode == "size" then
lines[#lines + 1] = ui.Line { ui.Span(utils.readable_size(f:size())) } lines[#lines + 1] = ui.Line { ui.Span(utils.readable_size(f:size())) }
elseif linemode == "mtime" then elseif linemode == "mtime" then
lines[#lines + 1] = ui.Line { ui.Span("mtime") } lines[#lines + 1] = ui.Line { ui.Span(os.date("%y-%m-%d %H:%M", f.modified)) }
elseif linemode == "permissions" then elseif linemode == "permissions" then
lines[#lines + 1] = ui.Line { ui.Span("permissions") } lines[#lines + 1] = ui.Line { ui.Span(f:permissions() or "") }
end end
end end
return ui.Paragraph(area, lines):align(ui.Alignment.RIGHT) return ui.Paragraph(area, lines):align(ui.Alignment.RIGHT)

View file

@ -47,13 +47,18 @@ end
function Status:permissions() function Status:permissions()
local h = cx.active.current.hovered local h = cx.active.current.hovered
if h == nil or h.permissions == nil then if h == nil then
return ui.Span("")
end
local perm = h:permissions()
if perm == nil then
return ui.Span("") return ui.Span("")
end end
local spans = {} local spans = {}
for i = 1, #h.permissions do for i = 1, #perm do
local c = h.permissions:sub(i, i) local c = perm:sub(i, i)
local style = THEME.status.permissions_t local style = THEME.status.permissions_t
if c == "-" then if c == "-" then
style = THEME.status.permissions_s style = THEME.status.permissions_s

View file

@ -1,3 +1,5 @@
use std::time::UNIX_EPOCH;
use config::THEME; use config::THEME;
use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef}; use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef};
@ -13,7 +15,6 @@ impl From<&core::files::File> for File {
impl UserData for File { impl UserData for File {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("url", |_, me| Ok(Url::from(&me.0.url))); fields.add_field_method_get("url", |_, me| Ok(Url::from(&me.0.url)));
fields.add_field_method_get("length", |_, me| Ok(me.0.length));
fields.add_field_method_get("link_to", |_, me| Ok(me.0.link_to().map(Url::from))); fields.add_field_method_get("link_to", |_, me| Ok(me.0.link_to().map(Url::from)));
fields.add_field_method_get("is_link", |_, me| Ok(me.0.is_link)); fields.add_field_method_get("is_link", |_, me| Ok(me.0.is_link));
fields.add_field_method_get("is_hidden", |_, me| Ok(me.0.is_hidden)); fields.add_field_method_get("is_hidden", |_, me| Ok(me.0.is_hidden));
@ -48,34 +49,55 @@ impl Files {
LUA.register_userdata_type::<core::files::File>(|reg| { LUA.register_userdata_type::<core::files::File>(|reg| {
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("link_to", |_, me| Ok(me.link_to().map(Url::from))); reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from)));
reg.add_field_method_get("is_link", |_, me| Ok(me.is_link)); reg.add_field_method_get("is_link", |_, me| Ok(me.is_link));
reg.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden)); reg.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden));
// Metadata
reg.add_field_method_get("is_file", |_, me| Ok(me.is_file()));
reg.add_field_method_get("is_dir", |_, me| Ok(me.is_dir()));
reg.add_field_method_get("is_symlink", |_, me| Ok(me.meta.is_symlink()));
#[cfg(unix)]
{
use std::os::unix::prelude::FileTypeExt;
reg.add_field_method_get("is_block_device", |_, me| {
Ok(me.meta.file_type().is_block_device())
});
reg
.add_field_method_get("is_char_device", |_, me| Ok(me.meta.file_type().is_char_device()));
reg.add_field_method_get("is_fifo", |_, me| Ok(me.meta.file_type().is_fifo()));
reg.add_field_method_get("is_socket", |_, me| Ok(me.meta.file_type().is_socket()));
}
reg.add_field_method_get("length", |_, me| Ok(me.meta.len()));
reg.add_field_method_get("created", |_, me| {
Ok(me.meta.created()?.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())
});
reg.add_field_method_get("modified", |_, me| {
Ok(me.meta.modified()?.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())
});
reg.add_field_method_get("accessed", |_, me| {
Ok(me.meta.accessed()?.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())
});
reg.add_method("permissions", |_, me, ()| Ok(shared::permissions(me.meta.permissions())));
// Extension
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_method_get("permissions", |_, me| {
Ok(shared::permissions(me.meta.permissions()))
});
reg.add_function("size", |_, me: AnyUserData| { reg.add_function("size", |_, me: AnyUserData| {
let file = me.borrow::<core::files::File>()?; let file = me.borrow::<core::files::File>()?;
if !file.is_dir() { if !file.is_dir() {
return Ok(file.length); return Ok(file.meta.len());
} }
let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?; let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?;
Ok(folder.files.sizes.get(&file.url).copied().unwrap_or(file.length)) Ok(folder.files.sizes.get(&file.url).copied().unwrap_or(file.meta.len()))
}); });
reg.add_function("mime", |_, me: AnyUserData| { reg.add_function("mime", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?; let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
let file = me.borrow::<core::files::File>()?; let file = me.borrow::<core::files::File>()?;
Ok(manager.mimetype.get(&file.url).cloned()) Ok(manager.mimetype.get(&file.url).cloned())
}); });
reg.add_function("prefix", |_, me: AnyUserData| { reg.add_function("prefix", |_, me: AnyUserData| {
let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?; let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?;
if !folder.cwd.is_search() { if !folder.cwd.is_search() {
@ -87,7 +109,6 @@ impl Files {
p.next_back(); p.next_back();
Ok(Some(p.as_path().to_string_lossy().to_string())) Ok(Some(p.as_path().to_string_lossy().to_string()))
}); });
reg.add_method("icon", |_, me, ()| { reg.add_method("icon", |_, me, ()| {
Ok( Ok(
THEME THEME
@ -97,7 +118,6 @@ impl Files {
.map(|x| x.display.to_string()), .map(|x| x.display.to_string()),
) )
}); });
reg.add_function("style", |_, me: AnyUserData| { reg.add_function("style", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?; let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
let file = me.borrow::<core::files::File>()?; let file = me.borrow::<core::files::File>()?;
@ -110,13 +130,11 @@ impl Files {
.map(|x| Style::from(x.style)), .map(|x| Style::from(x.style)),
) )
}); });
reg.add_function("is_hovered", |_, me: AnyUserData| { reg.add_function("is_hovered", |_, me: AnyUserData| {
let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?; let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?;
let file = me.borrow::<core::files::File>()?; let file = me.borrow::<core::files::File>()?;
Ok(matches!(folder.hovered(), Some(f) if f.url == file.url)) Ok(matches!(folder.hovered(), Some(f) if f.url == file.url))
}); });
reg.add_function("is_yanked", |_, me: AnyUserData| { reg.add_function("is_yanked", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?; let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
let file = me.borrow::<core::files::File>()?; let file = me.borrow::<core::files::File>()?;
@ -128,7 +146,6 @@ impl Files {
1u8 1u8
}) })
}); });
reg.add_function("is_selected", |_, me: AnyUserData| { reg.add_function("is_selected", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?; let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?; let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?;
@ -142,7 +159,6 @@ impl Files {
manager.active().mode.pending(folder.offset + idx, selected) manager.active().mode.pending(folder.offset + idx, selected)
}) })
}); });
reg.add_function("found", |lua, me: AnyUserData| { reg.add_function("found", |lua, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?; let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
let Some(finder) = &manager.active().finder else { let Some(finder) = &manager.active().finder else {
@ -158,7 +174,6 @@ impl Files {
} }
Ok(None) Ok(None)
}); });
reg.add_function("highlights", |_, me: AnyUserData| { reg.add_function("highlights", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?; let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
let Some(finder) = &manager.active().finder else { let Some(finder) = &manager.active().finder else {