Files
lazyfox/lua/plugins/nvim-cmp.lua
Archie Fox 7f1d7f48dd Init commit
2025-07-25 13:09:33 +03:00

306 lines
11 KiB
Lua
Raw 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.

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 = false, -- Разрешаем для 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,
}