mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: line mode
This commit is contained in:
parent
51ab86b1b8
commit
eac7b6fd8d
9 changed files with 105 additions and 48 deletions
|
|
@ -24,3 +24,15 @@ impl TryFrom<String> for Linemode {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Linemode {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Self::None => "none",
|
||||
Self::Size => "size",
|
||||
Self::Mtime => "mtime",
|
||||
Self::Permissions => "permissions",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,3 +36,17 @@ impl TryFrom<String> for SortBy {
|
|||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
||||
}
|
||||
|
||||
impl ToString for SortBy {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Self::None => "none",
|
||||
Self::Alphabetical => "alphabetical",
|
||||
Self::Created => "created",
|
||||
Self::Modified => "modified",
|
||||
Self::Natural => "natural",
|
||||
Self::Size => "size",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub struct Files {
|
|||
ticket: u64,
|
||||
pub(crate) version: u64,
|
||||
|
||||
sizes: BTreeMap<Url, u64>,
|
||||
pub sizes: BTreeMap<Url, u64>,
|
||||
selected: BTreeSet<Url>,
|
||||
|
||||
sorter: FilesSorter,
|
||||
|
|
@ -268,10 +268,6 @@ impl Files {
|
|||
#[inline]
|
||||
pub fn position(&self, url: &Url) -> Option<usize> { self.iter().position(|f| &f.url == url) }
|
||||
|
||||
// --- Sizes
|
||||
#[inline]
|
||||
pub fn size(&self, url: &Url) -> Option<u64> { self.sizes.get(url).copied() }
|
||||
|
||||
// --- Selected
|
||||
pub fn selected(&self, pending: &BTreeSet<usize>, unset: bool) -> Vec<&File> {
|
||||
if self.selected.is_empty() && (unset || pending.is_empty()) {
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ impl Tasks {
|
|||
|
||||
let targets: Vec<_> = targets
|
||||
.iter()
|
||||
.filter(|f| f.is_dir() && targets.size(&f.url).is_none())
|
||||
.filter(|f| f.is_dir() && !targets.sizes.contains_key(&f.url))
|
||||
.map(|f| &f.url)
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,53 @@ function Folder:by_kind(kind)
|
|||
end
|
||||
end
|
||||
|
||||
function Folder:highlighted_name(file)
|
||||
-- Complete prefix when searching across directories
|
||||
local prefix = file:prefix() or ""
|
||||
if prefix ~= "" then
|
||||
prefix = prefix .. "/"
|
||||
end
|
||||
|
||||
-- Range highlighting for filenames
|
||||
local highlights = file:highlights()
|
||||
local spans = ui.highlight_ranges(prefix .. file.name, highlights)
|
||||
|
||||
-- Show symlink target
|
||||
if MANAGER.show_symlink and file.link_to ~= nil then
|
||||
spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic()
|
||||
end
|
||||
|
||||
if highlights == nil or not file:is_hovered() then
|
||||
return spans
|
||||
end
|
||||
|
||||
local found = file:found()
|
||||
if found ~= nil then
|
||||
spans[#spans + 1] = ui.Span(" ")
|
||||
spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position)
|
||||
end
|
||||
return spans
|
||||
end
|
||||
|
||||
function Folder:labels(area)
|
||||
local linemode = cx.active.conf.linemode
|
||||
if linemode == "none" then
|
||||
return {}
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
for _, f in ipairs(self:by_kind(self.CURRENT).window) do
|
||||
if linemode == "size" then
|
||||
lines[#lines + 1] = ui.Line { ui.Span(utils.readable_size(f:size())) }
|
||||
elseif linemode == "mtime" then
|
||||
lines[#lines + 1] = ui.Line { ui.Span("mtime") }
|
||||
elseif linemode == "permissions" then
|
||||
lines[#lines + 1] = ui.Line { ui.Span("permissions") }
|
||||
end
|
||||
end
|
||||
return ui.Paragraph(area, lines):align(ui.Alignment.RIGHT)
|
||||
end
|
||||
|
||||
function Folder:markers(area, markers)
|
||||
if #markers == 0 then
|
||||
return {}
|
||||
|
|
@ -55,34 +102,6 @@ function Folder:markers(area, markers)
|
|||
return elements
|
||||
end
|
||||
|
||||
function Folder:highlighted_name(file)
|
||||
-- Complete prefix when searching across directories
|
||||
local prefix = file:prefix() or ""
|
||||
if prefix ~= "" then
|
||||
prefix = prefix .. "/"
|
||||
end
|
||||
|
||||
-- Range highlighting for filenames
|
||||
local highlights = file:highlights()
|
||||
local spans = ui.highlight_ranges(prefix .. file.name, highlights)
|
||||
|
||||
-- Show symlink target
|
||||
if MANAGER.show_symlink and file.link_to ~= nil then
|
||||
spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic()
|
||||
end
|
||||
|
||||
if highlights == nil or not file:is_hovered() then
|
||||
return spans
|
||||
end
|
||||
|
||||
local found = file:found()
|
||||
if found ~= nil then
|
||||
spans[#spans + 1] = ui.Span(" ")
|
||||
spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position)
|
||||
end
|
||||
return spans
|
||||
end
|
||||
|
||||
function Folder:parent(area)
|
||||
local folder = self:by_kind(self.PARENT)
|
||||
if folder == nil then
|
||||
|
|
@ -127,8 +146,7 @@ function Folder:current(area)
|
|||
markers[#markers + 1] = { i, 3 }
|
||||
end
|
||||
end
|
||||
|
||||
return { ui.List(area, items), table.unpack(self:markers(area, markers)) }
|
||||
return utils.flat { ui.List(area, items), self:labels(area), table.unpack(self:markers(area, markers)) }
|
||||
end
|
||||
|
||||
function Folder:preview(area)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ function Status:size()
|
|||
|
||||
local style = self.style()
|
||||
return ui.Line {
|
||||
ui.Span(" " .. utils.readable_size(h.length) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg),
|
||||
ui.Span(" " .. utils.readable_size(h:size()) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg),
|
||||
ui.Span(THEME.status.separator_close):fg(THEME.status.separator_style.fg),
|
||||
}
|
||||
end
|
||||
|
|
@ -109,9 +109,9 @@ function Status:progress(area, offset)
|
|||
end
|
||||
|
||||
local gauge = ui.Gauge(ui.Rect {
|
||||
x = area.x + math.max(0, area.w - offset - 21),
|
||||
x = math.max(0, area.w - offset - 21),
|
||||
y = area.y,
|
||||
w = math.min(20, area.w),
|
||||
w = math.max(0, math.min(20, area.w - offset - 1)),
|
||||
h = 1,
|
||||
})
|
||||
|
||||
|
|
@ -134,17 +134,12 @@ function Status:progress(area, offset)
|
|||
end
|
||||
|
||||
function Status:render(area)
|
||||
local chunks = ui.Layout()
|
||||
:direction(ui.Direction.HORIZONTAL)
|
||||
:constraints({ ui.Constraint.Percentage(50), ui.Constraint.Percentage(50) })
|
||||
:split(area)
|
||||
|
||||
local left = ui.Line { self:mode(), self:size(), self:name() }
|
||||
local right = ui.Line { self:permissions(), self:percentage(), self:position() }
|
||||
local progress = self:progress(chunks[2], right:width())
|
||||
local progress = self:progress(area, right:width())
|
||||
return {
|
||||
ui.Paragraph(chunks[1], { left }),
|
||||
ui.Paragraph(chunks[2], { right }):align(ui.Alignment.RIGHT),
|
||||
ui.Paragraph(area, { left }),
|
||||
ui.Paragraph(area, { right }):align(ui.Alignment.RIGHT),
|
||||
table.unpack(progress),
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,16 @@ impl<'a, 'b> Active<'a, 'b> {
|
|||
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
|
||||
})?;
|
||||
|
||||
LUA.register_userdata_type::<core::tab::Config>(|reg| {
|
||||
reg.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string()));
|
||||
reg.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive));
|
||||
reg.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse));
|
||||
reg.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first));
|
||||
|
||||
reg.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_string()));
|
||||
reg.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden));
|
||||
})?;
|
||||
|
||||
LUA.register_userdata_type::<core::tab::Folder>(|reg| {
|
||||
reg.add_field_method_get("cwd", |_, me| Ok(Url::from(&me.cwd)));
|
||||
reg.add_field_method_get("offset", |_, me| Ok(me.offset));
|
||||
|
|
@ -48,6 +58,7 @@ impl<'a, 'b> Active<'a, 'b> {
|
|||
pub(crate) fn make(&self) -> mlua::Result<AnyUserData<'a>> {
|
||||
let ud = self.scope.create_any_userdata_ref(self.inner)?;
|
||||
ud.set_named_user_value("mode", self.scope.create_any_userdata_ref(&self.inner.mode)?)?;
|
||||
ud.set_named_user_value("conf", self.scope.create_any_userdata_ref(&self.inner.conf)?)?;
|
||||
ud.set_named_user_value(
|
||||
"parent",
|
||||
self.inner.parent.as_ref().and_then(|p| self.folder(p, None).ok()),
|
||||
|
|
|
|||
|
|
@ -60,6 +60,16 @@ impl Files {
|
|||
Ok(shared::permissions(me.meta.permissions()))
|
||||
});
|
||||
|
||||
reg.add_function("size", |_, me: AnyUserData| {
|
||||
let file = me.borrow::<core::files::File>()?;
|
||||
if !file.is_dir() {
|
||||
return Ok(file.length);
|
||||
}
|
||||
|
||||
let folder = me.named_user_value::<UserDataRef<core::tab::Folder>>("folder")?;
|
||||
Ok(folder.files.sizes.get(&file.url).copied().unwrap_or(file.length))
|
||||
});
|
||||
|
||||
reg.add_function("mime", |_, me: AnyUserData| {
|
||||
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
|
||||
let file = me.borrow::<core::files::File>()?;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ impl<'a, 'b> Tabs<'a, 'b> {
|
|||
});
|
||||
|
||||
reg.add_field_function_get("mode", |_, me| me.named_user_value::<AnyUserData>("mode"));
|
||||
reg.add_field_function_get("conf", |_, me| me.named_user_value::<AnyUserData>("conf"));
|
||||
reg.add_field_function_get("parent", |_, me| me.named_user_value::<Value>("parent"));
|
||||
reg.add_field_function_get("current", |_, me| me.named_user_value::<AnyUserData>("current"));
|
||||
reg.add_field_function_get("preview", |_, me| me.named_user_value::<AnyUserData>("preview"));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue