Skip to content

Commit 323f65c

Browse files
authored
feat(#1917): add diagnostic highlighting and icon placement (#2396)
* feat(#1917): add renderer.highlight_diagnostics * feat(#1917): add renderer.highlight_diagnostics * feat(#1917): add enderer.icons.diagnostics_placement * feat(#1917): add renderer.icons.show.diagnostics * feat(#1917): document highlight overrides
1 parent 28c3980 commit 323f65c

File tree

7 files changed

+148
-64
lines changed

7 files changed

+148
-64
lines changed

doc/nvim-tree-lua.txt

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ applying configuration.
345345
add_trailing = false,
346346
group_empty = false,
347347
highlight_git = false,
348+
highlight_diagnostics = false,
348349
full_name = false,
349350
highlight_opened_files = "none",
350351
highlight_modified = "none",
@@ -373,6 +374,7 @@ applying configuration.
373374
},
374375
},
375376
git_placement = "before",
377+
diagnostics_placement = "signcolumn",
376378
modified_placement = "after",
377379
padding = " ",
378380
symlink_arrow = " ➛ ",
@@ -381,6 +383,7 @@ applying configuration.
381383
folder = true,
382384
folder_arrow = true,
383385
git = true,
386+
diagnostics = true,
384387
modified = true,
385388
},
386389
glyphs = {
@@ -689,15 +692,7 @@ Open a file or directory in your preferred application.
689692
Windows: `{ "/c", "start", '""' }`
690693

691694
*nvim-tree.diagnostics*
692-
Show LSP and COC diagnostics in the signcolumn
693-
Note that the modified sign will take precedence over the diagnostics signs.
694-
695-
`NOTE`: it will use the default diagnostic color groups to highlight the signs.
696-
If you wish to customize, you can override these groups:
697-
- `NvimTreeLspDiagnosticsError`
698-
- `NvimTreeLspDiagnosticsWarning`
699-
- `NvimTreeLspDiagnosticsInformation`
700-
- `NvimTreeLspDiagnosticsHint`
695+
Show LSP and COC diagnostics.
701696

702697
*nvim-tree.diagnostics.enable*
703698
Enable/disable the feature.
@@ -881,7 +876,7 @@ Window / buffer setup.
881876
Type: `boolean`, Default: `false`
882877

883878
*nvim-tree.view.signcolumn*
884-
Show diagnostic sign column. Value can be `"yes"`, `"auto"`, `"no"`.
879+
Show |signcolumn|. Value can be `"yes"`, `"auto"`, `"no"`.
885880
Type: `string`, Default: `"yes"`
886881

887882
*nvim-tree.view.float*
@@ -910,6 +905,8 @@ Window / buffer setup.
910905
*nvim-tree.renderer*
911906
UI rendering setup
912907

908+
Highlight override precedence: git < opened < modified < diagnostics
909+
913910
*nvim-tree.renderer.add_trailing*
914911
Appends a trailing slash to folder names.
915912
Type: `boolean`, Default: `false`
@@ -923,11 +920,17 @@ UI rendering setup
923920
Type: `boolean`, Default: `false`
924921

925922
*nvim-tree.renderer.highlight_git*
926-
Enable file highlight for git attributes using `NvimTreeGit*` highlight groups.
923+
Enable highlight for git attributes using `NvimTreeGit*` highlight groups.
927924
Requires |nvim-tree.git.enable|
928925
This can be used with or without the icons.
929926
Type: `boolean`, Default: `false`
930927

928+
*nvim-tree.renderer.highlight_diagnostics*
929+
Enable highlight for diagnostics using `LspDiagnosticsError*Text` highlight groups.
930+
Requires |nvim-tree.diagnostics.enable|
931+
This can be used with or without the icons.
932+
Type: `boolean`, Default: `false`
933+
931934
*nvim-tree.renderer.highlight_opened_files*
932935
Highlight icons and/or names for |bufloaded()| files using the
933936
`NvimTreeOpenedFile` highlight group.
@@ -979,6 +982,8 @@ UI rendering setup
979982
*nvim-tree.renderer.icons*
980983
Configuration options for icons.
981984

985+
Sign column icon precedence: git < modified < diagnostics
986+
982987
*nvim-tree.renderer.icons.web_devicons*
983988
Configure optional plugin `"nvim-tree/nvim-web-devicons"`
984989

@@ -1010,9 +1015,14 @@ UI rendering setup
10101015
Place where the git icons will be rendered.
10111016
Can be `"after"` or `"before"` filename (after the file/folders icons)
10121017
or `"signcolumn"` (requires |nvim-tree.view.signcolumn| enabled).
1013-
Note that the diagnostic signs and the modified sign will take precedence over the git signs.
10141018
Type: `string`, Default: `before`
10151019

1020+
*nvim-tree.renderer.icons.diagnostics_placement*
1021+
Place where the diagnostics icon will be rendered.
1022+
Can be `"after"` or `"before"` filename (after the file/folders icons)
1023+
or `"signcolumn"` (requires |nvim-tree.view.signcolumn| enabled).
1024+
Type: `string`, Default: `signcolumn`
1025+
10161026
*nvim-tree.renderer.icons.modified_placement*
10171027
Place where the modified icon will be rendered.
10181028
Can be `"after"` or `"before"` filename (after the file/folders icons)
@@ -1048,6 +1058,11 @@ UI rendering setup
10481058
Requires |git.enable| `= true`
10491059
Type: `boolean`, Default: `true`
10501060

1061+
*nvim-tree.renderer.icons.show.diagnostics*
1062+
Show a diagnostics status icon, see |renderer.icons.diagnostics_placement|
1063+
Requires |diagnostics.enable| `= true`
1064+
Type: `boolean`, Default: `true`
1065+
10511066
*nvim-tree.renderer.icons.show.modified*
10521067
Show a modified icon, see |renderer.icons.modified_placement|
10531068
Requires |modified.enable| `= true`
@@ -2079,6 +2094,14 @@ NvimTreeFileNew (NvimTreeGitNew)
20792094
NvimTreeFileDeleted (NvimTreeGitDeleted)
20802095
NvimTreeFileIgnored (NvimTreeGitIgnored)
20812096

2097+
There are also links for text highlight for diagnostic status, linked by
2098+
default to their icon equivalent.
2099+
2100+
NvimTreeLspDiagnosticsErrorText (NvimTreeLspDiagnosticsError)
2101+
NvimTreeLspDiagnosticsWarningText (NvimTreeLspDiagnosticsWarning)
2102+
NvimTreeLspDiagnosticsInfoText (NvimTreeLspDiagnosticsInformation)
2103+
NvimTreeLspDiagnosticsHintText (NvimTreeLspDiagnosticsHint)
2104+
20822105
There are 2 highlight groups for the live filter feature
20832106

20842107
NvimTreeLiveFilterPrefix

lua/nvim-tree.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
409409
add_trailing = false,
410410
group_empty = false,
411411
highlight_git = false,
412+
highlight_diagnostics = false,
412413
full_name = false,
413414
highlight_opened_files = "none",
414415
highlight_modified = "none",
@@ -437,6 +438,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
437438
},
438439
},
439440
git_placement = "before",
441+
diagnostics_placement = "signcolumn",
440442
modified_placement = "after",
441443
padding = " ",
442444
symlink_arrow = "",
@@ -445,6 +447,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
445447
folder = true,
446448
folder_arrow = true,
447449
git = true,
450+
diagnostics = true,
448451
modified = true,
449452
},
450453
glyphs = {

lua/nvim-tree/colors.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ local function get_links()
8181
FileStaged = "NvimTreeGitStaged",
8282
FileDeleted = "NvimTreeGitDeleted",
8383
FileIgnored = "NvimTreeGitIgnored",
84+
LspDiagnosticsError = "DiagnosticError",
85+
LspDiagnosticsWarning = "DiagnosticWarn",
86+
LspDiagnosticsInformation = "DiagnosticInfo",
87+
LspDiagnosticsHint = "DiagnosticHint",
88+
LspDiagnosticsErrorText = "NvimTreeLspDiagnosticsError",
89+
LspDiagnosticsWarningText = "NvimTreeLspDiagnosticsWarning",
90+
LspDiagnosticsInformationText = "NvimTreeLspDiagnosticsInformation",
91+
LspDiagnosticsHintText = "NvimTreeLspDiagnosticsHintFile",
8492
Popup = "Normal",
8593
GitIgnored = "Comment",
8694
StatusLine = "StatusLine",

lua/nvim-tree/diagnostics.lua

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,7 @@ local log = require "nvim-tree.log"
55

66
local M = {}
77

8-
local GROUP = "NvimTreeDiagnosticSigns"
9-
108
local severity_levels = { Error = 1, Warning = 2, Information = 3, Hint = 4 }
11-
local sign_names = {
12-
{ "NvimTreeSignError", "NvimTreeLspDiagnosticsError" },
13-
{ "NvimTreeSignWarning", "NvimTreeLspDiagnosticsWarning" },
14-
{ "NvimTreeSignInformation", "NvimTreeLspDiagnosticsInformation" },
15-
{ "NvimTreeSignHint", "NvimTreeLspDiagnosticsHint" },
16-
}
17-
18-
local function add_sign(linenr, severity)
19-
local buf = view.get_bufnr()
20-
if not vim.api.nvim_buf_is_valid(buf) or not vim.api.nvim_buf_is_loaded(buf) then
21-
return
22-
end
23-
local sign_name = sign_names[severity][1]
24-
vim.fn.sign_place(0, GROUP, sign_name, buf, { lnum = linenr, priority = 2 })
25-
end
269

2710
local function from_nvim_lsp()
2811
local buffer_severity = {}
@@ -85,14 +68,6 @@ local function is_using_coc()
8568
return vim.g.coc_service_initialized == 1
8669
end
8770

88-
function M.clear()
89-
if not M.enable or not view.is_buf_valid(view.get_bufnr()) then
90-
return
91-
end
92-
93-
vim.fn.sign_unplace(GROUP)
94-
end
95-
9671
function M.update()
9772
if not M.enable or not core.get_explorer() or not view.is_buf_valid(view.get_bufnr()) then
9873
return
@@ -108,8 +83,6 @@ function M.update()
10883
buffer_severity = from_nvim_lsp()
10984
end
11085

111-
M.clear()
112-
11386
local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, core.get_nodes_starting_line())
11487
for _, node in pairs(nodes_by_line) do
11588
node.diag_status = nil
@@ -129,26 +102,18 @@ function M.update()
129102
then
130103
log.line("diagnostics", " matched fold node '%s'", node.absolute_path)
131104
node.diag_status = severity
132-
add_sign(line, severity)
133105
elseif nodepath == bufpath then
134106
log.line("diagnostics", " matched file node '%s'", node.absolute_path)
135107
node.diag_status = severity
136-
add_sign(line, severity)
137108
end
138109
end
139110
end
140111
end
141112
log.profile_end(profile)
113+
require("nvim-tree.renderer").draw()
142114
end)
143115
end
144116

