Skip to content

chore(iterators): create Iterator module and migrate iterators to use it #1392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 20 additions & 24 deletions lua/nvim-tree/actions/collapse-all.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local renderer = require "nvim-tree.renderer"
local utils = require "nvim-tree.utils"
local core = require "nvim-tree.core"
local Iterator = require "nvim-tree.iterators.node-iterator"

local M = {}

Expand All @@ -9,34 +10,29 @@ function M.fn(keep_buffers)
return
end

local buffer_paths = {}
for _, buffer in ipairs(vim.api.nvim_list_bufs()) do
table.insert(buffer_paths, vim.api.nvim_buf_get_name(buffer))
end

local function iter(nodes)
for _, node in pairs(nodes) do
if node.open then
local new_open = false

if keep_buffers == true then
for _, buffer_path in ipairs(buffer_paths) do
local matches = utils.str_find(buffer_path, node.absolute_path)
if matches then
new_open = true
end
local buffer_paths = vim.tbl_map(function(buffer)
return vim.api.nvim_buf_get_name(buffer)
end, vim.api.nvim_list_bufs())

Iterator.builder(core.get_explorer().nodes)
:hidden()
:applier(function(node)
node.open = false
if keep_buffers == true then
for _, buffer_path in ipairs(buffer_paths) do
local matches = utils.str_find(buffer_path, node.absolute_path)
if matches then
node.open = true
return
end
end

node.open = new_open
end
if node.nodes then
iter(node.nodes)
end
end
end
end)
:recursor(function(n)
return n.nodes
end)
:iterate()

iter(core.get_explorer().nodes)
renderer.draw()
end

Expand Down
39 changes: 22 additions & 17 deletions lua/nvim-tree/actions/expand-all.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local core = require "nvim-tree.core"
local renderer = require "nvim-tree.renderer"
local utils = require "nvim-tree.utils"
local Iterator = require "nvim-tree.iterators.node-iterator"

local M = {}

Expand All @@ -20,34 +21,38 @@ local function expand(node)
end
end

local function should_expand(expansion_count, node)
local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY
local should_exclude = M.EXCLUDE[node.name]
return not should_halt and node.nodes and not node.open and not should_exclude
end

local function gen_iterator()
local expansion_count = 0

local function iterate(parent)
if expansion_count >= M.MAX_FOLDER_DISCOVERY then
return true
end

return function(parent)
if parent.parent and parent.nodes and not parent.open then
expansion_count = expansion_count + 1
expand(parent)
end

for _, node in pairs(parent.nodes) do
if node.nodes and not node.open and not M.EXCLUDE[node.name] then
expansion_count = expansion_count + 1
expand(node)
end

if node.open then
if iterate(node) then
return true
Iterator.builder(parent.nodes)
:hidden()
:applier(function(node)
if should_expand(expansion_count, node) then
expansion_count = expansion_count + 1
expand(node)
end
end
end)
:recursor(function(node)
return expansion_count < M.MAX_FOLDER_DISCOVERY and node.open and node.nodes
end)
:iterate()

if expansion_count >= M.MAX_FOLDER_DISCOVERY then
return true
end
end

return iterate
end

function M.fn(base_node)
Expand Down
63 changes: 21 additions & 42 deletions lua/nvim-tree/actions/find-file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ local view = require "nvim-tree.view"
local utils = require "nvim-tree.utils"
local renderer = require "nvim-tree.renderer"
local core = require "nvim-tree.core"
local Iterator = require "nvim-tree.iterators.node-iterator"

local M = {}

Expand All @@ -24,53 +25,31 @@ function M.fn(fname)
return
end

local i = core.get_nodes_starting_line() - 1
local tree_altered = false

local function iterate_nodes(nodes)
for _, node in ipairs(nodes) do
if not node.hidden then
i = i + 1

if not node.absolute_path or not uv.fs_stat(node.absolute_path) then
break
end

-- match against node absolute and link, as symlinks themselves will differ
if node.absolute_path == fname_real or node.link_to == fname_real then
return i
end
local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator)
local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator)
local path_matches = node.nodes and (abs_match or link_match)
if path_matches then
if not node.open then
node.open = true
tree_altered = true
end

if #node.nodes == 0 then
core.get_explorer():expand(node)
end

