Skip to content

feat: add renderer.icons.diagnostic_placement #2152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,14 @@ local function setup_autocommands(opts)
create_nvim_tree_autocmd("DiagnosticChanged", {
callback = function()
log.line("diagnostics", "DiagnosticChanged")
require("nvim-tree.diagnostics").update()
require("nvim-tree.renderer").draw()
end,
})
create_nvim_tree_autocmd("User", {
pattern = "CocDiagnosticChange",
callback = function()
log.line("diagnostics", "CocDiagnosticChange")
require("nvim-tree.diagnostics").update()
require("nvim-tree.renderer").draw()
end,
})
end
Expand Down Expand Up @@ -406,6 +406,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
},
icons = {
webdev_colors = true,
diagnostic_placement = "signcolumn",
git_placement = "before",
modified_placement = "after",
padding = " ",
Expand Down
82 changes: 29 additions & 53 deletions lua/nvim-tree/diagnostics.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local utils = require "nvim-tree.utils"
local view = require "nvim-tree.view"
local core = require "nvim-tree.core"
local log = require "nvim-tree.log"
Expand All @@ -15,7 +14,15 @@ local sign_names = {
{ "NvimTreeSignHint", "NvimTreeLspDiagnosticsHint" },
}

local function add_sign(linenr, severity)
function M.get_sign(severity)
if not severity then
return nil
end

return M.diagnostic_icons[severity]
end

function M.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
Expand Down Expand Up @@ -86,53 +93,16 @@ function M.clear()
vim.fn.sign_unplace(GROUP)
end

function M.update()
function M.get_diagnostics()
if not M.enable or not core.get_explorer() or not view.is_buf_valid(view.get_bufnr()) then
return
return {}
end
utils.debounce("diagnostics", M.debounce_delay, function()
local profile = log.profile_start "diagnostics update"
log.line("diagnostics", "update")

local buffer_severity
if is_using_coc() then
buffer_severity = from_coc()
else
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
end

for bufname, severity in pairs(buffer_severity) do
local bufpath = utils.canonical_path(bufname)
log.line("diagnostics", " bufpath '%s' severity %d", bufpath, severity)
if 0 < severity and severity < 5 then
for line, node in pairs(nodes_by_line) do
local nodepath = utils.canonical_path(node.absolute_path)
log.line("diagnostics", " %d checking nodepath '%s'", line, nodepath)
if
M.show_on_dirs
and vim.startswith(bufpath:gsub("\\", "/"), nodepath:gsub("\\", "/") .. "/")
and (not node.open or M.show_on_open_dirs)
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)
end)
if is_using_coc() then
return from_coc()
else
return from_nvim_lsp()
end
end

local links = {
Expand All @@ -146,18 +116,24 @@ function M.setup(opts)
M.enable = opts.diagnostics.enable
M.debounce_delay = opts.diagnostics.debounce_delay
M.severity = opts.diagnostics.severity
M.diagnostic_icons = {
{ str = opts.diagnostics.icons.error, hl = sign_names[1][2] },
{ str = opts.diagnostics.icons.warning, hl = sign_names[2][2] },
{ str = opts.diagnostics.icons.info, hl = sign_names[3][2] },
{ str = opts.diagnostics.icons.hint, hl = sign_names[4][2] },
}

if opts.renderer.icons.diagnostic_placement == "signcolumn" then
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] })
end

if M.enable then
log.line("diagnostics", "setup")
end

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
Expand Down
95 changes: 84 additions & 11 deletions lua/nvim-tree/renderer/builder.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
local utils = require "nvim-tree.utils"
local core = require "nvim-tree.core"

local log = require "nvim-tree.log"
local diagnostics = require "nvim-tree.diagnostics"
local git = require "nvim-tree.renderer.components.git"
local pad = require "nvim-tree.renderer.components.padding"
local icons = require "nvim-tree.renderer.components.icons"
Expand All @@ -23,6 +25,16 @@ function Builder.new(root_cwd)
}, Builder)
end

function Builder:configure_show_on_open_dirs(show_on_open_dirs)
self.show_on_open_dirs = show_on_open_dirs
return self
end

function Builder:configure_show_on_dirs(show_on_dirs)
self.show_on_dirs = show_on_dirs
return self
end

function Builder:configure_root_label(root_folder_label)
self.root_folder_label = root_folder_label or DEFAULT_ROOT_FOLDER_LABEL
return self
Expand Down Expand Up @@ -72,6 +84,14 @@ function Builder:configure_git_icons_placement(where)
return self
end

function Builder:configure_diagnostic_icons_placement(where)
if where ~= "after" and where ~= "before" and where ~= "signcolumn" then
where = "signcolumn"
end
self.diagnostic_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
Expand Down Expand Up @@ -225,6 +245,18 @@ function Builder:_get_modified_icon(node)
return modified_icon
end

---@param node table
---@return HighlightedString|nil icon
function Builder:_get_diagnostic_icon(node, diagnostic_severity)
if self.diagnostic_placement == "signcolumn" and diagnostic_severity then
node.diag_status = diagnostic_severity
diagnostics.add_sign(self.index + 1, diagnostic_severity)
return nil
end

