Skip to content

Commit 10aa799

Browse files
committed
chore(iterators): create Iterator module and migrate iterators to use it
1 parent 28c4bb0 commit 10aa799

File tree

7 files changed

+179
-156
lines changed

7 files changed

+179
-156
lines changed

lua/nvim-tree/actions/collapse-all.lua

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local renderer = require "nvim-tree.renderer"
22
local utils = require "nvim-tree.utils"
33
local core = require "nvim-tree.core"
4+
local Iterator = require "nvim-tree.iterators.node-iterator"
45

56
local M = {}
67

@@ -9,34 +10,29 @@ function M.fn(keep_buffers)
910
return
1011
end
1112

12-
local buffer_paths = {}
13-
for _, buffer in ipairs(vim.api.nvim_list_bufs()) do
14-
table.insert(buffer_paths, vim.api.nvim_buf_get_name(buffer))
15-
end
16-
17-
local function iter(nodes)
18-
for _, node in pairs(nodes) do
19-
if node.open then
20-
local new_open = false
21-
22-
if keep_buffers == true then
23-
for _, buffer_path in ipairs(buffer_paths) do
24-
local matches = utils.str_find(buffer_path, node.absolute_path)
25-
if matches then
26-
new_open = true
27-
end
13+
local buffer_paths = vim.tbl_map(function(buffer)
14+
return vim.api.nvim_buf_get_name(buffer)
15+
end, vim.api.nvim_list_bufs())
16+
17+
Iterator.builder(core.get_explorer().nodes)
18+
:hidden()
19+
:applier(function(node)
20+
node.open = false
21+
if keep_buffers == true then
22+
for _, buffer_path in ipairs(buffer_paths) do
23+
local matches = utils.str_find(buffer_path, node.absolute_path)
24+
if matches then
25+
node.open = true
26+
return
2827
end
2928
end
30-
31-
node.open = new_open
32-
end
33-
if node.nodes then
34-
iter(node.nodes)
3529
end
36-
end
37-
end
30+
end)
31+
:recursor(function(n)
32+
return n.nodes
33+
end)
34+
:iterate()
3835

39-
iter(core.get_explorer().nodes)
4036
renderer.draw()
4137
end
4238

lua/nvim-tree/actions/expand-all.lua

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local core = require "nvim-tree.core"
22
local renderer = require "nvim-tree.renderer"
33
local utils = require "nvim-tree.utils"
4+
local Iterator = require "nvim-tree.iterators.node-iterator"
45

56
local M = {}
67

@@ -20,34 +21,38 @@ local function expand(node)
2021
end
2122
end
2223

24+
local function should_expand(expansion_count, node)
25+
local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY
26+
local should_exclude = M.EXCLUDE[node.name]
27+
return not should_halt and node.nodes and not node.open and not should_exclude
28+
end
29+
2330
local function gen_iterator()
2431
local expansion_count = 0
2532

26-
local function iterate(parent)
27-
if expansion_count >= M.MAX_FOLDER_DISCOVERY then
28-
return true
29-
end
30-
33+
return function(parent)
3134
if parent.parent and parent.nodes and not parent.open then
3235
expansion_count = expansion_count + 1
3336
expand(parent)
3437
end
3538

36-
for _, node in pairs(parent.nodes) do
37-
if node.nodes and not node.open and not M.EXCLUDE[node.name] then
38-
expansion_count = expansion_count + 1
39-
expand(node)
40-
end
41-
42-
if node.open then
43-
if iterate(node) then
44-
return true
39+
Iterator.builder(parent.nodes)
40+
:hidden()
41+
:applier(function(node)
42+
if should_expand(expansion_count, node) then
43+
expansion_count = expansion_count + 1
44+
expand(node)
4545
end
46-
end
46+
end)
47+
:recursor(function(node)
48+
return expansion_count < M.MAX_FOLDER_DISCOVERY and node.open and node.nodes
49+
end)
50+
:iterate()
51+
52+
if expansion_count >= M.MAX_FOLDER_DISCOVERY then
53+
return true
4754
end
4855
end
49-
50-
return iterate
5156
end
5257

5358
function M.fn(base_node)

lua/nvim-tree/actions/find-file.lua

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local view = require "nvim-tree.view"
44
local utils = require "nvim-tree.utils"
55
local renderer = require "nvim-tree.renderer"
66
local core = require "nvim-tree.core"
7+
local Iterator = require "nvim-tree.iterators.node-iterator"
78

89
local M = {}
910

@@ -24,53 +25,31 @@ function M.fn(fname)
2425
return
2526
end
2627

27-
local i = core.get_nodes_starting_line() - 1
28-
local tree_altered = false
29-
30-
local function iterate_nodes(nodes)
31-
for _, node in ipairs(nodes) do
32-
if not node.hidden then
33-
i = i + 1
34-
35-
if not node.absolute_path or not uv.fs_stat(node.absolute_path) then
36-
break
37-
end
38-
39-
-- match against node absolute and link, as symlinks themselves will differ
40-
if node.absolute_path == fname_real or node.link_to == fname_real then
41-
return i
42-
end
43-
local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator)
44-
local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator)
45-
local path_matches = node.nodes and (abs_match or link_match)
46-
if path_matches then
47-
if not node.open then
48-
node.open = true
49-
tree_altered = true
50-
end
51-
52-
if #node.nodes == 0 then
53-
core.get_explorer():expand(node)
54-
end
55-
56-
if iterate_nodes(node.nodes) ~= nil then
57-
return i
58-
end
59-
-- mandatory to iterate i
60-
elseif node.open then
61-
iterate_nodes(node.nodes)
28+
local line = core.get_nodes_starting_line()
29+
30+
local found = Iterator.builder(core.get_explorer().nodes)
31+
:matcher(function(node)
32+
return node.absolute_path == fname_real or node.link_to == fname_real
33+
end)
34+
:applier(function(node)
35+
line = line + 1
36+
local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator)
37+
local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator)
38+
39+
if abs_match or link_match then
40+
node.open = true
41+
if #node.nodes == 0 then
42+
core.get_explorer():expand(node)
6243
end
6344
end
64-
end
65-
end
45+
end)
46+
:iterate()
6647