145-
local links = {
146-
NvimTreeLspDiagnosticsError = "DiagnosticError",
147-
NvimTreeLspDiagnosticsWarning = "DiagnosticWarn",
148-
NvimTreeLspDiagnosticsInformation = "DiagnosticInfo",
149-
NvimTreeLspDiagnosticsHint = "DiagnosticHint",
150-
}
151-
152117
function M.setup(opts)
153118
M.enable = opts.diagnostics.enable
154119
M.debounce_delay = opts.diagnostics.debounce_delay
@@ -160,14 +125,6 @@ function M.setup(opts)
160125

161126
M.show_on_dirs = opts.diagnostics.show_on_dirs
162127
M.show_on_open_dirs = opts.diagnostics.show_on_open_dirs
163-
vim.fn.sign_define(sign_names[1][1], { text = opts.diagnostics.icons.error, texthl = sign_names[1][2] })
164-
vim.fn.sign_define(sign_names[2][1], { text = opts.diagnostics.icons.warning, texthl = sign_names[2][2] })
165-
vim.fn.sign_define(sign_names[3][1], { text = opts.diagnostics.icons.info, texthl = sign_names[3][2] })
166-
vim.fn.sign_define(sign_names[4][1], { text = opts.diagnostics.icons.hint, texthl = sign_names[4][2] })
167-
168-
for lhs, rhs in pairs(links) do
169-
vim.cmd("hi def link " .. lhs .. " " .. rhs)
170-
end
171128
end
172129

