|
| 1 | +local git = require("nvim-tree.git") |
1 | 2 | local watch = require("nvim-tree.explorer.watch") |
2 | 3 |
|
3 | 4 | local BaseNode = require("nvim-tree.node") |
@@ -58,6 +59,118 @@ function DirectoryNode:destroy() |
58 | 59 | end |
59 | 60 | end |
60 | 61 |
|
| 62 | +---@return boolean |
| 63 | +function DirectoryNode:has_one_child_folder() |
| 64 | + return #self.nodes == 1 and self.nodes[1].nodes and vim.loop.fs_access(self.nodes[1].absolute_path, "R") or false |
| 65 | +end |
| 66 | + |
| 67 | +-- If node is grouped, return the last node in the group. Otherwise, return the given node. |
| 68 | +---@return Node |
| 69 | +function DirectoryNode:last_group_node() |
| 70 | + local node = self --[[@as BaseNode]] |
| 71 | + |
| 72 | + while node.group_next do |
| 73 | + node = node.group_next |
| 74 | + end |
| 75 | + |
| 76 | + return node |
| 77 | +end |
| 78 | + |
| 79 | +---Group empty folders |
| 80 | +-- Recursively group nodes |
| 81 | +---@return Node[] |
| 82 | +function DirectoryNode:group_empty_folders() |
| 83 | + local is_root = not self.parent |
| 84 | + local child_folder_only = self:has_one_child_folder() and self.nodes[1] |
| 85 | + if self.explorer.opts.renderer.group_empty and not is_root and child_folder_only then |
| 86 | + self.group_next = child_folder_only |
| 87 | + local ns = child_folder_only:group_empty_folders() |
| 88 | + self.nodes = ns or {} |
| 89 | + return ns |
| 90 | + end |
| 91 | + return self.nodes |
| 92 | +end |
| 93 | + |
| 94 | +---Ungroup empty folders |
| 95 | +-- If a node is grouped, ungroup it: put node.group_next to the node.nodes and set node.group_next to nil |
| 96 | +function DirectoryNode:ungroup_empty_folders() |
| 97 | + local cur = self |
| 98 | + while cur and cur.group_next do |
| 99 | + cur.nodes = { cur.group_next } |
| 100 | + cur.group_next = nil |
| 101 | + cur = cur.nodes[1] |
| 102 | + end |
| 103 | +end |
| 104 | + |
| 105 | +---Update the GitStatus of absolute path of the directory |
| 106 | +---@param parent_ignored boolean |
| 107 | +---@param status table|nil |
| 108 | +function DirectoryNode:update_git_status(parent_ignored, status) |
| 109 | + self.git_status = git.git_status_dir(parent_ignored, status, self.absolute_path) |
| 110 | +end |
| 111 | + |
| 112 | +---@return GitStatus|nil |
| 113 | +function BaseNode:get_git_status() |
| 114 | + if not self.git_status or not self.explorer.opts.git.show_on_dirs then |
| 115 | + return nil |
| 116 | + end |
| 117 | + |
| 118 | + local status = {} |
| 119 | + if not self:last_group_node().open or self.explorer.opts.git.show_on_open_dirs then |
| 120 | + -- dir is closed or we should show on open_dirs |
| 121 | + if self.git_status.file ~= nil then |
| 122 | + table.insert(status, self.git_status.file) |
| 123 | + end |
| 124 | + if self.git_status.dir ~= nil then |
| 125 | + if self.git_status.dir.direct ~= nil then |
| 126 | + for _, s in pairs(self.git_status.dir.direct) do |
| 127 | + table.insert(status, s) |
| 128 | + end |
| 129 | + end |
| 130 | + if self.git_status.dir.indirect ~= nil then |
| 131 | + for _, s in pairs(self.git_status.dir.indirect) do |
| 132 | + table.insert(status, s) |
| 133 | + end |
| 134 | + end |
| 135 | + end |
| 136 | + else |
| 137 | + -- dir is open and we shouldn't show on open_dirs |
| 138 | + if self.git_status.file ~= nil then |
| 139 | + table.insert(status, self.git_status.file) |
| 140 | + end |
| 141 | + if self.git_status.dir ~= nil and self.git_status.dir.direct ~= nil then |
| 142 | + local deleted = { |
| 143 | + [" D"] = true, |
| 144 | + ["D "] = true, |
| 145 | + ["RD"] = true, |
| 146 | + ["DD"] = true, |
| 147 | + } |
| 148 | + for _, s in pairs(self.git_status.dir.direct) do |
| 149 | + if deleted[s] then |
| 150 | + table.insert(status, s) |
| 151 | + end |
| 152 | + end |
| 153 | + end |
| 154 | + end |
| 155 | + if #status == 0 then |
| 156 | + return nil |
| 157 | + else |
| 158 | + return status |
| 159 | + end |
| 160 | +end |
| 161 | + |
| 162 | +---@param projects table |
| 163 | +function DirectoryNode:reload_node_status(projects) |
| 164 | + local toplevel = git.get_toplevel(self.absolute_path) |
| 165 | + local status = projects[toplevel] or {} |
| 166 | + for _, node in ipairs(self.nodes) do |
| 167 | + node:update_git_status(self:is_git_ignored(), status) |
| 168 | + if node.nodes and #node.nodes > 0 then |
| 169 | + self:reload_node_status(projects) |
| 170 | + end |
| 171 | + end |
| 172 | +end |
| 173 | + |
61 | 174 | ---Create a sanitized partial copy of a node, populating children recursively. |
62 | 175 | ---@return DirectoryNode cloned |
63 | 176 | function DirectoryNode:clone() |
|
0 commit comments