vim与neovim编辑器lsp cpp代码补全配置-补充

⌚Time: 2025-10-06 14:27:00

👨‍💻Author: Jack Ge

windows系统。

我尝试vim添加lsp代码补全插件。最后失败了。因为我用到了asyncomplete和asyncomplete-lsp这两个插件作为自动补全插件。他们不工作。

还用到了vim-lsp插件。它工作。

我把他们这些插件放到了vim配置目录下。vim的配置目录通过下面的命令可以得到

:echo &runtimepath

通常这个目录不是AI提示的什么pack/plugin/start目录,而是存在于用户或者vim安装目录下的vimfile目录。

我花了几个小时,问AI配置代码和错误提示。都没有解决。所以最后只有vim-lsp插件能用。它与lsp服务器clangd通信。能够进行lsp补全,通过ominifunc的方式。在按下ctrl+x,ctrl+o之后能够弹出智能补全菜单。在编辑器里也能提示代码错误和警告信息。能够进行跳转、引用、定义查找。

但是因为asyncomplete和asyncomplete-lsp不能用。无法自动弹出提示。每次想要看提示得按4个键,所以就是失败了。我放弃了使用vim。


之前我测试了nvim6的代码补全。我现在用了nvim8。在配置完成后打开代码出现了lsp智能补全。但是输入时候提示snippet引擎缺少配置。

后来我发现nvim cmp插件需要snippet插件的支持。很烦。

我下载了LuaSnip插件,地址是:https://github.com/L3MON4D3/LuaSnip

与之前插件的安装方式一样。nvim配置目录是:C:\Users\jack\AppData\Local\nvim

我放进了nvim插件目录pack/plugins/start。

它在之后正常补全。

下面的是AI生成的正常的init.lua代码

-- 基本设置
vim.opt.termguicolors = true
vim.opt.number = true
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true
vim.opt.smartindent = true
vim.opt.signcolumn = 'yes' -- 为 LSP 诊断信息留出空间
vim.opt.updatetime = 100 -- 更快的补全响应

--自定义补全菜单外观
vim.api.nvim_set_hl(0, 'Pmenu', { bg = '#2e3440', fg = '#d8dee9' })           -- 补全菜单背景
vim.api.nvim_set_hl(0, 'PmenuSel', { bg = '#5e81ac', fg = '#ffffff', bold = true }) -- 选中项
vim.api.nvim_set_hl(0, 'PmenuSbar', { bg = '#3b4252' })                      -- 滚动条背景
vim.api.nvim_set_hl(0, 'PmenuThumb', { bg = '#81a1c1' })                     -- 滚动条滑块

-- 确保 LSP 和 CMP 相关模块已加载
local lspconfig = require('lspconfig')
local cmp = require('cmp')

-- 获取 LSP 能力(用于与 nvim-cmp 集成)
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)

-- 全局 LSP 按键映射
local on_attach = function(client, bufnr)
    -- 启用补全
    vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')

    -- 按键映射
    local opts = { noremap = true, silent = true, buffer = bufnr }
    
    -- 查看定义
    vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
    -- 查看声明
    vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
    -- 查看实现
    vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
    -- 查看类型定义
    vim.keymap.set('n', 'gt', vim.lsp.buf.type_definition, opts)
    -- 查看引用
    vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
    -- 悬停提示
    vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
    -- 重命名
    vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
    -- 代码操作
    vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, opts)
    -- 格式化
    vim.keymap.set('n', '<leader>f', function()
        vim.lsp.buf.format({ async = true })
    end, opts)
    
    -- 显示行诊断
    vim.keymap.set('n', '<leader>e', vim.diagnostic.open_float, opts)
    -- 下一个诊断
    vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
    vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
end

-- 配置 clangd
lspconfig.clangd.setup{
    on_attach = on_attach,
    capabilities = capabilities,
    cmd = {
        "clangd",
        "--background-index",
        "--suggest-missing-includes",
        "--clang-tidy",
        "--header-insertion=never", -- 避免自动插入头文件
    },
    filetypes = {"c", "cpp", "objc", "objcpp", "cuda"},
    single_file_support = true,
}

-- nvim-cmp 配置
cmp.setup({
    snippet = {
        expand = function(args)
            require('luasnip').lsp_expand(args.body)
        end,
    },
    mapping = cmp.mapping.preset.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 }),
        ['<Tab>'] = cmp.mapping.select_next_item(),
        ['<S-Tab>'] = cmp.mapping.select_prev_item(),
    }),
    sources = cmp.config.sources({
        { name = 'nvim_lsp' },
        { name = 'luasnip' },
    }, {
        { name = 'buffer' },
    })
})
-- 自动命令:LSP 诊断显示
vim.api.nvim_create_autocmd('CursorHold', {
    callback = function()
        vim.diagnostic.open_float(nil, { focusable = false })
    end
})

-- 设置补全菜单的最大高度
vim.opt.pumheight = 10
--设置字体
vim.cmd([[set guifont=Courier\ New:h22]])
--动态命令查看字体列表 :set guifont=*
--设置默认工作目录
vim.cmd([[cd D:\ProjectSpace\Vim]])

附加选项,如果不需要代码审查和错误标记竖条

-- 禁用所有 LSP 诊断
vim.diagnostic.disable()
--取消signcolumn
vim.o.signcolumn = "no"


发现nvim启动某个程序:!./a.exe会在内置终端运行

内置终端会竟然会掠过std::cin和system("pause")。导致程序无法阻塞。很不好用!

办法就是启动一个终端:Terminal

或者在终端执行:Terminal a.exe

这样会得到一个新的终端窗口执行程序。并且操作与普通文件一样。默认在编辑模式,输入i/a可以进入插入模式。输入:进入命令模式


让clangd找到第三方库文件并智能提示的办法:在项目根目录下创建compile_flags.txt文件,并且输入mingw包含头文件目录的编译参数,比如:

compile_flags.txt

-mms-bitfields 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/gtk-3.0 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/cairo 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/pango-1.0 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/atk-1.0 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/cairo 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/pixman-1 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/freetype2 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/libpng15 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/gdk-pixbuf-2.0 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/libpng15 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/include/glib-2.0 
-ID:/BuildChanTools/gtk+-bundle_3.6.4-20130513_win32/lib/glib-2.0/include