Neovim built-in LSP client implementation is so lightweight and awesome. However, default settings for actions like go-to-definition, code-quickfix, etc may not seem user friendly for many users. But neovim LSP client is highly extensible with lua. This plugin focuses on making such LSP actions highly user friendly.
Fuzzy finding feature is optional for the time being. This is because fuzzy engine of popfix is still in developement. However, it usually doesn't crash and work as expected. For using it read custom options section. For the code snippet read sample theming section.
This plugin utilizes RishabhRD/popfix plugin for managing underlying popups and previews. It can be installed with any plugin manager. For example with vim-plug:
Plug 'RishabhRD/popfix'
Plug 'RishabhRD/nvim-lsputils'
Add following to init.vim lua chunk as:
lua <<EOF
if vim.fn.has('nvim-0.5.1') == 1 then
vim.lsp.handlers['textDocument/codeAction'] = require'lsputil.codeAction'.code_action_handler
vim.lsp.handlers['textDocument/references'] = require'lsputil.locations'.references_handler
vim.lsp.handlers['textDocument/definition'] = require'lsputil.locations'.definition_handler
vim.lsp.handlers['textDocument/declaration'] = require'lsputil.locations'.declaration_handler
vim.lsp.handlers['textDocument/typeDefinition'] = require'lsputil.locations'.typeDefinition_handler
vim.lsp.handlers['textDocument/implementation'] = require'lsputil.locations'.implementation_handler
vim.lsp.handlers['textDocument/documentSymbol'] = require'lsputil.symbols'.document_handler
vim.lsp.handlers['workspace/symbol'] = require'lsputil.symbols'.workspace_handler
else
local bufnr = vim.api.nvim_buf_get_number(0)
vim.lsp.handlers['textDocument/codeAction'] = function(_, _, actions)
require('lsputil.codeAction').code_action_handler(nil, actions, nil, nil, nil)
end
vim.lsp.handlers['textDocument/references'] = function(_, _, result)
require('lsputil.locations').references_handler(nil, result, { bufnr = bufnr }, nil)
end
vim.lsp.handlers['textDocument/definition'] = function(_, method, result)
require('lsputil.locations').definition_handler(nil, result, { bufnr = bufnr, method = method }, nil)
end
vim.lsp.handlers['textDocument/declaration'] = function(_, method, result)
require('lsputil.locations').declaration_handler(nil, result, { bufnr = bufnr, method = method }, nil)
end
vim.lsp.handlers['textDocument/typeDefinition'] = function(_, method, result)
require('lsputil.locations').typeDefinition_handler(nil, result, { bufnr = bufnr, method = method }, nil)
end
vim.lsp.handlers['textDocument/implementation'] = function(_, method, result)
require('lsputil.locations').implementation_handler(nil, result, { bufnr = bufnr, method = method }, nil)
end
vim.lsp.handlers['textDocument/documentSymbol'] = function(_, _, result, _, bufn)
require('lsputil.symbols').document_handler(nil, result, { bufnr = bufn }, nil)
end
vim.lsp.handlers['textDocument/symbol'] = function(_, _, result, _, bufn)
require('lsputil.symbols').workspace_handler(nil, result, { bufnr = bufn }, nil)
end
end
EOF
In normal mode:
Key | Action |
---|---|
<CR> | Applies the codeaction |
<Esc> | Quits the menu without applying codeaction |
q | Quits the menu without applying codeaction |
j | Selects next item |
k | Selects previous item |
<Down> | Selects next item |
<Up> | Selects previous item |
In insert mode(Fuzzy search mode):
Key | Action |
---|---|
<CR> | Applies the codeaction |
<C-c> | Quits the menu without applying codeaction |
<C-n> | Selects next item |
<C-p> | Selects previous item |
<Down> | Selects next item |
<Up> | Selects previous item |
(document symbols + workspace symbols + references + defintions)
In normal mode:
Key | Action |
---|---|
<CR> | Jump to location in same window |
<C-v> | Jump to location in a vertical split |
<C-x> | Jump to location in a horizontal split |
<C-t> | Jump to location in a new tab |
<Esc> | Quits the menu without jumping to location |
q | Quits the menu without jumping to location |
j | Selects next item |
k | Selects previous item |
<Down> | Selects next item |
<Up> | Selects previous item |
In insert mode(Fuzzy search mode):
Key | Action |
---|---|
<CR> | Jump to location in same window |
<C-v> | Jump to location in a vertical split |
<C-x> | Jump to location in a horizontal split |
<C-t> | Jump to location in a new tab |
<C-c> | Quits the menu without jumping to location |
<C-n> | Selects next item |
<C-p> | Selects previous item |
<Down> | Selects next item |
<Up> | Selects previous item |
nvim-lsputils export some custom filetypes for their created buffer. This enables users to do customization for nvim-lsputil buffers.
Custom filetypes are:
For codeaction:
For symbols (workspace and document symbols):
For locations (definition, declaration, references, implementation):
NOTE: EACH attribute of custom opts is optional. If not provided, a suitable default is used in place of it.
nvim-lsputils provides 3 global variables:
These 3 variables are supposed to have vimscript dictionary values (Lua tables)
lsp_utils_location_opts defines options for:
lsp_utils_symbols_opts defines options for:
lsp_utils_codeaction_opts defines options for:
lsp_utils_location_opts and lsp_utils_symbols_opts takes following key-value pairs:
border_chars = {
TOP_LEFT = '┌',
TOP_RIGHT = '┐',
MID_HORIZONTAL = '─',
MID_VERTICAL = '│',
BOTTOM_LEFT = '└',
BOTTOM_RIGHT = '┘',
}
If any of shown key of border_chars is missing then a space character
is used instead of it.border_chars = {
TOP_LEFT = '┌',
TOP_RIGHT = '┐',
MID_HORIZONTAL = '─',
MID_VERTICAL = '│',
BOTTOM_LEFT = '└',
BOTTOM_RIGHT = '┘',
}
If any of shown key of border_chars is missing then a space character
is used instead of it.
lsp_utils_codeaction_opts takes following key-value pairs:
border_chars = {
TOP_LEFT = '┌',
TOP_RIGHT = '┐',
MID_HORIZONTAL = '─',
MID_VERTICAL = '│',
BOTTOM_LEFT = '└',
BOTTOM_RIGHT = '┘',
}
If any of shown key of border_chars is missing then a space character
is used instead of it.border_chars = {
TOP_LEFT = '┌',
TOP_RIGHT = '┐',
MID_HORIZONTAL = '─',
MID_VERTICAL = '│',
BOTTOM_LEFT = '└',
BOTTOM_RIGHT = '┘',
}
If any of shown key of border_chars is missing then a space character
is used instead of it.See https://github.com/RishabhRD/popfix for more documentation of options.
These options helps to get better theme that suits your need.
local border_chars = {
TOP_LEFT = '┌',
TOP_RIGHT = '┐',
MID_HORIZONTAL = '─',
MID_VERTICAL = '│',
BOTTOM_LEFT = '└',
BOTTOM_RIGHT = '┘',
}
vim.g.lsp_utils_location_opts = {
height = 24,
mode = 'editor',
preview = {
title = 'Location Preview',
border = true,
border_chars = border_chars
},
keymaps = {
n = {
['<C-n>'] = 'j',
['<C-p>'] = 'k',
}
}
}
vim.g.lsp_utils_symbols_opts = {
height = 24,
mode = 'editor',
preview = {
title = 'Symbols Preview',
border = true,
border_chars = border_chars
},
prompt = {},
}
Symbols would have fuzzy find features with these configuration
nvim-lsputils provides some extension in handler function definition so that it can be integrated with some other lsp plugins easily.
Currently codeaction supports this extended defintion. Codeaction handler signature is something like:
code_action_handler(_, _, actions, _, _, _, customSelectionHandler)
customSelectionHandler
is not defined by standard docs. However, nvim-lsputils
provide it for easy extension and use with other plugins. customSelectionHandler
is expected to be a function
that accepts the selection action(from all codeactions) as parameter. If provided to the function,
the function executes this customSelectionHandler with selected action instead
of applying codeaction directly.
A simple customSelectionHandler
can look like:
local function customSelectionHandler(selectedAction)
print("Action selected: ", selectedAction)
end
One simple example is integration with nvim-jdtls.
local jdtls_ui = require'jdtls.ui'
function jdtls_ui.pick_one_async(items, _, _, cb)
require'lsputil.codeAction'.code_action_handler(nil, nil, items, nil, nil, nil, cb)
end
This code snippet modifies the nvim-jdtls UI to make use of nvim-lsputils UI. With this code snippet, nvim-lsputils would provide the UI but the action would be decided by the functin parameter cb.