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
This commit is contained in:
Alexander Courtis 2023-09-03 12:29:33 +10:00 committed by GitHub
parent 28c3980b25
commit 323f65cb9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 148 additions and 64 deletions

View File

@ -345,6 +345,7 @@ applying configuration.
add_trailing = false,
group_empty = false,
highlight_git = false,
highlight_diagnostics = false,
full_name = false,
highlight_opened_files = "none",
highlight_modified = "none",
@ -373,6 +374,7 @@ applying configuration.
},
},
git_placement = "before",
diagnostics_placement = "signcolumn",
modified_placement = "after",
padding = " ",
symlink_arrow = " ➛ ",
@ -381,6 +383,7 @@ applying configuration.
folder = true,
folder_arrow = true,
git = true,
diagnostics = true,
modified = true,
},
glyphs = {
@ -689,15 +692,7 @@ Open a file or directory in your preferred application.
Windows: `{ "/c", "start", '""' }`
*nvim-tree.diagnostics*
Show LSP and COC diagnostics in the signcolumn
Note that the modified sign will take precedence over the diagnostics signs.
`NOTE`: it will use the default diagnostic color groups to highlight the signs.
If you wish to customize, you can override these groups:
- `NvimTreeLspDiagnosticsError`
- `NvimTreeLspDiagnosticsWarning`
- `NvimTreeLspDiagnosticsInformation`
- `NvimTreeLspDiagnosticsHint`
Show LSP and COC diagnostics.
*nvim-tree.diagnostics.enable*
Enable/disable the feature.
@ -881,7 +876,7 @@ Window / buffer setup.
Type: `boolean`, Default: `false`
*nvim-tree.view.signcolumn*
Show diagnostic sign column. Value can be `"yes"`, `"auto"`, `"no"`.
Show |signcolumn|. Value can be `"yes"`, `"auto"`, `"no"`.
Type: `string`, Default: `"yes"`
*nvim-tree.view.float*
@ -910,6 +905,8 @@ Window / buffer setup.
*nvim-tree.renderer*
UI rendering setup
Highlight override precedence: git < opened < modified < diagnostics
*nvim-tree.renderer.add_trailing*
Appends a trailing slash to folder names.
Type: `boolean`, Default: `false`
@ -923,11 +920,17 @@ UI rendering setup
Type: `boolean`, Default: `false`
*nvim-tree.renderer.highlight_git*
Enable file highlight for git attributes using `NvimTreeGit*` highlight groups.
Enable highlight for git attributes using `NvimTreeGit*` highlight groups.
Requires |nvim-tree.git.enable|
This can be used with or without the icons.
Type: `boolean`, Default: `false`
*nvim-tree.renderer.highlight_diagnostics*
Enable highlight for diagnostics using `LspDiagnosticsError*Text` highlight groups.
Requires |nvim-tree.diagnostics.enable|
This can be used with or without the icons.
Type: `boolean`, Default: `false`
*nvim-tree.renderer.highlight_opened_files*
Highlight icons and/or names for |bufloaded()| files using the
`NvimTreeOpenedFile` highlight group.
@ -979,6 +982,8 @@ UI rendering setup
*nvim-tree.renderer.icons*
Configuration options for icons.
Sign column icon precedence: git < modified < diagnostics
*nvim-tree.renderer.icons.web_devicons*
Configure optional plugin `"nvim-tree/nvim-web-devicons"`
@ -1010,9 +1015,14 @@ UI rendering setup
Place where the git icons will be rendered.
Can be `"after"` or `"before"` filename (after the file/folders icons)
or `"signcolumn"` (requires |nvim-tree.view.signcolumn| enabled).
Note that the diagnostic signs and the modified sign will take precedence over the git signs.
Type: `string`, Default: `before`
*nvim-tree.renderer.icons.diagnostics_placement*
Place where the diagnostics icon will be rendered.
Can be `"after"` or `"before"` filename (after the file/folders icons)
or `"signcolumn"` (requires |nvim-tree.view.signcolumn| enabled).
Type: `string`, Default: `signcolumn`
*nvim-tree.renderer.icons.modified_placement*
Place where the modified icon will be rendered.
Can be `"after"` or `"before"` filename (after the file/folders icons)
@ -1048,6 +1058,11 @@ UI rendering setup
Requires |git.enable| `= true`
Type: `boolean`, Default: `true`
*nvim-tree.renderer.icons.show.diagnostics*
Show a diagnostics status icon, see |renderer.icons.diagnostics_placement|
Requires |diagnostics.enable| `= true`
Type: `boolean`, Default: `true`
*nvim-tree.renderer.icons.show.modified*
Show a modified icon, see |renderer.icons.modified_placement|
Requires |modified.enable| `= true`
@ -2079,6 +2094,14 @@ NvimTreeFileNew (NvimTreeGitNew)
NvimTreeFileDeleted (NvimTreeGitDeleted)
NvimTreeFileIgnored (NvimTreeGitIgnored)
There are also links for text highlight for diagnostic status, linked by
default to their icon equivalent.
NvimTreeLspDiagnosticsErrorText (NvimTreeLspDiagnosticsError)
NvimTreeLspDiagnosticsWarningText (NvimTreeLspDiagnosticsWarning)
NvimTreeLspDiagnosticsInfoText (NvimTreeLspDiagnosticsInformation)
NvimTreeLspDiagnosticsHintText (NvimTreeLspDiagnosticsHint)
There are 2 highlight groups for the live filter feature
NvimTreeLiveFilterPrefix

View File

@ -409,6 +409,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
add_trailing = false,
group_empty = false,
highlight_git = false,
highlight_diagnostics = false,
full_name = false,
highlight_opened_files = "none",
highlight_modified = "none",
@ -437,6 +438,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
},
},
git_placement = "before",
diagnostics_placement = "signcolumn",
modified_placement = "after",
padding = " ",
symlink_arrow = "",
@ -445,6 +447,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
folder = true,
folder_arrow = true,
git = true,
diagnostics = true,
modified = true,
},
glyphs = {

View File

@ -81,6 +81,14 @@ local function get_links()
FileStaged = "NvimTreeGitStaged",
FileDeleted = "NvimTreeGitDeleted",
FileIgnored = "NvimTreeGitIgnored",
LspDiagnosticsError = "DiagnosticError",
LspDiagnosticsWarning = "DiagnosticWarn",
LspDiagnosticsInformation = "DiagnosticInfo",
LspDiagnosticsHint = "DiagnosticHint",
LspDiagnosticsErrorText = "NvimTreeLspDiagnosticsError",
LspDiagnosticsWarningText = "NvimTreeLspDiagnosticsWarning",
LspDiagnosticsInformationText = "NvimTreeLspDiagnosticsInformation",
LspDiagnosticsHintText = "NvimTreeLspDiagnosticsHintFile",
Popup = "Normal",
GitIgnored = "Comment",
StatusLine = "StatusLine",

View File

@ -5,24 +5,7 @@ local log = require "nvim-tree.log"
local M = {}
local GROUP = "NvimTreeDiagnosticSigns"
local severity_levels = { Error = 1, Warning = 2, Information = 3, Hint = 4 }
local sign_names = {
{ "NvimTreeSignError", "NvimTreeLspDiagnosticsError" },
{ "NvimTreeSignWarning", "NvimTreeLspDiagnosticsWarning" },
{ "NvimTreeSignInformation", "NvimTreeLspDiagnosticsInformation" },
{ "NvimTreeSignHint", "NvimTreeLspDiagnosticsHint" },
}
local function add_sign(linenr, severity)
local buf = view.get_bufnr()
if not vim.api.nvim_buf_is_valid(buf) or not vim.api.nvim_buf_is_loaded(buf) then
return
end
local sign_name = sign_names[severity][1]
vim.fn.sign_place(0, GROUP, sign_name, buf, { lnum = linenr, priority = 2 })
end
local function from_nvim_lsp()
local buffer_severity = {}
@ -85,14 +68,6 @@ local function is_using_coc()
return vim.g.coc_service_initialized == 1
end
function M.clear()
if not M.enable or not view.is_buf_valid(view.get_bufnr()) then
return
end
vim.fn.sign_unplace(GROUP)
end
function M.update()
if not M.enable or not core.get_explorer() or not view.is_buf_valid(view.get_bufnr()) then
return
@ -108,8 +83,6 @@ function M.update()
buffer_severity = from_nvim_lsp()
end
M.clear()
local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, core.get_nodes_starting_line())
for _, node in pairs(nodes_by_line) do
node.diag_status = nil
@ -129,26 +102,18 @@ function M.update()
then
log.line("diagnostics", " matched fold node '%s'", node.absolute_path)
node.diag_status = severity
add_sign(line, severity)
elseif nodepath == bufpath then
log.line("diagnostics", " matched file node '%s'", node.absolute_path)
node.diag_status = severity
add_sign(line, severity)
end
end
end
end
log.profile_end(profile)
require("nvim-tree.renderer").draw()
end)
end
local links = {
NvimTreeLspDiagnosticsError = "DiagnosticError",
NvimTreeLspDiagnosticsWarning = "DiagnosticWarn",
NvimTreeLspDiagnosticsInformation = "DiagnosticInfo",
NvimTreeLspDiagnosticsHint = "DiagnosticHint",
}
function M.setup(opts)
M.enable = opts.diagnostics.enable
M.debounce_delay = opts.diagnostics.debounce_delay
@ -160,14 +125,6 @@ function M.setup(opts)
M.show_on_dirs = opts.diagnostics.show_on_dirs
M.show_on_open_dirs = opts.diagnostics.show_on_open_dirs
vim.fn.sign_define(sign_names[1][1], { text = opts.diagnostics.icons.error, texthl = sign_names[1][2] })
vim.fn.sign_define(sign_names[2][1], { text = opts.diagnostics.icons.warning, texthl = sign_names[2][2] })
vim.fn.sign_define(sign_names[3][1], { text = opts.diagnostics.icons.info, texthl = sign_names[3][2] })
vim.fn.sign_define(sign_names[4][1], { text = opts.diagnostics.icons.hint, texthl = sign_names[4][2] })
for lhs, rhs in pairs(links) do
vim.cmd("hi def link " .. lhs .. " " .. rhs)
end
end
return M

