From b12904e21db8a575ccdd35beec3a45072569ba6e Mon Sep 17 00:00:00 2001 From: peter-lyr Date: Mon, 24 Aug 2026 12:15:56 +0800 Subject: [PATCH] fix(explorer): handle Windows drive roots correctly in tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows, scandir("D:") (no trailing slash) resolves to the drive’s current directory (e.g. D:/ob1) instead of the root D:/. snacks’ explorer tree.norm() stripped the trailing slash from "D:/", producing "D:", so opening or navigating to a drive root showed the current directory’s contents (stale) instead of the actual root. Fix two things in tree.lua: 1. norm: keep the trailing slash for Windows drive roots (D:/). 2. Tree:child: skip empty path segment produced by the trailing slash, and keep the trailing slash for drive-letter root nodes, avoiding double slashes (D://name) when joining child paths. Verified headless on Windows: - open D:/ -> real root listing (many entries), not stale ob1 contents - normal directories unchanged - navigating D:/ob1 up to D:/ now shows the drive root correctly --- lua/snacks/explorer/tree.lua | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lua/snacks/explorer/tree.lua b/lua/snacks/explorer/tree.lua index 850c2ae10..d0d43651e 100644 --- a/lua/snacks/explorer/tree.lua +++ b/lua/snacks/explorer/tree.lua @@ -26,7 +26,13 @@ local uv = vim.uv or vim.loop local function norm(path) - return svim.fs.normalize(path):gsub("/$", ""):gsub("^$", "/") + path = svim.fs.normalize(path) + -- keep trailing slash for Windows drive roots (D:/), otherwise + -- scandir("D:") resolves to the drive's current dir, not its root + if not path:match("^%a:/$") then + path = path:gsub("/$", "") + end + return path:gsub("^$", "/") end local function assert_dir(path) @@ -77,9 +83,18 @@ end ---@param name string ---@param type string function Tree:child(node, name, type) + -- skip empty segment from trailing slash (e.g. drive root "D:/") + if name == "" then + return node + end if not node.children[name] then - local path = node.path .. "/" .. name - path = node == self.root and name or path + -- strip trailing slash from parent so drive roots don't double up ("D://name") + local base = node.path:gsub("/$", "") + local path = base .. "/" .. name + -- drive-letter root ("D:") keeps its trailing slash, so scandir hits the root + if node == self.root then + path = name:match("^%a:$") and (name .. "/") or name + end node.children[name] = { name = name, path = path,