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' -- Set completeopt to have a better completion experience vim.o.completeopt = 'menuone,longest,preview' cmp.setup({ experimental = { ghost_text = true, }, formatting = { format = lspkind.cmp_format { mode = 'symbol', menu = { nvim_lsp = '[LSP]', nvim_lua = '[Lua]', buffer = '[BUF]', }, }, }, snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end, }, mapping = { [''] = cmp.mapping.select_prev_item(), [''] = cmp.mapping.select_next_item(), [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete(), [''] = cmp.mapping.close(), [''] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.replace, select = false, }, [''] = cmp.mapping(function(fallback) if luasnip.expand_or_jumpable() then luasnip.expand_or_jump() elseif cmp.visible() then cmp.select_next_item() elseif has_words_before() then cmp.complete() else fallback() end end, { 'i', 's' }), [''] = cmp.mapping(function(fallback) if luasnip.jumpable(-1) then luasnip.jump(-1) elseif cmp.visible() then cmp.select_prev_item() else fallback() end end, { 'i', 's' }), }, sources = { { name = 'nvim_lsp' }, { name = 'nvim_lsp_signature_help' }, { name = 'nvim_lua' }, { name = 'luasnip' }, { name = 'path' }, { name = 'buffer' }, }, })