Skip to content

Commit d7228a8

Browse files
committed
fix(#2415): builder refactor (#2538)
* simplify builder signs * decorators take care of themselves and are priority ordered * simplify builder hl groups * refactor builder for icon arrays * builder use decorators generically
1 parent ca9e193 commit d7228a8

File tree

11 files changed

+156
-172
lines changed

11 files changed

+156
-172
lines changed

doc/nvim-tree-lua.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ Configuration options for tree indent markers.
893893
Configuration options for icons.
894894

895895
Icon sign column precedence:
896-
diagnostics > modified > git > bookmarked
896+
diagnostics > bookmarked > modified > git
897897

898898
*nvim-tree.renderer.icons.web_devicons*
899899
Configure optional plugin `"nvim-tree/nvim-web-devicons"`

lua/nvim-tree/renderer/builder.lua

+31-126
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,23 @@ local notify = require "nvim-tree.notify"
55
local pad = require "nvim-tree.renderer.components.padding"
66
local icons = require "nvim-tree.renderer.components.icons"
77

8-
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
9-
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
10-
118
--- @class Builder
12-
--- @field decorators Decorator[]
9+
--- @field deco Decorator[]
1310
local Builder = {}
1411
Builder.__index = Builder
1512

1613
local DEFAULT_ROOT_FOLDER_LABEL = ":~:s?$?/..?"
1714

18-
function Builder.new(root_cwd, decorators)
15+
function Builder.new(root_cwd, deco)
1916
return setmetatable({
2017
index = 0,
2118
depth = 0,
2219
highlights = {},
2320
lines = {},
2421
markers = {},
25-
signs = {},
22+
sign_names = {},
2623
root_cwd = root_cwd,
27-
decorators = decorators,
24+
deco = deco,
2825
}, Builder)
2926
end
3027

@@ -195,95 +192,18 @@ function Builder:_build_file(node)
195192
return icon, { str = node.name, hl = { hl } }
196193
end
197194

198-
---@param node table
199-
---@return HighlightedString[]|nil icon
200-
function Builder:_get_git_icons(node)
201-
local git_icons = self.decorators.git:get_icons(node)
202-
if git_icons and #git_icons > 0 and self.decorators.git.icon_placement == ICON_PLACEMENT.signcolumn then
203-
table.insert(self.signs, {
204-
sign = git_icons[1].hl[1],
205-
lnum = self.index + 1,
206-
priority = 1,
207-
})
208-
git_icons = nil
209-
end
210-
return git_icons
211-
end
212-
213-
---@param node table
214-
---@return HighlightedString[]|nil icon
215-
function Builder:_get_diagnostics_icon(node)
216-
local diagnostics_icon = self.decorators.diagnostics:get_icon(node)
217-
if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.signcolumn then
218-
table.insert(self.signs, {
219-
sign = diagnostics_icon.hl[1],
220-
lnum = self.index + 1,
221-
priority = 2,
222-
})
223-
diagnostics_icon = nil
224-
end
225-
return diagnostics_icon
226-
end
227-
228-
---@param node table
229-
---@return HighlightedString|nil icon
230-
function Builder:_get_modified_icon(node)
231-
local modified_icon = self.decorators.modified:get_icon(node)
232-
if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.signcolumn then
233-
table.insert(self.signs, {
234-
sign = modified_icon.hl[1],
235-
lnum = self.index + 1,
236-
priority = 3,
237-
})
238-
modified_icon = nil
239-
end
240-
return modified_icon
241-
end
242-
243-
---@param node table
244-
---@return HighlightedString[]|nil icon
245-
function Builder:_get_bookmark_icon(node)
246-
local bookmark_icon = self.decorators.bookmarks:get_icon(node)
247-
if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.signcolumn then
248-
table.insert(self.signs, {
249-
sign = bookmark_icon.hl[1],
250-
lnum = self.index + 1,
251-
priority = 4,
252-
})
253-
bookmark_icon = nil
254-
end
255-
return bookmark_icon
256-
end
257-
258-
---Append optional highlighting to icon or name.
259-
---@param node table
260-
---@param decorator Decorator
261-
---@param icon_hl string[] icons to append to
262-
---@param name_hl string[] names to append to
263-
function Builder:_append_dec_highlight(node, decorator, icon_hl, name_hl)
264-
local hl = decorator:get_highlight(node)
265-
if hl then
266-
if decorator.hl_pos == HL_POSITION.all or decorator.hl_pos == HL_POSITION.icon then
267-
table.insert(icon_hl, hl)
268-
end
269-
if decorator.hl_pos == HL_POSITION.all or decorator.hl_pos == HL_POSITION.name then
270-
table.insert(name_hl, hl)
271-
end
272-
end
273-
end
274-
275195
---@param indent_markers HighlightedString[]
276196
---@param arrows HighlightedString[]|nil
277197
---@param icon HighlightedString
278198
---@param name HighlightedString
279-
---@param git_icons HighlightedString[]|nil
280-
---@param diagnostics_icon HighlightedString|nil
281-
---@param modified_icon HighlightedString|nil
282-
---@param bookmark_icon HighlightedString|nil
199+
---@param node table
283200
---@return HighlightedString[]
284-
function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, diagnostics_icon, modified_icon, bookmark_icon)
201+
function Builder:_format_line(indent_markers, arrows, icon, name, node)
285202
local added_len = 0
286203
local function add_to_end(t1, t2)
204+
if not t2 then
205+
return
206+
end
287207
for _, v in ipairs(t2) do
288208
if added_len > 0 then
289209
table.insert(t1, { str = self.icon_padding })
@@ -301,32 +221,15 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia
301221

