mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
fix(diagnostic): allow virtual_{lines,text} cursor exclusivity #33517
Problem: virtual_text diagnostics are great when skimming a file, and virtual_lines are great when "zooming in" on a particular problem. Having both enabled results in duplicate diagnostics on-screen. Solution: This PR expands the behavior of `current_line` for virtual_text and virtual_lines by making `virtual_text.current_line = false` distinct from `nil`. If you set: vim.diagnostic.config({ virtual_text = { current_line = false }, virtual_lines = { current_line = true }, }) With this configuration, virtual_text will be used to display diagnostics until the cursor reaches the same line, at which point they will be hidden and virtual_lines will take its place.
This commit is contained in:
@@ -624,8 +624,12 @@ Lua module: vim.diagnostic *diagnostic-api*
|
|||||||
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show
|
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show
|
||||||
virtual text for diagnostics matching the given
|
virtual text for diagnostics matching the given
|
||||||
severity |diagnostic-severity|
|
severity |diagnostic-severity|
|
||||||
• {current_line}? (`boolean`) Only show diagnostics for the
|
• {current_line}? (`boolean`) Show or hide diagnostics based on
|
||||||
current line. (default `false`)
|
the current cursor line. If `true`, only
|
||||||
|
diagnostics on the current cursor line are
|
||||||
|
shown. If `false`, all diagnostics are shown
|
||||||
|
except on the current cursor line. If `nil`, all
|
||||||
|
diagnostics are shown. (default `nil`)
|
||||||
• {source}? (`boolean|"if_many"`) Include the diagnostic
|
• {source}? (`boolean|"if_many"`) Include the diagnostic
|
||||||
source in virtual text. Use `'if_many'` to only
|
source in virtual text. Use `'if_many'` to only
|
||||||
show sources if there is more than one
|
show sources if there is more than one
|
||||||
|
@@ -190,8 +190,10 @@ end
|
|||||||
--- severity |diagnostic-severity|
|
--- severity |diagnostic-severity|
|
||||||
--- @field severity? vim.diagnostic.SeverityFilter
|
--- @field severity? vim.diagnostic.SeverityFilter
|
||||||
---
|
---
|
||||||
--- Only show diagnostics for the current line.
|
--- Show or hide diagnostics based on the current cursor line. If `true`, only diagnostics on the
|
||||||
--- (default `false`)
|
--- current cursor line are shown. If `false`, all diagnostics are shown except on the current
|
||||||
|
--- cursor line. If `nil`, all diagnostics are shown.
|
||||||
|
--- (default `nil`)
|
||||||
--- @field current_line? boolean
|
--- @field current_line? boolean
|
||||||
---
|
---
|
||||||
--- Include the diagnostic source in virtual text. Use `'if_many'` to only
|
--- Include the diagnostic source in virtual text. Use `'if_many'` to only
|
||||||
@@ -1562,12 +1564,15 @@ M.handlers.underline = {
|
|||||||
--- @param diagnostics table<integer, vim.Diagnostic[]>
|
--- @param diagnostics table<integer, vim.Diagnostic[]>
|
||||||
--- @param opts vim.diagnostic.Opts.VirtualText
|
--- @param opts vim.diagnostic.Opts.VirtualText
|
||||||
local function render_virtual_text(namespace, bufnr, diagnostics, opts)
|
local function render_virtual_text(namespace, bufnr, diagnostics, opts)
|
||||||
|
local lnum = api.nvim_win_get_cursor(0)[1] - 1
|
||||||
api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1)
|
api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1)
|
||||||
|
|
||||||
for line, line_diagnostics in pairs(diagnostics) do
|
for line, line_diagnostics in pairs(diagnostics) do
|
||||||
local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts)
|
local virt_texts = M._get_virt_text_chunks(line_diagnostics, opts)
|
||||||
|
local skip = (opts.current_line == true and line ~= lnum)
|
||||||
|
or (opts.current_line == false and line == lnum)
|
||||||
|
|
||||||
if virt_texts then
|
if virt_texts and not skip then
|
||||||
api.nvim_buf_set_extmark(bufnr, namespace, line, 0, {
|
api.nvim_buf_set_extmark(bufnr, namespace, line, 0, {
|
||||||
hl_mode = opts.hl_mode or 'combine',
|
hl_mode = opts.hl_mode or 'combine',
|
||||||
virt_text = virt_texts,
|
virt_text = virt_texts,
|
||||||
@@ -1621,32 +1626,18 @@ M.handlers.virtual_text = {
|
|||||||
|
|
||||||
local line_diagnostics = diagnostic_lines(diagnostics)
|
local line_diagnostics = diagnostic_lines(diagnostics)
|
||||||
|
|
||||||
if opts.virtual_text.current_line == true then
|
if opts.virtual_text.current_line ~= nil then
|
||||||
api.nvim_create_autocmd('CursorMoved', {
|
api.nvim_create_autocmd('CursorMoved', {
|
||||||
buffer = bufnr,
|
buffer = bufnr,
|
||||||
group = ns.user_data.virt_text_augroup,
|
group = ns.user_data.virt_text_augroup,
|
||||||
callback = function()
|
callback = function()
|
||||||
local lnum = api.nvim_win_get_cursor(0)[1] - 1
|
render_virtual_text(ns.user_data.virt_text_ns, bufnr, line_diagnostics, opts.virtual_text)
|
||||||
render_virtual_text(
|
|
||||||
ns.user_data.virt_text_ns,
|
|
||||||
bufnr,
|
|
||||||
{ [lnum] = diagnostics_at_cursor(line_diagnostics) },
|
|
||||||
opts.virtual_text
|
|
||||||
)
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
-- Also show diagnostics for the current line before the first CursorMoved event.
|
|
||||||
local lnum = api.nvim_win_get_cursor(0)[1] - 1
|
|
||||||
render_virtual_text(
|
|
||||||
ns.user_data.virt_text_ns,
|
|
||||||
bufnr,
|
|
||||||
{ [lnum] = diagnostics_at_cursor(line_diagnostics) },
|
|
||||||
opts.virtual_text
|
|
||||||
)
|
|
||||||
else
|
|
||||||
render_virtual_text(ns.user_data.virt_text_ns, bufnr, line_diagnostics, opts.virtual_text)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
render_virtual_text(ns.user_data.virt_text_ns, bufnr, line_diagnostics, opts.virtual_text)
|
||||||
|
|
||||||
save_extmarks(ns.user_data.virt_text_ns, bufnr)
|
save_extmarks(ns.user_data.virt_text_ns, bufnr)
|
||||||
end,
|
end,
|
||||||
hide = function(namespace, bufnr)
|
hide = function(namespace, bufnr)
|
||||||
|
@@ -2144,6 +2144,25 @@ describe('vim.diagnostic', function()
|
|||||||
eq(1, #result)
|
eq(1, #result)
|
||||||
eq(' Error here!', result[1][4].virt_text[3][1])
|
eq(' Error here!', result[1][4].virt_text[3][1])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can hide virtual_text for the current line', function()
|
||||||
|
local result = exec_lua(function()
|
||||||
|
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||||
|
|
||||||
|
vim.diagnostic.config({ virtual_text = { current_line = false } })
|
||||||
|
|
||||||
|
vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
|
||||||
|
_G.make_error('Error here!', 0, 0, 0, 0, 'foo_server'),
|
||||||
|
_G.make_error('Another error there!', 1, 0, 1, 0, 'foo_server'),
|
||||||
|
})
|
||||||
|
|
||||||
|
local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
|
||||||
|
return extmarks
|
||||||
|
end)
|
||||||
|
|
||||||
|
eq(1, #result)
|
||||||
|
eq(' Another error there!', result[1][4].virt_text[3][1])
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('handlers.virtual_lines', function()
|
describe('handlers.virtual_lines', function()
|
||||||
|
Reference in New Issue
Block a user