hrsh7th / nvim-cmp

A completion plugin for neovim coded in Lua.
MIT License
7.47k stars 370 forks source link

cmp:visible() is slow when typing due to onetime config #1797

Open dhleong opened 5 months ago

dhleong commented 5 months ago

FAQ

Announcement

Minimal reproducible full config

local function try_accept_completion(key)
  return cmp.mapping(function(fallback)
    if cmp:visible() and cmp.get_active_entry() then
      local entry = cmp.get_active_entry()

      cmp.confirm()

      if key and not entry_has_key(entry, key) then
        vim.api.nvim_feedkeys(key, 'nt', false)
      end
    else
      fallback()
    end
  end, { 'i', 'c' })
end

cmp.setup({
  -- ...
  mapping = {
    ['<Space>'] = try_accept_completion(' '),
  },
})

Description

I have this configured so, for example, I can naturally select and auto-import constants by continuing to type after selecting the suggestion. I use it with other characters as well, but space is the one that causes me the most trouble. The idea here is, if I have actually selected something for completion to "confirm" that selection (to trigger auto imports) and insert the key provided, if it wasn't already part of the completion (for example, some servers will include parens, in which case I don't want to insert a second one)

In most cases this hasn't been a problem, but I've noticed that especially with the Godot language server, and especially typing in a comment, this causes nvim to hang. Upon investigation, I finally narrowed it down to this try_accept_completion function and, in particular, cmp:visible(). I can fix the hangs by swapping cmp:visible() for this hack:

local function fast_cmp_visible()
  if not (cmp.core.view and cmp.core.view.custom_entries_view) then
    return false
  end
  return cmp.core.view.custom_entries_view:visible()
end

I believe what's happening is the config.get() call is essentially never hitting the cache, due to the oneshot revision constantly increasing. Just typing iasdf <esc> into a blank buffer in a fresh instance can result in require'cmp.config'.onetime == { revision = 8 } with the minimal vimrc.

As far as what's causing the onetime revisions, as far as I can tell it's the async_filter function in core.lua. I added some logging to the other usages of config.set_onetime in the repo and none of them triggered with the above repro except async_filter.

Steps to reproduce

For the many revisions issue, see above. For the slowness in Godot:

  1. Open the Godot editor so the language server is running
  2. Open a Godot file in vim
  3. Start a comment on a newline with eg o# and just type some words separated by spaces
  4. Notice how it hangs

Expected behavior

It should not hang

Actual behavior

It does

Additional context

Thank you!