feat: add "jump" options to vim.diagnostic.config() (#29067)

Problem: There is no easy way to configure the behavior of the default
diagnostic "jump" mappings. For example, some users way want to show the
floating window, and some may not (likewise, some way want to only move
between warnings/errors, or disable the "wrap" parameter).

Solution: Add a "jump" table to vim.diagnostic.config() that sets
default values for vim.diagnostic.jump().

Alternatives: Users can override the default mappings to use the exact
options to vim.diagnostic.jump() that they want, but this has a couple
issues:

  - While the default mappings are not complicated, they are also not
    trivial, so overriding them requires users to understand
    implementation details (specifically things like setting "count"
    properly).
  - If plugins want to change the default mappings, or configure the
    behavior in any way (e.g. floating window display), it becomes even
    harder for users to tweak specific behavior.

vim.diagnostic.config() already works quite well as the "entry point"
for tuning knobs with diagnostic UI elements, so this fits in nicely and
composes well with existing mental models and idioms.
This commit is contained in:
Gregory Anders
2024-05-28 14:54:50 -05:00
committed by GitHub
parent f09f5c45fa
commit efa45832ea
5 changed files with 60 additions and 14 deletions

View File

@ -381,7 +381,8 @@ Lua module: vim.diagnostic *diagnostic-api*
*vim.diagnostic.JumpOpts* *vim.diagnostic.JumpOpts*
Extends: |vim.diagnostic.GetOpts| Extends: |vim.diagnostic.GetOpts|
Configuration table with the following keys: Configuration table with the keys listed below. Some parameters can have
their default values changed with |vim.diagnostic.config()|.
Fields: ~ Fields: ~
• {diagnostic}? (`vim.Diagnostic`) The diagnostic to jump to. Mutually • {diagnostic}? (`vim.Diagnostic`) The diagnostic to jump to. Mutually
@ -419,7 +420,7 @@ Lua module: vim.diagnostic *diagnostic-api*
• {disabled}? (`boolean`) • {disabled}? (`boolean`)
*vim.diagnostic.Opts* *vim.diagnostic.Opts*
Each of the configuration options below accepts one of the following: Many of the configuration options below accept one of the following:
• `false`: Disable this feature • `false`: Disable this feature
• `true`: Enable this feature, use default settings. • `true`: Enable this feature, use default settings.
• `table`: Enable this feature with overrides. Use an empty table to use • `table`: Enable this feature with overrides. Use an empty table to use
@ -450,6 +451,9 @@ Lua module: vim.diagnostic *diagnostic-api*
displayed before lower severities (e.g. ERROR is displayed before lower severities (e.g. ERROR is
displayed before WARN). Options: displayed before WARN). Options:
• {reverse}? (boolean) Reverse sort order • {reverse}? (boolean) Reverse sort order
• {jump}? (`vim.diagnostic.Opts.Jump`) Default values for
|vim.diagnostic.jump()|. See
|vim.diagnostic.Opts.Jump|.
*vim.diagnostic.Opts.Float* *vim.diagnostic.Opts.Float*
@ -509,6 +513,16 @@ Lua module: vim.diagnostic *diagnostic-api*
• {focus_id}? (`string`) • {focus_id}? (`string`)
• {border}? (`string`) see |nvim_open_win()|. • {border}? (`string`) see |nvim_open_win()|.
*vim.diagnostic.Opts.Jump*
Fields: ~
• {float}? (`boolean|vim.diagnostic.Opts.Float`) Default value of
the {float} parameter of |vim.diagnostic.jump()|.
• {wrap}? (`boolean`) Default value of the {wrap} parameter of
|vim.diagnostic.jump()|.
• {severity}? (`vim.diagnostic.SeverityFilter`) Default value of the
{severity} parameter of |vim.diagnostic.jump()|.
*vim.diagnostic.Opts.Signs* *vim.diagnostic.Opts.Signs*
Fields: ~ Fields: ~

View File

@ -38,6 +38,11 @@ DEFAULTS
• |[D-default| and |]D-default| jump to the first and last diagnostic in the • |[D-default| and |]D-default| jump to the first and last diagnostic in the
current buffer, respectively. current buffer, respectively.
DIAGNOSTICS
• |vim.diagnostic.config()| accepts a "jump" table to specify defaults for
|vim.diagnostic.jump()|.
EDITOR EDITOR
• The order in which signs are placed was changed. Higher priority signs will • The order in which signs are placed was changed. Higher priority signs will

View File

@ -180,19 +180,19 @@ do
--- See |[d-default|, |]d-default|, and |CTRL-W_d-default|. --- See |[d-default|, |]d-default|, and |CTRL-W_d-default|.
do do
vim.keymap.set('n', ']d', function() vim.keymap.set('n', ']d', function()
vim.diagnostic.jump({ count = vim.v.count1, float = false }) vim.diagnostic.jump({ count = vim.v.count1 })
end, { desc = 'Jump to the next diagnostic in the current buffer' }) end, { desc = 'Jump to the next diagnostic in the current buffer' })
vim.keymap.set('n', '[d', function() vim.keymap.set('n', '[d', function()
vim.diagnostic.jump({ count = -vim.v.count1, float = false }) vim.diagnostic.jump({ count = -vim.v.count1 })
end, { desc = 'Jump to the previous diagnostic in the current buffer' }) end, { desc = 'Jump to the previous diagnostic in the current buffer' })
vim.keymap.set('n', ']D', function() vim.keymap.set('n', ']D', function()
vim.diagnostic.jump({ count = math.huge, wrap = false, float = false }) vim.diagnostic.jump({ count = math.huge, wrap = false })
end, { desc = 'Jump to the last diagnostic in the current buffer' }) end, { desc = 'Jump to the last diagnostic in the current buffer' })
vim.keymap.set('n', '[D', function() vim.keymap.set('n', '[D', function()
vim.diagnostic.jump({ count = -math.huge, wrap = false, float = false }) vim.diagnostic.jump({ count = -math.huge, wrap = false })
end, { desc = 'Jump to the first diagnostic in the current buffer' }) end, { desc = 'Jump to the first diagnostic in the current buffer' })
vim.keymap.set('n', '<C-W>d', function() vim.keymap.set('n', '<C-W>d', function()

View File

@ -42,7 +42,7 @@ local M = {}
--- ---
--- @field namespace? integer --- @field namespace? integer
--- Each of the configuration options below accepts one of the following: --- Many of the configuration options below accept one of the following:
--- - `false`: Disable this feature --- - `false`: Disable this feature
--- - `true`: Enable this feature, use default settings. --- - `true`: Enable this feature, use default settings.
--- - `table`: Enable this feature with overrides. Use an empty table to use default values. --- - `table`: Enable this feature with overrides. Use an empty table to use default values.
@ -78,6 +78,9 @@ local M = {}
--- - {reverse}? (boolean) Reverse sort order --- - {reverse}? (boolean) Reverse sort order
--- (default: `false`) --- (default: `false`)
--- @field severity_sort? boolean|{reverse?:boolean} --- @field severity_sort? boolean|{reverse?:boolean}
---
--- Default values for |vim.diagnostic.jump()|. See |vim.diagnostic.Opts.Jump|.
--- @field jump? vim.diagnostic.Opts.Jump
--- @class (private) vim.diagnostic.OptsResolved --- @class (private) vim.diagnostic.OptsResolved
--- @field float vim.diagnostic.Opts.Float --- @field float vim.diagnostic.Opts.Float
@ -241,6 +244,20 @@ local M = {}
--- whole line the sign is placed in. --- whole line the sign is placed in.
--- @field linehl? table<vim.diagnostic.Severity,string> --- @field linehl? table<vim.diagnostic.Severity,string>
--- @class vim.diagnostic.Opts.Jump
---
--- Default value of the {float} parameter of |vim.diagnostic.jump()|.
--- @field float? boolean|vim.diagnostic.Opts.Float
---
--- Default value of the {wrap} parameter of |vim.diagnostic.jump()|.
--- @field wrap? boolean
---
--- Default value of the {severity} parameter of |vim.diagnostic.jump()|.
--- @field severity? vim.diagnostic.SeverityFilter
---
--- Default value of the {_highest} parameter of |vim.diagnostic.jump()|.
--- @field package _highest? boolean
-- TODO: inherit from `vim.diagnostic.Opts`, implement its fields. -- TODO: inherit from `vim.diagnostic.Opts`, implement its fields.
--- Optional filters |kwargs|, or `nil` for all. --- Optional filters |kwargs|, or `nil` for all.
--- @class vim.diagnostic.Filter --- @class vim.diagnostic.Filter
@ -284,6 +301,13 @@ local global_diagnostic_options = {
float = true, float = true,
update_in_insert = false, update_in_insert = false,
severity_sort = false, severity_sort = false,
jump = {
-- Do not show floating window
float = false,
-- Wrap around buffer
wrap = true,
},
} }
--- @class (private) vim.diagnostic.Handler --- @class (private) vim.diagnostic.Handler
@ -1212,7 +1236,8 @@ end
--- See |diagnostic-severity|. --- See |diagnostic-severity|.
--- @field severity? vim.diagnostic.SeverityFilter --- @field severity? vim.diagnostic.SeverityFilter
--- Configuration table with the following keys: --- Configuration table with the keys listed below. Some parameters can have their default values
--- changed with |vim.diagnostic.config()|.
--- @class vim.diagnostic.JumpOpts : vim.diagnostic.GetOpts --- @class vim.diagnostic.JumpOpts : vim.diagnostic.GetOpts
--- ---
--- The diagnostic to jump to. Mutually exclusive with {count}, {namespace}, --- The diagnostic to jump to. Mutually exclusive with {count}, {namespace},
@ -1256,12 +1281,17 @@ end
--- @param opts vim.diagnostic.JumpOpts --- @param opts vim.diagnostic.JumpOpts
--- @return vim.Diagnostic? # The diagnostic that was moved to. --- @return vim.Diagnostic? # The diagnostic that was moved to.
function M.jump(opts) function M.jump(opts)
vim.validate('opts', opts, 'table')
-- One of "diagnostic" or "count" must be provided -- One of "diagnostic" or "count" must be provided
assert( assert(
opts.diagnostic or opts.count, opts.diagnostic or opts.count,
'One of "diagnostic" or "count" must be specified in the options to vim.diagnostic.jump()' 'One of "diagnostic" or "count" must be specified in the options to vim.diagnostic.jump()'
) )
-- Apply configuration options from vim.diagnostic.config()
opts = vim.tbl_deep_extend('keep', opts, global_diagnostic_options.jump)
if opts.diagnostic then if opts.diagnostic then
goto_diagnostic(opts.diagnostic, opts) goto_diagnostic(opts.diagnostic, opts)
return opts.diagnostic return opts.diagnostic
@ -1279,18 +1309,15 @@ function M.jump(opts)
opts.cursor_position = nil opts.cursor_position = nil
end end
-- Copy the opts table so that we can modify it
local opts_ = vim.deepcopy(opts, true)
local diag = nil local diag = nil
while count ~= 0 do while count ~= 0 do
local next = next_diagnostic(count > 0, opts_) local next = next_diagnostic(count > 0, opts)
if not next then if not next then
break break
end end
-- Update cursor position -- Update cursor position
opts_.pos = { next.lnum + 1, next.col } opts.pos = { next.lnum + 1, next.col }
if count > 0 then if count > 0 then
count = count - 1 count = count - 1

View File

@ -379,7 +379,7 @@ local function tbl_extend(behavior, deep_extend, ...)
for i = 1, select('#', ...) do for i = 1, select('#', ...) do
local tbl = select(i, ...) local tbl = select(i, ...)
vim.validate({ ['after the second argument'] = { tbl, 't' } }) vim.validate('after the second argument', tbl, 'table')
--- @cast tbl table<any,any> --- @cast tbl table<any,any>
if tbl then if tbl then
for k, v in pairs(tbl) do for k, v in pairs(tbl) do