Make signature and documentation seperate. Signature opens automatically and documentation

opens by calling the open documentation function which can be assigned to keys (ie. <C-S-k>)
main
Bryan 2024-12-23 13:12:59 -06:00
parent 9b4a44c441
commit 3a2a09ea38
2 changed files with 282 additions and 267 deletions

View File

@ -21,11 +21,14 @@ local function get_parameter_label(result)
return "" return ""
end end
if activeParameter > #signature.parameters then if activeParameter >= #signature.parameters then
activeParameter = 0 activeParameter = #signature.parameters - 1
end
if signature.parameters[activeParameter + 1] == nil then
return ""
end end
-- local nextParameter = signature.parameters[activeParameter + 1]
local param = signature.parameters[activeParameter + 1].label local param = signature.parameters[activeParameter + 1].label
local param_str local param_str
-- Handle both string and table parameter labels -- Handle both string and table parameter labels
@ -34,7 +37,7 @@ local function get_parameter_label(result)
local e = param[2] local e = param[2]
param_str = string.sub(signature.label, s, e) param_str = string.sub(signature.label, s, e)
elseif type(param) == "string" then elseif type(param) == "string" then
param_str = label param_str = signature.label
end end
return param_str return param_str
@ -86,9 +89,9 @@ local function _wrap_lines(str, maxlen, opts)
return lines return lines
end end
---@param signature_help table --@param signature_help string[]
---@param maxlen integer --@param maxlen integer
local function convert_signature_help_to_lines(signature_help, maxlen) local function make_signature_lines(signature_help, maxlen)
if not signature_help.signatures then if not signature_help.signatures then
return return
end end
@ -97,6 +100,7 @@ local function convert_signature_help_to_lines(signature_help, maxlen)
if active_signature >= #signature_help.signatures or active_signature < 0 then if active_signature >= #signature_help.signatures or active_signature < 0 then
active_signature = 0 active_signature = 0
end end
local signature = signature_help.signatures[active_signature + 1] local signature = signature_help.signatures[active_signature + 1]
if not signature then if not signature then
return return
@ -111,27 +115,28 @@ local function convert_signature_help_to_lines(signature_help, maxlen)
return wrapped_lines return wrapped_lines
end end
local function apply_treesitter_highlighting(buf, syntax) local function make_doc_lines(result, ft)
if not api.nvim_buf_is_valid(buf) then local active_signature = result.activeSignature or 0
local signature = result.signatures[active_signature + 1]
local doc_lines = {}
if not signature then
return return
end end
if signature.documentation then
if not pcall(require, "nvim-treesitter") then -- if LSP returns plain string, we treat it as plaintext. This avoids
return -- special characters like underscore or similar from being interpreted
-- as markdown font modifiers
if type(signature.documentation) == "string" then
signature.documentation = { kind = "plaintext", value = signature.documentation }
end end
vim.lsp.util.convert_input_to_markdown_lines(signature.documentation, doc_lines)
-- Store current window and buffer end
local current_win = api.nvim_get_current_win() for _, parameter in ipairs(signature.parameters) do
local current_buf = api.nvim_get_current_buf() if parameter.documentation then
vim.lsp.util.convert_input_to_markdown_lines(parameter.documentation, doc_lines)
-- Apply treesitter highlighting end
pcall(function() end
require("nvim-treesitter.highlight").attach(buf, syntax) return doc_lines
end)
-- Restore focus
api.nvim_set_current_win(current_win)
api.nvim_set_current_buf(current_buf)
end end
local _make_floating_popup_size = function(contents, opts) local _make_floating_popup_size = function(contents, opts)
@ -147,7 +152,7 @@ local _make_floating_popup_size = function(contents, opts)
end end
-- local border_width = get_border_size(opts).width -- local border_width = get_border_size(opts).width
local border_width = 2 --TODO: do we need to deal with this parametrically? local border_width = 2 --TODO: do we need to deal with this programmatically?
local screen_width = api.nvim_win_get_width(0) local screen_width = api.nvim_win_get_width(0)
width = math.min(width, screen_width) width = math.min(width, screen_width)
width = math.min(width, max_width) width = math.min(width, max_width)
@ -179,133 +184,188 @@ end
---@param content table window content ---@param content table window content
---@param opts table window options ---@param opts table window options
---@returns (table) Options ---@returns (table) Options
local function _make_floating_popup_options(content, opts) local function _make_floating_popup_options(sig_content, doc_content, opts)
local width, height = _make_floating_popup_size(content, opts) local sig_width, sig_height = _make_floating_popup_size(sig_content, opts)
local doc_width, doc_height = _make_floating_popup_size(doc_content, opts)
local border_height = 2 --TODO: get this from opts
local offset_y = opts.offset_y or 0 local offset_y = opts.offset_y or 0
local offset_x = opts.offset_x or 0 local offset_x = opts.offset_x or 0
local anchor_bias = opts.anchor_bias or "auto" local anchor_bias = opts.anchor_bias or "auto"
local relative = opts.relative or "cursor" local relative = "win"
local anchor = "" local sig_anchor
local row, col local doc_anchor
local sig_row, sig_col
local doc_row, doc_col
local curs_row = vim.fn.winline()
local curs_col = vim.fn.wincol()
local lines_above = opts.relative == "mouse" and vim.fn.getmousepos().line - 1 or vim.fn.winline() - 1 local lines_above = curs_row - 1
local lines_below = vim.fn.winheight(0) - lines_above local lines_below = vim.fn.winheight(0) - lines_above
if if -- figure out signature anchor and height
lines_above < height lines_above < sig_height + border_height
or (anchor_bias == "below" and lines_below > height + offset_y) or (anchor_bias == "below" and lines_below > sig_height + border_height + offset_y)
or (anchor_bias == "auto" and lines_below > lines_above) or (anchor_bias == "auto" and lines_below > lines_above)
then then
anchor = anchor .. "N" sig_anchor = "N"
height = math.min(lines_below - offset_y, height) sig_height = math.min(lines_below - offset_y, sig_height)
row = 1 + offset_y sig_row = curs_row + offset_y
else else
anchor = anchor .. "S" sig_anchor = "S"
height = math.min(lines_above - offset_y, height) sig_height = math.min(lines_above - offset_y, sig_height)
row = 0 - offset_y sig_row = curs_row - 1 - offset_y
end end
local wincol = opts.relative == "mouse" and vim.fn.getmousepos().column or vim.fn.wincol() if sig_anchor == "N" then
lines_below = lines_below - (sig_height + border_height) --new lines_below including sig
if wincol + width + offset_x <= vim.o.columns then
anchor = anchor .. "W"
col = 0 - wincol
else else
anchor = anchor .. "E" lines_above = lines_above - (sig_height + border_height) --new lines_above including sig
col = 1 - wincol
end end
offset_x = opts.offset_x or 0 if -- figure out documentation anchor and height
lines_above < doc_height + border_height
or (anchor_bias == "below" and lines_below > doc_height + border_height)
or (anchor_bias == "auto" and lines_below > lines_above)
then
doc_anchor = "N"
doc_height = math.min(lines_below, doc_height)
if sig_anchor == "N" then --docs and sigs below
doc_row = curs_row + offset_y + (sig_height + border_height) - 1
else --docs above sigs below
doc_row = curs_row - 1 - offset_y
end
else
doc_anchor = "S"
doc_height = math.min(lines_above, doc_height)
if sig_anchor == "S" then --docs and sigs above
doc_row = curs_row - (offset_y + sig_height + border_height)
else --docs below sigs above
doc_row = curs_row - 1 - offset_y
end
end
local wincol = vim.fn.wincol()
if wincol + sig_width + offset_x <= vim.o.columns then
sig_anchor = sig_anchor .. "W"
doc_anchor = doc_anchor .. "W"
sig_col = curs_col - wincol
doc_col = curs_col - wincol
else
sig_anchor = sig_anchor .. "E"
doc_anchor = doc_anchor .. "E"
sig_col = curs_col + 1 - wincol
doc_col = curs_col + 1 - wincol
end
local first_col = vim.fn.getwininfo(vim.fn.win_getid())[1].textoff local first_col = vim.fn.getwininfo(vim.fn.win_getid())[1].textoff
return { return { --signature window options
anchor = anchor, anchor = sig_anchor,
row = row, row = sig_row,
col = col + first_col + offset_x, col = sig_col + first_col + offset_x,
width = width, width = sig_width,
height = height, height = sig_height,
focusable = opts.focusable, focusable = opts.focusable,
relative = relative, relative = relative,
style = "minimal", style = "minimal",
border = opts.border or "rounded", border = opts.border or "rounded",
zindex = opts.zindex or 50, zindex = opts.zindex or 50,
-- winblend = opts.winblend or 10,
}, { --documentation window options
anchor = doc_anchor,
row = doc_row,
col = doc_col + first_col + offset_x,
width = doc_width,
height = doc_height,
focusable = opts.focusable,
relative = relative,
style = "minimal",
border = opts.border or "rounded",
zindex = opts.zindex or 50,
-- winblend = opts.winblend or 10,
} }
end end
local function create_float_window(content, syntax, opts) ---@param result string[] signature help result
---@param syntax string syntax language for highlighting. i.e. "lua" or "markdown"
---@param opts table window options
---@return function function to open signature window
---@return function function to open documentation window
local function create_float_windows(result, syntax, opts)
local npcall = vim.F.npcall local npcall = vim.F.npcall
vim.validate({ vim.validate({
contents = { content, "t" }, result = { result, "t" },
syntax = { syntax, "s", true }, syntax = { syntax, "s", true },
opts = { opts, "t", true }, opts = { opts, "t", true },
}) })
opts = opts or {} opts = opts or {}
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
local existing_float = npcall(api.nvim_buf_get_var, bufnr, "lsp_floating_preview") local existing_sig_win = npcall(api.nvim_buf_get_var, bufnr, "lsp_sig_win")
local existing_doc_win = npcall(api.nvim_buf_get_var, bufnr, "lsp_doc_win")
if existing_float and api.nvim_win_is_valid(existing_float) then if existing_sig_win and api.nvim_win_is_valid(existing_sig_win) then
api.nvim_win_close(existing_float, true) api.nvim_win_close(existing_sig_win, true)
end
if existing_doc_win and api.nvim_win_is_valid(existing_doc_win) then
api.nvim_win_close(existing_doc_win, true)
end end
-- Create the buffer -- Create the buffers
local floating_bufnr = api.nvim_create_buf(false, true) local sig_bufnr = api.nvim_create_buf(false, true)
local doc_bufnr = api.nvim_create_buf(false, true)
if syntax then syntax = syntax or "text"
vim.bo[floating_bufnr].syntax = syntax vim.bo[sig_bufnr].syntax = syntax
vim.bo[floating_bufnr].ft = syntax vim.bo[sig_bufnr].ft = syntax
vim.treesitter.start(floating_bufnr) vim.treesitter.start(sig_bufnr)
end vim.bo[doc_bufnr].syntax = "markdown"
api.nvim_buf_set_lines(floating_bufnr, 0, -1, true, content) vim.bo[doc_bufnr].ft = "markdown"
vim.treesitter.start(doc_bufnr)
local float_options = _make_floating_popup_options(content, opts) local sig_content = make_signature_lines(result, opts.max_width)
local floating_winnr = api.nvim_open_win(floating_bufnr, false, float_options) local doc_content = make_doc_lines(result, syntax)
api.nvim_buf_set_lines(sig_bufnr, 0, -1, true, sig_content)
api.nvim_buf_set_lines(doc_bufnr, 0, -1, true, doc_content)
vim.wo[floating_winnr].conceallevel = 2 local sig_float_options, doc_float_options = _make_floating_popup_options(sig_content, doc_content, opts)
vim.wo[floating_winnr].foldenable = false return function()
vim.bo[floating_bufnr].modifiable = false local sig_winnr = api.nvim_open_win(sig_bufnr, false, sig_float_options)
vim.bo[floating_bufnr].bufhidden = "wipe" vim.wo[sig_winnr].conceallevel = 2
vim.wo[sig_winnr].foldenable = false
api.nvim_buf_set_keymap( vim.bo[sig_bufnr].modifiable = false
floating_bufnr, vim.bo[sig_bufnr].bufhidden = "hide"
"n", -- save focus_id
"q", api.nvim_buf_set_var(bufnr, "lsp_sig_win", sig_winnr)
"<cmd>bdelete<cr>", return sig_bufnr, sig_winnr, sig_content
{ silent = true, noremap = true, nowait = true } end, function()
) local doc_winnr = api.nvim_open_win(doc_bufnr, false, doc_float_options)
vim.wo[doc_winnr].conceallevel = 2
vim.wo[doc_winnr].foldenable = false
vim.bo[doc_bufnr].modifiable = false
vim.bo[doc_bufnr].bufhidden = "hide"
-- save focus_id -- save focus_id
api.nvim_buf_set_var(bufnr, "lsp_floating_preview", floating_winnr) api.nvim_buf_set_var(doc_bufnr, "lsp_doc_win", doc_winnr)
return doc_bufnr, doc_winnr
return floating_bufnr, floating_winnr end
end end
local function close_float_window(win, buf) local function close_float_window(winnr)
-- Store current window and buffer if winnr and api.nvim_win_is_valid(winnr) then
local current_win = api.nvim_get_current_win() pcall(api.nvim_win_close, winnr, true)
local current_buf = api.nvim_get_current_buf()
if win and api.nvim_win_is_valid(win) then
pcall(api.nvim_win_close, win, true)
end end
if buf and api.nvim_buf_is_valid(buf) then end
pcall(api.nvim_buf_delete, buf, { force = true })
end
win = nil
buf = nil
-- Restore focus local function delete_buffer(bufnr)
pcall(api.nvim_set_current_win, current_win) if bufnr and api.nvim_buf_is_valid(bufnr) then
pcall(api.nvim_set_current_buf, current_buf) pcall(api.nvim_buf_delete, bufnr, { force = true })
-- end end
end end
return { return {
get_parameter_label = get_parameter_label, get_parameter_label = get_parameter_label,
convert_signature_help_to_lines = convert_signature_help_to_lines, create_float_windows = create_float_windows,
apply_treesitter_highlighting = apply_treesitter_highlighting,
create_float_window = create_float_window,
close_float_window = close_float_window, close_float_window = close_float_window,
delete_buffer = delete_buffer,
} }

