refacto: rewrite reloader

next step needs to merge the reloader and the explorer, the ancient code
was super complicated and long and the new one is very similar to the explorer.
This commit is contained in:
kiyan
2022-02-06 23:18:12 +01:00
parent 7fec0f658b
commit e1c3744631

View File

@@ -1,5 +1,5 @@
local api = vim.api local api = vim.api
local luv = vim.loop local uv = vim.loop
local utils = require'nvim-tree.utils' local utils = require'nvim-tree.utils'
local eutils = require'nvim-tree.explorer.utils' local eutils = require'nvim-tree.explorer.utils'
@@ -7,67 +7,60 @@ local builders = require'nvim-tree.explorer.node-builders'
local M = {} local M = {}
local function key_by(nodes, key)
local v = {}
for _, node in ipairs(nodes) do
v[node[key]] = node
end
return v
end
function M.reload(node, cwd, status) function M.reload(node, cwd, status)
local handle = luv.fs_scandir(cwd) local handle = uv.fs_scandir(cwd)
if type(handle) == 'string' then if type(handle) == 'string' then
api.nvim_err_writeln(handle) api.nvim_err_writeln(handle)
return return
end end
local named_nodes = {} if node.group_next then
local cached_nodes = {} node.group_next = nil
local nodes_idx = {} node.nodes = {}
for i, child in ipairs(node.nodes) do
child.git_status = (node and node.git_status == '!!' and '!!')
or (status.files and status.files[child.absolute_path])
or (status.dirs and status.dirs[child.absolute_path])
cached_nodes[i] = child.name
nodes_idx[child.name] = i
named_nodes[child.name] = child
end end
local dirs = {} local child_names = {}
local links = {}
local files = {}
local new_nodes = {}
local num_new_nodes = 0
local node_ignored = node.git_status == '!!'
local nodes_by_path = key_by(node.nodes, "absolute_path")
while true do 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 if not name then break end
num_new_nodes = num_new_nodes + 1
local abs = utils.path_join({cwd, name}) local abs = utils.path_join({cwd, name})
if not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then t = t or (uv.fs_stat(abs) or {}).type
if not t then child_names[abs] = true
local stat = luv.fs_stat(abs) if not nodes_by_path[abs] and not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then
t = stat and stat.type if t == 'directory' and uv.fs_access(abs, 'R') then
end table.insert(node.nodes, builders.folder(abs, name, status, node_ignored))
if t == 'directory' then
table.insert(dirs, name)
new_nodes[name] = true
elseif t == 'file' then elseif t == 'file' then
table.insert(files, name) table.insert(node.nodes, builders.file(abs, name, status, node_ignored))
new_nodes[name] = true
elseif t == 'link' then elseif t == 'link' then
table.insert(links, name) local link = builders.link(abs, name, status, node_ignored)
new_nodes[name] = true if link.link_to ~= nil then
table.insert(node.nodes, link)
end
end end
end end
end end
-- Handle grouped dirs for i, n in ipairs(node.nodes) do
local child_node = node.group_next if not child_names[n.absolute_path] then
if child_node then table.remove(node.nodes, i)
child_node.open = true end
if num_new_nodes ~= 1 or not new_nodes[child_node.name] then end
-- dir is no longer only containing a group dir, or group dir has been removed
-- either way: sever the group link on current dir if vim.g.nvim_tree_group_empty == 1 then
node.nodes = node.group_next local child_node = node.nodes[1]
node.group_next = nil if #(node.nodes) == 1 and child_node.nodes and uv.fs_access(child_node.absolute_path, 'R') then
named_nodes[child_node.name] = child_node
else
node.group_next = child_node node.group_next = child_node
local ns = M.reload(child_node, child_node.absolute_path, status) local ns = M.reload(child_node, child_node.absolute_path, status)
node.nodes = ns or {} node.nodes = ns or {}
@@ -75,68 +68,7 @@ function M.reload(node, cwd, status)
end end
end end
local idx = 1
for _, name in ipairs(cached_nodes) do
local named_node = named_nodes[name]
if named_node and named_node.link_to then
-- If the link has been modified: remove it in case the link target has changed.
local stat = luv.fs_stat(node.absolute_path)
if stat and named_node.last_modified ~= stat.mtime.sec then
new_nodes[name] = nil
named_nodes[name] = nil
end
end
if not new_nodes[name] then
table.remove(node.nodes, idx)
else
idx = idx + 1
end
end
local all = {
{ nodes = dirs, fn = builders.folder, check = function(_, abs) return luv.fs_access(abs, 'R') end },
{ nodes = links, fn = builders.link, check = function(name) return name ~= nil end },
{ nodes = files, fn = builders.file, check = function() return true end }
}
local prev = nil
local change_prev
local new_nodes_added = false
local parent_ignored = 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 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
if prev then
idx = nodes_idx[prev] + 1
end
table.insert(node.nodes, idx, n)
nodes_idx[name] = idx
cached_nodes[idx] = name
else
change_prev = false
end
end
if change_prev and not (child_node and child_node.name == name) then
prev = name
end
end
end
if child_node then
table.insert(node.nodes, 1, child_node)
end
if new_nodes_added then
utils.merge_sort(node.nodes, eutils.node_comparator) utils.merge_sort(node.nodes, eutils.node_comparator)
end
return node.nodes return node.nodes
end end