|
1 | 1 | local api = vim.api
|
2 |
| -local luv = vim.loop |
| 2 | +local uv = vim.loop |
3 | 3 |
|
4 | 4 | local utils = require'nvim-tree.utils'
|
5 | 5 | local eutils = require'nvim-tree.explorer.utils'
|
6 | 6 | local builders = require'nvim-tree.explorer.node-builders'
|
7 | 7 |
|
8 | 8 | local M = {}
|
9 | 9 |
|
| 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 | + |
10 | 18 | function M.reload(node, cwd, status)
|
11 |
| - local handle = luv.fs_scandir(cwd) |
| 19 | + local handle = uv.fs_scandir(cwd) |
12 | 20 | if type(handle) == 'string' then
|
13 | 21 | api.nvim_err_writeln(handle)
|
14 | 22 | return
|
15 | 23 | end
|
16 | 24 |
|
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 = {} |
27 | 28 | end
|
28 | 29 |
|
29 |
| - local dirs = {} |
30 |
| - local links = {} |
31 |
| - local files = {} |
32 |
| - local new_nodes = {} |
33 |
| - local num_new_nodes = 0 |
| 30 | + local child_names = {} |
34 | 31 |
|
| 32 | + local node_ignored = node.git_status == '!!' |
| 33 | + local nodes_by_path = key_by(node.nodes, "absolute_path") |
35 | 34 | while true do
|
36 |
| - local name, t = luv.fs_scandir_next(handle) |
| 35 | + local name, t = uv.fs_scandir_next(handle) |
37 | 36 | if not name then break end
|
38 |
| - num_new_nodes = num_new_nodes + 1 |
39 | 37 |
|
40 | 38 | 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)) |
50 | 44 | 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)) |
53 | 46 | 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 |
56 | 51 | end
|
57 | 52 | end
|
58 | 53 | end
|
59 | 54 |
|
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 |
71 | 64 | node.group_next = child_node
|
72 | 65 | local ns = M.reload(child_node, child_node.absolute_path, status)
|
73 | 66 | node.nodes = ns or {}
|
74 | 67 | return ns
|
75 | 68 | end
|
76 | 69 | end
|
77 | 70 |
|
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) |
140 | 72 | return node.nodes
|
141 | 73 | end
|
142 | 74 |
|
|
0 commit comments