173130
return M

lua/nvim-tree/renderer/builder.lua

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local git = require "nvim-tree.renderer.components.git"
55
local pad = require "nvim-tree.renderer.components.padding"
66
local icons = require "nvim-tree.renderer.components.icons"
77
local modified = require "nvim-tree.renderer.components.modified"
8+
local diagnostics = require "nvim-tree.renderer.components.diagnostics"
89

910
local Builder = {}
1011
Builder.__index = Builder
@@ -72,6 +73,14 @@ function Builder:configure_git_icons_placement(where)
7273
return self
7374
end
7475

76+
function Builder:configure_diagnostics_icon_placement(where)
77+
if where ~= "after" and where ~= "before" and where ~= "signcolumn" then
78+
where = "before" -- default before
79+
end
80+
self.diagnostics_placement = where
81+
return self
82+
end
83+
7584
function Builder:configure_modified_placement(where)
7685
if where ~= "after" and where ~= "before" and where ~= "signcolumn" then
7786
where = "after" -- default after
@@ -206,20 +215,29 @@ end
206215
function Builder:_get_git_icons(node)
207216
local git_icons = git.get_icons(node)
208217
if git_icons and #git_icons > 0 and self.git_placement == "signcolumn" then
209-
local sign = git_icons[1]
210-
table.insert(self.signs, { sign = sign.hl, lnum = self.index + 1, priority = 1 })
218+
table.insert(self.signs, { sign = git_icons[1].hl, lnum = self.index + 1, priority = 1 })
211219
git_icons = nil
212220
end
213221
return git_icons
214222
end
215223

