ray-x / lsp_signature.nvim

LSP signature hint as you type
Apache License 2.0
2.02k stars 58 forks source link

Floating window breaks ultisnip placeholder jumping #143

Closed ranebrown closed 2 years ago

ranebrown commented 2 years ago

When setting floating_window = true and using an LSP provided snippet it is not possible to jump between argument placeholders. Works as expected when set to false. See https://github.com/quangnguyen30192/cmp-nvim-ultisnips/issues/13 for more detail and minimal config to reproduce.

ray-x commented 2 years ago

Seems there are something missing in your config. I do not see ultsnips in cmp pop up, also it does not expand from lsp. Thus failed to reproduce.

ray-x commented 2 years ago

Also could you try without lsp_install?

ranebrown commented 2 years ago

Still seeing the same thing with lspinstaller removed. Here is a minimal config and steps to reproduce. Thanks for taking a look.

  1. Install clangd and have in your PATH
  2. Save below content in minimal_init.lua and test.cpp
  3. nvim -u minimal_init.lua -> wait for install of plugins and treesitter then :quit
  4. nvim -u minimal_init.lua test.cpp
    1. Move to main function and type sum to trigger cmp menu
    2. Select sum with tab or c-n and then c-y to expand LSP snippet
    3. Enter value for first placeholder then tab to jump to next placeholder (second argument) but literal tab is inserted
  5. Repeat step 4 with floating_window = false and it works as expected

I also noticed that after expanding the snippet the signature window appears and then disappears and then comes back up after typing the first value. Not sure if that is related to the problem.

Minimal init ```lua vim.cmd([[set runtimepath=$VIMRUNTIME]]) vim.cmd([[set packpath=/tmp/nvim/site]]) local package_root = "/tmp/nvim/site/pack" local install_path = package_root .. "/packer/start/packer.nvim" local function load_plugins() require("packer").startup({ function(use) use({ "wbthomason/packer.nvim" }) use({ "SirVer/ultisnips" }) use({ "hrsh7th/nvim-cmp", requires = { "hrsh7th/cmp-nvim-lsp", "quangnguyen30192/cmp-nvim-ultisnips", }, config = function() local cmp = require("cmp") local cmp_ultisnips_mappings = require( "cmp_nvim_ultisnips.mappings" ) cmp.setup({ snippet = { expand = function(args) vim.fn["UltiSnips#Anon"](args.body) end, }, mapping = { [""] = cmp.mapping(function(fallback) cmp_ultisnips_mappings.compose({ "jump_forwards", "select_next_item", })(fallback) end, { "i", "s", "c", }), [""] = cmp.mapping(function(fallback) cmp_ultisnips_mappings.compose({ "jump_backwards", "select_prev_item", })(fallback) end, { "i", "s", "c", }), }, sources = { { name = "nvim_lsp", priority = 100, group_index = 1 }, { name = "ultisnips", priority = 80, group_index = 1 }, }, }) end, }) use({ "nvim-treesitter/nvim-treesitter", config = function() require("nvim-treesitter.configs").setup({ ensure_installed = { "cpp" }, highlight = { enable = true }, }) end, run = ":TSUpdate", }) use({ "neovim/nvim-lspconfig", config = function() local on_attach = function(client) if client.resolved_capabilities.signature_help then require("lsp_signature").on_attach({ floating_window = true, }) end end -- config that activates keymaps and enables snippet support local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require("cmp_nvim_lsp").update_capabilities( capabilities ) local nvim_lsp = require("lspconfig") nvim_lsp["clangd"].setup({ on_attach = on_attach, capabilities = capabilities, }) end, }) use({ "ray-x/lsp_signature.nvim" }) end, config = { package_root = package_root, compile_path = install_path .. "/plugin/packer_compiled.lua", }, }) 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() else load_plugins() require("packer").sync() end ```
Test cpp file ```cpp #include auto sum(int a, int b) -> int { return a+b; } auto main(int argc, char *argv[]) -> int { return 0; } ```
ranebrown commented 2 years ago

Should also note that the same behavior is present without "quangnguyen30192/cmp-nvim-ultisnips" and the associated mappings but in that case you need to set/use the Ultisnip key maps for jumping between placeholders.

ray-x commented 2 years ago

I would say it is an upstream issue. ultisnip can not handle floating windows/buffer of neovim The here from ultisnips:

class TabStop(EditableTextObject):

    """See module docstring."""

    def __init__(self, parent, token, start=None, end=None):
        if start is not None:
            self._number = token
            EditableTextObject.__init__(self, parent, start, end)
        else:
            self._number = token.number
            EditableTextObject.__init__(self, parent, token)
        parent._tabstops[self._number] = self  # pylint:disable=protected-access

This object was created multiple times when signature floating windows popup up. I think ultisnip trying to create a tabstop object for each buffer, but when you press <Tab>, it failed to use correct tabstop object and the one it choosen is empty. Thus you can not jump from one placeholder to next.

ranebrown commented 2 years ago

@sirver, @hrsh7th do either of you mind taking a look at this? I'm happy to open an issue in the correct repo but not sure where the problem stems from. Thanks!

hrsh7th commented 2 years ago

I think it caused by neovim itself. https://github.com/neovim/neovim/blob/master/runtime/lua/vim/lsp/util.lua#L970

The neovim doesn't specify the noautocmd: true. (maybe)

ranebrown commented 2 years ago

Adding noautocmd = true, in that file does seem to fix the problem. Is that an additional option that can be passed when the signature floating window is created or does it really need to be the default set by neovim?

Bahex commented 2 years ago

Thanks for figuring this out. Putting this in init.lua should fix it without the need to modify neovim's files.

local old_make_floating = vim.lsp.util.make_floating_popup_options
if not old_make_floating(0, 0, {}).noautocmd then
    vim.lsp.util.make_floating_popup_options = function(width, height, opts)
        local ret = old_make_floating(width, height, opts)
        ret.noautocmd = true
        return ret
    end
end
ray-x commented 2 years ago

@ranebrown @Bahex I updated the plugin for this. Could you check if latest version works for you

Bahex commented 2 years ago

@ray-x Works as expected :+1: