-- Contains object mappings for vim diagnostics. local vim = assert(vim) -- indw: next diagnostic warning -- ildw: last diagnostic warning -- inde: next diagnostic error -- ilde: last diagnostic error -- indi: next diagnostic info -- ildi: last diagnostic info -- inda: next any diagnostic -- ilda: last any diagnostic local M = {} local function compare_pos(diag, pos) if diag.lnum + 1 < pos[1] then return -1 end if diag.lnum + 1 > pos[1] then return 1 end if diag.col > pos[1] then return 1 end if diag.col < pos[1] then return -1 end return 0 end function M.get_matching_diagnostic(last_or_next, severity) local current_pos = vim.api.nvim_win_get_cursor(0) local bufnr = vim.api.nvim_get_current_buf() local all_diagnostics = vim.diagnostic.get(bufnr) local all_matching_diagnostics = {} for _, diag in pairs(all_diagnostics) do if diag.severity == severity or severity == -1 then table.insert(all_matching_diagnostics, diag) end end local last_matching_diag = nil for _, diag in ipairs(all_matching_diagnostics) do if compare_pos(diag, current_pos) < 0 then if (severity == -1 or diag.severity == severity) and last_or_next ~= 'next' then last_matching_diag = diag end elseif compare_pos(diag, current_pos) > 0 then if last_or_next ~= 'next' then break end if (severity == -1 or diag.severity == severity) then last_matching_diag = diag break end end end if not last_matching_diag and #all_matching_diagnostics > 0 then if last_or_next == 'next' then last_matching_diag = all_matching_diagnostics[1] else last_matching_diag = all_matching_diagnostics[-1] end end return last_matching_diag end local function normalize_position(diag) local lnum = diag.lnum + 1 local elnum = math.max(diag.end_lnum + 1, lnum) local col = math.max(diag.col, 0) local ecol = diag.end_col if elnum == lnum then ecol = math.max(col, ecol) end return lnum, col, elnum, ecol end function M.highlight_matching_diagnostic(last_or_next, severity) local diag = M.get_matching_diagnostic(last_or_next, severity) if diag then local l, c, el, ec = normalize_position(diag); -- col, lnum, end_col, end_lnum vim.api.nvim_win_set_cursor(0, { l, c }) if l == el and c == ec and vim.v.operator:match('[cd]') then -- hack to get zero-width matches to work. vim.cmd("normal! i ") end vim.cmd("normal! v") vim.api.nvim_win_set_cursor(0, { el, ec }) else vim.fn.feedkeys('') end end return M