View File

@ -5,6 +5,7 @@ local git = require "nvim-tree.renderer.components.git"
local pad = require "nvim-tree.renderer.components.padding"
local icons = require "nvim-tree.renderer.components.icons"
local modified = require "nvim-tree.renderer.components.modified"
local diagnostics = require "nvim-tree.renderer.components.diagnostics"
local Builder = {}
Builder.__index = Builder
@ -72,6 +73,14 @@ function Builder:configure_git_icons_placement(where)
return self
end
function Builder:configure_diagnostics_icon_placement(where)
if where ~= "after" and where ~= "before" and where ~= "signcolumn" then
where = "before" -- default before
end
self.diagnostics_placement = where
return self
end
function Builder:configure_modified_placement(where)
if where ~= "after" and where ~= "before" and where ~= "signcolumn" then
where = "after" -- default after
@ -206,20 +215,29 @@ end
function Builder:_get_git_icons(node)
local git_icons = git.get_icons(node)
if git_icons and #git_icons > 0 and self.git_placement == "signcolumn" then
local sign = git_icons[1]
table.insert(self.signs, { sign = sign.hl, lnum = self.index + 1, priority = 1 })
table.insert(self.signs, { sign = git_icons[1].hl, lnum = self.index + 1, priority = 1 })
git_icons = nil
end
return git_icons
end
---@param node table
---@return HighlightedString[]|nil icon
function Builder:_get_diagnostics_icon(node)
local diagnostics_icon = diagnostics.get_icon(node)
if diagnostics_icon and self.diagnostics_placement == "signcolumn" then
table.insert(self.signs, { sign = diagnostics_icon.hl, lnum = self.index + 1, priority = 2 })
diagnostics_icon = nil
end
return diagnostics_icon
end
---@param node table
---@return HighlightedString|nil icon
function Builder:_get_modified_icon(node)
local modified_icon = modified.get_icon(node)
if modified_icon and self.modified_placement == "signcolumn" then
local sign = modified_icon
table.insert(self.signs, { sign = sign.hl, lnum = self.index + 1, priority = 3 })
table.insert(self.signs, { sign = modified_icon.hl, lnum = self.index + 1, priority = 3 })
modified_icon = nil
end
return modified_icon
@ -263,6 +281,12 @@ function Builder:_get_highlight_override(node, unloaded_bufnr)
end
end
-- diagnostic status
local diagnostic_highlight = diagnostics.get_highlight(node)
if diagnostic_highlight then
name_hl = diagnostic_highlight
end
return icon_hl, name_hl
end
@ -270,9 +294,10 @@ end
---@param icon HighlightedString
---@param name HighlightedString
---@param git_icons HighlightedString[]|nil
---@param diagnostics_icon HighlightedString|nil
---@param modified_icon HighlightedString|nil
---@return HighlightedString[]
function Builder:_format_line(padding, icon, name, git_icons, modified_icon)
function Builder:_format_line(padding, icon, name, git_icons, diagnostics_icon, modified_icon)
local added_len = 0
local function add_to_end(t1, t2)
for _, v in ipairs(t2) do
@ -298,13 +323,21 @@ function Builder:_format_line(padding, icon, name, git_icons, modified_icon)
if modified_icon and self.modified_placement == "before" then
add_to_end(line, { modified_icon })
end
if diagnostics_icon and self.diagnostics_placement == "before" then
add_to_end(line, { diagnostics_icon })
end
add_to_end(line, { name })
if git_icons and self.git_placement == "after" then
add_to_end(line, git_icons)
end
if modified_icon and self.modified_placement == "after" then
add_to_end(line, { modified_icon })
end
if diagnostics_icon and self.diagnostics_placement == "after" then
add_to_end(line, { diagnostics_icon })
end
return line
end
@ -314,6 +347,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
local padding = pad.get_padding(self.depth, idx, num_children, node, self.markers)
local git_icons = self:_get_git_icons(node)
local modified_icon = self:_get_modified_icon(node)
local diagnostics_icon = self:_get_diagnostics_icon(node)
-- main components
local is_folder = node.nodes ~= nil
@ -336,7 +370,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
name.hl = name_hl
end
local line = self:_format_line(padding, icon, name, git_icons, modified_icon)
local line = self:_format_line(padding, icon, name, git_icons, diagnostics_icon, modified_icon)
self:_insert_line(self:_unwrap_highlighted_strings(line))
self.index = self.index + 1