224+
---@param node table
225+
---@return HighlightedString[]|nil icon
226+
function Builder:_get_diagnostics_icon(node)
227+
local diagnostics_icon = diagnostics.get_icon(node)
228+
if diagnostics_icon and self.diagnostics_placement == "signcolumn" then
229+
table.insert(self.signs, { sign = diagnostics_icon.hl, lnum = self.index + 1, priority = 2 })
230+
diagnostics_icon = nil
231+
end
232+
return diagnostics_icon
233+
end
234+
216235
---@param node table
217236
---@return HighlightedString|nil icon
218237
function Builder:_get_modified_icon(node)
219238
local modified_icon = modified.get_icon(node)
220239
if modified_icon and self.modified_placement == "signcolumn" then
221-
local sign = modified_icon
222-
table.insert(self.signs, { sign = sign.hl, lnum = self.index + 1, priority = 3 })
240+
table.insert(self.signs, { sign = modified_icon.hl, lnum = self.index + 1, priority = 3 })
223241
modified_icon = nil
224242
end
225243
return modified_icon
@@ -263,16 +281,23 @@ function Builder:_get_highlight_override(node, unloaded_bufnr)
263281
end
264282
end
265283

284+
-- diagnostic status
285+
local diagnostic_highlight = diagnostics.get_highlight(node)
286+
if diagnostic_highlight then
287+
name_hl = diagnostic_highlight
288+
end
289+
266290
return icon_hl, name_hl
267291
end
268292

269293
---@param padding HighlightedString
270294
---@param icon HighlightedString
271295
---@param name HighlightedString
272296
---@param git_icons HighlightedString[]|nil
297+
---@param diagnostics_icon HighlightedString|nil
273298
---@param modified_icon HighlightedString|nil
274299
---@return HighlightedString[]
275-
function Builder:_format_line(padding, icon, name, git_icons, modified_icon)
300+
function Builder:_format_line(padding, icon, name, git_icons, diagnostics_icon, modified_icon)
276301
local added_len = 0
277302
local function add_to_end(t1, t2)
278303
for _, v in ipairs(t2) do
@@ -298,13 +323,21 @@ function Builder:_format_line(padding, icon, name, git_icons, modified_icon)
298323
if modified_icon and self.modified_placement == "before" then
299324
add_to_end(line, { modified_icon })
300325
end
326+
if diagnostics_icon and self.diagnostics_placement == "before" then
327+
add_to_end(line, { diagnostics_icon })
328+
end
329+
301330
add_to_end(line, { name })
331+
302332
if git_icons and self.git_placement == "after" then
303333
add_to_end(line, git_icons)
304334
end
305335
if modified_icon and self.modified_placement == "after" then
306336
add_to_end(line, { modified_icon })
307337
end
338+
if diagnostics_icon and self.diagnostics_placement == "after" then
339+
add_to_end(line, { diagnostics_icon })
340+
end
308341

309342
return line
310343
end
@@ -314,6 +347,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
314347
local padding = pad.get_padding(self.depth, idx, num_children, node, self.markers)
315348
local git_icons = self:_get_git_icons(node)
316349
local modified_icon = self:_get_modified_icon(node)
350+
local diagnostics_icon = self:_get_diagnostics_icon(node)
317351

318352
-- main components
319353
local is_folder = node.nodes ~= nil
@@ -336,7 +370,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
336370
name.hl = name_hl
337371
end
338372

339-
local line = self:_format_line(padding, icon, name, git_icons, modified_icon)
373+
local line = self:_format_line(padding, icon, name, git_icons, diagnostics_icon, modified_icon)
340374
self:_insert_line(self:_unwrap_highlighted_strings(line))
341375

342376
self.index = self.index + 1

0 commit comments

Comments
 (0)