blink.cmp icon indicating copy to clipboard operation
blink.cmp copied to clipboard

Configurable delay for displaying the menu

Open soifou opened this issue 1 year ago • 3 comments

Feature Description

Similar to the documentation, the completion menu could benefit of an additional auto_show_delay_ms. This would be a middle ground between "always" (showing on every keystroke / min_keyword_length) and "never" (triggering manually).

From a UX perspective, this could reduces cognitive load by minimizing visual noise and display the list only during brief, intentional pauses. From a performance point of view, this could alleviate some unnecessary work.

Takes effect only if auto_show is enabled. The trigger characters should take priority over it.

Related: #446 Somewhat related: #402, #336

soifou avatar Dec 17 '24 13:12 soifou

when completion is expensive this could also alleviate performance problems

hesxenon avatar Dec 18 '24 13:12 hesxenon

I think a more accurate term for this feature is debounce_delay_ms.

casprwang avatar Jan 10 '25 20:01 casprwang

Hello. I did a manual timer for now:

  -- Delay blink.cmp completion by 1 second.
  {
    "blink.cmp",
    optional = true,
    opts = function(_, opts)
      local delay_ms = 1000
      -- disable auto_show
      opts.completion = opts.completion or {}
      opts.completion.menu = opts.completion.menu or {}
      opts.completion.menu.auto_show = false
      --
      opts.sources = opts.sources or {}
      local min_keyword_length = opts.sources.min_keyword_length or 4
      --
      local ok_to_run = function()
        -- Only run in insert mode.
        if vim.api.nvim_get_mode()["mode"] ~= "i" then return false end
        -- Do not run if the word below cursor is short.
        if #vim.fn.expand "<cword>" < min_keyword_length then return false end
        return true
      end
      -- setup timer
      local timer = vim.loop.new_timer()
      assert(timer)
      vim.api.nvim_create_autocmd({ "CursorMovedI", "TextChangedI" }, {
        callback = function()
          if not ok_to_run() then return end
          -- Remember buffer number.
          local bufnr = vim.api.nvim_get_current_buf()
          -- Stop any previous timer execution.
          timer:stop()
          timer:start(delay_ms, 0, function()
            timer:stop()
            vim.schedule(function()
              -- Only run in proper buffer.
              if bufnr ~= vim.api.nvim_get_current_buf() then return end
              if not ok_to_run() then return end
              require("blink.cmp").show()
            end)
          end)
        end,
      })
    end,
  },

I tried looking into the code base, but I just do not know where this debouncing should be implemented it. But I think inside trigger.show() https://github.com/Saghen/blink.cmp/blob/main/lua/blink/cmp/completion/trigger/init.lua#L213 needs to track a timer() depending on trigger_kind show it instantly or wait. Something like this https://github.com/Kamilcuk/blink.cmp/commit/701c364b20c0c87fae3c346fdbcd805b76c7d24b .

Kamilcuk avatar Apr 02 '25 00:04 Kamilcuk

That's great, works great. Thank you for implementing, you are great!

Kamilcuk avatar Sep 26 '25 20:09 Kamilcuk