feat(lsp): add 'above' codelens position and setup config

This commit is contained in:
2026-04-15 22:05:02 +02:00
parent fe51624839
commit 66b1966fa7
+61 -21
View File
@@ -6,9 +6,11 @@ local REFRESH_DEBOUNCE_MS = 200
local M = {} local M = {}
---@type "eol" | "right_align" | "inline" ---@alias ow.lsp.codelens.Position "eol" | "right_align" | "inline" | "above"
M.virt_text_pos = "eol"
M.separator = " | " ---@type ow.lsp.codelens.Position
local position = "above"
local separator = " | "
---@type table<integer, ow.lsp.codelens.State> ---@type table<integer, ow.lsp.codelens.State>
local state_by_buf = {} local state_by_buf = {}
@@ -69,12 +71,38 @@ function Row:render(buf)
for i, lens in ipairs(self.ready) do for i, lens in ipairs(self.ready) do
table.insert(parts, { lens.command.title, "LspCodeLens" }) table.insert(parts, { lens.command.title, "LspCodeLens" })
if i < #self.ready then if i < #self.ready then
table.insert(parts, { M.separator, "LspCodeLensSeparator" }) table.insert(parts, { separator, "LspCodeLensSeparator" })
end end
end end
local col = M.virt_text_pos == "inline"
and self.ready[1].range.start.character local col, opts
or 0 if position == "above" then
local line = vim.api.nvim_buf_get_lines(
buf,
self.row,
self.row + 1,
false
)[1] or ""
local indent = line:match("^%s*") or ""
local chunks = parts
if indent ~= "" then
chunks = { { indent, "LspCodeLensSeparator" } }
vim.list_extend(chunks, parts)
end
col = 0
opts = {
virt_lines = { chunks },
virt_lines_above = true,
hl_mode = "combine",
}
else
col = position == "inline" and self.ready[1].range.start.character or 0
opts = {
virt_text = parts,
virt_text_pos = position,
hl_mode = "combine",
}
end
-- One extmark per row. Extmarks auto-shift with edits, so multiple from -- One extmark per row. Extmarks auto-shift with edits, so multiple from
-- prior refreshes can end up on the same row; pick the first and drop -- prior refreshes can end up on the same row; pick the first and drop
@@ -95,22 +123,21 @@ function Row:render(buf)
end end
end end
if if primary and primary.col == col and primary.details then
primary local d = primary.details --[[@as vim.api.keyset.extmark_details]]
and primary.col == col local same = opts.virt_lines
and primary.details and vim.deep_equal(d.virt_lines, opts.virt_lines)
and primary.details.virt_text_pos == M.virt_text_pos and d.virt_lines_above == opts.virt_lines_above
and vim.deep_equal(primary.details.virt_text, parts) or not opts.virt_lines
then and d.virt_text_pos == opts.virt_text_pos
and vim.deep_equal(d.virt_text, opts.virt_text)
if same then
return return
end end
end
vim.api.nvim_buf_set_extmark(buf, NS, self.row, col, { opts.id = primary and primary.id or nil
id = primary and primary.id or nil, vim.api.nvim_buf_set_extmark(buf, NS, self.row, col, opts)
virt_text = parts,
virt_text_pos = M.virt_text_pos,
hl_mode = "combine",
})
end end
---@class ow.lsp.codelens.State ---@class ow.lsp.codelens.State
@@ -292,7 +319,20 @@ function M.toggle(buf)
get_state(buf):toggle() get_state(buf):toggle()
end end
function M.setup() ---@class ow.lsp.codelens.SetupOpts
---@field position? ow.lsp.codelens.Position
---@field separator? string
---@param opts? ow.lsp.codelens.SetupOpts
function M.setup(opts)
opts = opts or {}
if opts.position ~= nil then
position = opts.position
end
if opts.separator ~= nil then
separator = opts.separator
end
vim.api.nvim_create_autocmd({ "BufEnter", "LspAttach" }, { vim.api.nvim_create_autocmd({ "BufEnter", "LspAttach" }, {
group = GROUP, group = GROUP,
callback = function(ev) callback = function(ev)