Skip to content

Commit e1c3744

Browse files
committed
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.
1 parent 7fec0f6 commit e1c3744

File tree

1 file changed

+37
-105
lines changed

1 file changed

+37
-105
lines changed

lua/nvim-tree/explorer/reload.lua

Lines changed: 37 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,74 @@
11
local api = vim.api
2-
local luv = vim.loop
2+
local uv = vim.loop
33

44
local utils = require'nvim-tree.utils'
55
local eutils = require'nvim-tree.explorer.utils'
66
local builders = require'nvim-tree.explorer.node-builders'
77

88
local M = {}
99

10+
local function key_by(nodes, key)
11+
local v = {}
12+
for _, node in ipairs(nodes) do
13+
v[node[key]] = node
14+
end
15+
return v
16+
end
17+
1018
function M.reload(node, cwd, status)
11-
local handle = luv.fs_scandir(cwd)
19+
local handle = uv.fs_scandir(cwd)
1220
if type(handle) == 'string' then
1321
api.nvim_err_writeln(handle)
1422
return
1523
end
1624

17-
local named_nodes = {}
18-
local cached_nodes = {}
19-
local nodes_idx = {}
20-
for i, child in ipairs(node.nodes) do
21-
child.git_status = (node and node.git_status == '!!' and '!!')
22-
or (status.files and status.files[child.absolute_path])
23-
or (status.dirs and status.dirs[child.absolute_path])
24-
cached_nodes[i] = child.name
25-
nodes_idx[child.name] = i
26-
named_nodes[child.name] = child
25+
if node.group_next then
26+
node.group_next = nil
27+
node.nodes = {}
2728
end
2829

29-
local dirs = {}
30-
local links = {}
31-
local files = {}
32-
local new_nodes = {}
33-
local num_new_nodes = 0
30+
local child_names = {}
3431

32+
local node_ignored = node.git_status == '!!'
33+
local nodes_by_path = key_by(node.nodes, "absolute_path")
3534
while true do
36-
local name, t = luv.fs_scandir_next(handle)
35+
local name, t = uv.fs_scandir_next(handle)
3736
if not name then break end
38-
num_new_nodes = num_new_nodes + 1
3937

4038
local abs = utils.path_join({cwd, name})
41-
if not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then
42-
if not t then
43-
local stat = luv.fs_stat(abs)
44-
t = stat and stat.type
45-
end
46-
47-
if t == 'directory' then
48-
table.insert(dirs, name)
49-
new_nodes[name] = true
39+
t = t or (uv.fs_stat(abs) or {}).type
40+
child_names[abs] = true
41+
if not nodes_by_path[abs] and not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then
42+
if t == 'directory' and uv.fs_access(abs, 'R') then
43+
table.insert(node.nodes, builders.folder(abs, name, status, node_ignored))
5044
elseif t == 'file' then
51-
table.insert(files, name)
52-
new_nodes[name] = true
45+
table.insert(node.nodes, builders.file(abs, name, status, node_ignored))
5346
elseif t == 'link' then
54-
table.insert(links, name)
55-
new_nodes[name] = true
47+
local link = builders.link(abs, name, status, node_ignored)
48+
if link.link_to ~= nil then
49+
table.insert(node.nodes, link)
50+
end
5651
end
5752
end
5853
end
5954

60-
-- Handle grouped dirs
61-
local child_node = node.group_next
62-
if child_node then
63-
child_node.open = true
64-
if num_new_nodes ~= 1 or not new_nodes[child_node.name] then
65-
-- dir is no longer only containing a group dir, or group dir has been removed
66-
-- either way: sever the group link on current dir
67-
node.nodes = node.group_next
68-
node.group_next = nil
69-
named_nodes[child_node.name] = child_node
70-
else
55+
for i, n in ipairs(node.nodes) do
56+
if not child_names[n.absolute_path] then
57+
table.remove(node.nodes, i)
58+
end
59+
end
60+
61+
if vim.g.nvim_tree_group_empty == 1 then
62+
local child_node = node.nodes[1]
63+
if #(node.nodes) == 1 and child_node.nodes and uv.fs_access(child_node.absolute_path, 'R') then
7164
node.group_next = child_node
7265
local ns = M.reload(child_node, child_node.absolute_path, status)
7366
node.nodes = ns or {}
7467
return ns
7568
end
7669
end
7770

78-
local idx = 1
79-
for _, name in ipairs(cached_nodes) do
80-
local named_node = named_nodes[name]
81-
if named_node and named_node.link_to then
82-
-- If the link has been modified: remove it in case the link target has changed.
83-
local stat = luv.fs_stat(node.absolute_path)
84-
if stat and named_node.last_modified ~= stat.mtime.sec then
85-
new_nodes[name] = nil
86-
named_nodes[name] = nil
87-
end
88-
end
89-
90-
if not new_nodes[name] then
91-
table.remove(node.nodes, idx)
92-
else
93-
idx = idx + 1
94-
end
95-
end
96-
97-
local all = {
98-
{ nodes = dirs, fn = builders.folder, check = function(_, abs) return luv.fs_access(abs, 'R') end },
99-
{ nodes = links, fn = builders.link, check = function(name) return name ~= nil end },
100-
{ nodes = files, fn = builders.file, check = function() return true end }
101-
}
102-
103-
local prev = nil
104-
local change_prev
105-
local new_nodes_added = false
106-
local parent_ignored = node.git_status == '!!'
107-
for _, e in ipairs(all) do
108-
for _, name in ipairs(e.nodes) do
109-
change_prev = true
110-
if not named_nodes[name] then
111-
local abs = utils.path_join({cwd, name})
112-
local n = e.fn(abs, name, status, parent_ignored)
113-
if e.check(n.link_to, n.absolute_path) then
114-
new_nodes_added = true
115-
idx = 1
116-
if prev then
117-
idx = nodes_idx[prev] + 1
118-
end
119-
table.insert(node.nodes, idx, n)
120-
nodes_idx[name] = idx
121-
cached_nodes[idx] = name
122-
else
123-
change_prev = false
124-
end
125-
end
126-
if change_prev and not (child_node and child_node.name == name) then
127-
prev = name
128-
end
129-
end
130-
end
131-
132-
if child_node then
133-
table.insert(node.nodes, 1, child_node)
134-
end
135-
136-
if new_nodes_added then
137-
utils.merge_sort(node.nodes, eutils.node_comparator)
138-
end
139-
71+
utils.merge_sort(node.nodes, eutils.node_comparator)
14072
return node.nodes
14173
end
14274

0 commit comments

Comments
 (0)