302222
local line = { indent_markers, arrows }
303223
add_to_end(line, { icon })
304-
if git_icons and self.decorators.git.icon_placement == ICON_PLACEMENT.before then
305-
add_to_end(line, git_icons)
306-
end
307-
if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.before then
308-
add_to_end(line, { modified_icon })
309-
end
310-
if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.before then
311-
add_to_end(line, { diagnostics_icon })
312-
end
313-
if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.before then
314-
add_to_end(line, { bookmark_icon })
224+
225+
for i = #self.deco, 1, -1 do
226+
add_to_end(line, self.deco[i]:icons_before(node))
315227
end
316228

317229
add_to_end(line, { name })
318230

319-
if git_icons and self.decorators.git.icon_placement == ICON_PLACEMENT.after then
320-
add_to_end(line, git_icons)
321-
end
322-
if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.after then
323-
add_to_end(line, { modified_icon })
324-
end
325-
if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.after then
326-
add_to_end(line, { diagnostics_icon })
327-
end
328-
if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.after then
329-
add_to_end(line, { bookmark_icon })
231+
for i = #self.deco, 1, -1 do
232+
add_to_end(line, self.deco[i]:icons_after(node))
330233
end
331234

332235
return line
@@ -337,11 +240,15 @@ function Builder:_build_line(node, idx, num_children)
337240
local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers)
338241
local arrows = pad.get_arrows(node)
339242

340-
-- adds icons to signcolumn
341-
local bookmark_icon = self:_get_bookmark_icon(node)
342-
local git_icons = self:_get_git_icons(node)
343-
local modified_icon = self:_get_modified_icon(node)
344-
local diagnostics_icon = self:_get_diagnostics_icon(node)
243+
-- signs, use the highest priority
244+
local sign_name
245+
for _, d in ipairs(self.deco) do
246+
sign_name = d:sign_name(node)
247+
if sign_name then
248+
self.sign_names[self.index] = sign_name
249+
break
250+
end
251+
end
345252

346253
-- main components
347254
local is_folder = node.nodes ~= nil
@@ -355,16 +262,14 @@ function Builder:_build_line(node, idx, num_children)
355262
icon, name = self:_build_file(node)
356263
end
357264

