nvim/plug: +nvim-cmp@master +cmp plugins...

This commit adds (nvim-)cmp as our completion engine / framework.

We also add completion sources for (file)paths, buffer contents, LSP
actions and snippets -- courtesy of vsnip.

This provides similar functionality to coc's completion engine, but
with (much) better support for LSP actions, lua native key maps and
significantly more configuration options that can be easily overridden
but psoxizsh users.

We add similar default key maps as with what existed in coc, namely
that <CR> exits the autocompletion window, <C-Space> does the selected
LSP action, <Tab>/<S-Tab> cycles through options and <PageUp/Down>
scrolls documentation of the current item.

We also explicitly enable completion / snippet support in client capacities
sent to LSP servers, as many require this before offering completions
This commit is contained in:
Paul Stemmet 2022-09-03 14:34:16 +00:00
parent b3cbfbd26f
commit 267fb252c7
Signed by: Paul Stemmet
GPG Key ID: EDEA539F594E7E75
4 changed files with 136 additions and 1 deletions

View File

@ -64,6 +64,21 @@ M.Global.C {
-- ############################
M.Global.I {
{ mode = 'i' },
-- #####################
-- ## Auto completion ##
-- #####################
--
Completion = G {
{ skip = true },
Confirm = B { 'Select the active completion entry and insert it' , key = '<C-Space>' , } ,
Next = B { 'Cycle selected completion item in completion menu' , key = '<Tab>' , } ,
Prev = B { 'Reverse cycle selected completion item in completion menu' , key = '<S-Tab>' , } ,
ScrollUp = B { 'Scroll up completion item documentation' , key = '<PageUp>' , } ,
ScrollDown = B { 'Scroll down completion item documentation' , key = '<PageDown>' , } ,
},
}
-- ############################
@ -71,6 +86,8 @@ M.Global.I {
-- ############################
M.Global.V {
{ mode = 'v' },
Completion = M.Global.I.Completion:new({ mode = 'v' })
}
M.Buffer.N {

View File

@ -1,5 +1,5 @@
return function()
local lspconfig, util = require 'lspconfig', require 'psoxizsh.util'
local lspconfig, cmp, util = require 'lspconfig', require 'cmp_nvim_lsp', require 'psoxizsh.util'
local keys, servers = require 'psoxizsh.key', require 'psoxizsh.lsp.servers'
local defaults = {}
@ -9,6 +9,11 @@ return function()
keys.Buffer.Lsp:register({ buffer = bnum })
end
-- Update LSP capabilities we send to servers to include the features supported by nvim-cmp
defaults.capabilities = cmp.update_capabilities(lspconfig.util.default_config.capabilities)
-- Dependent on a snippet manager in nvim-cmp (currently using vsnip)
defaults.capabilities.textDocument.completion.completionItem.snippetSupport = true
-- Ideally, this would be registered on some Psoxizsh.Plug.Post autocmd
-- but I don't feel like refactoring psoxizsh.plugin now.
--

View File

@ -0,0 +1,93 @@
return function()
local cmp, util = require 'cmp', require 'psoxizsh.util'
local kmap, cfg, lspkind = cmp.mapping, cmp.config, require 'lspkind'
local sources, w = cfg.sources, cfg.window
local mode = { insert = kmap.preset.insert, cmd = kmap.preset.cmdline }
local defaults = { snippet = {}, mapping = {}, sources = {} }
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 fkey = function(key, md)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), md or '', true)
end
-- Snippet provider
defaults.snippet.expand = function(args)
vim.fn['vsnip#anonymous'](args.body)
end
-- Key maps for auto completion
defaults.mapping = {
['<Tab>'] = kmap(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
fkey '<Plug>(vsnip-expand-or-jump)'
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = kmap(function()
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#jumpable'](-1) == 1 then
fkey '<Plug>(vsnip-jump-prev)'
end
end, { 'i', 's' }),
['<PageUp>'] = kmap.scroll_docs(-4),
['<PageDown>'] = kmap.scroll_docs(4),
['<C-Space>'] = kmap.confirm({ behavior = cmp.ConfirmBehavior.Insert, select = true }),
}
defaults.mapping = mode.insert(defaults.mapping)
defaults.mapping = mode.cmd(defaults.mapping)
-- Sources of auto completion
--
-- Each group of completions is prioritized in ascending order;
-- that is, 'path's will be shown before 'nvim_lsp's, etc
defaults.sources = sources(
{
{ name = 'path', },
},
{
{ name = 'nvim_lsp', keyword_length = 2 },
{ name = 'nvim_lsp_signature_help', },
},
{
{ name = 'vsnip', keyword_length = 2 },
},
{
{ name = 'buffer', keyword_length = 2 },
}
)
-- Auto completion window settings
defaults.window = {
completion = {
col_offset = -3,
side_padding = 0,
},
documentation = w.bordered(),
}
-- Auto completion item formatting
defaults.formatting = {
fields = { 'kind', 'abbr', 'menu' },
format = function(entry, item)
local kind = lspkind.cmp_format({ mode = 'symbol_text', maxwidth = 50 })(entry, item)
local strings = vim.split(kind.kind, '%s', { trimempty = true })
kind.kind = ' ' .. strings[1] .. ' '
kind.menu = ' (' .. strings[2] .. ')'
return kind
end,
}
cmp.setup(util.mconfig('config.nvim-cmp', defaults))
end

View File

@ -120,12 +120,32 @@ local plugins = {
{ 'luochen1990/rainbow' },
{ 'sheerun/vim-polyglot' },
-- Autocompletion + snippets + vim.diagnostic sources
-- Completion framework
{ 'hrsh7th/nvim-cmp',
requires = { 'onsails/lspkind.nvim' },
config = require 'psoxizsh.plugins.config.nvim-cmp'
},
-- Snippets
{ 'hrsh7th/vim-vsnip' },
-- LSP sources
{ 'hrsh7th/cmp-nvim-lsp' },
{ 'hrsh7th/cmp-nvim-lsp-signature-help' },
-- Other sources:
{ 'hrsh7th/cmp-vsnip' },
{ 'hrsh7th/cmp-path' },
{ 'hrsh7th/cmp-buffer' },
-- Tree sitter
{ 'nvim-treesitter/nvim-treesitter',
requires = { 'p00f/nvim-ts-rainbow' },
run = function() require('nvim-treesitter.install').update({ with_sync = true }) end,
config = require 'psoxizsh.plugins.config.nvim-treesitter'
},
-- Fuzzy search helpers
{ 'junegunn/fzf',
cmd = 'FZF',