mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Fix the scrolling bug
This commit is contained in:
parent
d156508423
commit
dce7115850
5 changed files with 57 additions and 80 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
|
@ -96,9 +96,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ansi-to-tui"
|
||||
version = "8.0.0"
|
||||
version = "8.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdfd3cbf4843347ca072771a797484f1c3434a14d57f39d31c92dfb93a8799a8"
|
||||
checksum = "e42366bb9d958f042bf58f0a85e1b2d091997c1257ca49bddd7e4827aadc65fd"
|
||||
dependencies = [
|
||||
"nom 8.0.0",
|
||||
"ratatui-core",
|
||||
|
|
@ -541,9 +541,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
version = "1.2.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
|
|
@ -1063,9 +1063,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.9.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
||||
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
|
||||
|
||||
[[package]]
|
||||
name = "deadpool"
|
||||
|
|
@ -1483,9 +1483,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
|
||||
|
||||
[[package]]
|
||||
name = "finl_unicode"
|
||||
|
|
@ -4478,9 +4478,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.10+spec-1.1.0"
|
||||
version = "0.9.11+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48"
|
||||
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ lto = false
|
|||
debug = false
|
||||
|
||||
[workspace.dependencies]
|
||||
ansi-to-tui = "8.0.0"
|
||||
ansi-to-tui = "8.0.1"
|
||||
anyhow = "1.0.100"
|
||||
base64 = "0.22.1"
|
||||
bitflags = { version = "2.10.0", features = [ "serde" ] }
|
||||
|
|
@ -59,7 +59,7 @@ thiserror = "2.0.17"
|
|||
tokio = { version = "1.49.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.18"
|
||||
tokio-util = "0.7.18"
|
||||
toml = { version = "0.9.10" }
|
||||
toml = { version = "0.9.11" }
|
||||
tracing = { version = "0.1.44", features = [ "max_level_debug", "release_max_level_debug" ] }
|
||||
twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
|
||||
typed-path = "0.12.0"
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ pub struct Partition {
|
|||
|
||||
impl Partition {
|
||||
// Match mount types that do not reliably emit change notifications, or do not
|
||||
// update directory metadata on changes, and should be refreshed frequently /
|
||||
// heuristically.
|
||||
// update directory metadata on changes, and should be refreshed frequently.
|
||||
pub fn heuristic(&self) -> bool {
|
||||
let b: &[u8] = self.fstype.as_ref().map_or(b"", |s| s.as_encoded_bytes());
|
||||
matches!(b, b"exfat" | b"fuse.rclone")
|
||||
|
|
|
|||
|
|
@ -34,12 +34,11 @@ impl Partitions {
|
|||
pub fn heuristic(&self, _cha: Cha) -> bool {
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
{
|
||||
self.by_dev(_cha.dev).is_none_or(|p| p.heuristic())
|
||||
self.by_dev(_cha.dev).is_some_and(|p| p.heuristic())
|
||||
}
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
{
|
||||
// For now, assume other targets update directory stat data correctly & do not
|
||||
// need heuristic polling.
|
||||
// For now, assume other targets update directory stat data correctly
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,24 @@ local M = {}
|
|||
|
||||
function M:peek(job)
|
||||
local limit = job.area.h
|
||||
local files, bound, err = self.list_archive({ "-p", tostring(job.file.path) }, job.skip, limit)
|
||||
local files, err = self.list_archive({ "-p", tostring(job.file.path) }, job.skip, limit)
|
||||
|
||||
local first = (#files == 1 and files[1]) or (#files == 0 and M.list_if_only_one(job.file.path))
|
||||
if first and M.should_decompress_tar(first) then
|
||||
files, bound, err = self.list_compressed_tar({ "-p", tostring(job.file.path) }, job.skip, limit)
|
||||
files, err = self.list_compressed_tar({ "-p", tostring(job.file.path) }, job.skip, limit)
|
||||
end
|
||||
|
||||
if err then
|
||||
return ya.preview_widget(job, err)
|
||||
elseif job.skip > 0 and bound < job.skip + limit then
|
||||
return ya.emit("peek", { math.max(0, bound - limit), only_if = job.file.url, upper_bound = true })
|
||||
elseif job.skip > 0 and #files < job.skip + limit then
|
||||
return ya.emit("peek", { math.max(0, #files - limit), only_if = job.file.url, upper_bound = true })
|
||||
elseif #files == 0 then
|
||||
files = { M.make_file { path = job.file.url.stem } }
|
||||
end
|
||||
|
||||
local left, right = {}, {}
|
||||
for _, f in ipairs(M.treelize(files)) do
|
||||
for i = job.skip + 1, #files do
|
||||
local f = files[i]
|
||||
local icon = File({
|
||||
url = Url(f.path),
|
||||
cha = Cha { mode = tonumber(f.is_dir and "40700" or "100644", 8) },
|
||||
|
|
@ -105,7 +106,6 @@ end
|
|||
---@param skip integer
|
||||
---@param limit integer
|
||||
---@return table files
|
||||
---@return integer bound
|
||||
---@return Error? err
|
||||
function M.list_archive(args, skip, limit)
|
||||
local child = M.spawn_7z { "l", "-ba", "-slt", "-sccUTF-8", table.unpack(args) }
|
||||
|
|
@ -113,10 +113,10 @@ function M.list_archive(args, skip, limit)
|
|||
return {}, 0, Err("Failed to start either `7zz` or `7z`. Do you have 7-zip installed?")
|
||||
end
|
||||
|
||||
local files, bound, err = M.parse_7z_slt(child, skip, limit)
|
||||
local files, err = M.parse_7z_slt(child, skip, limit)
|
||||
child:start_kill()
|
||||
|
||||
return files, bound, err
|
||||
return files, err
|
||||
end
|
||||
|
||||
---List files in a compressed tarball
|
||||
|
|
@ -124,7 +124,6 @@ end
|
|||
---@param skip integer
|
||||
---@param limit integer
|
||||
---@return table files
|
||||
---@return integer bound
|
||||
---@return Error? err
|
||||
function M.list_compressed_tar(args, skip, limit)
|
||||
local src, dst = M.spawn_7z_piped(
|
||||
|
|
@ -135,11 +134,11 @@ function M.list_compressed_tar(args, skip, limit)
|
|||
return {}, 0, Err("Failed to start either `7zz` or `7z`. Do you have 7-zip installed?")
|
||||
end
|
||||
|
||||
local files, bound, err = M.parse_7z_slt(dst, skip, limit)
|
||||
local files, err = M.parse_7z_slt(dst, skip, limit)
|
||||
src:start_kill()
|
||||
dst:start_kill()
|
||||
|
||||
return files, bound, err
|
||||
return files, err
|
||||
end
|
||||
|
||||
function M.list_if_only_one(path)
|
||||
|
|
@ -171,7 +170,7 @@ end
|
|||
|
||||
---List metadata of an archive
|
||||
---@param args table
|
||||
---@return string|nil type
|
||||
---@return string? type
|
||||
---@return integer code
|
||||
--- 0: success
|
||||
--- 1: failed to spawn
|
||||
|
|
@ -214,14 +213,14 @@ function M.is_encrypted(s) return s:find(" Wrong password", 1, true) end
|
|||
|
||||
function M.is_tar(path) return M.list_meta { "-p", tostring(path) } == "tar" end
|
||||
|
||||
function M.make_file(fields)
|
||||
fields = fields or {}
|
||||
fields.path = type(fields.path or "") == "string" and Path.os(fields.path or "") or fields.path
|
||||
fields.size = tonumber(fields.size) or 0
|
||||
fields.packed_size = tonumber(fields.packed_size) or 0
|
||||
fields.attr = fields.attr or ""
|
||||
fields.folder = fields.folder or ""
|
||||
return fields
|
||||
function M.make_file(t)
|
||||
t = t or {}
|
||||
t.path = type(t.path or "") == "string" and Path.os(t.path or "") or t.path
|
||||
t.size = tonumber(t.size) or 0
|
||||
t.packed_size = tonumber(t.packed_size) or 0
|
||||
t.attr = t.attr or ""
|
||||
t.folder = t.folder or ""
|
||||
return t
|
||||
end
|
||||
|
||||
function M.should_decompress_tar(file)
|
||||
|
|
@ -234,11 +233,10 @@ end
|
|||
---@param skip integer
|
||||
---@param limit integer
|
||||
---@return table files
|
||||
---@return integer bound
|
||||
---@return Error? err
|
||||
function M.parse_7z_slt(child, skip, limit)
|
||||
local i, files, err = 0, { M.make_file() }, nil
|
||||
local key, value, stderr = "", "", {}
|
||||
local files, parents, err = { M.make_file() }, {}, nil
|
||||
local key, value, empty, stderr = "", "", Path.os(""), {}
|
||||
repeat
|
||||
local next, event = child:read_line()
|
||||
if event == 1 and M.is_encrypted(next) then
|
||||
|
|
@ -252,13 +250,11 @@ function M.parse_7z_slt(child, skip, limit)
|
|||
end
|
||||
|
||||
if next == "\n" or next == "\r\n" then
|
||||
i = i + 1
|
||||
if files[#files].path ~= Path.os("") then
|
||||
if files[#files].path ~= empty then
|
||||
M.treelize(files, parents)
|
||||
files[#files + 1] = M.make_file()
|
||||
end
|
||||
goto continue
|
||||
elseif i < skip then
|
||||
goto continue
|
||||
end
|
||||
|
||||
key, value = next:match("^(%u[%a ]+) = (.-)[\r\n]+")
|
||||
|
|
@ -275,7 +271,7 @@ function M.parse_7z_slt(child, skip, limit)
|
|||
end
|
||||
|
||||
::continue::
|
||||
until i >= skip + limit
|
||||
until #files > skip + limit
|
||||
|
||||
if files[#files].path == Path.os("") then
|
||||
files[#files] = nil
|
||||
|
|
@ -283,51 +279,34 @@ function M.parse_7z_slt(child, skip, limit)
|
|||
if #stderr ~= 0 then
|
||||
err = Err("7-zip errored out while listing files, stderr: %s", table.concat(stderr, "\n"))
|
||||
end
|
||||
return files, i, err
|
||||
return files, err
|
||||
end
|
||||
|
||||
---Convert a flat list of files into a tree structure
|
||||
---@param files table
|
||||
---@return table tree
|
||||
function M.treelize(files)
|
||||
if #files == 0 then
|
||||
return files
|
||||
---@param parents Path[]
|
||||
function M.treelize(files, parents)
|
||||
local f = table.remove(files)
|
||||
while #parents > 0 and not f.path:starts_with(parents[#parents]) do
|
||||
parents[#parents] = nil
|
||||
end
|
||||
|
||||
local parent = files[1].path.parent
|
||||
while parent do
|
||||
table.insert(files, 1, M.make_file { path = parent, is_dir = true })
|
||||
parent = parent.parent
|
||||
local buf, it = {}, f.path.parent
|
||||
while it and it ~= parents[#parents] 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]
|
||||
end
|
||||
|
||||
local tree, parents, prev_parent = {}, {}, nil
|
||||
for _, f in ipairs(files) do
|
||||
while #parents > 0 and not f.path:starts_with(parents[#parents]) do
|
||||
parents[#parents] = nil
|
||||
end
|
||||
f.depth = #parents
|
||||
f.is_dir = f.folder == "+" or f.attr:sub(1, 1) == "D"
|
||||
|
||||
f.depth = #parents
|
||||
f.is_dir = f.is_dir or f.folder == "+" or f.attr:sub(1, 1) == "D"
|
||||
|
||||
if f.is_dir then
|
||||
parents[#parents + 1] = f.path
|
||||
elseif prev_parent ~= f.path.parent then
|
||||
local buf, parent = {}, f.path.parent
|
||||
while parent and parent ~= parents[#parents] do
|
||||
buf[#buf + 1], parent = parent, parent.parent
|
||||
end
|
||||
for j = #buf, 1, -1 do
|
||||
tree[#tree + 1] = M.make_file { path = buf[j], depth = #parents, is_dir = true }
|
||||
parents[#parents + 1] = buf[j]
|
||||
end
|
||||
f.depth = #parents
|
||||
end
|
||||
|
||||
tree[#tree + 1] = f
|
||||
prev_parent = f.path.parent
|
||||
files[#files + 1] = f
|
||||
if f.is_dir then
|
||||
parents[#parents + 1] = f.path
|
||||
end
|
||||
|
||||
return tree
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue