VonHeikemen / lsp-zero.nvim

A starting point to setup some lsp related features in neovim.
https://lsp-zero.netlify.app/v4.x/
MIT License
3.75k stars 95 forks source link

Issue with keybindings, lazy loading and session managers #312

Closed serranomorante closed 1 year ago

serranomorante commented 1 year ago

Update (fewer steps to replicate)


The replication steps on the original post are quite cumbersome, you can replicate the same problem just by doing :LspRestart on any of the buffers in the vsplit view (without using auto-sessions at all).

  1. Repeat the 3rd step on the original issue below: Add your custom keybinding to gr.
  2. Open 2 different buffers in a vsplit view and check that your lsp servers are attached.
  3. Execute :LspRestart on 1 of your buffers.
  4. Now do :nmap gr on each buffer and check if they refer to your custom keymap (from step 1) or the default lsp keybindings from lsp-zero.

Original issue (more steps to replicate)


t-rec_13

When restoring a saved session (with ANY session manager plugin), my custom keybindings act weird. At least 1 buffer have the correct keybinding while the others use the default keybindings provided by lsp-zero.

You can notice in the screenshot that I'm doing :nmap gr and for the buffer on the right it shows my custom keymap ✅ but for the buffer on the left it shows the default keymap ❌

The lsp servers work as expected, the issue is with the custom keymaps only.

Version

lsp-zero: dev-v3 lazy.nvim: latest

Steps to replicate

  1. Add a session manager plugin to your config, for lazy:

.../plugins/auto-session.lua

Don't worry, the following spec is configured to never do any kind of auto-saving... everything is manual.

return {
    "rmagatti/auto-session",
    opts = {
        log_level = "error",
        auto_session_root_dir = vim.fn.stdpath("data") .. "/sessions/",
        auto_session_suppress_dirs = { os.getenv("HOME") },
        auto_session_enable_last_session = false,
        auto_session_enabled = false,
        auto_session_create_enabled = false,
        auto_save_enabled = false,
        auto_restore_enabled = false,
        auto_session_use_git_branch = false,
    },
    event = "VeryLazy"
}
  1. Add these sessionoptions:
vim.o.sessionoptions = "buffers,curdir,folds,globals,tabpages,winpos,winsize"
  1. Add your custom keybinding to gr.

.../plugins/lsp-zero.lua

For the following snippets I used these guides: LSP: Creating new keybindings References and guides: Lazy loading with lazy.nvim

Notice the lazy = false in the neovim/nvim-lspconfig spec. Either with true or false the problem persist.

return {
   ...
    {
        "VonHeikemen/lsp-zero.nvim",
        branch = "dev-v3",
        lazy = true,
        config = false,
         ...

    {
        "neovim/nvim-lspconfig",
        lazy = false,
        cmd = { "LspInfo", "LspInstall", "LspStart" },
        event = { "BufReadPre", "BufNewFile" },
                ...
        config = function()
            local lsp = require("lsp-zero")
            lsp.extend_lspconfig()

            lsp.on_attach(function(_, bufnr)
                -- Disable some keybindings
                -- See: https://github.com/VonHeikemen/lsp-zero.nvim/blob/dev-v3/doc/md/lsp.md#disable-keybindings
                lsp.default_keymaps({ buffer = bufnr, exclude = { "<F2>", "<F3>" } })

                -- Add new keybindings
                -- See: https://github.com/VonHeikemen/lsp-zero.nvim/blob/dev-v3/doc/md/lsp.md#creating-new-keybindings
                vim.keymap.set("n", "gr", function()
                    -- require("telescope.builtin").lsp_references()
                                        vim.print("my custom keybinding!")
                end, { buffer = true })
                                ....
...
  1. Now that your setup is complete, open 2 different buffers in a vsplit view and save a new session with :SessionSave (please make sure to close any tree plugin before saving the session... nerd-tree, neo-tree, etc)

  2. Now quit and reopen vim :qa and then nvim in the same directory (the session in saved by directory). Your session will not be restored automatically, this is normal.

  3. Manually restore your session with SessionRestore. You should see your same buffers in a vsplit view.

  4. Now do :nmap gr on each buffer and check if they refer to your custom keymap or the default lsp keybindings.

Clean up

Clean the saved session with :Autosession delete

Expected result

I did several tests with different session managers and this problem is present in all of them (that is because all of those plugins use the builtin neovim session functionality). It would be amazing to have a solution in which I'm able to restore a session without losing my custom keymaps for lsp-zero.

References

These are my dotfiles

serranomorante commented 1 year ago

Only solution for now seems to be re-sourcing all the buffers after restoring a session and waiting at least 1 second before doing so. This presents it's own challenges but is a workaround for now.

.../plugins/auto-session.lua

local function resource_buffers()
    vim.schedule(function()
        vim.cmd("sleep 1")
        vim.cmd("bufdo e")
    end)
end

return {
    "rmagatti/auto-session",
    opts = {
        log_level = "error",
                ...
        post_restore_cmds = { resource_buffers },
        ...
...
serranomorante commented 1 year ago

I did an update on my original post with fewer steps to replicate the same issue. After executing :LspRestart only 1 buffer keeps my custom keymaps (added with the lsp.on_attach(...) handler) and the other buffers fallback to lsp-zero default keymaps instead of preserving my custom keymaps.

serranomorante commented 1 year ago

I ended up migrating to my own lsp setup and both of my problems dissapeared (session managers and :LspRestart). Thank you so much for this guide: You might not need lsp-zero and for this one: lsp-zero under the hood

Here are the commits of my migration in case anyone is interested.

I opted for doing the server setups in the lspconfig plugin instead of doing them in mason-lspconfig, maybe that was the culprit of the problem but I'm not really sure.

VonHeikemen commented 1 year ago

I could not reproduce the issue.

And I have no clue what could be the cause. default_keymaps() is not doing anything special.

serranomorante commented 1 year ago

I could not reproduce the issue.

And I have no clue what could be the cause. default_keymaps() is not doing anything special.

Thank you for your reply! I'm sorry you couldn't replicate the issue. I'm willing to debug this a little bit further. I will create a minimal git repo that you can clone y and test the issue there, would that be ok?

VonHeikemen commented 1 year ago

Okay. I manage to reproduce the issue with another config. I think the problem is that Neovim assigns your custom keybinding only to one buffer because you have {buffer = true}.

Try to use the variable bufnr when making your custom keybinding ({buffer = bufnr}). This should work.

vim.keymap.set("n", "gr", function()
  vim.print("my custom keybinding!")
end, { buffer = bufnr })
serranomorante commented 1 year ago

Okay. I manage to reproduce the issue with another config. I think the problem is that Neovim assigns your custom keybinding only to one buffer because you have {buffer = true}.

Try to use the variable bufnr when making your custom keybinding ({buffer = bufnr}). This should work.

vim.keymap.set("n", "gr", function()
  vim.print("my custom keybinding!")
end, { buffer = bufnr })

I totally missed that!! This solves the issue. Thank you so much and sorry about that :cry: