mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
feat: deduplicate empty directories in preset archive previewer (#3676)
This commit is contained in:
parent
30ec603441
commit
a8a4b684a1
3 changed files with 77 additions and 30 deletions
|
|
@ -237,7 +237,7 @@ end
|
|||
---@return table files
|
||||
---@return Error? err
|
||||
function M.parse_7z_slt(child, skip, limit)
|
||||
local files, parents, err = { M.make_file() }, {}, nil
|
||||
local files, tops, parents, err = { M.make_file() }, {}, {}, nil
|
||||
local key, value, empty, stderr = "", "", Path.os(""), {}
|
||||
repeat
|
||||
local next, event = child:read_line()
|
||||
|
|
@ -253,7 +253,8 @@ function M.parse_7z_slt(child, skip, limit)
|
|||
|
||||
if next == "\n" or next == "\r\n" then
|
||||
if files[#files].path ~= empty then
|
||||
M.treelize(files, parents)
|
||||
M.treelize(files, tops, parents)
|
||||
M.pop_dup_dir(files, parents, false)
|
||||
files[#files + 1] = M.make_file()
|
||||
end
|
||||
goto continue
|
||||
|
|
@ -273,12 +274,17 @@ function M.parse_7z_slt(child, skip, limit)
|
|||
end
|
||||
|
||||
::continue::
|
||||
until #files > skip + limit
|
||||
until #files - 1 > skip + limit
|
||||
|
||||
if files[#files].path == empty then
|
||||
files[#files] = nil
|
||||
else
|
||||
M.treelize(files, parents)
|
||||
M.treelize(files, tops, parents)
|
||||
end
|
||||
|
||||
M.pop_dup_dir(files, parents, #files <= skip + limit)
|
||||
if #files > skip + limit then
|
||||
files[#files] = nil
|
||||
end
|
||||
|
||||
if #stderr ~= 0 then
|
||||
|
|
@ -289,29 +295,50 @@ end
|
|||
|
||||
---Convert a flat list of files into a tree structure
|
||||
---@param files table
|
||||
---@param parents Path[]
|
||||
function M.treelize(files, parents)
|
||||
---@param tops Path[]
|
||||
---@param parents table<string, boolean>
|
||||
function M.treelize(files, tops, parents)
|
||||
local f = table.remove(files)
|
||||
while #parents > 0 and not f.path:starts_with(parents[#parents]) do
|
||||
parents[#parents] = nil
|
||||
while #tops > 0 and not f.path:starts_with(tops[#tops]) do
|
||||
tops[#tops] = nil
|
||||
end
|
||||
|
||||
local buf, it = {}, f.path.parent
|
||||
while it and it ~= parents[#parents] do
|
||||
while it and it ~= tops[#tops] do
|
||||
buf[#buf + 1], it = it, it.parent
|
||||
end
|
||||
for i = #buf, 1, -1 do
|
||||
files[#files + 1] = M.make_file { path = buf[i], depth = #parents, is_dir = true }
|
||||
parents[#parents + 1] = buf[i]
|
||||
files[#files + 1] = M.make_file { path = buf[i], depth = #tops, is_dir = true }
|
||||
tops[#tops + 1] = buf[i]
|
||||
M.pop_dup_dir(files, parents, false)
|
||||
end
|
||||
|
||||
f.depth = #parents
|
||||
f.depth = #tops
|
||||
f.is_dir = f.folder == "+" or f.attr:sub(1, 1) == "D"
|
||||
|
||||
if not f.is_dir then
|
||||
files[#files + 1] = f
|
||||
elseif f.path ~= parents[#parents] then
|
||||
files[#files + 1], parents[#parents + 1] = f, f.path
|
||||
elseif f.path ~= tops[#tops] then
|
||||
files[#files + 1], tops[#tops + 1] = f, f.path
|
||||
end
|
||||
end
|
||||
|
||||
---@param files table
|
||||
---@param parents table<string, boolean>
|
||||
---@param eof boolean
|
||||
function M.pop_dup_dir(files, parents, eof)
|
||||
local n, i = #files, eof and #files or #files - 1
|
||||
if not files[i] or not files[i].is_dir then
|
||||
return
|
||||
end
|
||||
|
||||
local p = tostring(files[i].path)
|
||||
if not parents[p] then
|
||||
parents[p] = true
|
||||
elseif eof then
|
||||
files[n] = nil
|
||||
elseif not files[n].path:starts_with(files[i].path) then
|
||||
files[i], files[n] = files[n], nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,48 @@
|
|||
use mlua::{Function, Lua, MultiValue};
|
||||
use std::{any::TypeId, fmt::Write};
|
||||
|
||||
use mlua::{Function, Lua, MultiValue, Value};
|
||||
use tracing::{debug, error};
|
||||
|
||||
use super::Utils;
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn dbg(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, values: MultiValue| {
|
||||
let s = values.into_iter().map(|v| format!("{v:#?}")).collect::<Vec<_>>().join(" ");
|
||||
Ok(debug!("{s}"))
|
||||
})
|
||||
lua.create_function(|_, values: MultiValue| Ok(debug!("{}", Self::format_all(values)?)))
|
||||
}
|
||||
|
||||
pub(super) fn err(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, values: MultiValue| {
|
||||
let s = values.into_iter().map(|v| format!("{v:#?}")).collect::<Vec<_>>().join(" ");
|
||||
Ok(error!("{s}"))
|
||||
lua.create_function(|_, values: MultiValue| Ok(error!("{}", Self::format_all(values)?)))
|
||||
}
|
||||
|
||||
fn format_all(values: MultiValue) -> anyhow::Result<String> {
|
||||
let mut s = String::new();
|
||||
for value in values {
|
||||
if !s.is_empty() {
|
||||
s.push(' ');
|
||||
}
|
||||
Utils::format_one(&mut s, value)?;
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn format_one(buf: &mut String, value: Value) -> anyhow::Result<()> {
|
||||
let Value::UserData(ud) = &value else {
|
||||
return Ok(write!(buf, "{value:#?}")?);
|
||||
};
|
||||
|
||||
let id = ud.type_id();
|
||||
let ptr = ud.to_pointer();
|
||||
Ok(match id {
|
||||
Some(t) if t == TypeId::of::<yazi_binding::Url>() => {
|
||||
write!(buf, "Url({ptr:?}): {:?}", **ud.borrow::<yazi_binding::Url>()?)?
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_binding::Path>() => {
|
||||
write!(buf, "Path({ptr:?}): {:?}", **ud.borrow::<yazi_binding::Path>()?)?
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_binding::Id>() => {
|
||||
write!(buf, "Id({ptr:?}): {}", **ud.borrow::<yazi_binding::Id>()?)?
|
||||
}
|
||||
_ => write!(buf, "{value:#?}")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,14 +164,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_inner(&self) -> P
|
||||
where
|
||||
P: Clone,
|
||||
{
|
||||
self.inner.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> P { self.inner }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue