Extends the built-in Neovim LSP signature helper handler to add additional functionality, focussing on enhancements for method overloads.
Screen.Recording.05-07-2022.09-38-32.mp4
- Native LSP signatureHelper handler doesn't provide an easy way to view all the possible overloads and parameter details for signatures
- Other Neovim LSP plugins either don't support method overloads in the signatureHelper popup view, or don't focus specifically on method overloads and are therefore lacking in the functionality I wanted from handling multiple signatures
- Neovim ≥ 0.7.0
Install the plugin with the package manager of choice:
--Packer
use { 'Issafalcon/lsp-overloads.nvim'}
Within your custom on-attach
function that you provide as part of the options to the LSP server, setup the plugin, which will override
the built-in signatureHelper
LSP handler:
Example without option overrides
--- Guard against servers without the signatureHelper capability
if client.server_capabilities.signatureHelpProvider then
require('lsp-overloads').setup(client, { })
end
Example with option overrides (defaults shown)
--- Guard against servers without the signatureHelper capability
if client.server_capabilities.signatureHelpProvider then
require('lsp-overloads').setup(client, {
-- UI options are mostly the same as those passed to vim.lsp.util.open_floating_preview
ui = {
border = "single" -- The border to use for the signature popup window. Accepts same border values as |nvim_open_win()|.
height = nil, -- Height of the signature popup window (nil allows dynamic sizing based on content of the help)
width = nil, -- Width of the signature popup window (nil allows dynamic sizing based on content of the help)
wrap = true, -- Wrap long lines
wrap_at = nil, -- Character to wrap at for computing height when wrap enabled
max_width = nil, -- Maximum signature popup width
max_height = nil, -- Maximum signature popup height
-- Events that will close the signature popup window: use {"CursorMoved", "CursorMovedI", "InsertCharPre"} to hide the window when typing
close_events = { "CursorMoved", "BufHidden", "InsertLeave" },
focusable = true, -- Make the popup float focusable
focus = false, -- If focusable is also true, and this is set to true, navigating through overloads will focus into the popup window (probably not what you want)
offset_x = 0, -- Horizontal offset of the floating window relative to the cursor position
offset_y = 0, -- Vertical offset of the floating window relative to the cursor position
floating_window_above_cur_line = false, -- Attempt to float the popup above the cursor position
-- (note, if the height of the float would be greater than the space left above the cursor, it will default
-- to placing the float below the cursor. The max_height option allows for finer tuning of this)
silent = true, -- Prevents noisy notifications (make false to help debug why signature isn't working)
-- Highlight options is null by default, but this just shows an example of how it can be used to modify the LspSignatureActiveParameter highlight property
highlight = {
italic = true,
bold = true,
fg = "#ffffff",
... -- Other options accepted by the `val` parameter of vim.api.nvim_set_hl()
}
},
keymaps = {
next_signature = "<C-j>",
previous_signature = "<C-k>",
next_parameter = "<C-l>",
previous_parameter = "<C-h>",
close_signature = "<A-s>"
},
display_automatically = true -- Uses trigger characters to automatically display the signature overloads when typing a method signature
})
end
LSP trigger characters will cause the signature popup to be displayed. If there are any overloads, the popup will indicate this is the case and you will be able to navigate between the overloads.
Regardless of whether or not overloads exist, you will also be able to navigate between the parameters which will change the content of the signature popup to display the details of the highlighted parameter.
❗NOTE:
- In order to allow the mappings to function correctly, you will need to create mappings for the specific buffer that your LSP client is attached to. Therefore, the mapping below should all be created
within the custom
on_attach
function of the LSP-server.
To trigger the lsp-overloads signature popup manually when in normal mode, you can create the following mapping, as an example:
-- Inside the on_attach function (which passes in 'client' and 'bufnr' params)
...
if client.server_capabilities.signatureHelpProvider then
vim.api.nvim_set_keymap("n", "<A-s>", ":LspOverloadsSignature<CR>", { noremap = true, silent = true, buffer = bufnr })
end
It is also useful to create the corresponding trigger mapping for insert mode too (helps when toggling the popup while in insert mode)
-- Inside the on_attach function (which passes in 'client' and 'bufnr' params)
...
if client.server_capabilities.signatureHelpProvider then
vim.api.nvim_set_keymap("i", "<A-s>", "<cmd>LspOverloadsSignature<CR>", { noremap = true, silent = true, buffer = bufnr })
end
Closing the popup while typing can be done using the pre-configured close_signature
keybind created when the signature window is created (see Keybinds)
- It is recommended to override this to match the keybind you use to trigger the overload popup manually, so toggling is more intuitive
lsp-overloads automatically shows itself by default when you are inside of a function signature and begin typing. You can toggle this feature using
:LspOverloadsSignatureAutoToggle
You can disable this automatic triggering of lsp-overloads by setting 'display_automatically' to false as part of the config.
The default mappings are used to navigate between various signature overloads and parameters when the signature popup is displayed:
next_signature = "<C-j>"
previous_signature = "<C-k>"
next_parameter = "<C-l>"
previous_parameter = "<C-h>"
close_signature = "<A-s>"
NOTE: If you already have a keybinding that matches one of the above, it will only get overwritten when the signature popup is open. When the popup is closed, your original keybinding will be restored in the buffer. If you still need to keep your original mappings while the signature popup is open, you will need to modify these bindings so they no longer conflict
-
Any calls to
vim.lsp.buf.signature_help()
made while the plugin's signature popup is displayed, will behave in the same way as the built-in signature popup (i.e. Whenfocusable
set to true Cursor will enter the popup in normal mode, allowing scrolling behaviour) -
If signatures aren't showing up when you expect them to, try setting
silent
to false. If you then see a popup that statesNo signature help found
, then at least you know it's probably the LSP that isn't returning the signature help.
- omnisharp-vim - For providing the approach that I used to handle the signature overloads and keymappings
- lsp_signature.nvim - The fully featured LSP signature enhancement plugin that I took inspiration from for this plugin
- seblj dotfiles - The starter code I used in this plugin to kick off the signature request
- Neovim core codebase - The handler code that has been modified for this plugin