---@class NodeIterator local NodeIterator = {} NodeIterator.__index = NodeIterator ---@param nodes Node[] ---@return 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 ---@return NodeIterator function NodeIterator:hidden() self._filter_hidden = function(_) return true end return self end ---@param f fun(node: Node): boolean ---@return NodeIterator function NodeIterator:matcher(f) self._match = f return self end ---@param f fun(node: Node, i: number) ---@return NodeIterator function NodeIterator:applier(f) self._apply_fn_on_node = f return self end ---@param f fun(node: Node): any ---@return NodeIterator function NodeIterator:recursor(f) self._recurse_with = f return self end ---@return Node|nil ---@return number|nil function NodeIterator:iterate() local iteration_count = 0 local function iter(nodes) for _, node in ipairs(nodes) do if self._filter_hidden(node) then if not node.group_next then iteration_count = iteration_count + 1 end if self._match(node) then return node, iteration_count end self._apply_fn_on_node(node, iteration_count) local children = self._recurse_with(node) if children then local n = iter(children) if n then return n, iteration_count end end end end return nil, 0 end return iter(self.nodes) end return NodeIterator