Scope-based diagnostic handler dispatching for Neovim. Routes diagnostic display commands to configurable handlers based on scope (cursor, line, buffer, workspace).
- Scope-based commands:
DiagCursor,DiagLine,DiagBuffer,DiagWorkspacewith handler and severity arguments - Navigation:
DiagNext,DiagPrevwith optional severity filtering - Handler lifecycle: Automatic
hide()/show()when switching between handlers for the same scope - Tab completion: Context-aware completion for handler names (filtered by scope) and severity levels
Using lazy.nvim:
{
"njhoffman/diagnostics.nvim",
config = function()
require("diagnostics").setup({
handlers = {
default = my_float_handler,
inline = my_inline_handler,
quickfix = my_quickfix_handler,
},
scopes = {
cursor = "default",
line = "default",
buffer = "quickfix",
workspace = "quickfix",
},
})
end,
}Each handler is a factory function that returns:
function my_handler(opts)
-- opts: user-provided configuration for this handler
return {
scopes = { cursor = true, line = true, buffer = false, workspace = false },
show = function(show_opts)
-- show_opts = { scope = "cursor", severity = number|nil, diagnostics = table }
-- Display diagnostics using your preferred method
end,
hide = function()
-- Optional: clean up display state when switching away from this handler
end,
}
endFloat handler (wraps vim.diagnostic.open_float):
local float_handler = function(opts, float_opts)
float_opts = float_opts or {}
return {
scopes = { cursor = true, line = true, buffer = false, workspace = false },
show = function(show_opts)
show_opts = show_opts or {}
vim.diagnostic.open_float(nil, vim.tbl_extend("force", float_opts, {
severity = show_opts.severity and { min = show_opts.severity } or nil,
}))
end,
hide = function() end,
}
endInline handler (wraps tiny-inline-diagnostic.nvim):
local inline_handler = function(opts)
opts = vim.tbl_deep_extend("force", { preset = "modern" }, opts or {})
require("tiny-inline-diagnostic").setup(opts)
return {
scopes = { cursor = true, line = true, buffer = true, workspace = false },
show = function(show_opts)
show_opts = show_opts or {}
if show_opts.severity then
require("tiny-inline-diagnostic").change_severities({ show_opts.severity })
else
require("tiny-inline-diagnostic").reset()
end
require("tiny-inline-diagnostic").enable()
vim.diagnostic.config({ virtual_text = false })
end,
hide = function()
require("tiny-inline-diagnostic").disable()
vim.diagnostic.config({ virtual_text = true })
end,
}
endQuickfix handler (wraps vim.diagnostic.setqflist):
local quickfix_handler = function(opts)
opts = vim.tbl_deep_extend("force", { title = "LSP Diagnostics" }, opts or {})
return {
scopes = { cursor = false, line = false, buffer = true, workspace = true },
show = function(show_opts)
show_opts = show_opts or {}
local qf_opts = { title = opts.title }
if show_opts.severity then
qf_opts.severity = { min = show_opts.severity }
end
vim.diagnostic.setqflist(qf_opts)
end,
hide = function()
vim.cmd("cclose")
end,
}
end| Command | Scope | Args |
|---|---|---|
DiagCursor |
Cursor position | [handler] [severity] |
DiagLine |
Current line | [handler] [severity] |
DiagBuffer |
Current buffer | [handler] [severity] |
DiagWorkspace |
All buffers | [handler] [severity] |
DiagNext |
Jump forward | [severity] [count] |
DiagPrev |
Jump backward | [severity] [count] |
Severity values: ERROR, WARN, INFO, HINT
:DiagLine " Show line diagnostics with the default handler
:DiagLine inline " Show line diagnostics with the inline handler
:DiagBuffer ERROR " Show buffer diagnostics, errors only
:DiagBuffer inline WARN " Show buffer diagnostics with inline handler, warnings and above
:DiagNext WARN " Jump to next warning-or-above diagnostic
:DiagNext ERROR 3 " Jump forward 3 error diagnostics| Key | Type | Description |
|---|---|---|
handlers |
table<string, function> |
Map of handler name to factory function |
scopes |
table<string, string> |
Map of scope name to default handler name |
Default scope mapping:
{
cursor = "default",
line = "default",
buffer = "quickfix",
workspace = "quickfix",
}make test # Run plenary tests
make lint # Run luacheck + stylua check
make format # Format with stylua