hrsh7th / cmp-cmdline

nvim-cmp source for vim's cmdline
MIT License
550 stars 42 forks source link

Manual completion does not work #62

Open uberbrodt opened 2 years ago

uberbrodt commented 2 years ago

I only want to manually trigger completion, since I don't like having to hit <ENTER> twice (once to select the completion and another to execute) if I know what command I want. However, when I use <TAB> to do the completion, it just completes to the next word (which I believe is default vim behavior) and does not show a menu. I would expect that hitting <TAB> would pop the menu. When autocomplete is enabled, <TAB> works as expected. Thanks for your help!

# init.vim
call plug#begin(stdpath('data') . '/plugged')
Plug 'neovim/nvim-lspconfig'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/nvim-cmp'
Plug 'f3fora/cmp-spell'
Plug 'hrsh7th/cmp-calc'
Plug 'lukas-reineke/cmp-rg'
Plug 'hrsh7th/cmp-=nvim-lsp-signature-help'

" For luasnip users.
" Plug 'L3MON4D3/LuaSnip'
" Plug 'saadparwaiz1/cmp_luasnip'

call plug#end()

# cmp.lua
local has_words_before = function()
  local line, col = unpack(vim.api.nvim_win_get_cursor(0))
  return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local luasnip = require("luasnip")
local cmp = require("cmp")
local lspkind = require("lspkind")

local function snippetCompleteNext(fallback)
  if cmp.visible() then
    cmp.select_next_item()
  elseif luasnip.expand_or_jumpable() then
    luasnip.expand_or_jump()
  elseif has_words_before() then
    cmp.complete()
    cmp.close()
  else
    fallback()
  end
end

local function snippetCompletePrev(fallback)
  if cmp.visible() then
    cmp.select_prev_item()
  elseif luasnip.jumpable(-1) then
    luasnip.jump(-1)
  else
    fallback()
  end
end

cmp.setup({
  formatting = {
    format = lspkind.cmp_format({
      with_text = false,
      maxwidth = 50,
      mode = "symbol",
      menu = {
        buffer = "BUF",
        rg = "RG",
        nvim_lsp = "LSP",
        path = "PATH",
        luasnip = "SNIP",
        calc = "CALC",
        spell = "SPELL",
      },
    }),
  },
  snippet = {
    expand = function(args)
      require("luasnip").lsp_expand(args.body)
    end,
  },
  mapping = {
    ["<Tab>"] = cmp.mapping({
      i = snippetCompleteNext,
      s = snippetCompleteNext,
      c = function(fallback)
        if cmp.visible() then
          cmp.select_next_item()
        elseif has_words_before() then
          cmp.complete()
          cmp.close()
        else
          fallback()
        end
      end,
    }),

    ["<S-Tab>"] = cmp.mapping({
      i = snippetCompletePrev,
      s = snippetCompletePrev,
      c = function(fallback)
        if cmp.visible() then
          cmp.select_prev_item()
        else
          fallback()
        end
      end,
    }),
    ["<Down>"] = cmp.mapping(cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }), { "i" }),
    ["<Up>"] = cmp.mapping(cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }), { "i" }),
    ["<C-b>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }),
    ["<C-f>"] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }),
    ["<C-Space>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
    ["<C-e>"] = cmp.mapping({ i = cmp.mapping.close(), c = cmp.mapping.close() }),
    ["<CR>"] = cmp.mapping({
      i = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true }),
      c = function(fallback)
        if cmp.visible() then
          cmp.confirm({ behavior = cmp.ConfirmBehavior.Insert, select = false })
          cmp.close()
        else
          fallback()
        end
      end,
    }),
  },
  sources = {
    { name = "nvim_lsp" },
    { name = "nvim_lsp_signature_help" },
    { name = "buffer", keyword_length = 5 },
    { name = "luasnip" },
    { name = "calc" },
    { name = "spell", keyword_length = 5 },
    { name = "path" },
    { name = "rg", keyword_length = 5 },
    { name = "orgmode" },
  },
})

-- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline("/", {
  mapping = cmp.mapping.preset.cmdline(),
  sources = {
    { name = "buffer" },
  },
})

-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(":", {
  mapping = cmp.mapping.preset.cmdline(),
  completion = {
    -- autocomplete = { "TextChanged" },
    autocomplete = false,
  },
  sources = cmp.config.sources({
    { name = "path" },
  }, {
    { name = "cmdline", keyword_length = 4 },
  }),
})