feat(explorer): added diagnostics file/directory status

This commit is contained in:
Folke Lemaitre 2025-02-07 08:45:38 +01:00
parent cc1b6c77aa
commit 7f1b60d557
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
7 changed files with 83 additions and 8 deletions

View file

@ -0,0 +1,36 @@
---@diagnostic disable: missing-fields
local M = {}
---@param cwd string
function M.update(cwd)
local Tree = require("snacks.explorer.tree")
local node = Tree:find(cwd)
Tree:walk(node, function(n)
n.severity = nil
end, { all = true })
local diags = vim.diagnostic.get()
---@param path string
---@param diag vim.Diagnostic
local function add(path, diag)
local n = Tree:find(path)
local severity = tonumber(diag.severity) or vim.diagnostic.severity.INFO
n.severity = math.min(n.severity or severity, severity)
end
for _, diag in ipairs(diags) do
local path = diag.bufnr and vim.api.nvim_buf_get_name(diag.bufnr)
path = path and path ~= "" and vim.fs.normalize(path) or nil
if path then
add(path, diag)
add(cwd, diag)
for dir in Snacks.picker.util.parents(path, cwd) do
add(dir, diag)
end
end
end
end
return M

View file

@ -12,6 +12,7 @@
---@field last? boolean child of the parent
---@field utime? number
---@field children table<string, snacks.picker.explorer.Node>
---@field severity? number
local uv = vim.uv or vim.loop

View file

@ -60,7 +60,9 @@ function M.refresh()
if not picker.list.target then
picker.list:set_target()
end
picker:find()
vim.schedule(function()
picker:find()
end)
end
end)
end

View file

@ -151,6 +151,8 @@ local defaults = {
severity = {
icons = true, -- show severity icons
level = false, -- show severity level
---@type "left"|"right"
pos = "left", -- position of the diagnostics
},
},
---@class snacks.picker.previewers.Config

View file

@ -42,6 +42,8 @@ M.buffers = {
---@field tree? boolean show the file tree (default: true)
---@field git_status? boolean show git status (default: true)
---@field git_status_open? boolean show recursive git status for open directories
---@field diagnostics? boolean show diagnostics
---@field diagnostics_open? boolean show recursive diagnostics for open directories
---@field watch? boolean watch for file changes
M.explorer = {
finder = "explorer",
@ -49,6 +51,8 @@ M.explorer = {
supports_live = true,
tree = true,
watch = true,
diagnostics = true,
diagnostics_open = false,
git_status = true,
git_status_open = false,
follow_file = true,
@ -59,7 +63,10 @@ M.explorer = {
-- to show the explorer to the right, add the below to
-- your config under `opts.picker.sources.explorer`
-- layout = { layout = { position = "right" } },
formatters = { file = { filename_only = true } },
formatters = {
file = { filename_only = true },
severity = { pos = "right" },
},
matcher = { sort_empty = false, fuzzy = false },
config = function(opts)
return require("snacks.picker.source.explorer").setup(opts)

View file

@ -15,14 +15,27 @@ function M.severity(item, picker)
local lower = severity:lower()
local cap = severity:sub(1, 1):upper() .. lower:sub(2)
if picker.opts.formatters.severity.pos == "right" then
return {
{
col = 0,
virt_text = { { picker.opts.icons.diagnostics[cap], "Diagnostic" .. cap } },
virt_text_pos = "right_align",
hl_mode = "combine",
},
}
end
if picker.opts.formatters.severity.icons then
ret[#ret + 1] = { picker.opts.icons.diagnostics[cap], "Diagnostic" .. cap, virtual = true }
ret[#ret + 1] = { " ", virtual = true }
end
if picker.opts.formatters.severity.level then
ret[#ret + 1] = { lower:upper(), "Diagnostic" .. cap, virtual = true }
ret[#ret + 1] = { " ", virtual = true }
end
return ret
end
@ -120,20 +133,20 @@ function M.file(item, picker)
ret[#ret + 1] = { " ", virtual = true }
end
if item.severity then
vim.list_extend(ret, M.severity(item, picker))
end
if item.parent then
vim.list_extend(ret, M.tree(item, picker))
end
vim.list_extend(ret, M.filename(item, picker))
if item.status then
vim.list_extend(ret, M.file_git_status(item, picker))
end
if item.severity then
vim.list_extend(ret, M.severity(item, picker))
end
vim.list_extend(ret, M.filename(item, picker))
if item.comment then
table.insert(ret, { item.comment, "SnacksPickerComment" })
table.insert(ret, { " " })

View file

@ -71,6 +71,15 @@ function State.new(picker)
end
end)
picker.list.win:on("DiagnosticChanged", function(_, ev)
local p = ref()
if p then
require("snacks.explorer.diagnostics").update(p:cwd())
p.list:set_target()
p:find()
end
end)
-- schedule initial follow
if opts.follow_file then
picker.list.win:on({ "WinEnter", "BufEnter" }, function(_, ev)
@ -212,6 +221,10 @@ function M.explorer(opts, ctx)
})
end
if opts.diagnostics then
require("snacks.explorer.diagnostics").update(ctx.filter.cwd)
end
return function(cb)
if state.on_find then
ctx.picker.matcher.task:on("done", vim.schedule_wrap(state.on_find))
@ -232,6 +245,7 @@ function M.explorer(opts, ctx)
status = (not node.dir or not node.open or opts.git_status_open) and node.status or nil,
last = true,
type = node.type,
severity = (not node.dir or not node.open or opts.diagnostics_open) and node.severity or nil,
}
if last[node.parent] then
last[node.parent].last = false