Skip to content

Commit 6148f69

Browse files
committed
feat(#2948): pass api nodes to user decorators
1 parent 3ab3980 commit 6148f69

File tree

8 files changed

+60
-29
lines changed

8 files changed

+60
-29
lines changed

lua/nvim-tree/_meta/api_decorator.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ local nvim_tree = { api = { decorator = { AbstractDecorator = {} } } }
1313
---Constructor must call:
1414
--- :init
1515
--- :define_sign when using "signcolumn" range
16+
---Decorator must be registered via api.decorator.register
1617

1718
---Highlight group range as per nvim-tree.renderer.highlight_*
1819
---@alias nvim_tree.api.decorator.HighlightRange "none" | "icon" | "name" | "all"
@@ -125,4 +126,5 @@ function MyDecorator:highlight_group(node)
125126
end
126127
end
127128

128-
return MyDecorator
129+
---Register the decorator, below Cut in priority
130+
require("nvim-tree.api").decorator.register({ decorator = MyDecorator, below = "Cut" })

lua/nvim-tree/node/directory-link.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ function DirectoryLinkNode:highlighted_name()
7373
end
7474

7575
---Create a sanitized partial copy of a node, populating children recursively.
76+
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
7677
---@return nvim_tree.api.DirectoryLinkNode cloned
77-
function DirectoryLinkNode:clone()
78-
local clone = DirectoryNode.clone(self) --[[@as nvim_tree.api.DirectoryLinkNode]]
78+
function DirectoryLinkNode:clone(api_nodes)
79+
local clone = DirectoryNode.clone(self, api_nodes) --[[@as nvim_tree.api.DirectoryLinkNode]]
7980

8081
clone.link_to = self.link_to
8182
clone.fs_stat_target = self.fs_stat_target

lua/nvim-tree/node/directory.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,17 +271,18 @@ function DirectoryNode:highlighted_name()
271271
end
272272

273273
---Create a sanitized partial copy of a node, populating children recursively.
274+
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
274275
---@return nvim_tree.api.DirectoryNode cloned
275-
function DirectoryNode:clone()
276-
local clone = Node.clone(self) --[[@as nvim_tree.api.DirectoryNode]]
276+
function DirectoryNode:clone(api_nodes)
277+
local clone = Node.clone(self, api_nodes) --[[@as nvim_tree.api.DirectoryNode]]
277278

278279
clone.has_children = self.has_children
279280
clone.nodes = {}
280281
clone.open = self.open
281282

282283
local clone_child
283284
for _, child in ipairs(self.nodes) do
284-
clone_child = child:clone()
285+
clone_child = child:clone(api_nodes)
285286
clone_child.parent = clone
286287
table.insert(clone.nodes, clone_child)
287288
end

lua/nvim-tree/node/file-link.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ function FileLinkNode:highlighted_name()
5858
end
5959

6060
---Create a sanitized partial copy of a node
61+
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
6162
---@return nvim_tree.api.FileLinkNode cloned
62-
function FileLinkNode:clone()
63-
local clone = FileNode.clone(self) --[[@as nvim_tree.api.FileLinkNode]]
63+
function FileLinkNode:clone(api_nodes)
64+
local clone = FileNode.clone(self, api_nodes) --[[@as nvim_tree.api.FileLinkNode]]
6465

6566
clone.link_to = self.link_to
6667
clone.fs_stat_target = self.fs_stat_target

lua/nvim-tree/node/file.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,10 @@ function FileNode:highlighted_name()
9494
end
9595

9696
---Create a sanitized partial copy of a node
97+
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
9798
---@return nvim_tree.api.FileNode cloned
98-
function FileNode:clone()
99-
local clone = Node.clone(self) --[[@as nvim_tree.api.FileNode]]
99+
function FileNode:clone(api_nodes)
100+
local clone = Node.clone(self, api_nodes) --[[@as nvim_tree.api.FileNode]]
100101

101102
clone.extension = self.extension
102103

lua/nvim-tree/node/init.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,9 @@ function Node:highlighted_name()
121121
end
122122

123123
---Create a sanitized partial copy of a node, populating children recursively.
124+
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
124125
---@return nvim_tree.api.Node cloned
125-
function Node:clone()
126+
function Node:clone(api_nodes)
126127
---@type nvim_tree.api.Node
127128
local clone = {
128129
uid_node = self.uid_node,
@@ -137,6 +138,10 @@ function Node:clone()
137138
diag_severity = self.diag_status and self.diag_status.value or nil,
138139
}
139140

141+
if api_nodes then
142+
api_nodes[self.uid_node] = clone
143+
end
144+
140145
return clone
141146
end
142147

lua/nvim-tree/node/root.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ function RootNode:destroy()
2323
end
2424

2525
---Create a sanitized partial copy of a node, populating children recursively.
26+
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
2627
---@return nvim_tree.api.RootNode cloned
27-
function RootNode:clone()
28-
local clone = DirectoryNode.clone(self) --[[@as nvim_tree.api.RootNode]]
28+
function RootNode:clone(api_nodes)
29+
local clone = DirectoryNode.clone(self, api_nodes) --[[@as nvim_tree.api.RootNode]]
2930

3031
return clone
3132
end

lua/nvim-tree/renderer/builder.lua

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ local pad = require("nvim-tree.renderer.components.padding")
2828
---@field private markers boolean[] indent markers
2929
---@field private decorators Decorator[]
3030
---@field private hidden_display fun(node: Node): string|nil
31+
---@field private api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node for user decorators
3132
local Builder = Class:extend()
3233

3334
---@class Builder
@@ -51,20 +52,33 @@ function Builder:new(args)
5152
self.virtual_lines = {}
5253
self.decorators = {}
5354
self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts)
55+
self.api_nodes = nil
5456

