From b76602182f871faa3d51e297d34e25001e9e1e3e Mon Sep 17 00:00:00 2001 From: kiyan Date: Sun, 6 Feb 2022 18:51:17 +0100 Subject: [PATCH] refacto: simplify explorer and make it a bit faster Also fixes #933 --- lua/nvim-tree/explorer/explore.lua | 65 +++++++----------------- lua/nvim-tree/explorer/node-builders.lua | 9 ++-- lua/nvim-tree/explorer/reload.lua | 4 +- lua/nvim-tree/explorer/utils.lua | 20 -------- 4 files changed, 25 insertions(+), 73 deletions(-) diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index a035a1be..3a7a0d5a 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -1,5 +1,5 @@ local api = vim.api -local luv = vim.loop +local uv = vim.loop local utils = require'nvim-tree.utils' local eutils = require'nvim-tree.explorer.utils' @@ -8,72 +8,45 @@ local builders = require'nvim-tree.explorer.node-builders' local M = {} function M.explore(node, cwd, status) - local handle = luv.fs_scandir(cwd) + local handle = uv.fs_scandir(cwd) if type(handle) == 'string' then api.nvim_err_writeln(handle) return end - local dirs = {} - local links = {} - local files = {} + local node_ignored = node.git_status == '!!' while true do - local name, t = luv.fs_scandir_next(handle) + local name, t = uv.fs_scandir_next(handle) if not name then break end local abs = utils.path_join({cwd, name}) + t = t or (uv.fs_stat(abs) or {}).type if not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then - if not t then - local stat = luv.fs_stat(abs) - t = stat and stat.type - end - - if t == 'directory' then - table.insert(dirs, name) + if t == 'directory' and uv.fs_access(abs, 'R') then + table.insert(node.nodes, builders.folder(abs, name, status, node_ignored)) elseif t == 'file' then - table.insert(files, name) + table.insert(node.nodes, builders.file(abs, name, status, node_ignored)) elseif t == 'link' then - table.insert(links, name) + local link = builders.link(abs, name, status, node_ignored) + if link.link_to ~= nil then + table.insert(node.nodes, link) + end end end end - local node_ignored = node.git_status == '!!' - -- Group empty dirs if vim.g.nvim_tree_group_empty == 1 then - if eutils.should_group(cwd, dirs, files, links) then - local child_node - if dirs[1] then child_node = builders.folder(cwd, dirs[1], status, node_ignored) end - if links[1] then child_node = builders.link(cwd, links[1], status, node_ignored) end - if luv.fs_access(child_node.absolute_path, 'R') then - node.group_next = child_node - child_node.git_status = node.git_status - M.explore(child_node, child_node.absolute_path, status) - return - end + local child_node = node.nodes[1] + if #(node.nodes) == 1 and child_node.nodes and uv.fs_access(child_node.absolute_path, 'R') then + node.group_next = child_node + child_node.git_status = node.git_status + node.nodes = {} + M.explore(child_node, child_node.absolute_path, status) + return end end - for _, dirname in ipairs(dirs) do - local dir = builders.folder(cwd, dirname, status, node_ignored) - if luv.fs_access(dir.absolute_path, 'R') then - table.insert(node.nodes, dir) - end - end - - for _, linkname in ipairs(links) do - local link = builders.link(cwd, linkname, status, node_ignored) - if link.link_to ~= nil then - table.insert(node.nodes, link) - end - end - - for _, filename in ipairs(files) do - local file = builders.file(cwd, filename, status, node_ignored) - table.insert(node.nodes, file) - end - utils.merge_sort(node.nodes, eutils.node_comparator) end diff --git a/lua/nvim-tree/explorer/node-builders.lua b/lua/nvim-tree/explorer/node-builders.lua index 969aa5e2..a89f9877 100644 --- a/lua/nvim-tree/explorer/node-builders.lua +++ b/lua/nvim-tree/explorer/node-builders.lua @@ -14,8 +14,7 @@ local function get_dir_git_status(parent_ignored, status, absolute_path) return dir_status or file_status end -function M.folder(cwd, name, status, parent_ignored) - local absolute_path = utils.path_join({cwd, name}) +function M.folder(absolute_path, name, status, parent_ignored) local handle = uv.fs_scandir(absolute_path) local has_children = handle and uv.fs_scandir_next(handle) ~= nil @@ -37,8 +36,7 @@ local function is_executable(absolute_path, ext) return uv.fs_access(absolute_path, 'X') end -function M.file(cwd, name, status, parent_ignored) - local absolute_path = utils.path_join({cwd, name}) +function M.file(absolute_path, name, status, parent_ignored) local ext = string.match(name, ".?[^.]+%.(.*)") or "" return { @@ -55,9 +53,8 @@ end -- links (for instance libr2.so in /usr/lib) and thus even with a C program realpath fails -- when it has no real reason to. Maybe there is a reason, but errno is definitely wrong. -- So we need to check for link_to ~= nil when adding new links to the main tree -function M.link(cwd, name, status, parent_ignored) +function M.link(absolute_path, name, status, parent_ignored) --- I dont know if this is needed, because in my understanding, there isnt hard links in windows, but just to be sure i changed it. - local absolute_path = utils.path_join({ cwd, name }) local link_to = uv.fs_realpath(absolute_path) local stat = uv.fs_stat(absolute_path) local open, nodes diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index 6ed0abb8..5744426b 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -100,11 +100,13 @@ function M.reload(nodes, cwd, parent_node, status) local prev = nil local change_prev local new_nodes_added = false + local parent_ignored = parent_node.git_status == '!!' for _, e in ipairs(all) do for _, name in ipairs(e.nodes) do change_prev = true if not named_nodes[name] then - local n = e.fn(cwd, name, status) + local abs = utils.path_join({cwd, name}) + local n = e.fn(abs, name, status, parent_ignored) if e.check(n.link_to, n.absolute_path) then new_nodes_added = true idx = 1 diff --git a/lua/nvim-tree/explorer/utils.lua b/lua/nvim-tree/explorer/utils.lua index d3af7c45..d604517c 100644 --- a/lua/nvim-tree/explorer/utils.lua +++ b/lua/nvim-tree/explorer/utils.lua @@ -1,4 +1,3 @@ -local uv = vim.loop local utils = require'nvim-tree.utils' local M = { @@ -6,25 +5,6 @@ local M = { exclude_list = {}, } --- Returns true if there is either exactly 1 dir, or exactly 1 symlink dir. Otherwise, false. --- @param cwd Absolute path to the parent directory --- @param dirs List of dir names --- @param files List of file names --- @param links List of symlink names -function M.should_group(cwd, dirs, files, links) - if #dirs == 1 and #files == 0 and #links == 0 then - return true - end - - if #dirs == 0 and #files == 0 and #links == 1 then - local absolute_path = utils.path_join({ cwd, links[1] }) - local link_to = uv.fs_realpath(absolute_path) - return (link_to ~= nil) and uv.fs_stat(link_to).type == 'directory' - end - - return false -end - function M.node_comparator(a, b) if not (a and b) then return true