return diagnostics.get_sign(diagnostic_severity)
end

---@param node table
---@return string icon_highlight, string name_highlight
function Builder:_get_highlight_override(node, unloaded_bufnr)
Expand Down Expand Up @@ -272,9 +304,9 @@ end
---@param git_icons 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, modified_icon, diagnostic_icon)
local added_len = 0
local function add_to_end(t1, t2)
local function append_to_line(t1, t2)
for _, v in ipairs(t2) do
if added_len > 0 then
table.insert(t1, { str = self.icon_padding })
Expand All @@ -291,29 +323,39 @@ function Builder:_format_line(padding, icon, name, git_icons, modified_icon)
end

local line = { padding }
add_to_end(line, { icon })
append_to_line(line, { icon })

if git_icons and self.git_placement == "before" then
add_to_end(line, git_icons)
append_to_line(line, git_icons)
end
if modified_icon and self.modified_placement == "before" then
add_to_end(line, { modified_icon })
append_to_line(line, { modified_icon })
end
add_to_end(line, { name })
if diagnostic_icon and self.diagnostic_placement == "before" then
append_to_line(line, { diagnostic_icon })
end

append_to_line(line, { name })

if git_icons and self.git_placement == "after" then
add_to_end(line, git_icons)
append_to_line(line, git_icons)
end
if modified_icon and self.modified_placement == "after" then
add_to_end(line, { modified_icon })
append_to_line(line, { modified_icon })
end
if diagnostic_icon and self.diagnostic_placement == "after" then
append_to_line(line, { diagnostic_icon })
end

return line
end

function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
function Builder:_build_line(node, idx, num_children, unloaded_bufnr, diagnostic_severity)
-- various components
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 diagnostic_icon = self:_get_diagnostic_icon(node, diagnostic_severity)

-- main components
local is_folder = node.nodes ~= nil
Expand All @@ -336,7 +378,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, modified_icon, diagnostic_icon)
self:_insert_line(self:_unwrap_highlighted_strings(line))

self.index = self.index + 1
Expand Down Expand Up @@ -366,13 +408,44 @@ end

function Builder:build(tree, unloaded_bufnr)
local num_children = self:_get_nodes_number(tree.nodes)
local diagnostic_severities_by_path = diagnostics.get_diagnostics()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't fit in here; it should go back in diagnostics.lua.

I like _get_diagnostic_icon - nice and consistent.

Proposal:

  • Move this back into diagnostics.update
  • diagnostics.update records the diagnostic state of the node. Something like git_status
  • call draw following diagnostics.update
  • _get_diagnostic_icon calls something like local diagnostic_icon = diagnostics.get_icon(node)


if self.diagnostic_placement == "signcolumn" then
diagnostics.clear()
end

local idx = 1

local profile = log.profile_start "diagnostic update"
log.line("diagnostics", "update")
for _, node in ipairs(tree.nodes) do
if not node.hidden then
self:_build_line(node, idx, num_children, unloaded_bufnr)
local is_folder = node.nodes ~= nil
local nodepath = utils.canonical_path(node.absolute_path)

local severity = nil
if is_folder then
for bufname, buf_severity in pairs(diagnostic_severities_by_path) do
local bufpath = utils.canonical_path(bufname)
log.line("diagnostics", " %d checking nodepath '%s'", idx, nodepath)
if
self.show_on_dirs
and vim.startswith(bufpath:gsub("\\", "/"), nodepath:gsub("\\", "/") .. "/")
and (not node.open or self.show_on_open_dirs)
then
log.line("diagnostics", " matched folder node '%s'", nodepath)
severity = buf_severity
end
end
elseif diagnostic_severities_by_path[nodepath] then
log.line("diagnostics", " matched file node '%s'", nodepath)
severity = diagnostic_severities_by_path[nodepath]
end
self:_build_line(node, idx, num_children, unloaded_bufnr, severity)
idx = idx + 1
end
end
log.profile_end(profile)

return self
end
Expand Down
6 changes: 4 additions & 2 deletions lua/nvim-tree/renderer/init.lua
Original file line number Diff line number Diff line change
@@ -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 modified = require "nvim-tree.renderer.components.modified"
Expand Down Expand Up @@ -68,6 +67,9 @@ 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_diagnostic_icons_placement(M.config.icons.diagnostic_placement)
:configure_show_on_dirs(M.config.diagnostics.show_on_dirs)
:configure_show_on_open_dirs(M.config.diagnostics.show_on_open_dirs)
:configure_modified_placement(M.config.icons.modified_placement)
:configure_symlink_destination(M.config.symlink_destination)
:configure_filter(live_filter.filter, live_filter.prefix)
Expand All @@ -83,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()
Expand All @@ -93,6 +94,7 @@ end

function M.setup(opts)
M.config = opts.renderer
M.config.diagnostics = opts.diagnostics
M.config.modified = opts.modified

_padding.setup(opts)
Expand Down