lspactions provide handlers for various lsp actions. lspactions also provide utility functions for exposing UI for other components. lspactions targets to be highly extensible and customizable. It uses floating windows for handlers if it really improves workflow(I am biased) otherwise try to provide similar (but highy customizable) handlers to nvim's default handlers.
lspactions require neovim nightly release
Current lspactions handlers:
- codeaction (floating win)
- rename (floating win + robust prompt)
- references (customizable quickfix)
- definition (customizable quickfix)
- declaration (customizable quickfix)
- implementation (customizable quickfix)
- diagnostics (layer on vim.diagnostics)
Current UI exposing functions:
- select (floating win selector for items)
- input (floating prompt input)
document_symbols and workspace_symbols are good with telescope and hence is not targetted. If you feel there is some better way to do the same, feel free to make a PR.
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-lua/popup.nvim'
Plug 'RishabhRD/lspactions'
Floating menu for user to pick a single item from a collection of entries.
vim.ui.select = require'lspactions'.select
It has mostly same spec as vim.ui.select. Please refer :h vim.ui.select
Additional to vim.ui.select
, select suppports following additional options:
- opts.keymaps : table
Sample table(Also default):
opts.keymaps = {
quit = {
n = {
"q",
"<Esc>",
},
},
exec = {
n = {
"<CR>",
},
},
}
Floating menu prompt for user to input some text. The prompt doesn't have any neovim prompt buffer problems.
vim.ui.input = require'lspactions'.input
It has mostly same spec as vim.ui.input. Please refer :h vim.ui.input
Addition to the options provided in vim.ui.input
it supports following
additional options:
- opts.keymaps : table
Sample table(Also default):
opts.keymaps = {
quit = {
i = {
"<C-c>",
},
n = {
"q",
"<Esc>",
},
},
exec = {
i = {
"<CR>",
},
n = {
"<CR>",
},
},
}
quit contains mappings for keys where we don't accept the current input and just want to close the buffer.
exec contains mappings for keys where we accept the current input and have to act upon it.
vim.ui.input = require'lspactions'.input
for renaming functionality.
If user doesn't wish to use floating buffer input globally, then user can use
lspactions rename module.
nnoremap <leader>ar :lua require'lspactions'.rename()<CR>
It doesn't have any of problem that neovim's prompt buffer have that means prompt has old name as initial text and user can seamlessly edit the text inside prompt.
Customization:
require'lspactions'.rename(nil, {
input = vim.ui.input, -- NOT lspactions default
keymap = <keymap_table> -- sample shown in input section
})
input function has same specifications as vim.ui.input
. It describes how
user would input new name for the node.
vim.lsp.handlers["textDocument/codeAction"] = require'lspactions'.codeaction
vim.cmd [[ nnoremap <leader>af :lua require'lspactions'.code_action()<CR> ]]
vim.cmd [[ nnoremap <leader>af :lua require'lspactions'.range_code_action()<CR> ]]
Floating menu for codeaction. You can scroll same as normal vim movements. Press enter to select the action. Or like: press 4 to select action 4.
Customization:
vim.lsp.handlers["textDocument/codeAction"] = vim.lsp.with(require'lspactions'.codeaction, {
transform = function(result) return result end,
ui_select = vim.ui.select, -- NOT lspactions default
})
ui_select has same specifications as vim.ui.select
has. It describes how
user would be prompted to select a code action from a list of codeactions.
So providing vim.ui.select
would provide selection menu as vim's default
selection menu. And not overriding this option would give a floating list as
selection menu.
transform function accepts a function that takes result returned from lsp-server as argument, and return a new result by making some transformation on it. The transformation can be anything like sorting, etc.
vim.lsp.handlers["textDocument/references"] = require'lspactions'.references
vim.cmd [[ nnoremap <leader>af :lua vim.lsp.buf.references()<CR> ]]
Similar to lsp references, but way more customizable.
Customization:
vim.lsp.handlers["textDocument/references"] = vim.lsp.with(require'lspactions'.references, {
open_list = true,
jump_to_result = true,
jump_to_list = false,
loclist = false,
always_qf = false,
transform = function(result) return result end
})
- loclist: use location list instead
- open_list: to open quickfix/loclist list or not
- jump_to_result: jump to first result of operation in current window
- jump_to_list: make quickfix/loclist list current window
- always_qf: open quickfix/loclist even if there is only one result
- transform: a function that accepts result returned from lsp-server, do some transformation on it(maybe like sorting) and return the new result.
vim.lsp.handlers["textDocument/definition"] = require'lspactions'.definition
vim.cmd [[ nnoremap <leader>af :lua vim.lsp.buf.definition()<CR> ]]
Similar to lsp definition, but way more customizable.
Customization:
vim.lsp.handlers["textDocument/definition"] = vim.lsp.with(require'lspactions'.definition, {
open_list = true,
jump_to_result = true,
jump_to_list = false,
loclist = false,
always_qf = false,
transform = function(result) return result end
})
- loclist: use location list instead
- open_list: to open quickfix/loclist list or not
- jump_to_result: jump to first result of operation in current window
- jump_to_list: make quickfix/loclist list current window
- always_qf: open quickfix/loclist even if there is only one result
- transform: a function that accepts result returned from lsp-server, do some transformation on it(maybe like sorting) and return the new result.
vim.lsp.handlers["textDocument/declaration"] = require'lspactions'.declaration
vim.cmd [[ nnoremap <leader>af :lua vim.lsp.buf.declaration()<CR> ]]
Similar to lsp declaration, but way more customizable.
Customization:
vim.lsp.handlers["textDocument/declaration"] = vim.lsp.with(require'lspactions'.declaration, {
open_list = true,
jump_to_result = true,
jump_to_list = false,
loclist = false,
always_qf = false,
transform = function(result) return result end
})
- loclist: use location list instead
- open_list: to open quickfix/loclist list or not
- jump_to_result: jump to first result of operation in current window
- jump_to_list: make quickfix/loclist list current window
- always_qf: open quickfix/loclist even if there is only one result
- transform: a function that accepts result returned from lsp-server, do some transformation on it(maybe like sorting) and return the new result.
vim.lsp.handlers["textDocument/implementation"] = require'lspactions'.implementation
vim.cmd [[ nnoremap <leader>af :lua vim.lsp.buf.implementation()<CR> ]]
Similar to lsp implementation, but way more customizable.
Customization:
vim.lsp.handlers["textDocument/implementation"] = vim.lsp.with(require'lspactions'.implementation, {
open_list = true,
jump_to_result = true,
jump_to_list = false,
loclist = false,
always_qf = false,
transform = function(result) return result end
})
- loclist: use location list instead
- open_list: to open quickfix/loclist list or not
- jump_to_result: jump to first result of operation in current window
- jump_to_list: make quickfix/loclist list current window
- always_qf: open quickfix/loclist even if there is only one result
- transform: a function that accepts result returned from lsp-server, do some transformation on it(maybe like sorting) and return the new result.
All the parameters presented in code of this section are optional.
local diag = require'lspactions'.diagnostics
diag.show_position_diagnostics(opts, bufnr, position)
- opts : table with fields
- severity : string with possible values: {ERROR, WARN, INFO, HINT}
diag.show_line_diagnostics(opts, bufnr, position)
- opts : table with fields
- severity : string with possible values: {ERROR, WARN, INFO, HINT}
diag.goto_next(opts)
- opts : table with fields
- severity : string with possible values: {ERROR, WARN, INFO, HINT}
- wrap : bool (default true) Whether to loop around file or not
- float: bool (default true) Whether to open floating window after jumping to next diagnostic
diag.goto_prev(opts)
- opts : table with fields
- severity : string with possible values: {ERROR, WARN, INFO, HINT}
- wrap : bool (default true) Whether to loop around file or not
- float: bool (default true) Whether to open floating window after jumping to previous diagnostic
diag.set_qflist(opts)
- opts : table with fields
- severity : string with possible values: {ERROR, WARN, INFO, HINT}
- client_id : Which client to diagnostics to display
diag.set_loclist(opts)
- opts : table with fields
- severity : string with possible values: {ERROR, WARN, INFO, HINT}
- client_id : Which client to diagnostics to display