@@ -8,6 +8,7 @@ local icons = require "nvim-tree.renderer.components.icons"
88--- @field private index number
99--- @field private depth number
1010--- @field private highlights table[] hl_group , line , col_start , col_end arguments for vim.api.nvim_buf_add_highlight
11+ --- @field private combined_groups boolean[] combined group names
1112--- @field private lines string[] includes icons etc.
1213--- @field private markers boolean[] indent markers
1314--- @field private sign_names string[] line signs
@@ -23,6 +24,7 @@ function Builder.new(root_cwd, decorators)
2324 index = 0 ,
2425 depth = 0 ,
2526 highlights = {},
27+ combined_groups = {},
2628 lines = {},
2729 markers = {},
2830 sign_names = {},
@@ -75,15 +77,11 @@ function Builder:configure_group_name_modifier(group_name_modifier)
7577end
7678
7779--- Insert ranged highlight groups into self.highlights
78- --- neovim 0.9 is limited to two highlight groups for a range so choose the highest two
7980--- @param groups string[]
8081--- @param start number
8182--- @param end_ number | nil
8283function Builder :_insert_highlight (groups , start , end_ )
83- local top_two_groups = {}
84- table.insert (top_two_groups , groups [# groups - 1 ])
85- table.insert (top_two_groups , groups [# groups ])
86- table.insert (self .highlights , { top_two_groups , self .index , start , end_ or - 1 })
84+ table.insert (self .highlights , { groups , self .index , start , end_ or - 1 })
8785end
8886
8987function Builder :_insert_line (line )
@@ -261,6 +259,70 @@ function Builder:_build_signs(node)
261259 end
262260end
263261
262+ function Builder :_combined_group_name (groups )
263+ return table.concat (groups )
264+ end
265+
266+ --- Create a highlight group for groups with later groups overriding previous.
267+ --- @param groups string[] highlight group names
268+ function Builder :_create_combined_group (groups )
269+ local combined_name = self :_combined_group_name (groups )
270+
271+ -- only create if necessary
272+ if not self .combined_groups [combined_name ] then
273+ local combined_hl = {}
274+
275+ -- build the highlight, overriding values
276+ for _ , group in ipairs (groups ) do
277+ local hl = vim .api .nvim_get_hl (0 , { name = group , link = false })
278+ combined_hl = vim .tbl_extend (" force" , combined_hl , hl )
279+ end
280+
281+ -- create and note the name
282+ vim .api .nvim_set_hl (0 , combined_name , combined_hl )
283+ self .combined_groups [combined_name ] = true
284+ end
285+ end
286+
287+ --- Calculate highlight group for icon and name. A combined highlight group will be created
288+ --- when there is more than one highlight.
289+ --- @param node Node
290+ --- @return string | nil icon_hl_group
291+ --- @return string | nil name_hl_group
292+ function Builder :_add_highlights (node )
293+ -- result
294+ local icon_hl_group , name_hl_group
295+
296+ -- calculate all groups
297+ local icon_groups = {}
298+ local name_groups = {}
299+ local d , icon , name
300+ for i = # self .decorators , 1 , - 1 do
301+ d = self .decorators [i ]
302+ icon , name = d :groups_icon_name (node )
303+ table.insert (icon_groups , icon )
304+ table.insert (name_groups , name )
305+ end
306+
307+ -- one or many icon groups
308+ if # icon_groups > 1 then
309+ icon_hl_group = self :_combined_group_name (icon_groups )
310+ self :_create_combined_group (icon_groups )
311+ else
312+ icon_hl_group = icon_groups [1 ]
313+ end
314+
315+ -- one or many name groups
316+ if # name_groups > 1 then
317+ name_hl_group = self :_combined_group_name (name_groups )
318+ self :_create_combined_group (name_groups )
319+ else
320+ name_hl_group = name_groups [1 ]
321+ end
322+
323+ return icon_hl_group , name_hl_group
324+ end
325+
264326function Builder :_build_line (node , idx , num_children )
265327 -- various components
266328 local indent_markers = pad .get_indent_markers (self .depth , idx , num_children , node , self .markers )
@@ -279,12 +341,9 @@ function Builder:_build_line(node, idx, num_children)
279341 end
280342
281343 -- highighting
282- for i = # self .decorators , 1 , - 1 do
283- local d = self .decorators [i ]
284- local icon_group , name_group = d :groups_icon_name (node )
285- table.insert (icon .hl , icon_group )
286- table.insert (name .hl , name_group )
287- end
344+ local icon_hl_group , name_hl_group = self :_add_highlights (node )
345+ table.insert (icon .hl , icon_hl_group )
346+ table.insert (name .hl , name_hl_group )
288347
289348 local line = self :_format_line (indent_markers , arrows , icon , name , node )
290349 self :_insert_line (self :_unwrap_highlighted_strings (line ))
0 commit comments