local M = {} local check_backspace = function() local col = vim.fn.col "." - 1 return col == 0 or vim.fn.getline("."):sub(col, col):match "%s" end local function T(str) return vim.api.nvim_replace_termcodes(str, true, true, true) end local is_emmet_active = function() local clients = vim.lsp.buf_get_clients() for _, client in pairs(clients) do if client.name == "emmet_ls" then return true end end return false end M.config = function() local status_cmp_ok, cmp = pcall(require, "cmp") if not status_cmp_ok then return end local status_luasnip_ok, luasnip = pcall(require, "luasnip") if not status_luasnip_ok then return end options.builtin.cmp = { formatting = { format = function(entry, vim_item) local icons = require("lsp.kind").icons vim_item.kind = icons[vim_item.kind] vim_item.menu = ({ nvim_lsp = "(LSP)", emoji = "(Emoji)", path = "(Path)", calc = "(Calc)", cmp_tabnine = "(Tabnine)", vsnip = "(Snippet)", luasnip = "(Snippet)", buffer = "(Buffer)", })[entry.source.name] vim_item.dup = ({ buffer = 1, path = 1, nvim_lsp = 0, })[entry.source.name] or 0 return vim_item end, }, snippet = { expand = function(args) require("luasnip").lsp_expand(args.body) end, }, documentation = { border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, }, sources = { { name = "nvim_lsp" }, { name = "path" }, { name = "luasnip" }, { name = "cmp_tabnine" }, { name = "nvim_lua" }, { name = "buffer" }, { name = "calc" }, { name = "emoji" }, { name = "treesitter" }, { name = "crates" }, }, mapping = { [""] = cmp.mapping.scroll_docs(-4), [""] = cmp.mapping.scroll_docs(4), -- TODO: potentially fix emmet nonsense [""] = cmp.mapping(function() if vim.fn.pumvisible() == 1 then vim.fn.feedkeys(T "", "n") elseif luasnip.expand_or_jumpable() then vim.fn.feedkeys(T "luasnip-expand-or-jump", "") elseif check_backspace() then vim.fn.feedkeys(T "", "n") elseif is_emmet_active() then return vim.fn["cmp#complete"]() else vim.fn.feedkeys(T "", "n") end end, { "i", "s", }), [""] = cmp.mapping(function(fallback) if vim.fn.pumvisible() == 1 then vim.fn.feedkeys(T "", "n") elseif luasnip.jumpable(-1) then vim.fn.feedkeys(T "luasnip-jump-prev", "") else fallback() end end, { "i", "s", }), [""] = cmp.mapping.complete(), [""] = cmp.mapping.close(), [""] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = true, }, }, } end M.setup = function() require("luasnip/loaders/from_vscode").lazy_load() require("cmp").setup(options.builtin.cmp) end return M