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