67-
local index = iterate_nodes(core.get_explorer().nodes)
68-
if tree_altered then
48+
if found and view.is_visible() then
6949
renderer.draw()
50+
view.set_cursor { line, 0 }
7051
end
71-
if index and view.is_visible() then
72-
view.set_cursor { index, 0 }
73-
end
52+
7453
running[fname] = false
7554

7655
log.profile_end(ps, "find file %s", fname)

lua/nvim-tree/git/init.lua

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local utils = require "nvim-tree.utils"
33
local git_utils = require "nvim-tree.git.utils"
44
local Runner = require "nvim-tree.git.runner"
55
local Watcher = require("nvim-tree.watcher").Watcher
6+
local Iterator = require "nvim-tree.iterators.node-iterator"
67

78
local M = {
89
config = {},
@@ -84,21 +85,19 @@ local function reload_tree_at(project_root)
8485
local project_files = project.files and project.files or {}
8586
local project_dirs = project.dirs and project.dirs or {}
8687

87-
local function iterate(n)
88-
local parent_ignored = n.git_status == "!!"
89-
for _, node in pairs(n.nodes) do
88+
Iterator.builder(root_node.nodes)
89+
:hidden()
90+
:applier(function(node)
91+
local parent_ignored = node.parent.git_status == "!!"
9092
node.git_status = project_dirs[node.absolute_path] or project_files[node.absolute_path]
9193
if not node.git_status and parent_ignored then
9294
node.git_status = "!!"
9395
end
94-
95-
if node.nodes and #node.nodes > 0 then
96-
iterate(node)
97-
end
98-
end
99-
end
100-
101-
iterate(root_node)
96+
end)
97+
:recursor(function(node)
98+
return node.nodes and #node.nodes > 0 and node.nodes
99+
end)
100+
:iterate()
102101

103102
require("nvim-tree.renderer").draw()
104103
end
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
local NodeIterator = {}
2+
NodeIterator.__index = NodeIterator
3+
4+
function NodeIterator.builder(nodes)
5+
return setmetatable({
6+
nodes = nodes,
7+
_filter_hidden = function(node)
8+
return not node.hidden
9+
end,
10+
_apply_fn_on_node = function(_) end,
11+
_match = function(_) end,
12+
_recurse_with = function(node)
13+
return node.nodes
14+
end,
15+
}, NodeIterator)
16+
end
17+
18+
function NodeIterator:hidden()
19+
self._filter_hidden = function(_)
20+
return true
21+
end
22+
return self
23+
end
24+
25+
function NodeIterator:matcher(f)
26+
self._match = f
27+
return self
28+
end
29+
30+
function NodeIterator:applier(f)
31+
self._apply_fn_on_node = f
32+
return self
33+
end
34+
35+
function NodeIterator:recursor(f)
36+
self._recurse_with = f
37+
return self
38+
end
39+
40+
function NodeIterator:iterate()
41+
local function iter(nodes)
42+
local i = 1
43+
for _, node in ipairs(nodes) do
44+
if self._filter_hidden(node) then
45+
if self._match(node) then
46+
return node, i
47+
end
48+
self._apply_fn_on_node(node)
49+
local children = self._recurse_with(node)
50+
if children then
51+
local n, idx = iter(children)
52+
i = i + idx
53+
if n then
54+
return n, i
55+
else
56+
i = i + 1
57+
end
58+
end
59+
end
60+
end
61+
return nil, i
62+
end
63+
64+
return iter(self.nodes)
65+
end
66+
67+
return NodeIterator

lua/nvim-tree/live-filter.lua

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local a = vim.api
22

33
local view = require "nvim-tree.view"
4+
local Iterator = require "nvim-tree.iterators.node-iterator"
45

56
local M = {
67
filter = nil,
@@ -11,15 +12,13 @@ local function redraw()
1112
end
1213

1314
local function reset_filter(node_)
14-
local function iterate(n)
15-
n.hidden = false
16-
if n.nodes then
17-
for _, node in pairs(n.nodes) do
18-
iterate(node)
19-
end
20-
end
21-
end
22-
iterate(node_ or TreeExplorer)
15+
node_ = node_ or TreeExplorer
16+
Iterator.builder(node_.nodes)
17+
:hidden()
18+
:applier(function(node)
19+
node.hidden = false
20+
end)
21+
:iterate()
2322
end
2423

2524
local overlay_bufnr = nil
@@ -47,6 +46,8 @@ function M.apply_filter(node_)
4746
return
4847
end
4948

49+
-- TODO(kiyan): this iterator cannot yet be refactored with the Iterator module
50+
-- since the node mapper is based on its children
5051
local function iterate(node)
5152
local filtered_nodes = 0
5253
local nodes = node.group_next and { node.group_next } or node.nodes

0 commit comments

Comments
 (0)