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:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user