358-
-- extra highighting
359-
self:_append_dec_highlight(node, self.decorators.git, icon.hl, name.hl)
360-
self:_append_dec_highlight(node, self.decorators.opened, icon.hl, name.hl)
361-
self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl)
362-
self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl)
363-
self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl)
364-
self:_append_dec_highlight(node, self.decorators.copied, icon.hl, name.hl)
365-
self:_append_dec_highlight(node, self.decorators.cut, icon.hl, name.hl)
265+
-- highighting
266+
for _, d in ipairs(self.deco) do
267+
local icon_group, name_group = d:groups_icon_name(node)
268+
table.insert(icon.hl, icon_group)
269+
table.insert(name.hl, name_group)
270+
end
366271

367-
local line = self:_format_line(indent_markers, arrows, icon, name, git_icons, diagnostics_icon, modified_icon, bookmark_icon)
272+
local line = self:_format_line(indent_markers, arrows, icon, name, node)
368273
self:_insert_line(self:_unwrap_highlighted_strings(line))
369274

370275
self.index = self.index + 1
@@ -438,7 +343,7 @@ function Builder:build_header(show_header)
438343
end
439344

440345
function Builder:unwrap()
441-
return self.lines, self.highlights, self.signs
346+
return self.lines, self.highlights, self.sign_names
442347
end
443348

444349
return Builder

lua/nvim-tree/renderer/decorator/bookmarks.lua

