Make triggering signature help more robust

main
Bryan 2024-12-20 08:13:15 -06:00
parent 2b21a2aa51
commit 867ac5b1df
1 changed files with 640 additions and 612 deletions

View File

@ -47,7 +47,7 @@ function SignatureHelp.new()
max_width = 40,
floating_window_above_cur_line = true,
preview_parameters = true,
debounce_time = 30,
debounce_time = 100,
dock_toggle_key = "<Leader>sd",
toggle_key = "<C-k>",
dock_mode = {
@ -70,7 +70,7 @@ local function signature_index_comment(index)
if #vim.bo.commentstring ~= 0 then
return vim.bo.commentstring:format(index)
else
return '(' .. index .. ')'
return "(" .. index .. ")"
end
end
@ -92,45 +92,34 @@ local function markdown_for_signature_list(signatures, config)
end
table.insert(labels, #lines + 1)
local suffix = number and (' ' .. signature_index_comment(index)) or ''
local padding = config.render_style.align_icons
and string.rep(" ", max_method_len - #signature.label)
or " "
local suffix = number and (" " .. signature_index_comment(index)) or ""
local padding = config.render_style.align_icons and string.rep(" ", max_method_len - #signature.label) or " "
-- Method signature with syntax highlighting
table.insert(lines, string.format("```%s", vim.bo.filetype))
-- table.insert(lines, string.format("%s Method:", config.icons.method))
table.insert(lines, string.format("%s %s%s%s",
config.icons.method,
signature.label,
padding,
suffix
))
table.insert(lines, string.format("%s %s%s%s", config.icons.method, signature.label, padding, suffix))
table.insert(lines, "```")
-- Parameters section
-- -- Parameters section
-- if signature.parameters and #signature.parameters > 0 then
-- if config.render_style.separator then
-- table.insert(lines, string.rep("─", 40))
-- end
-- table.insert(lines, string.format("%s Parameters:", config.icons.parameter))
-- for _, param in ipairs(signature.parameters) do
-- local param_doc = param.documentation and
-- string.format(" - %s", param.documentation.value or param.documentation) or ""
-- table.insert(lines, string.format(" • %s = %s", param.label, param_doc))
-- local param_doc = param.documentation and string.format(" - %s", vim.inspect(param.documentation))
-- table.insert(lines, string.format(" • %s = %s", vim.inspect(param.label), param_doc))
-- end
-- end
-- Documentation section
if signature.documentation then
if config.render_style.separator then
table.insert(lines, string.rep("-", 40))
table.insert(lines, string.rep("", 40))
end
table.insert(lines, string.format("%s Documentation:", config.icons.documentation))
local doc_lines = vim.split(
signature.documentation.value or signature.documentation,
"\n"
)
local doc_lines = vim.split(signature.documentation.value or signature.documentation, "\n")
for _, line in ipairs(doc_lines) do
table.insert(lines, " " .. line)
end
@ -176,13 +165,12 @@ function SignatureHelp:create_float_window(contents)
self.win = api.nvim_open_win(self.buf, false, win_config)
end
api.nvim_buf_set_option(self.buf, "modifiable", true)
vim.bo[self.buf].modifiable = true
api.nvim_buf_set_lines(self.buf, 0, -1, false, contents)
api.nvim_buf_set_option(self.buf, "modifiable", false)
api.nvim_win_set_option(self.win, "foldenable", false)
api.nvim_win_set_option(self.win, "wrap", true)
api.nvim_win_set_option(self.win, "winblend", self.config.winblend)
vim.bo[self.buf].modifiable = false
vim.wo[self.win][self.buf].foldenable = false
vim.wo[self.win][self.buf].wrap = true
vim.wo[self.win][self.buf].winblend = self.config.winblend
self.visible = true
end
@ -206,6 +194,7 @@ function SignatureHelp:hide()
self.buf = nil
end
self.current_signatures = nil
self.visible = false
-- Restore focus
@ -224,26 +213,29 @@ function SignatureHelp:find_parameter_range(signature_str, parameter_label)
local escaped_label = vim.pesc(parameter_label)
-- Look for the parameter with word boundaries
local pattern = [[\b]] .. escaped_label .. [[\b]]
local start_pos = signature_str:find(pattern)
local pattern = [[\<]] .. escaped_label .. [[\>]]
local start_pos, end_pos = signature_str:find(pattern)
if not start_pos then
-- Fallback: try finding exact match if word boundary search fails
start_pos = signature_str:find(escaped_label)
start_pos, end_pos = signature_str:find(escaped_label)
end
if not start_pos then return nil, nil end
if not start_pos then
return nil, nil
end
local end_pos = start_pos + #parameter_label - 1
-- local end_pos = start_pos + #parameter_label
return start_pos, end_pos
end
function SignatureHelp:extract_default_value(param_info)
-- Check if parameter has documentation that might contain default value
if not param_info.documentation then return nil end
if not param_info.documentation then
return nil
end
local doc = type(param_info.documentation) == "string"
and param_info.documentation
local doc = type(param_info.documentation) == "string" and param_info.documentation
or param_info.documentation.value
-- Look for common default value patterns
@ -255,14 +247,18 @@ function SignatureHelp:extract_default_value(param_info)
for _, pattern in ipairs(patterns) do
local default = doc:match(pattern)
if default then return default end
if default then
return default
end
end
return nil
end
function SignatureHelp:set_active_parameter_highlights(active_parameter, signatures, labels)
if not self.buf or not api.nvim_buf_is_valid(self.buf) then return end
if not self.buf or not api.nvim_buf_is_valid(self.buf) then
return
end
-- Clear existing highlights
api.nvim_buf_clear_namespace(self.buf, -1, 0, -1)
@ -277,12 +273,25 @@ function SignatureHelp:set_active_parameter_highlights(active_parameter, signatu
local signature_str = signature.label
local start_pos, end_pos = self:find_parameter_range(signature_str, label)
if start_pos and end_pos then
api.nvim_buf_add_highlight(self.buf, -1, "LspSignatureActiveParameter", labels[index], start_pos,
end_pos)
api.nvim_buf_add_highlight(
self.buf,
-1,
"LspSignatureActiveParameter",
labels[index],
start_pos,
end_pos
)
end
elseif type(label) == "table" then
local start_pos, end_pos = unpack(label)
api.nvim_buf_add_highlight(self.buf, -1, "LspSignatureActiveParameter", labels[index], start_pos + 5, end_pos + 5)
api.nvim_buf_add_highlight(
self.buf,
-1,
"LspSignatureActiveParameter",
labels[index],
start_pos + 6,
end_pos + 6
)
end
end
end
@ -322,14 +331,7 @@ function SignatureHelp:highlight_icons()
local line = api.nvim_buf_get_lines(self.buf, line_num, line_num + 1, false)[1]
local start_col = line:find(vim.pesc(icon))
if start_col then
api.nvim_buf_add_highlight(
self.buf,
-1,
hl_group,
line_num,
start_col - 1,
start_col - 1 + #icon
)
api.nvim_buf_add_highlight(self.buf, -1, hl_group, line_num, start_col - 1, start_col - 1 + #icon)
end
line_num = line_num + 1
end
@ -347,8 +349,11 @@ function SignatureHelp:display(result)
local current_buf = api.nvim_get_current_buf()
-- Prevent duplicate displays of identical content
if self.current_signatures and vim.deep_equal(result.signatures, self.current_signatures) and
result.activeParameter == self.current_active_parameter then
if
self.current_signatures
and vim.deep_equal(result.signatures, self.current_signatures)
and result.activeParameter == self.current_active_parameter
then
return
end
@ -406,7 +411,10 @@ function SignatureHelp:apply_treesitter_highlighting()
end
function SignatureHelp:trigger()
if not self.enabled then return end
if not self.enabled then
return
end
vim.notify("trigger")
local params = vim.lsp.util.make_position_params()
vim.lsp.buf_request(0, "textDocument/signatureHelp", params, function(err, result, _, _)
@ -454,26 +462,31 @@ function SignatureHelp:setup_autocmds()
local group = api.nvim_create_augroup("LspSignatureHelp", { clear = true })
local function debounced_trigger()
-- vim.defer_fn(function()
-- self:trigger()
-- end, 30)
if self.timer then
vim.fn.timer_stop(self.timer)
end
self.timer = vim.fn.timer_start(30, function()
self.timer = vim.fn.timer_start(self.debounce_time, function()
self:trigger()
end)
end
api.nvim_create_autocmd({ "CursorMovedI", "TextChangedI" }, {
api.nvim_create_autocmd({ "InsertEnter", "CursorMovedI" }, {
group = group,
callback = function()
local cmp_visible = require("cmp").visible()
if cmp_visible then
self:hide()
elseif vim.fn.pumvisible() == 0 then
-- vim.notify("trigger")
-- local cmp_visible = require("cmp").visible()
-- if cmp_visible then
-- self:hide()
-- elseif vim.fn.pumvisible() == 0 then
debounced_trigger()
else
self:hide()
end
end
-- else
-- self:hide()
-- end
end,
})
api.nvim_create_autocmd({ "CursorMoved" }, {
@ -482,15 +495,15 @@ function SignatureHelp:setup_autocmds()
if self.normal_mode_active then
debounced_trigger()
end
end
end,
})
api.nvim_create_autocmd({ "InsertLeave", "BufHidden", "BufLeave" }, {
api.nvim_create_autocmd({ "InsertLeave" }, {
group = group,
callback = function()
self:hide()
self.normal_mode_active = false
end
end,
})
api.nvim_create_autocmd("LspAttach", {
@ -499,7 +512,7 @@ function SignatureHelp:setup_autocmds()
vim.defer_fn(function()
self:check_capability()
end, 100)
end
end,
})
api.nvim_create_autocmd("ColorScheme", {
@ -507,9 +520,13 @@ function SignatureHelp:setup_autocmds()
callback = function()
if self.visible then
self:apply_treesitter_highlighting()
self:set_active_parameter_highlights(self.current_signatures.activeParameter, self.current_signatures, {})
end
self:set_active_parameter_highlights(
self.current_signatures.activeParameter,
self.current_signatures,
{}
)
end
end,
})
end
@ -541,9 +558,7 @@ function SignatureHelp:create_dock_window()
local padding = self.config.dock_mode.padding
local dock_width = win_width - (padding * 2)
local row = self.config.dock_mode.position == "bottom"
and win_height - dock_height - padding
or padding
local row = self.config.dock_mode.position == "bottom" and win_height - dock_height - padding or padding
-- Create dock window with enhanced config
self.dock_win = api.nvim_open_win(self.dock_buf, false, {
@ -575,11 +590,21 @@ function SignatureHelp:create_dock_window()
-- Set up dock window keymaps
local dock_buf_keymaps = {
["q"] = function() self:hide() end,
["<Esc>"] = function() self:hide() end,
["<C-c>"] = function() self:hide() end,
["<C-n>"] = function() self:next_signature() end,
["<C-p>"] = function() self:prev_signature() end,
["q"] = function()
self:hide()
end,
["<Esc>"] = function()
self:hide()
end,
["<C-c>"] = function()
self:hide()
end,
["<C-n>"] = function()
self:next_signature()
end,
["<C-p>"] = function()
self:prev_signature()
end,
}
for key, func in pairs(dock_buf_keymaps) do
@ -598,7 +623,9 @@ end
function SignatureHelp:close_dock_window()
-- Fast check for existing dock window
if not self.dock_win_id then return end
if not self.dock_win_id then
return
end
-- Try to find window by ID
local wins = api.nvim_list_wins()
@ -622,7 +649,9 @@ end
-- Add navigation between multiple signatures
function SignatureHelp:next_signature()
if not self.current_signatures then return end
if not self.current_signatures then
return
end
self.current_signature_idx = (self.current_signature_idx or 0) + 1
if self.current_signature_idx > #self.current_signatures then
self.current_signature_idx = 1
@ -630,12 +659,14 @@ function SignatureHelp:next_signature()
self:display({
signatures = self.current_signatures,
activeParameter = self.current_active_parameter,
activeSignature = self.current_signature_idx - 1
activeSignature = self.current_signature_idx - 1,
})
end
function SignatureHelp:prev_signature()
if not self.current_signatures then return end
if not self.current_signatures then
return
end
self.current_signature_idx = (self.current_signature_idx or 1) - 1
if self.current_signature_idx < 1 then
self.current_signature_idx = #self.current_signatures
@ -643,7 +674,7 @@ function SignatureHelp:prev_signature()
self:display({
signatures = self.current_signatures,
activeParameter = self.current_active_parameter,
activeSignature = self.current_signature_idx - 1
activeSignature = self.current_signature_idx - 1,
})
end
@ -675,7 +706,7 @@ function SignatureHelp:toggle_dock_mode()
if current_sigs then
self:display({
signatures = current_sigs,
activeParameter = current_active
activeParameter = current_active,
})
end
@ -712,10 +743,7 @@ function M.setup(opts)
local signature_help = SignatureHelp.new()
-- Deep merge user config with defaults
signature_help.config = vim.tbl_deep_extend("force",
signature_help._default_config,
opts
)
signature_help.config = vim.tbl_deep_extend("force", signature_help._default_config, opts)
-- Setup highlights with user config
local function setup_highlights()