if iterate_nodes(node.nodes) ~= nil then
return i
end
-- mandatory to iterate i
elseif node.open then
iterate_nodes(node.nodes)
local line = core.get_nodes_starting_line()

local found = Iterator.builder(core.get_explorer().nodes)
:matcher(function(node)
return node.absolute_path == fname_real or node.link_to == fname_real
end)
:applier(function(node)
line = line + 1
local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator)
local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator)

if abs_match or link_match then
node.open = true
if #node.nodes == 0 then
core.get_explorer():expand(node)
end
end
end
end
end)
:iterate()

local index = iterate_nodes(core.get_explorer().nodes)
if tree_altered then
if found and view.is_visible() then
renderer.draw()
view.set_cursor { line, 0 }
end
if index and view.is_visible() then
view.set_cursor { index, 0 }
end

running[fname] = false

log.profile_end(ps, "find file %s", fname)
Expand Down
21 changes: 10 additions & 11 deletions lua/nvim-tree/git/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local utils = require "nvim-tree.utils"
local git_utils = require "nvim-tree.git.utils"
local Runner = require "nvim-tree.git.runner"
local Watcher = require("nvim-tree.watcher").Watcher
local Iterator = require "nvim-tree.iterators.node-iterator"

local M = {
config = {},
Expand Down Expand Up @@ -84,21 +85,19 @@ local function reload_tree_at(project_root)
local project_files = project.files and project.files or {}
local project_dirs = project.dirs and project.dirs or {}

local function iterate(n)
local parent_ignored = n.git_status == "!!"
for _, node in pairs(n.nodes) do
Iterator.builder(root_node.nodes)
:hidden()
:applier(function(node)
local parent_ignored = node.parent.git_status == "!!"
node.git_status = project_dirs[node.absolute_path] or project_files[node.absolute_path]
if not node.git_status and parent_ignored then
node.git_status = "!!"
end

if node.nodes and #node.nodes > 0 then
iterate(node)
end
end
end

iterate(root_node)
end)
:recursor(function(node)
return node.nodes and #node.nodes > 0 and node.nodes
end)
:iterate()

require("nvim-tree.renderer").draw()
end
Expand Down
67 changes: 67 additions & 0 deletions lua/nvim-tree/iterators/node-iterator.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
local NodeIterator = {}
NodeIterator.__index = NodeIterator

function NodeIterator.builder(nodes)
return setmetatable({
nodes = nodes,
_filter_hidden = function(node)
return not node.hidden
end,
_apply_fn_on_node = function(_) end,
_match = function(_) end,
_recurse_with = function(node)
return node.nodes
end,
}, NodeIterator)
end

function NodeIterator:hidden()
self._filter_hidden = function(_)
return true
end
return self
end

function NodeIterator:matcher(f)
self._match = f
return self
end

function NodeIterator:applier(f)
self._apply_fn_on_node = f
return self
end

function NodeIterator:recursor(f)
self._recurse_with = f
return self
end

function NodeIterator:iterate()
local function iter(nodes)
local i = 1
for _, node in ipairs(nodes) do
if self._filter_hidden(node) then
if self._match(node) then
return node, i
end
self._apply_fn_on_node(node)
local children = self._recurse_with(node)
if children then
local n, idx = iter(children)
i = i + idx
if n then
return n, i
else
i = i + 1
end
end
end
end
return nil, i
end

return iter(self.nodes)
end

return NodeIterator
19 changes: 10 additions & 9 deletions lua/nvim-tree/live-filter.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local a = vim.api

local view = require "nvim-tree.view"
local Iterator = require "nvim-tree.iterators.node-iterator"

local M = {
filter = nil,
Expand All @@ -11,15 +12,13 @@ local function redraw()
end

local function reset_filter(node_)
local function iterate(n)
n.hidden = false
if n.nodes then
for _, node in pairs(n.nodes) do
iterate(node)
end
end
end
iterate(node_ or TreeExplorer)
node_ = node_ or TreeExplorer
Iterator.builder(node_.nodes)
:hidden()
:applier(function(node)
node.hidden = false
end)
:iterate()
end

local overlay_bufnr = nil
Expand Down Expand Up @@ -47,6 +46,8 @@ function M.apply_filter(node_)
return
end

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