5557
---@type DecoratorArgs
5658
local decorator_args = { explorer = self.explorer }
5759

58-
-- lowest priority is registered first
60+
-- instantiate all the decorators
5961
for _, d in ipairs(decorator_registry.registered) do
6062
if d:is(DecoratorUser) then
61-
table.insert(self.decorators, 1, d())
63+
self:build_api_nodes()
64+
table.insert(self.decorators, d())
6265
else
63-
table.insert(self.decorators, 1, d(decorator_args))
66+
table.insert(self.decorators, d(decorator_args))
6467
end
6568
end
6669
end
6770

71+
---Create and populate api_nodes if not present
72+
---@private
73+
function Builder:build_api_nodes()
74+
if self.api_nodes then
75+
return
76+
end
77+
78+
self.api_nodes = {}
79+
self.explorer:clone(self.api_nodes)
80+
end
81+
6882
---Insert ranged highlight groups into self.highlights
6983
---@private
7084
---@param groups string[]
@@ -122,22 +136,25 @@ function Builder:format_line(indent_markers, arrows, icon, name, node)
122136
end
123137
end
124138

139+
-- use the api node for user decorators
140+
local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]]
141+
125142
local line = { indent_markers, arrows }
126143
add_to_end(line, { icon })
127144

128-
for i = #self.decorators, 1, -1 do
129-
add_to_end(line, self.decorators[i]:icons_before(node))
145+
for _, d in ipairs(self.decorators) do
146+
add_to_end(line, d:icons_before(d:is(DecoratorUser) and api_node or node))
130147
end
131148

132149
add_to_end(line, { name })
133150

134-
for i = #self.decorators, 1, -1 do
135-
add_to_end(line, self.decorators[i]:icons_after(node))
151+
for _, d in ipairs(self.decorators) do
152+
add_to_end(line, d:icons_after(d:is(DecoratorUser) and api_node or node))
136153
end
137154

138155
local rights = {}
139-
for i = #self.decorators, 1, -1 do
140-
add_to_end(rights, self.decorators[i]:icons_right_align(node))
156+
for _, d in ipairs(self.decorators) do
157+
add_to_end(rights, d:icons_right_align(d:is(DecoratorUser) and api_node or node))
141158
end
142159
if #rights > 0 then
143160
self.extmarks[self.index] = rights
@@ -149,10 +166,14 @@ end
149166
---@private
150167
---@param node Node
151168
function Builder:build_signs(node)
169+
-- use the api node for user decorators
170+
local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]]
171+
152172
-- first in priority order
153-
local sign_name
154-
for _, d in ipairs(self.decorators) do
155-
sign_name = d:sign_name(node)
173+
local d, sign_name
174+
for i = #self.decorators, 1, -1 do
175+
d = self.decorators[i]
176+
sign_name = d:sign_name(d:is(DecoratorUser) and api_node or node)
156177
if sign_name then
157178
self.signs[self.index] = sign_name
158179
break
@@ -203,10 +224,8 @@ function Builder:icon_name_decorated(node)
203224
-- calculate node icon and all decorated highlight groups
204225
local icon_groups = {}
205226
local name_groups = {}
206-
local decorator, hl_icon, hl_name
207-
for i = #self.decorators, 1, -1 do
208-
decorator = self.decorators[i]
209-
227+
local hl_icon, hl_name
228+
for _, decorator in ipairs(self.decorators) do
210229
-- maybe overridde icon
211230
icon = decorator:icon_node(node) or icon
212231

0 commit comments

Comments
 (0)