nvim-lspconfig
nvim-lspconfig copied to clipboard
How to set per-client commands to start_client?
Description
neovim/neovim#16101 makes it possible to use per-client command handlers.
However, there seems to be no way to actually pass this to start_client
call.
Neovim version
NVIM v0.6.1 Build type: Release LuaJIT 2.1.0-beta3
Nvim-lspconfig version
c276536bcdb03f2e1c353b04abb1a719814d4197
Operating system and version
ArchLinux 5.16.11-zen1-1-zen
Affected language servers
all
Steps to reproduce
The
setup{}
function takes a table which contains a superset of the keys listed in:help vim.lsp.start_client()
with the following unique entries
Per documentation, the following should work, but in fact doesn't:
require('lspconfig').ltex.setup {
commands = {
['_ltex.addToDictionary'] = function() end,
}
}
Because lspconfig takes the commands
key as a different meaning, as explained in the lspconfig-configurations
section of the documentation.
commands
is a map ofname:definition
key:value pairs, wheredefinition
is a list whose first value is a function implementing the command, and the rest are either array values which will be formed into flags for the command, or special keys likedescription
.
So the above code errors out as it doesn't pass the check.
I'm aware of vim.lsp.commands
as a workaround but I think it should be possible to make use of neovim/neovim#16101 and set custom command handlers.
Or at least the documentation should be updated to mention the different meaning of the commands
key when passed to setup
.
Actual behavior
Error during start up:
...m/site/pack/paqs/opt/lspconfig/lua/lspconfig/configs.lua:46: attempt to index local 'v' (a function value)
Expected behavior
No response
Minimal config
local on_windows = vim.loop.os_uname().version:match 'Windows'
local function join_paths(...)
local path_sep = on_windows and '\\' or '/'
local result = table.concat({ ... }, path_sep)
return result
end
vim.cmd [[set runtimepath=$VIMRUNTIME]]
local temp_dir = vim.loop.os_getenv 'TEMP' or '/tmp'
vim.cmd('set packpath=' .. join_paths(temp_dir, 'nvim', 'site'))
local package_root = join_paths(temp_dir, 'nvim', 'site', 'pack')
local install_path = join_paths(package_root, 'packer', 'start', 'packer.nvim')
local compile_path = join_paths(install_path, 'plugin', 'packer_compiled.lua')
local function load_plugins()
require('packer').startup {
{
'wbthomason/packer.nvim',
'neovim/nvim-lspconfig',
},
config = {
package_root = package_root,
compile_path = compile_path,
},
}
end
_G.load_config = function()
vim.lsp.set_log_level 'trace'
if vim.fn.has 'nvim-0.5.1' == 1 then
require('vim.lsp.log').set_format_func(vim.inspect)
end
local nvim_lsp = require 'lspconfig'
local on_attach = function(_, bufnr)
local function buf_set_keymap(...)
vim.api.nvim_buf_set_keymap(bufnr, ...)
end
local function buf_set_option(...)
vim.api.nvim_buf_set_option(bufnr, ...)
end
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap = true, silent = true }
buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
end
-- Add the server that troubles you here
local name = 'ltex'
if not name then
print 'You have not defined a server name, please edit minimal_init.lua'
end
if not nvim_lsp[name].document_config.default_config.cmd and not cmd then
print [[You have not defined a server default cmd for a server
that requires it please edit minimal_init.lua]]
end
nvim_lsp[name].setup {
cmd = cmd,
on_attach = on_attach,
commands = {
['_ltex.addToDictionary'] = function() end,
}
}
print [[You can find your log at $HOME/.cache/nvim/lsp.log. Please paste in a github issue under a details tag as described in the issue template.]]
end
if vim.fn.isdirectory(install_path) == 0 then
vim.fn.system { 'git', 'clone', 'https://github.com/wbthomason/packer.nvim', install_path }
load_plugins()
require('packer').sync()
vim.cmd [[autocmd User PackerComplete ++once lua load_config()]]
else
load_plugins()
require('packer').sync()
_G.load_config()
end
LSP log
https://gist.github.com/Aetf/a7279f4adde759bb2060aeb773961b42
Hmm, yes. I'm not quite sure what to do with this. Maybe commands
was an unfortunate naming choice on our part in core.
Is the problem here that the commands
property of the client dictionary is being used to create command :SomeCustomCommand
and also used as the handlers for clientside code action and code lenses?
I am running into a similar thing. i can bypass the error the OP here sees by setting the value in the commands dictionary to a list
commands = {
["elixir.lens.test.run"] = {
function()
-- stuff
end,
},
},
but when it actually goes to run the the client side command in response when attempting to run the code lens (in this case, run a unit test), it fails because the command is a table and not a function.
E5108: Error executing lua ...m/ref-master/share/nvim/runtime/lua/vim/lsp/codelens.lua:39: attempt to call local 'fn' (a table value)
stack traceback:
...m/ref-master/share/nvim/runtime/lua/vim/lsp/codelens.lua:39: in function 'execute_lens'
...m/ref-master/share/nvim/runtime/lua/vim/lsp/codelens.lua:92: in function 'run'
[string ":lua"]:1: in main chunk
Sorry if I just repeated something obvious, but wanted to clarify this.
Also, because the key in the command table needs to be the command sent by the code lens, i get a failure when it tries to create neovim commands from the name
Error executing vim.schedule lua callback: .../pack/packer/start/nvim-lspconfig/lua/lspconfig/util.lua:78: Vim(command):E182: Invalid command name
stack traceback:
[C]: in function 'nvim_command'
.../pack/packer/start/nvim-lspconfig/lua/lspconfig/util.lua:78: in function 'create_module_commands'
...ck/packer/start/nvim-lspconfig/lua/lspconfig/configs.lua:282: in function '_setup_buffer'
...ck/packer/start/nvim-lspconfig/lua/lspconfig/configs.lua:185: in function ''
vim/_editor.lua: in function <vim/_editor.lua:0>
Is the problem here that the commands property of the client dictionary is being used to create command :SomeCustomCommand and also used as the handlers for clientside code action and code lenses?
It is only used for the former. And it's not possible to pass client side command handlers this way, thus this issue.
I've found a workaround, though. You can actually set the per-client command handler in
on_init
. See https://github.com/Aetf/ucw.nvim/blob/main/lua/ucw/lsp/lang/ltex.lua#L135-L139
https://github.com/neovim/nvim-lspconfig/pull/1838 should address this by renaming the key for creating user_commands (via nvim_create_user_commands) to user_commands
which will free up commands