Revert "refactor(#2871, #2886): multi instance: node classes created (#2916)"

This reverts commit 38aac09151.
This commit is contained in:
Alexander Courtis
2024-10-08 18:07:47 +11:00
parent 010ae0365a
commit 50e919426a
43 changed files with 742 additions and 835 deletions

View File

@@ -1,15 +1,15 @@
local builders = require("nvim-tree.explorer.node-builders")
local git = require("nvim-tree.git")
local log = require("nvim-tree.log")
local notify = require("nvim-tree.notify")
local utils = require("nvim-tree.utils")
local view = require("nvim-tree.view")
local node_factory = require("nvim-tree.node.factory")
local RootNode = require("nvim-tree.node.root")
local Watcher = require("nvim-tree.watcher")
local watch = require("nvim-tree.explorer.watch")
local explorer_node = require("nvim-tree.explorer.node")
local Iterator = require("nvim-tree.iterators.node-iterator")
local NodeIterator = require("nvim-tree.iterators.node-iterator")
local Watcher = require("nvim-tree.watcher")
local Filters = require("nvim-tree.explorer.filters")
local Marks = require("nvim-tree.marks")
@@ -22,20 +22,23 @@ local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
local config
---@class (exact) Explorer: RootNode
---@class Explorer
---@field opts table user options
---@field absolute_path string
---@field nodes Node[]
---@field open boolean
---@field watcher Watcher|nil
---@field renderer Renderer
---@field filters Filters
---@field live_filter LiveFilter
---@field sorters Sorter
---@field marks Marks
---@field clipboard Clipboard
local Explorer = RootNode:new()
local Explorer = {}
---Static factory method
---@param path string?
---@return Explorer?
function Explorer:create(path)
---@param path string|nil
---@return Explorer|nil
function Explorer:new(path)
local err
if path then
@@ -45,22 +48,21 @@ function Explorer:create(path)
end
if not path then
notify.error(err)
return nil
return
end
---@type Explorer
local explorer_placeholder = nil
local o = {
opts = config,
absolute_path = path,
nodes = {},
open = true,
sorters = Sorters:new(config),
}
local o = RootNode:create(explorer_placeholder, path, "..", nil)
setmetatable(o, self)
self.__index = self
o = self:new(o) --[[@as Explorer]]
o.explorer = o
o.open = true
o.opts = config
o.sorters = Sorters:new(config)
o.watcher = watch.create_watcher(o)
o.renderer = Renderer:new(config, o)
o.filters = Filters:new(config, o)
o.live_filter = LiveFilter:new(config, o)
@@ -77,6 +79,18 @@ function Explorer:expand(node)
self:_load(node)
end
function Explorer:destroy()
local function iterate(node)
explorer_node.node_destroy(node)
if node.nodes then
for _, child in pairs(node.nodes) do
iterate(child)
end
end
end
iterate(self)
end
---@param node Node
---@param git_status table|nil
function Explorer:reload(node, git_status)
@@ -97,7 +111,7 @@ function Explorer:reload(node, git_status)
local remain_childs = {}
local node_ignored = node:is_git_ignored()
local node_ignored = explorer_node.is_git_ignored(node)
---@type table<string, Node>
local nodes_by_path = utils.key_by(node.nodes, "absolute_path")
@@ -124,19 +138,32 @@ function Explorer:reload(node, git_status)
if filter_reason == FILTER_REASON.none then
remain_childs[abs] = true
-- Type must come from fs_stat and not fs_scandir_next to maintain sshfs compatibility
local t = stat and stat.type or nil
-- Recreate node if type changes.
if nodes_by_path[abs] then
local n = nodes_by_path[abs]
if not stat or n.type ~= stat.type then
if n.type ~= t then
utils.array_remove(node.nodes, n)
n:destroy()
explorer_node.node_destroy(n)
nodes_by_path[abs] = nil
end
end
if not nodes_by_path[abs] then
local new_child = node_factory.create_node(self, node, abs, stat, name)
local new_child = nil
if t == "directory" and vim.loop.fs_access(abs, "R") and Watcher.is_fs_event_capable(abs) then
new_child = builders.folder(node, abs, name, stat)
elseif t == "file" then
new_child = builders.file(node, abs, name, stat)
elseif t == "link" then
local link = builders.link(node, abs, name, stat)
if link.link_to ~= nil then
new_child = link
end
end
if new_child then
table.insert(node.nodes, new_child)
nodes_by_path[abs] = new_child
@@ -144,7 +171,7 @@ function Explorer:reload(node, git_status)
else
local n = nodes_by_path[abs]
if n then
n.executable = utils.is_executable(abs) or false
n.executable = builders.is_executable(abs) or false
n.fs_stat = stat
end
end
@@ -163,14 +190,14 @@ function Explorer:reload(node, git_status)
if remain_childs[n.absolute_path] then
return remain_childs[n.absolute_path]
else
n:destroy()
explorer_node.node_destroy(n)
return false
end
end, node.nodes)
)
local is_root = not node.parent
local child_folder_only = node:has_one_child_folder() and node.nodes[1]
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
if config.renderer.group_empty and not is_root and child_folder_only then
node.group_next = child_folder_only
local ns = self:reload(child_folder_only, git_status)
@@ -185,6 +212,26 @@ function Explorer:reload(node, git_status)
return node.nodes
end
---TODO #2837 #2871 move this and similar to node
---Refresh contents and git status for a single node
---@param node Node
---@param callback function
function Explorer:refresh_node(node, callback)
if type(node) ~= "table" then
callback()
end
local parent_node = utils.get_parent_of_group(node)
self:reload_and_get_git_project(node.absolute_path, function(toplevel, project)
self:reload(parent_node, project)
self:update_parent_statuses(parent_node, project, toplevel)
callback()
end)
end
---Refresh contents of all nodes to a path: actual directory and links.
---Groups will be expanded if needed.
---@param path string absolute path
@@ -212,7 +259,7 @@ function Explorer:refresh_parent_nodes_for_path(path)
local project = git.get_project(toplevel) or {}
self:reload(node, project)
node:update_parent_statuses(project, toplevel)
self:update_parent_statuses(node, project, toplevel)
end
log.profile_end(profile)
@@ -227,19 +274,65 @@ function Explorer:_load(node)
end
---@private
---@param nodes_by_path Node[]
---@param nodes_by_path table
---@param node_ignored boolean
---@param status table|nil
---@return fun(node: Node): table
function Explorer:update_status(nodes_by_path, node_ignored, status)
return function(node)
if nodes_by_path[node.absolute_path] then
node:update_git_status(node_ignored, status)
explorer_node.update_git_status(node, node_ignored, status)
end
return node
end
end
---TODO #2837 #2871 move this and similar to node
---@private
---@param path string
---@param callback fun(toplevel: string|nil, project: table|nil)
function Explorer:reload_and_get_git_project(path, callback)
local toplevel = git.get_toplevel(path)
git.reload_project(toplevel, path, function()
callback(toplevel, git.get_project(toplevel) or {})
end)
end
---TODO #2837 #2871 move this and similar to node
---@private
---@param node Node
---@param project table|nil
---@param root string|nil
function Explorer:update_parent_statuses(node, project, root)
while project and node do
-- step up to the containing project
if node.absolute_path == root then
-- stop at the top of the tree
if not node.parent then
break
end
root = git.get_toplevel(node.parent.absolute_path)
-- stop when no more projects
if not root then
break
end
-- update the containing project
project = git.get_project(root)
git.reload_project(root, node.absolute_path, nil)
end
-- update status
explorer_node.update_git_status(node, explorer_node.is_git_ignored(node.parent), project)
-- maybe parent
node = node.parent
end
end
---@private
---@param handle uv.uv_fs_t
---@param cwd string
@@ -247,7 +340,7 @@ end
---@param git_status table
---@param parent Explorer
function Explorer:populate_children(handle, cwd, node, git_status, parent)
local node_ignored = node:is_git_ignored()
local node_ignored = explorer_node.is_git_ignored(node)
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
local filter_status = parent.filters:prepare(git_status)
@@ -275,11 +368,23 @@ function Explorer:populate_children(handle, cwd, node, git_status, parent)
local stat = vim.loop.fs_lstat(abs)
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] then
local child = node_factory.create_node(self, node, abs, stat, name)
-- Type must come from fs_stat and not fs_scandir_next to maintain sshfs compatibility
local t = stat and stat.type or nil
local child = nil
if t == "directory" and vim.loop.fs_access(abs, "R") then
child = builders.folder(node, abs, name, stat)
elseif t == "file" then
child = builders.file(node, abs, name, stat)
elseif t == "link" then
local link = builders.link(node, abs, name, stat)
if link.link_to ~= nil then
child = link
end
end
if child then
table.insert(node.nodes, child)
nodes_by_path[child.absolute_path] = true
child:update_git_status(node_ignored, git_status)
explorer_node.update_git_status(child, node_ignored, git_status)
end
else
for reason, value in pairs(FILTER_REASON) do
@@ -311,7 +416,7 @@ function Explorer:explore(node, status, parent)
self:populate_children(handle, cwd, node, status, parent)
local is_root = not node.parent
local child_folder_only = node:has_one_child_folder() and node.nodes[1]
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
if config.renderer.group_empty and not is_root and child_folder_only then
local child_cwd = child_folder_only.link_to or child_folder_only.absolute_path
local child_status = git.load_project_status(child_cwd)
@@ -368,13 +473,14 @@ function Explorer:reload_git()
event_running = true
local projects = git.reload()
self:reload_node_status(projects)
explorer_node.reload_node_status(self, projects)
self.renderer:draw()
event_running = false
end
function Explorer:setup(opts)
function Explorer.setup(opts)
config = opts
require("nvim-tree.explorer.node").setup(opts)
require("nvim-tree.explorer.watch").setup(opts)
end