如何通过nvim-lspconfig在Neovim中配置带自动补全功能的Elixir-LS
我完全懂这种对着一堆零散文档瞎折腾还搞不定的挫败感——Elixir-LS的配置确实容易因为依赖和插件配合出问题,尤其是自动补全这块。下面给你一套从安装到配置的完整流程,每一步都讲清楚为什么要做,避免你复制粘贴看不懂的代码:
一、先搞定Elixir-LS的安装
你说asdf装不了?没关系,推荐用Mix安装(能和你的Elixir版本自动匹配),步骤很简单:
打开终端执行:
mix archive.install hex elixir_ls
如果遇到版本兼容问题,直接指定版本号(选Elixir-LS的最新稳定版即可):
mix archive.install hex elixir_ls 0.17.10
要是你偏好手动下载预编译包:
解压后把language_server.sh(Linux/macOS)或language_server.bat(Windows)的路径记下来,后面配置LSP的时候要用到。
二、必备插件清单(只装必要的,拒绝冗余)
你不需要装一堆花里胡哨的插件,核心就这几个:
nvim-lspconfig:帮你快速对接Neovim内置的LSP客户端nvim-cmp:Neovim最常用的补全核心插件cmp-nvim-lsp:把Elixir-LS的补全数据传给nvim-cmp的桥梁- 可选插件:
cmp-buffer(当前文档内容补全)、cmp-path(文件路径补全)
用你的插件管理器安装,比如Packer的配置:
use { 'neovim/nvim-lspconfig', 'hrsh7th/cmp-nvim-lsp', 'hrsh7th/nvim-cmp', -- 下面两个可选,按需添加 'hrsh7th/cmp-buffer', 'hrsh7th/cmp-path' }
三、分模块配置(LSP + 自动补全,清晰不混乱)
把配置拆成两部分,先搞定LSP连接,再配置补全逻辑,避免混淆。
1. 配置Elixir-LS连接
在你的init.lua或者专门的LSP配置文件(比如after/plugin/lsp.lua)里添加:
local lspconfig = require('lspconfig') -- 配置Elixir-LS lspconfig.elixirls.setup({ -- 如果你是手动下载的预编译包,取消下面注释并替换成你的路径 -- cmd = { "/home/你的用户名/.elixir-ls/language_server.sh" }, -- Mix安装的话不用管cmd,lspconfig会自动找到 on_attach = function(client, bufnr) -- 这里配置常用的LSP快捷键,按需调整 vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', { noremap = true, silent = true }) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', { noremap = true, silent = true }) vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', { noremap = true, silent = true }) end, settings = { elixirLS = { -- 可选配置:启用dialyzer静态分析、自动拉取依赖 dialyzerEnabled = true, fetchDeps = true, } } })
2. 配置自动补全(让nvim-cmp和LSP联动)
接下来把补全逻辑接上,关键是让Elixir-LS把补全数据传给nvim-cmp:
local cmp = require('cmp') local cmp_lsp = require('cmp_nvim_lsp') -- 让LSP具备nvim-cmp需要的补全能力 local capabilities = cmp_lsp.default_capabilities() -- 把capabilities传给Elixir-LS的配置(直接加在之前的setup里即可) lspconfig.elixirls.setup({ -- 保留之前的cmd、on_attach、settings... capabilities = capabilities }) -- 配置nvim-cmp的具体行为 cmp.setup({ snippet = { -- 如果你用代码片段插件(比如luasnip),这里替换成对应配置;不用的话留空也能正常补全 expand = function(args) vim.fn["vsnip#anonymous"](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 }), -- 回车选中第一个补全项 ['<C-k>'] = cmp.mapping.select_prev_item(), -- 向上选补全项 ['<C-j>'] = cmp.mapping.select_next_item(), -- 向下选补全项 }), sources = cmp.config.sources({ { name = 'nvim_lsp' }, -- 核心:来自Elixir-LS的补全 { name = 'buffer' }, -- 可选:当前文档里的文字补全 { name = 'path' }, -- 可选:文件路径补全 }) })
四、常见问题快速排查
- 文档弹窗没反应:先按
:LspInfo看Elixir-LS是否正常启动,再检查on_attach里的K快捷键有没有配置对。 - 补全列表不能滚动:上面的配置里已经加了
<C-k>和<C-j>,要是还是不行,检查有没有其他插件占用了这些快捷键。 - Elixir-LS启动失败:执行
:LspLog查看日志,大概率是路径不对(手动安装的话)或者Elixir版本和Elixir-LS不兼容(比如老版本Elixir要装对应版本的Elixir-LS)。
内容的提问来源于stack exchange,提问作者Adam Millerchip




