Better defaults for nvim-lsp actions
nvim-lsputils
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.
Features
- Floating popup for code actions
- Preview window for references
- Preview window for definition, declaration, type-definition, implementation
- Preview window for document symbol and workspace symbol
- Fuzzy finding of symbols, references, defintion and codeActions [optional]
, , opens tabs, vertical split and horizontal split for
Demo
Code Action:
References:
Custom theming (See below for more details)
Fuzzy search:
Future goals
- LspSearch command to search symbol over workspace and list it in a window.
Prerequisite
- Neovim nightly
Installation
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'
Setup
Add following to init.vim lua chunk as:
lua <
vim.lsp.handlers['textDocument/codeAction'] = function(, , actions) require('lsputil.codeAction').codeactionhandler(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
Default keymaps
For codeaction
In normal mode:
|Key |Action | |:------:|-------------------------------------------| |\
In insert mode(Fuzzy search mode):
|Key |Action | |:------:|-------------------------------------------| |\
For symbols, references, and defintions
(document symbols + workspace symbols + references + defintions)
In normal mode:
|Key |Action | |:------:|-------------------------------------------| |\
In insert mode(Fuzzy search mode):
|Key |Action | |:------:|-------------------------------------------| |\Custom Filetypes
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):
Custom Options
**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:
- lsputilslocation_opts
- lsputilssymbols_opts
- lsputilscodeaction_opts
lsputilslocation_opts defines options for:
- definition handler
- references handler
- declaration handler
- implementation handler
- type_definition hander
- workspace symbol handler
- files symbols handler
- code_action handler
- height (integer) (Defines height of window)
- width (integer) (Defines width of window)
- mode (string)
- list (vimscript dictionary / Lua tables) Accepts 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.
- preview (vimscript dictionary / Lua tables) Accepts 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.
- keymaps (vimscript dictionary / Lua tables) Additional keymaps.
See https://github.com/RishabhRD/popfix to read about keymaps documentation.
lsputilscodeaction_opts takes following key-value pairs:
- height (integer) (Defines height of window)
if value is 0 then a suitable default height is provided. (Specially for
editor mode)
- width (integer) (Defines width of window)
- mode (string)
- split (for split previews (default))
- editor (for floating previews)
- list (vimscript dictionary / Lua tables) Accepts following key/value pairs:
- border (boolean) (borders in floating mode)
- numbering (boolean) (vim window numbering active or not)
- title (string) (title for window)
- border_chars (vimscript dictionary/ Lua table) (border characters for list)
Sample border_chars example:
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.
- prompt (table) (optional and may break)
- border (boolean) (borders in floating mode)
- numbering (boolean) (vim window numbering active or not)
- border_chars (vimscript dictionary/ Lua table) (border characters for list)
Sample border_chars example:
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.
Sample themeing with lua
local border_chars = {
TOP_LEFT = 'โ',
TOP_RIGHT = 'โ',
MID_HORIZONTAL = 'โ',
MID_VERTICAL = 'โ',
BOTTOM_LEFT = 'โ',
BOTTOM_RIGHT = 'โ',
}
vim.g.lsputilslocation_opts = {
height = 24,
mode = 'editor',
preview = {
title = 'Location Preview',
border = true,
borderchars = borderchars
},
keymaps = {
n = {
['Symbols would have fuzzy find features with these configuration
Advanced 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:
lua codeactionhandler(, , 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:</code></pre>lua local function customSelectionHandler(selectedAction) print("Action selected: ", selectedAction) end <pre><code class="lang-">One simple example is integration with nvim-jdtls.</code></pre>lua local jdtls_ui = require'jdtls.ui' function jdtlsui.pickoneasync(items, , _, cb) require'lsputil.codeAction'.codeactionhandler(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.