View File

@ -0,0 +1,58 @@
local M = {}
local H = {}
local I = {}
---diagnostics text highlight group if there is a status
---@param node table
---@return string|nil highlight
function M.get_highlight(node)
if M.config.diagnostics.enable and M.config.renderer.highlight_diagnostics then
return H[node.diag_status]
end
end
---diagnostics icon if there is a status
---@param node table
---@return HighlightedString|nil modified icon
function M.get_icon(node)
if M.config.diagnostics.enable and M.config.renderer.icons.show.diagnostics then
return I[node.diag_status]
end
end
function M.setup(opts)
M.config = {
diagnostics = opts.diagnostics,
renderer = opts.renderer,
}
H[vim.diagnostic.severity.ERROR] = "NvimTreeLspDiagnosticsErrorText"
H[vim.diagnostic.severity.WARN] = "NvimTreeLspDiagnosticsWarningText"
H[vim.diagnostic.severity.INFO] = "NvimTreeLspDiagnosticsInfoText"
H[vim.diagnostic.severity.HINT] = "NvimTreeLspDiagnosticsHintText"
I[vim.diagnostic.severity.ERROR] = {
str = M.config.diagnostics.icons.error,
hl = "NvimTreeLspDiagnosticsError",
}
I[vim.diagnostic.severity.WARN] = {
str = M.config.diagnostics.icons.warning,
hl = "NvimTreeLspDiagnosticsWarning",
}
I[vim.diagnostic.severity.INFO] = {
str = M.config.diagnostics.icons.info,
hl = "NvimTreeLspDiagnosticsInfo",
}
I[vim.diagnostic.severity.HINT] = {
str = M.config.diagnostics.icons.hint,
hl = "NvimTreeLspDiagnosticsHint",
}
for _, i in ipairs(I) do
vim.fn.sign_define(i.hl, { text = i.str, texthl = i.hl })
end
end
return M

