How to use neovim LSP key bindings starting with <space>?

I have neovim 0.6.1 configured with some LSPs and using the default configurations found here: https://github.com/neovim/nvim-lspconfig#suggested-configuration. Some of the key bindings start with <space>, such as vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts). I assumed <space> meant the space bar, but that does not work. For example, with the rename key binding if I press SPACE-r-n I end up just replacing the char under the cursor with n… as expected with just r-n. How do I use these key bindings that start with <space>?

The vim.lsp.buf.rename() command works correctly if I call it manually… just to rule that out right away. The issue is with not being able to use the key binding. Also, the other key bindings from the default config that do not start with <space>, such as g-d work just fine.

:help mapleader
:help timeout

Reading :help mapleader led me to try :let mapleader = "<space>", but that is not working. I then tried adding vim.g.mapleader = "<space> " and then vim.g.mapleader = " " to my init.lua, but the shortcut defined with <space>rn in the suggested configuration is still not working.

I also just tried changing

vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)

to

vim.api.nvim_buf_set_keymap(bufnr, 'n', '<Leader>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)

and that also did not work.

I also did a simple test by setting :noremap <space>w :q!<cr> and that successfully quit neovim. So it seems my space leader key works correctly.

OK, narrowing it down even more. If I do :noremap <space>rn :lua vim.lsp.buf.rename()<CR> during a session the rename keybinding works correctly. What could cause the lua keybindings with <space> to not take effect in my init.lua, but the similar ones adjacent to it to work just fine.

Maybe there are some other mappings interfering? What does :nmap <space> print?

That prints:

n  <Space>q    * <Cmd>lua vim.diagnostic.setloclist()<CR>
n  <Space>e    * <Cmd>lua vim.diagnostic.open_float()<CR>

Did you run that in a buffer where other suggested keybindings like gd work?

I did, but it seems I was misled into thinking gd was working because it did something similar, but when I run the command manually it is a bit different. So, it seems that entire block of commands is not working.

Then it seems you haven’t configured LSP correctly.

LSP is working though. I get autocompletion and those commands work fine if I call them manually… just not with the keybindings. Also, :LspInfo shows:

Language client log: /home/ryan/.cache/nvim/lsp.log
Detected filetype:   python

1 client(s) attached to this buffer:

Client: pylsp (id: 1, pid: 96402, bufnr: [1])
   filetypes:       python
   autostart:       true
   root directory:  /home/ryan/programming       
   cmd:             pylsp

Configured servers list: pylsp, ccls, gopls

I notice the ones that work use vim.api.nvim_set_keymap(... and the ones that don’t use vim.api.nvim_buf_set_keymap(bufnr.... Maybe that is a clue?

Maybe this part is not working:

-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)

Having a hard time debugging though since I don’t know lua or about nvim coding.

I think the issue is related to this:

Note: you must pass the defined on_attach as an argument to every setup {} call and the keybindings in on_attach only take effect on buffers with an active language server.

But I’m not sure how to do that. I thought maybe this loop was doing that:

-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
for _, lsp in pairs(servers) do
  require('lspconfig')[lsp].setup {
    on_attach = on_attach,
    flags = {
      -- This will be the default in neovim 0.7+
      debounce_text_changes = 150,
    }
  }
end

And I have this array set: local servers = {'ccls', 'gopls', 'pylsp'}

Maybe it is because you have already called setup() for language servers before, so calling again doesn’t work.

1 Like

That solved it! Turns out the default config for nvim-cmp also called setup and wiped the on_attach callback. The readme even mentions to look out for this, but it was hard to find within the default setup from another plugin. Thanks for all the help.

So, how did you solve the problem. Thanks a lot!

I had code copied from different example configs calling the setup method on the same servers more than once. Make sure this method is only called once per server and consolidate all necessary code from other calls.