aboutsummaryrefslogtreecommitdiff
path: root/lua/diagnostic_objects.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/diagnostic_objects.lua')
-rw-r--r--lua/diagnostic_objects.lua113
1 files changed, 113 insertions, 0 deletions
diff --git a/lua/diagnostic_objects.lua b/lua/diagnostic_objects.lua
new file mode 100644
index 0000000..f0fbf97
--- /dev/null
+++ b/lua/diagnostic_objects.lua
@@ -0,0 +1,113 @@
+-- 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