View File

@ -1,5 +1,4 @@
local core = require "nvim-tree.core"
local diagnostics = require "nvim-tree.diagnostics"
local log = require "nvim-tree.log"
local view = require "nvim-tree.view"
local events = require "nvim-tree.events"
@ -9,6 +8,7 @@ local _padding = require "nvim-tree.renderer.components.padding"
local icon_component = require "nvim-tree.renderer.components.icons"
local full_name = require "nvim-tree.renderer.components.full-name"
local git = require "nvim-tree.renderer.components.git"
local diagnostics = require "nvim-tree.renderer.components.diagnostics"
local Builder = require "nvim-tree.renderer.builder"
local live_filter = require "nvim-tree.live-filter"
local marks = require "nvim-tree.marks"
@ -69,6 +69,7 @@ function M.draw(unloaded_bufnr)
:configure_modified_highlighting(M.config.highlight_modified)
:configure_icon_padding(M.config.icons.padding)
:configure_git_icons_placement(M.config.icons.git_placement)
:configure_diagnostics_icon_placement(M.config.icons.diagnostics_placement)
:configure_modified_placement(M.config.icons.modified_placement)
:configure_symlink_destination(M.config.symlink_destination)
:configure_filter(live_filter.filter, live_filter.prefix)
@ -84,7 +85,6 @@ function M.draw(unloaded_bufnr)
vim.api.nvim_win_set_cursor(view.get_winnr(), cursor)
end
diagnostics.update()
marks.draw()
view.grow_from_content()
@ -102,6 +102,7 @@ function M.setup(opts)
full_name.setup(opts)
git.setup(opts)
modified.setup(opts)
diagnostics.setup(opts)
icon_component.setup(opts)
end