mirror of
https://github.com/folke/snacks.nvim
synced 2025-12-23 08:47:57 +00:00
fix(explorer): mounted directories being detected as non-directories in Tree:expand (#2053)
## Description In certain filesystems — such as bind mounts, NFS, FUSE, or other mounted paths — uv.fs_scandir_next() may return a nil type for valid directories. This causes the snacks.nvim explorer to treat mounted folders as files, making them unexpandable in the UI. This patch adds a fallback to resolve the correct type when fs_scandir_next() returns nil. It uses uv.fs_stat() first, and falls back to vim.fn.isdirectory() if needed. This ensures that mounted directories are properly marked as navigable. Code change summary: - Inside Tree:expand, we now check t == nil - If so, we call uv.fs_stat() to get the true type - If fs_stat fails, we fallback to vim.fn.isdirectory - Final dir = true logic remains intact Impact: - Fixes a long-standing bug in mounted directories under /mnt, FUSE, etc. - Only runs extra checks when needed (no performance hit for regular files) - No changes elsewhere — clean, isolated patch ## Related Issue(s) - Fixes #2036 ## Screenshots before: <img width="1907" height="946" alt="image" src="https://github.com/user-attachments/assets/15e1b8a5-c999-49e8-8ab5-1d23c60e4969" /> after: <img width="343" height="902" alt="Screenshot_20250715_222920" src="https://github.com/user-attachments/assets/c7ca2fa0-e0cc-4e3d-a4bb-5345538408f7" /> --------- Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
This commit is contained in:
parent
68da653d20
commit
7a5eb1036a
4 changed files with 18 additions and 2 deletions
|
|
@ -141,6 +141,7 @@ function Tree:expand(node)
|
|||
if not name then
|
||||
break
|
||||
end
|
||||
t = t or Snacks.util.path_type(node.path .. "/" .. name)
|
||||
found[name] = true
|
||||
local child = self:child(node, name, t)
|
||||
child.type = t
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ function M.directory(ctx)
|
|||
ctx.preview:set_title(ctx.item.title or name)
|
||||
local ls = {} ---@type {file:string, type:"file"|"directory"}[]
|
||||
for file, t in vim.fs.dir(ctx.item.file) do
|
||||
t = t or Snacks.util.path_type(ctx.item.file .. "/" .. file)
|
||||
ls[#ls + 1] = { file = file, type = t }
|
||||
end
|
||||
ctx.preview:set_lines(vim.split(string.rep("\n", #ls), "\n"))
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ function M.dir(item)
|
|||
local path = type(item) == "table" and M.path(item) or item
|
||||
---@cast path string
|
||||
path = svim.fs.normalize(path)
|
||||
return vim.fn.isdirectory(path) == 1 and path or vim.fs.dirname(path)
|
||||
return Snacks.util.path_type(path) == "directory" and path or vim.fs.dirname(path)
|
||||
end
|
||||
|
||||
---@param paths string[]
|
||||
|
|
@ -476,7 +476,7 @@ function M.copy_path(from, to)
|
|||
Snacks.notify.error(("File `%s` does not exist"):format(from))
|
||||
return
|
||||
end
|
||||
if vim.fn.isdirectory(from) == 1 then
|
||||
if Snacks.util.path_type(from) == "directory" then
|
||||
M.copy_dir(from, to)
|
||||
else
|
||||
M.copy_file(from, to)
|
||||
|
|
|
|||
|
|
@ -458,4 +458,18 @@ function M.parse(parser, range, on_parse)
|
|||
end
|
||||
end
|
||||
|
||||
--- Better validation to check if path is a dir or a file
|
||||
---@param path string
|
||||
---@return "directory"|"file"
|
||||
function M.path_type(path)
|
||||
local stat = uv.fs_stat(path)
|
||||
if stat and stat.type then
|
||||
return stat.type
|
||||
end
|
||||
if vim.fn.isdirectory(path) == 1 then
|
||||
return "directory"
|
||||
end
|
||||
return "file"
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue