1
+ local colors = require " nvim-tree.colors"
1
2
local utils = require " nvim-tree.utils"
2
3
local notify = require " nvim-tree.notify"
3
4
@@ -8,6 +9,7 @@ local icons = require "nvim-tree.renderer.components.icons"
8
9
--- @field private index number
9
10
--- @field private depth number
10
11
--- @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
11
13
--- @field private lines string[] includes icons etc.
12
14
--- @field private markers boolean[] indent markers
13
15
--- @field private sign_names string[] line signs
@@ -23,6 +25,7 @@ function Builder.new(root_cwd, decorators)
23
25
index = 0 ,
24
26
depth = 0 ,
25
27
highlights = {},
28
+ combined_groups = {},
26
29
lines = {},
27
30
markers = {},
28
31
sign_names = {},
@@ -75,15 +78,11 @@ function Builder:configure_group_name_modifier(group_name_modifier)
75
78
end
76
79
77
80
--- 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
79
81
--- @param groups string[]
80
82
--- @param start number
81
83
--- @param end_ number | nil
82
84
function 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 })
87
86
end
88
87
89
88
function Builder :_insert_line (line )
@@ -261,6 +260,76 @@ function Builder:_build_signs(node)
261
260
end
262
261
end
263
262
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
+
264
333
function Builder :_build_line (node , idx , num_children )
265
334
-- various components
266
335
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)
279
348
end
280
349
281
350
-- 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 )
288
354
289
355
local line = self :_format_line (indent_markers , arrows , icon , name , node )
290
356
self :_insert_line (self :_unwrap_highlighted_strings (line ))
0 commit comments