Files
lazyfox/lua/plugins/nvim-cmp.lua
2025-08-15 02:02:47 +03:00

307 lines
11 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local lspkind = require("lspkind")
return {
"hrsh7th/nvim-cmp",
version = false, -- last release is way too old
event = "InsertEnter",
dependencies = {
"hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-path",
"hrsh7th/cmp-cmdline",
"hrsh7th/cmp-nvim-lua",
"hrsh7th/cmp-emoji",
"hrsh7th/cmp-calc",
"f3fora/cmp-spell",
"hrsh7th/cmp-nvim-lsp-signature-help",
"onsails/lspkind.nvim",
},
opts = function()
vim.api.nvim_set_hl(0, "CmpGhostText", { link = "Comment", default = true })
local cmp = require("cmp")
local defaults = require("cmp.config.default")()
-- local lspkind = require("lspkind")
-- Проверяем наличие luasnip
local has_luasnip = pcall(require, "luasnip")
local luasnip = has_luasnip and require("luasnip") or nil
return {
completion = {
completeopt = "menu,menuone,noinsert",
},
snippet = {
expand = function(args)
if luasnip then
luasnip.lsp_expand(args.body)
end
end,
},
mapping = cmp.mapping.preset.insert({
["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
["<C-b>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.abort(),
["<CR>"] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item
["<S-CR>"] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = true,
}), -- Accept currently selected item and replace
["<C-CR>"] = function(fallback)
cmp.abort()
fallback()
end,
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip and luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip and luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { "i", "s" }),
}),
sources = cmp.config.sources({
{
name = "nvim_lsp",
priority = 1000,
-- Специальные настройки для Go
entry_filter = function(entry, ctx)
local kind = entry:get_kind()
-- Для Go файлов приоритизируем функции и методы
if vim.bo.filetype == "go" then
if
kind == require("cmp.types").lsp.CompletionItemKind.Function
or kind == require("cmp.types").lsp.CompletionItemKind.Method
then
return true
end
end
return true
end,
},
-- Добавляем luasnip только если он доступен
has_luasnip and { name = "luasnip", priority = 750 } or nil,
{ name = "nvim_lsp_signature_help", priority = 700 },
{ name = "nvim_lua", priority = 600 },
}, {
{ name = "buffer", priority = 500, keyword_length = 3 },
{ name = "path", priority = 400 },
{ name = "emoji", priority = 300 },
{ name = "calc", priority = 250 },
{ name = "spell", priority = 200, keyword_length = 4 },
}),
formatting = {
format = lspkind.cmp_format({
mode = "symbol_text",
maxwidth = 50,
ellipsis_char = "...",
before = function(entry, vim_item)
-- Специальная обработка для Go
if vim.bo.filetype == "go" then
-- Добавляем тип для Go функций и методов
if entry.source.name == "nvim_lsp" then
local completion_item = entry.completion_item
if completion_item.detail then
-- Обрезаем слишком длинные детали для Go
local detail = completion_item.detail
if string.len(detail) > 30 then
detail = string.sub(detail, 1, 27) .. "..."
end
vim_item.menu = detail
else
vim_item.menu = "[LSP]"
end
end
else
-- Source name для других языков
vim_item.menu = ({
nvim_lsp = "[LSP]",
luasnip = "[Snippet]",
buffer = "[Buffer]",
path = "[Path]",
nvim_lua = "[Lua]",
emoji = "[Emoji]",
calc = "[Calc]",
spell = "[Spell]",
nvim_lsp_signature_help = "[Signature]",
})[entry.source.name] or "[Unknown]"
end
return vim_item
end,
}),
},
experimental = {
ghost_text = {
hl_group = "CmpGhostText",
},
},
sorting = defaults.sorting,
window = {
completion = cmp.config.window.bordered({
border = "rounded",
winhighlight = "Normal:CmpPmenu,CursorLine:CmpSel,Search:None",
}),
documentation = cmp.config.window.bordered({
border = "rounded",
winhighlight = "Normal:CmpDoc",
}),
},
preselect = cmp.PreselectMode.Item,
performance = {
debounce = 60,
throttle = 30,
fetching_timeout = 500,
confirm_resolve_timeout = 80,
async_budget = 1,
max_view_entries = 200,
},
matching = {
disallow_fuzzy_matching = false,
disallow_fullfuzzy_matching = false,
disallow_partial_fuzzy_matching = true,
disallow_partial_matching = false,
disallow_prefix_unmatching = false,
},
}
end,
config = function(_, opts)
local cmp = require("cmp")
cmp.setup(opts)
-- Специальная конфигурация для Go файлов
local go_sources = {
{
name = "nvim_lsp",
priority = 1000,
-- Настройки специально для gopls
option = {
-- Включаем документацию для всех элементов
get_trigger_characters = function()
return { ".", ":" }
end,
},
},
{ name = "nvim_lsp_signature_help", priority = 700 },
}
-- Добавляем luasnip только если он доступен
-- if has_luasnip then
-- table.insert(go_sources, 2, { name = "luasnip", priority = 750 })
-- end
--
-- cmp.setup.filetype("go", {
-- sources = cmp.config.sources(go_sources, {
-- { name = "buffer", priority = 500, keyword_length = 2 }, -- Меньше символов для Go
-- { name = "path", priority = 400 },
-- }),
-- formatting = {
-- format = lspkind.cmp_format({
-- mode = "symbol_text",
-- maxwidth = 60, -- Больше места для Go типов
-- ellipsis_char = "...",
-- before = function(entry, vim_item)
-- if entry.source.name == "nvim_lsp" then
-- local completion_item = entry.completion_item
-- if completion_item.detail then
-- local detail = completion_item.detail
-- -- Специальная обработка Go типов
-- if string.match(detail, "^func") then
-- vim_item.menu = "[func] " .. detail:sub(1, 40)
-- elseif string.match(detail, "^type") then
-- vim_item.menu = "[type] " .. detail:sub(1, 40)
-- elseif string.match(detail, "^var") then
-- vim_item.menu = "[var] " .. detail:sub(1, 40)
-- elseif string.match(detail, "^const") then
-- vim_item.menu = "[const] " .. detail:sub(1, 40)
-- else
-- vim_item.menu = detail:sub(1, 50)
-- end
-- else
-- vim_item.menu = "[LSP]"
-- end
-- else
-- vim_item.menu = ({
-- luasnip = "[Snippet]",
-- buffer = "[Buffer]",
-- path = "[Path]",
-- nvim_lsp_signature_help = "[Signature]",
-- })[entry.source.name] or "[Unknown]"
-- end
-- return vim_item
-- end,
-- }),
-- },
-- matching = {
-- disallow_fuzzy_matching = false,
-- disallow_fullfuzzy_matching = false,
-- disallow_partial_fuzzy_matching = true, -- Разрешаем для Go
-- disallow_partial_matching = false,
-- disallow_prefix_unmatching = false,
-- },
-- })
-- Use buffer source for `/` and `?` (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(),
-- sources = cmp.config.sources({
-- { name = "path" },
-- }, {
-- { name = "cmdline" },
-- }),
-- matching = { disallow_symbol_nonprefix_matching = false },
-- })
-- Auto-pairs integration (проверяем наличие плагина)
local has_autopairs, cmp_autopairs = pcall(require, "nvim-autopairs.completion.cmp")
if has_autopairs then
cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done())
end
-- Go specific autocmds
vim.api.nvim_create_autocmd("FileType", {
pattern = "go",
callback = function()
-- Настройки для улучшения работы с gopls
vim.opt_local.completeopt = "menu,menuone,noinsert,preview"
-- Автоматический импорт при автодополнении
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*.go",
callback = function()
local params = vim.lsp.util.make_range_params()
params.context = { only = { "source.organizeImports" } }
local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, 1000)
for _, res in pairs(result or {}) do
for _, r in pairs(res.result or {}) do
if r.edit then
vim.lsp.util.apply_workspace_edit(r.edit, "utf-8")
end
end
end
end,
})
end,
})
end,
}