diff --git a/lua/lazyvim/plugins/lsp/keymaps.lua b/lua/lazyvim/plugins/lsp/keymaps.lua index 52dfed9f..65db0057 100644 --- a/lua/lazyvim/plugins/lsp/keymaps.lua +++ b/lua/lazyvim/plugins/lsp/keymaps.lua @@ -3,8 +3,8 @@ local M = {} ---@type LazyKeysLspSpec[]|nil M._keys = nil ----@alias LazyKeysLspSpec LazyKeysSpec|{has?:string} ----@alias LazyKeysLsp LazyKeys|{has?:string} +---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string, cond?:fun():boolean} +---@alias LazyKeysLsp LazyKeys|{has?:string, cond?:fun():boolean} ---@return LazyKeysLspSpec[] function M.get() @@ -40,8 +40,14 @@ function M.get() desc = "Source Action", has = "codeAction", }, - { "]]", function() LazyVim.lsp.words.jump(vim.v.count1) end, has = "documentHighlight", desc = "Next Reference" }, - { "[[", function() LazyVim.lsp.words.jump(-vim.v.count1) end, has = "documentHighlight", desc = "Prev Reference" }, + { "]]", function() LazyVim.lsp.words.jump(vim.v.count1) end, has = "documentHighlight", + desc = "Next Reference", cond = function() return LazyVim.lsp.words.enabled end }, + { "[[", function() LazyVim.lsp.words.jump(-vim.v.count1) end, has = "documentHighlight", + desc = "Prev Reference", cond = function() return LazyVim.lsp.words.enabled end }, + { "", function() LazyVim.lsp.words.jump(vim.v.count1, true) end, has = "documentHighlight", + desc = "Next Reference", cond = function() return LazyVim.lsp.words.enabled end }, + { "", function() LazyVim.lsp.words.jump(-vim.v.count1, true) end, has = "documentHighlight", + desc = "Prev Reference", cond = function() return LazyVim.lsp.words.enabled end }, } if LazyVim.has("inc-rename.nvim") then M._keys[#M._keys + 1] = { @@ -72,7 +78,7 @@ function M.has(buffer, method) return false end ----@return (LazyKeys|{has?:string})[] +---@return LazyKeysLsp[] function M.resolve(buffer) local Keys = require("lazy.core.handler.keys") if not Keys.resolve then @@ -93,8 +99,12 @@ function M.on_attach(_, buffer) local keymaps = M.resolve(buffer) for _, keys in pairs(keymaps) do - if not keys.has or M.has(buffer, keys.has) then + local has = not keys.has or M.has(buffer, keys.has) + local cond = not (keys.cond == false or ((type(keys.cond) == "function") and not keys.cond())) + + if has and cond then local opts = Keys.opts(keys) + opts.cond = nil opts.has = nil opts.silent = opts.silent ~= false opts.buffer = buffer diff --git a/lua/lazyvim/util/lsp.lua b/lua/lazyvim/util/lsp.lua index c281fa85..24a2bc98 100644 --- a/lua/lazyvim/util/lsp.lua +++ b/lua/lazyvim/util/lsp.lua @@ -210,8 +210,9 @@ function M.format(opts) end end ----@alias LspWord {from:{[1]:number, [2]:number}, to:{[1]:number, [2]:number}, current?:boolean} 1-0 indexed +---@alias LspWord {from:{[1]:number, [2]:number}, to:{[1]:number, [2]:number}} 1-0 indexed M.words = {} +M.words.enabled = false M.words.ns = vim.api.nvim_create_namespace("vim_lsp_references") ---@param opts? {enabled?: boolean} @@ -220,11 +221,13 @@ function M.words.setup(opts) if not opts.enabled then return end + M.words.enabled = true local handler = vim.lsp.handlers["textDocument/documentHighlight"] vim.lsp.handlers["textDocument/documentHighlight"] = function(err, result, ctx, config) if not vim.api.nvim_buf_is_loaded(ctx.bufnr) then return end + vim.lsp.buf.clear_references() return handler(err, result, ctx, config) end @@ -233,7 +236,7 @@ function M.words.setup(opts) group = vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true }), buffer = buf, callback = function(ev) - if not M.words.at() then + if not ({ M.words.get() })[2] then if ev.event:find("CursorMoved") then vim.lsp.buf.clear_references() else @@ -245,38 +248,35 @@ function M.words.setup(opts) end) end ----@return LspWord[] +---@return LspWord[] words, number? current function M.words.get() local cursor = vim.api.nvim_win_get_cursor(0) - return vim.tbl_map(function(extmark) - local ret = { + local current, ret = nil, {} ---@type number?, LspWord[] + for _, extmark in ipairs(vim.api.nvim_buf_get_extmarks(0, M.words.ns, 0, -1, { details = true })) do + local w = { from = { extmark[2] + 1, extmark[3] }, to = { extmark[4].end_row + 1, extmark[4].end_col }, } - if cursor[1] >= ret.from[1] and cursor[1] <= ret.to[1] and cursor[2] >= ret.from[2] and cursor[2] <= ret.to[2] then - ret.current = true - end - return ret - end, vim.api.nvim_buf_get_extmarks(0, M.words.ns, 0, -1, { details = true })) -end - ----@param words? LspWord[] ----@return LspWord?, number? -function M.words.at(words) - for idx, word in ipairs(words or M.words.get()) do - if word.current then - return word, idx + ret[#ret + 1] = w + if cursor[1] >= w.from[1] and cursor[1] <= w.to[1] and cursor[2] >= w.from[2] and cursor[2] <= w.to[2] then + current = #ret end end + return ret, current end -function M.words.jump(count) - local words = M.words.get() - local _, idx = M.words.at(words) +---@param count number +---@param cycle? boolean +function M.words.jump(count, cycle) + local words, idx = M.words.get() if not idx then return end - local target = words[idx + count] + idx = idx + count + if cycle then + idx = (idx - 1) % #words + 1 + end + local target = words[idx] if target then vim.api.nvim_win_set_cursor(0, target.from) end