+4-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ local DecoratorBookmarks = Decorator:new()
1313
--- @return DecoratorBookmarks
1414
function DecoratorBookmarks:new(opts)
1515
local o = Decorator.new(self, {
16+
enabled = true,
1617
hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none,
1718
icon_placement = ICON_PLACEMENT[opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.none,
1819
})
@@ -30,14 +31,14 @@ function DecoratorBookmarks:new(opts)
3031
end
3132

3233
--- Bookmark icon: renderer.icons.show.bookmarks and node is marked
33-
function DecoratorBookmarks:get_icon(node)
34+
function DecoratorBookmarks:calculate_icons(node)
3435
if marks.get_mark(node) then
35-
return self.icon
36+
return { self.icon }
3637
end
3738
end
3839

3940
--- Bookmark highlight: renderer.highlight_bookmarks and node is marked
40-
function DecoratorBookmarks:get_highlight(node)
41+
function DecoratorBookmarks:calculate_highlight(node)
4142
if self.hl_pos ~= HL_POSITION.none and marks.get_mark(node) then
4243
return "NvimTreeBookmarkHL"
4344
end

lua/nvim-tree/renderer/decorator/copied.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ local DecoratorCopied = Decorator:new()
1414
--- @return DecoratorCopied
1515
function DecoratorCopied:new(opts)
1616
local o = Decorator.new(self, {
17+
enabled = true,
1718
hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none,
1819
icon_placement = ICON_PLACEMENT.none,
1920
})
@@ -26,7 +27,7 @@ function DecoratorCopied:new(opts)
2627
end
2728

2829
--- Cut highlight: renderer.highlight_clipboard and node is copied
29-
function DecoratorCopied:get_highlight(node)
30+
function DecoratorCopied:calculate_highlight(node)
3031
if self.hl_pos ~= HL_POSITION.none and copy_paste.is_copied(node) then
3132
return "NvimTreeCopiedHL"
3233
end

lua/nvim-tree/renderer/decorator/cut.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ local DecoratorCut = Decorator:new()
1414
--- @return DecoratorCut
1515
function DecoratorCut:new(opts)
1616
local o = Decorator.new(self, {
17+
enabled = true,
1718
hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none,
1819
icon_placement = ICON_PLACEMENT.none,
1920
})
@@ -26,7 +27,7 @@ function DecoratorCut:new(opts)
2627
end
2728

2829
--- Cut highlight: renderer.highlight_clipboard and node is cut
29-
function DecoratorCut:get_highlight(node)
30+
function DecoratorCut:calculate_highlight(node)
3031
if self.hl_pos ~= HL_POSITION.none and copy_paste.is_cut(node) then
3132
return "NvimTreeCutHL"
3233
end

lua/nvim-tree/renderer/decorator/diagnostics.lua

+6-5
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,19 @@ local ICON_KEYS = {
3131
}
3232

3333
--- @class DecoratorDiagnostics: Decorator
34-
--- @field enabled boolean
3534
--- @field icons HighlightedString[]
3635
local DecoratorDiagnostics = Decorator:new()
3736

3837
--- @param opts table
3938
--- @return DecoratorDiagnostics
4039
function DecoratorDiagnostics:new(opts)
4140
local o = Decorator.new(self, {
41+
enabled = opts.diagnostics.enable,
4242
hl_pos = HL_POSITION[opts.renderer.highlight_diagnostics] or HL_POSITION.none,
4343
icon_placement = ICON_PLACEMENT[opts.renderer.icons.diagnostics_placement] or ICON_PLACEMENT.none,
4444
})
4545
---@cast o DecoratorDiagnostics
4646

47-
o.enabled = opts.diagnostics.enable
4847
if not o.enabled then
4948
return o
5049
end
@@ -64,14 +63,16 @@ function DecoratorDiagnostics:new(opts)
6463
end
6564

6665
--- Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status
67-
function DecoratorDiagnostics:get_icon(node)
66+
function DecoratorDiagnostics:calculate_icons(node)
6867
if node and self.enabled and self.icons then
69-
return self.icons[node.diag_status]
68+
if node.diag_status then
69+
return { self.icons[node.diag_status] }
70+
end
7071
end
7172
end
7273

7374
--- Diagnostic highlight: diagnostics.enable, renderer.highlight_diagnostics and node has status
74-
function DecoratorDiagnostics:get_highlight(node)
75+
function DecoratorDiagnostics:calculate_highlight(node)
7576
if not node or not self.enabled or self.hl_pos == HL_POSITION.none then
7677
return nil
7778
end

lua/nvim-tree/renderer/decorator/git.lua

+15-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
77
local Decorator = require "nvim-tree.renderer.decorator"
88

99
--- @class DecoratorGit: Decorator
10-
--- @field enabled boolean
1110
--- @field file_hl string[]
1211
--- @field folder_hl string[]
1312
--- @field git_icons table
@@ -115,12 +114,12 @@ end
115114
--- @return DecoratorGit
116115
function DecoratorGit:new(opts)
117116
local o = Decorator.new(self, {
117+
enabled = opts.git.enable,
118118
hl_pos = HL_POSITION[opts.renderer.highlight_git] or HL_POSITION.none,
119119
icon_placement = ICON_PLACEMENT[opts.renderer.icons.git_placement] or ICON_PLACEMENT.none,
120120
})
121121
---@cast o DecoratorGit
122122

123-
o.enabled = opts.git.enable
124123
if not o.enabled then
125124
return o
126125
end
@@ -140,7 +139,7 @@ end
140139
--- Git icons: git.enable, renderer.icons.show.git and node has status
141140
--- @param node table
142141
--- @return HighlightedString[]|nil modified icon
143-
function DecoratorGit:get_icons(node)
142+
function DecoratorGit:calculate_icons(node)
144143
if not node or not self.enabled or not self.git_icons then
145144
return nil
146145
end
@@ -184,8 +183,20 @@ function DecoratorGit:get_icons(node)
184183
return iconss
185184
end
186185

186+
--- Get the first icon as the sign if appropriate
187+
function DecoratorGit:sign_name(node)
188+
if self.icon_placement ~= ICON_PLACEMENT.signcolumn then
189+
return
190+
end
191+
192+
local icons = self:calculate_icons(node)
193+
if icons and #icons > 0 then
194+
return icons[1].hl[1]
195+
end
196+
end
197+
187198
--- Git highlight: git.enable, renderer.highlight_git and node has status
188-
function DecoratorGit:get_highlight(node)
199+
function DecoratorGit:calculate_highlight(node)
189200
if not node or not self.enabled or self.hl_pos == HL_POSITION.none then
190201
return nil
191202
end

0 commit comments

Comments
 (0)