View File

@ -8,11 +8,13 @@ SignatureHelp.__index = SignatureHelp
function SignatureHelp.new() function SignatureHelp.new()
local instance = setmetatable({ local instance = setmetatable({
sig_win = nil, _display_sig_win = function() end, -- function to open signatures window
sig_buf = nil, _display_doc_win = function() end, -- function to open documentation window
doc_win = nil, sig_content = nil, -- current signature buffer content
doc_buf = nil, sig_winnr = nil,
showing = false, sig_bufnr = nil,
sig_win_height = nil,
sig_win_showing = false,
ns = nil, ns = nil,
markid = nil, markid = nil,
timer = nil, timer = nil,
@ -20,6 +22,11 @@ function SignatureHelp.new()
enabled = false, enabled = false,
normal_mode_active = false, normal_mode_active = false,
current_signature_idx = nil, current_signature_idx = nil,
doc_winnr = nil,
doc_bufnr = nil,
doc_win_showing = false,
doc_win_focused = false,
config = nil, config = nil,
}, SignatureHelp) }, SignatureHelp)
@ -28,8 +35,8 @@ function SignatureHelp.new()
number = true, number = true,
icons = { icons = {
parameter = "", parameter = "",
method = "󰡱", method = "󰡱 ",
documentation = "󱪙", documentation = "󱪙 ",
}, },
colors = { colors = {
parameter = "#86e1fc", parameter = "#86e1fc",
@ -47,7 +54,7 @@ function SignatureHelp.new()
winblend = 10, winblend = 10,
zindex = 200, zindex = 200,
focusable = false, focusable = false,
max_height = 10, max_height = 20,
max_width = 80, max_width = 80,
anchor_bias = "below", -- below|above|auto anchor_bias = "below", -- below|above|auto
relative = "cursor", relative = "cursor",
@ -59,7 +66,6 @@ function SignatureHelp.new()
auto_close = true, auto_close = true,
preview_parameters = true, preview_parameters = true,
debounce_time = 100, debounce_time = 100,
toggle_key = "<C-k>",
render_style = { render_style = {
separator = true, separator = true,
compact = true, compact = true,
@ -70,122 +76,28 @@ function SignatureHelp.new()
return instance return instance
end end
-- local function signature_index_comment(index)
-- if #vim.bo.commentstring ~= 0 then
-- return vim.bo.commentstring:format(index)
-- else
-- return "(" .. index .. ")"
-- end
-- end
-- local function markdown_for_signature_list(signatures, config)
-- local lines, labels = {}, {}
-- local number = config.number and #signatures > 1
-- local max_method_len = 0
--
-- -- First pass to calculate alignment
-- if config.render_style.align_icons then
-- for _, signature in ipairs(signatures) do
-- max_method_len = math.max(max_method_len, #signature.label)
-- end
-- end
--
-- for index, signature in ipairs(signatures) do
-- if not config.render_style.compact then
-- table.insert(lines, "")
-- 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 " "
--
-- -- 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, "```")
--
-- -- -- 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", 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))
-- end
-- table.insert(lines, string.format("%s Documentation:", config.icons.documentation))
-- local doc_lines = vim.split(signature.documentation.value or signature.documentation, "\n")
-- for _, line in ipairs(doc_lines) do
-- table.insert(lines, " " .. line)
-- end
-- end
--
-- if index ~= #signatures and config.render_style.separator then
-- table.insert(lines, string.rep("═", 40))
-- end
-- end
-- return lines, labels
-- end
--
-- function SignatureHelp:create_float_window(contents)
-- local max_width = math.min(self.config.max_width, vim.o.columns)
-- local max_height = math.min(self.config.max_height, #contents)
--
-- -- Calculate optimal position
-- local cursor = api.nvim_win_get_cursor(0)
-- local cursor_line = cursor[1]
-- local screen_line = vim.fn.screenpos(0, cursor_line, 1).row
--
-- local row_offset = self.config.floating_window_above_cur_line and -max_height - 1 or 1
-- if screen_line + row_offset < 1 then
-- row_offset = 2 -- Show below if not enough space above
-- end
--
-- local win_config = {
-- relative = "cursor",
-- row = row_offset - 1,
-- col = 0,
-- width = max_width,
-- height = max_height,
-- style = "minimal",
-- border = self.config.border,
-- zindex = 50, -- Ensure it's above most other floating windows
-- }
--
-- if self.win and api.nvim_win_is_valid(self.win) then
-- api.nvim_win_set_config(self.win, win_config)
-- api.nvim_win_set_buf(self.win, self.buf)
-- else
-- self.buf = api.nvim_create_buf(false, true)
-- self.win = api.nvim_open_win(self.buf, false, win_config)
-- end
--
-- vim.bo[self.buf].modifiable = true
-- api.nvim_buf_set_lines(self.buf, 0, -1, false, contents)
-- 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
--
function SignatureHelp:hide_sig_win() function SignatureHelp:hide_sig_win()
helper.close_float_window(self.sig_win, self.sig_buf) if self.sig_win_showing then
helper.close_float_window(self.sig_winnr)
end
helper.delete_buffer(self.sig_bufnr)
helper.delete_buffer(self.doc_bufnr)
self:hide_doc_win()
self.sig_winnr = nil
self.sig_bufnr = nil
self.doc_bufnr = nil -- we want to nil this here and not when we hide the doc win in case we want to reopen the doc win
self.current_signatures = nil self.current_signatures = nil
self.showing = false self.sig_win_showing = false
end end
function SignatureHelp:hide_doc_win() function SignatureHelp:hide_doc_win()
helper.close_float_window(self.doc_win, self.doc_buf) if self.doc_win_showing then
helper.close_float_window(self.doc_winnr)
self.doc_winnr = nil
self.doc_win_showing = false
end
end end
function SignatureHelp:extract_default_value(param_info) function SignatureHelp:extract_default_value(param_info)
@ -215,7 +127,7 @@ function SignatureHelp:extract_default_value(param_info)
end end
function SignatureHelp:set_active_parameter_highlights(param_str, lines) function SignatureHelp:set_active_parameter_highlights(param_str, lines)
if not self.sig_buf or not api.nvim_buf_is_valid(self.sig_buf) then if not self.sig_bufnr or not api.nvim_buf_is_valid(self.sig_bufnr) then
return return
end end
@ -234,7 +146,7 @@ function SignatureHelp:set_active_parameter_highlights(param_str, lines)
if s and e and s > 0 then if s and e and s > 0 then
self.markid = api.nvim_buf_set_extmark( self.markid = api.nvim_buf_set_extmark(
self.sig_buf, self.sig_bufnr,
self.ns, self.ns,
line_num, line_num,
s, s,
@ -243,21 +155,59 @@ function SignatureHelp:set_active_parameter_highlights(param_str, lines)
end end
end end
function SignatureHelp:display(result) function SignatureHelp:display_sig_win(result)
if not result or not result.signatures or #result.signatures == 0 then if not result or not result.signatures or #result.signatures == 0 then
self:hide_sig_win() self:hide_sig_win()
if self.doc_win_showing then
self:hide_doc_win()
end
return return
end end
local content = helper.convert_signature_help_to_lines(result, self.config.win_opts.max_width) if not self.sig_win_showing then
if not self.showing then local ft = vim.bo.ft
self.sig_buf, self.sig_win = helper.create_float_window(content, "lua", self.config.win_opts) -- TODO: programmatically set file type: self._display_sig_win, self._display_doc_win = helper.create_float_windows(result, ft, self.config.win_opts)
self.sig_bufnr, self.sig_winnr, self.sig_content = self._display_sig_win()
local param_str = helper.get_parameter_label(result) local param_str = helper.get_parameter_label(result)
self:set_active_parameter_highlights(param_str, content) self:set_active_parameter_highlights(param_str, self.sig_content)
self.showing = true self.sig_win_showing = true
end end
local param_str = helper.get_parameter_label(result) local param_str = helper.get_parameter_label(result)
self:set_active_parameter_highlights(param_str, content) self:set_active_parameter_highlights(param_str, self.sig_content)
end
function SignatureHelp:display_doc_win()
if self.doc_win_showing then
return
else
self.doc_bufnr, self.doc_winnr = self._display_doc_win()
self.doc_win_showing = true
self.doc_win_focused = true
local active_winnr = vim.api.nvim_get_current_win()
vim.api.nvim_set_current_win(self.doc_winnr)
exit_docs = function()
vim.api.nvim_set_current_win(active_winnr)
vim.fn.feedkeys("i", "t") --put us back into insert mode
self.doc_win_focused = false
end
if self.doc_bufnr ~= nil then
vim.keymap.set(
"n",
"q",
exit_docs,
{ silent = true, noremap = true, nowait = true, buffer = self.doc_bufnr }
)
vim.keymap.set(
"n",
"<esc>",
exit_docs,
{ silent = true, noremap = true, nowait = true, buffer = self.doc_bufnr }
)
end
end
end end
function SignatureHelp:trigger() function SignatureHelp:trigger()
@ -272,14 +222,17 @@ function SignatureHelp:trigger()
vim.notify("Error in LSP Signature Help: " .. vim.inspect(err), vim.log.levels.ERROR) vim.notify("Error in LSP Signature Help: " .. vim.inspect(err), vim.log.levels.ERROR)
end end
self:hide_sig_win() self:hide_sig_win()
self:hide_doc_win()
return return
end end
if result and result.signatures and #result.signatures > 0 then if result and result.signatures and #result.signatures > 0 then
self.current_signatures = result.signatures self.current_signatures = result.signatures
self:display(result)
self:display_sig_win(result)
else else
self:hide_sig_win() self:hide_sig_win()
self:hide_doc_win()
-- Only notify if not silent and if there was actually no signature help -- Only notify if not silent and if there was actually no signature help
if not self.config.silent and result then if not self.config.silent and result then
vim.notify("No signature help available", vim.log.levels.INFO) vim.notify("No signature help available", vim.log.levels.INFO)
@ -299,22 +252,10 @@ function SignatureHelp:check_capability()
self.enabled = false self.enabled = false
end end
function SignatureHelp:toggle_normal_mode()
self.normal_mode_active = not self.normal_mode_active
if self.normal_mode_active then
self:trigger()
else
self:hide_sig_win()
end
end
function SignatureHelp:setup_autocmds() 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
@ -326,8 +267,6 @@ function SignatureHelp:setup_autocmds()
api.nvim_create_autocmd({ "InsertEnter", "CursorMovedI" }, { api.nvim_create_autocmd({ "InsertEnter", "CursorMovedI" }, {
group = group, group = group,
callback = function() callback = function()
-- vim.notify("trigger")
-- local cmp_visible = require("cmp").visible() -- local cmp_visible = require("cmp").visible()
-- if cmp_visible then -- if cmp_visible then
-- self:hide() -- self:hide()
@ -351,8 +290,11 @@ function SignatureHelp:setup_autocmds()
api.nvim_create_autocmd({ "InsertLeave" }, { api.nvim_create_autocmd({ "InsertLeave" }, {
group = group, group = group,
callback = function() callback = function()
if self.doc_win_focused == false then
self:hide_sig_win() self:hide_sig_win()
self:hide_doc_win()
self.normal_mode_active = false self.normal_mode_active = false
end
end, end,
}) })
@ -375,7 +317,7 @@ function SignatureHelp:next_signature()
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
end end
self:display({ self:display_sig_win({
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,
@ -390,21 +332,28 @@ function SignatureHelp:prev_signature()
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
end end
self:display({ self:display_sig_win({
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:setup_keymaps() function SignatureHelp:toggle_docs()
-- Setup toggle keys using the actual config -- vim.notify("doc_win_showing: " .. vim.inspect(self.doc_win_showing))
local toggle_key = self.config.toggle_key if self.doc_win_showing then
self:hide_doc_win()
elseif self.sig_win_showing then
self:display_doc_win()
end
end
if toggle_key then function SignatureHelp:toggle_normal_mode()
vim.keymap.set("n", toggle_key, function() self.normal_mode_active = not self.normal_mode_active
self:toggle_normal_mode() if self.normal_mode_active then
end, { noremap = true, silent = true, desc = "Toggle signature help in normal mode" }) self:trigger()
else
self:hide_sig_win()
end end
end end
@ -447,14 +396,22 @@ function M.setup(opts)
callback = setup_highlights, callback = setup_highlights,
}) })
-- Setup autocmds and keymaps -- Setup autocmds
signature_help:setup_autocmds() signature_help:setup_autocmds()
signature_help:setup_keymaps()
-- Store instance for potential reuse -- Store instance for potential reuse
M._initialized = true M._initialized = true
M._instance = signature_help M._instance = signature_help
-- Add API methods for external use
M.toggle_docs = function()
signature_help:toggle_docs()
end
M.toggle_normal_mode = function()
signature_help:toggle_normal_mode()
end
return signature_help return signature_help
end end
@ -464,6 +421,4 @@ M.dependencies = {
"nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter",
} }
-- Add API methods for external use
return M return M