Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Outdated completion item with mini.snippets #2119

Open
2 tasks done
xzbdmw opened this issue Dec 27, 2024 · 0 comments
Open
2 tasks done

Outdated completion item with mini.snippets #2119

xzbdmw opened this issue Dec 27, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@xzbdmw
Copy link

xzbdmw commented Dec 27, 2024

FAQ

  • I have checked the FAQ and it didn't resolve my problem.

Announcement

Minimal reproducible full config

repro.lua, run with nvim -u repro.lua

local root = vim.fn.fnamemodify("./.repro", ":p")
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
    vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "--single-branch",
        "https://github.com/folke/lazy.nvim.git",
        lazypath,
    })
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
    -- do not remove the colorscheme!
    "folke/tokyonight.nvim",
    "neovim/nvim-lspconfig",
    {
        "hrsh7th/nvim-cmp",
        lazy = false,
        dependencies = {
            "hrsh7th/cmp-nvim-lsp",
        },
        config = function(_, opts)
            local cmp = require("cmp")
            require("cmp").setup({
                mapping = cmp.mapping.preset.insert({
                    ["<cr>"] = cmp.mapping(function(fallback)
                        if cmp.visible() then
                            cmp.confirm()
                        end
                    end, { "i", "c", "s" }),
                }),
                completion = {
                    completeopt = "menu,menuone,noinsert",
                },
                snippet = {
                    expand = function(args)
                        local insert = MiniSnippets.config.expand.insert or MiniSnippets.default_insert
                        insert({ body = args.body })
                    end,
                },
                sources = require("cmp").config.sources({
                    { name = "nvim_lsp" },
                }, {}),
            })
        end,
    },
    {
        "echasnovski/mini.snippets",
        version = false,
        config = function()
            local gen_loader = require("mini.snippets").gen_loader
            require("mini.snippets").setup({
                snippets = {
                    -- Load custom file with global snippets first (adjust for Windows)
                    gen_loader.from_file("~/.config/nvim/snippets/global.json"),

                    -- Load snippets based on current language by reading files from
                    -- "snippets/" subdirectories from 'runtimepath' directories.
                    gen_loader.from_lang(),
                },
            })
        end,
    },
    -- add any other pugins here
}

require("lazy").setup(plugins, {
    root = root .. "/plugins",
})

require("lspconfig").lua_ls.setup({
    settings = {
        capabilities = require("cmp_nvim_lsp").default_capabilities(),
        Lua = {
            runtime = {
                version = "LuaJIT",
            },
            workspace = {
                library = {
                    "/usr/local/share/nvim/runtime",
                },
            },
            completion = {
                callSnippet = "Replace",
            },
        },
    },
})
vim.cmd([[colorscheme tokyonight]])

Description

Some chars are swallowed when expanding:
typing sequence : vim.sc<cr>fun<cr> result in right pair missing;
typing sequence : vim.sc<cr><cr> has correct result,
typing sequence : vim.schedule()<left>fun<cr> has correct result,

iShot_2024-12-24_08.10.18.mp4

I debug to find cmp removing the pair before snippet expanding, needs more investment.

The whole process is following, | stands for cursor:

  1. type vim.sc<cr> expanding to vim.schedule(|fn)
  2. lua_ls interprets it as if user types vim.schedule(fn) suggesting fun as a snippet completion item
  3. user continues typing fun, completion item stays unchanged, but cmp knows before expanding the snippets, it needs to clear the fun typed by user, to let snippet engine expand correctly.
  4. user types <cr>, cmp turn vim.schedule(fun) to vim.schedule() correctly, BUT, it calls vim.lsp.util.apply_text_edits before expanding, while the TextEdit looks like this:
cmp stage before { "vim.schedule()" } -- This is before apply text edit
function#function#if completion_item.textEdit: {
  _index = 1,
  newText = "",
  range = {
    ["end"] = {
      character = 15, 
      line = 765
    },
    start = {
      character = 13,
      line = 765
    }
  }
}
cmp stage after { "vim.schedule(" } -- This is after appying

notice the range is [13,15) which stands for fn in the original placeholder.

vim.snippet.expand works correctly because it stays in select mode, does not trigger completion at all, only after user typing fun lua_ls will begin to send correct TextEdits, anyway, by that time placeholder is already gone.

To my understanding, the fix would be suspending completion request to stop step 2 from firing when first expanding.

Steps to reproduce

above

Expected behavior

no outdated completion item

Actual behavior

outdated completion item swallows ')'

Additional context

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant