11local git = require (" nvim-tree.git" )
22
3+ --- TODO remove all @cast, @as
34--- TODO remove all references to directory fields:
45---- --@field has_children boolean
56---- --@field group_next Node? -- If node is grouped, this points to the next child dir/link node
@@ -38,6 +39,11 @@ function BaseNode:new(o)
3839 return o
3940end
4041
42+ -- TODO temporary hack to allow DirectoryNode methods in this file, for easier reviewing
43+ --- @class DirectoryNode
44+ local DirectoryNode = BaseNode :new ()
45+ BaseNode .dn = DirectoryNode --- @diagnostic disable-line : inject-field
46+
4147function BaseNode :destroy ()
4248 if self .watcher then
4349 self .watcher :destroy ()
@@ -63,25 +69,8 @@ function BaseNode:is(T)
6369end
6470
6571--- @return boolean
66- function BaseNode :has_one_child_folder ()
67- return false
68- end
69-
70- -- If node is grouped, return the last node in the group. Otherwise, return the given node.
71- --- @return Node
72- function BaseNode :last_group_node ()
73- return self
74- end
75-
76- --- Group empty folders
77- -- Recursively group nodes
78- --- @return Node[]
79- function BaseNode :group_empty_folders ()
80- return {}
81- end
82-
83- --- Ungroup empty folders
84- function BaseNode :ungroup_empty_folders ()
72+ function DirectoryNode :has_one_child_folder ()
73+ return # self .nodes == 1 and self .nodes [1 ].nodes and vim .loop .fs_access (self .nodes [1 ].absolute_path , " R" ) or false
8574end
8675
8776--- Update the GitStatus of the node
9483function BaseNode :get_git_status ()
9584end
9685
97- --- @param _ table projects
98- function BaseNode :reload_node_status (_ )
86+ --- @return GitStatus | nil
87+ function DirectoryNode :get_git_status ()
88+ if not self .git_status or not self .explorer .opts .git .show_on_dirs then
89+ return nil
90+ end
91+
92+ local status = {}
93+ if not self :last_group_node ().open or self .explorer .opts .git .show_on_open_dirs then
94+ -- dir is closed or we should show on open_dirs
95+ if self .git_status .file ~= nil then
96+ table.insert (status , self .git_status .file )
97+ end
98+ if self .git_status .dir ~= nil then
99+ if self .git_status .dir .direct ~= nil then
100+ for _ , s in pairs (self .git_status .dir .direct ) do
101+ table.insert (status , s )
102+ end
103+ end
104+ if self .git_status .dir .indirect ~= nil then
105+ for _ , s in pairs (self .git_status .dir .indirect ) do
106+ table.insert (status , s )
107+ end
108+ end
109+ end
110+ else
111+ -- dir is open and we shouldn't show on open_dirs
112+ if self .git_status .file ~= nil then
113+ table.insert (status , self .git_status .file )
114+ end
115+ if self .git_status .dir ~= nil and self .git_status .dir .direct ~= nil then
116+ local deleted = {
117+ [" D" ] = true ,
118+ [" D " ] = true ,
119+ [" RD" ] = true ,
120+ [" DD" ] = true ,
121+ }
122+ for _ , s in pairs (self .git_status .dir .direct ) do
123+ if deleted [s ] then
124+ table.insert (status , s )
125+ end
126+ end
127+ end
128+ end
129+ if # status == 0 then
130+ return nil
131+ else
132+ return status
133+ end
134+ end
135+
136+ --- @param projects table
137+ function DirectoryNode :reload_node_status (projects )
138+ local toplevel = git .get_toplevel (self .absolute_path )
139+ local status = projects [toplevel ] or {}
140+ for _ , node in ipairs (self .nodes ) do
141+ node :update_git_status (self :is_git_ignored (), status )
142+ if node .nodes and # node .nodes > 0 then
143+ self :reload_node_status (projects )
144+ end
145+ end
99146end
100147
101148--- @return boolean
@@ -116,6 +163,18 @@ function BaseNode:is_dotfile()
116163 return false
117164end
118165
166+ -- If node is grouped, return the last node in the group. Otherwise, return the given node.
167+ --- @return Node
168+ function DirectoryNode :last_group_node ()
169+ local node = self --[[ @as BaseNode]]
170+
171+ while node .group_next do
172+ node = node .group_next
173+ end
174+
175+ return node
176+ end
177+
119178--- @param project table ?
120179--- @param root string ?
121180function BaseNode :update_parent_statuses (project , root )
@@ -186,7 +245,7 @@ function BaseNode:get_all_nodes_in_group()
186245end
187246
188247-- Toggle group empty folders
189- function BaseNode :toggle_group_folders ()
248+ function DirectoryNode :toggle_group_folders ()
190249 local is_grouped = self .group_next ~= nil
191250
192251 if is_grouped then
@@ -196,6 +255,32 @@ function BaseNode:toggle_group_folders()
196255 end
197256end
198257
258+ --- Group empty folders
259+ -- Recursively group nodes
260+ --- @return Node[]
261+ function DirectoryNode :group_empty_folders ()
262+ local is_root = not self .parent
263+ local child_folder_only = self :has_one_child_folder () and self .nodes [1 ]
264+ if self .explorer .opts .renderer .group_empty and not is_root and child_folder_only then
265+ self .group_next = child_folder_only
266+ local ns = child_folder_only :group_empty_folders ()
267+ self .nodes = ns or {}
268+ return ns
269+ end
270+ return self .nodes
271+ end
272+
273+ --- Ungroup empty folders
274+ -- If a node is grouped, ungroup it: put node.group_next to the node.nodes and set node.group_next to nil
275+ function DirectoryNode :ungroup_empty_folders ()
276+ local cur = self --[[ @as DirectoryNode]]
277+ while cur and cur .group_next do
278+ cur .nodes = { cur .group_next }
279+ cur .group_next = nil
280+ cur = cur .nodes [1 ] --[[ @as DirectoryNode]]
281+ end
282+ end
283+
199284function BaseNode :expand_or_collapse (toggle_group )
200285 toggle_group = toggle_group or false
201286 if self .has_children then
@@ -208,6 +293,7 @@ function BaseNode:expand_or_collapse(toggle_group)
208293 end
209294
210295 local head_node = self :get_parent_of_group ()
296+ --- @cast head_node DirectoryNode -- TODO move this to the class
211297 if toggle_group then
212298 head_node :toggle_group_folders ()
213299 end
@@ -251,4 +337,34 @@ function BaseNode:clone()
251337 return clone
252338end
253339
340+ --
341+ -- TODO temporary hack to allow DirectoryNode methods in this file, for easier reviewing
342+ --
343+
344+ --- @return boolean
345+ function BaseNode :has_one_child_folder ()
346+ return false
347+ end
348+
349+ --- @param _ table projects
350+ function BaseNode :reload_node_status (_ )
351+ end
352+
353+ -- If node is grouped, return the last node in the group. Otherwise, return the given node.
354+ --- @return Node
355+ function BaseNode :last_group_node ()
356+ return self
357+ end
358+
359+ --- Group empty folders
360+ -- Recursively group nodes
361+ --- @return Node[]
362+ function BaseNode :group_empty_folders ()
363+ return {}
364+ end
365+
366+ --- Ungroup empty folders
367+ function BaseNode :ungroup_empty_folders ()
368+ end
369+
254370return BaseNode
0 commit comments