1+ local colors = require " nvim-tree.colors"
12local utils = require " nvim-tree.utils"
23local notify = require " nvim-tree.notify"
34
@@ -8,6 +9,7 @@ local icons = require "nvim-tree.renderer.components.icons"
89--- @field private index number
910--- @field private depth number
1011--- @field private highlights table[] hl_group , line , col_start , col_end arguments for vim.api.nvim_buf_add_highlight
12+ --- @field private combined_groups boolean[] combined group names
1113--- @field private lines string[] includes icons etc.
1214--- @field private markers boolean[] indent markers
1315--- @field private sign_names string[] line signs
@@ -23,6 +25,7 @@ function Builder.new(root_cwd, decorators)
2325 index = 0 ,
2426 depth = 0 ,
2527 highlights = {},
28+ combined_groups = {},
2629 lines = {},
2730 markers = {},
2831 sign_names = {},
@@ -75,15 +78,11 @@ function Builder:configure_group_name_modifier(group_name_modifier)
7578end
7679
7780--- 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
7981--- @param groups string[]
8082--- @param start number
8183--- @param end_ number | nil
8284function 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 })
85+ table.insert (self .highlights , { groups , self .index , start , end_ or - 1 })
8786end
8887
8988function Builder :_insert_line (line )
@@ -261,6 +260,76 @@ function Builder:_build_signs(node)
261260 end
262261end
263262
263+ --- Combined group name less than the 200 byte limit of highlight group names
264+ --- @param groups string[] highlight group names
265+ --- @return string name " NvimTreeCombinedHL" .. sha256
266+ function Builder :_combined_group_name (groups )
267+ return string.format (" NvimTreeCombinedHL%s" , vim .fn .sha256 (table.concat (groups )))
268+ end
269+
270+ --- Create a highlight group for groups with later groups overriding previous.
271+ --- @param groups string[] highlight group names
272+ function Builder :_create_combined_group (groups )
273+ local combined_name = self :_combined_group_name (groups )
274+
275+ -- only create if necessary
276+ if not self .combined_groups [combined_name ] then
277+ local combined_hl = {}
278+
279+ -- build the highlight, overriding values
280+ for _ , group in ipairs (groups ) do
281+ local hl = vim .api .nvim_get_hl (0 , { name = group , link = false })
282+ combined_hl = vim .tbl_extend (" force" , combined_hl , hl )
283+ end
284+
285+ -- highlight directly in the namespace
286+ vim .api .nvim_set_hl_ns_fast (colors .NS_ID )
287+ vim .api .nvim_set_hl (colors .NS_ID , combined_name , combined_hl )
288+
289+ self .combined_groups [combined_name ] = true
290+ end
291+ end
292+
293+ --- Calculate highlight group for icon and name. A combined highlight group will be created
294+ --- when there is more than one highlight.
295+ --- A highlight group is always calculated and upserted for the case of highlights changing.
296+ --- @param node Node
297+ --- @return string | nil icon_hl_group
298+ --- @return string | nil name_hl_group
299+ function Builder :_add_highlights (node )
300+ -- result
301+ local icon_hl_group , name_hl_group
302+
303+ -- calculate all groups
304+ local icon_groups = {}
305+ local name_groups = {}
306+ local d , icon , name
307+ for i = # self .decorators , 1 , - 1 do
308+ d = self .decorators [i ]
309+ icon , name = d :groups_icon_name (node )
310+ table.insert (icon_groups , icon )
311+ table.insert (name_groups , name )
312+ end
313+
314+ -- one or many icon groups
315+ if # icon_groups > 1 then
316+ icon_hl_group = self :_combined_group_name (icon_groups )
317+ self :_create_combined_group (icon_groups )
318+ else
319+ icon_hl_group = icon_groups [1 ]
320+ end
321+
322+ -- one or many name groups
323+ if # name_groups > 1 then
324+ name_hl_group = self :_combined_group_name (name_groups )
325+ self :_create_combined_group (name_groups )
326+ else
327+ name_hl_group = name_groups [1 ]
328+ end
329+
330+ return icon_hl_group , name_hl_group
331+ end
332+
264333function Builder :_build_line (node , idx , num_children )
265334 -- various components
266335 local indent_markers = pad .get_indent_markers (self .depth , idx , num_children , node , self .markers )
@@ -279,12 +348,9 @@ function Builder:_build_line(node, idx, num_children)
279348 end
280349
281350 -- 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
351+ local icon_hl_group , name_hl_group = self :_add_highlights (node )
352+ table.insert (icon .hl , icon_hl_group )
353+ table.insert (name .hl , name_hl_group )
288354
289355 local line = self :_format_line (indent_markers , arrows , icon , name , node )
290356 self :_insert_line (self :_unwrap_highlighted_strings (line ))
0 commit comments