mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 18:58:12 +00:00
feat(explorer): added diagnostics file/directory status
This commit is contained in:
parent
cc1b6c77aa
commit
7f1b60d557
7 changed files with 83 additions and 8 deletions
36
lua/snacks/explorer/diagnostics.lua
Normal file
36
lua/snacks/explorer/diagnostics.lua
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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, { " " })
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue