如何实现Neovim LSP on_init异步执行 解决EFM项目配置加载UI冻结问题
解决方案
你可以使用 Neovim 内置的 libuv 异步接口 vim.loop.spawn 替换原有的同步 systemlist 调用,无需修改核心配置逻辑即可解决UI阻塞问题。修改后的代码如下:
on_init = function(client) -- 异步执行pip list命令,完全不阻塞主UI线程 local stdout = vim.loop.new_pipe(false) local stderr = vim.loop.new_pipe(false) -- 启动异步子进程执行poetry命令 vim.loop.spawn('poetry', { args = { 'run', 'pip', 'list', '--disable-pip-version-check' }, stdio = { nil, stdout, stderr }, }, vim.schedule_wrap(function(code, signal) -- 进程退出后清理管道资源 stdout:read_stop() stderr:read_stop() stdout:close() stderr:close() end)) local matched_packages = {} -- 异步读取命令标准输出 stdout:read_start(vim.schedule_wrap(function(err, data) if err then return end if data then -- 逐行匹配需要的工具包,替代grep逻辑 for line in vim.gsplit(data, '\n', { plain = true, trimempty = true }) do local pkg_name = line:match('^(%w+)%s+') if pkg_name and vim.tbl_contains({'black', 'yapf', 'flake8', 'isort', 'mypy'}, pkg_name) then table.insert(matched_packages, pkg_name) end end else -- 输出读取完成后更新LSP配置 for _, pkg in ipairs(matched_packages) do local pkg_config = M[pkg] if pkg_config then table.insert(client.config.settings.languages.python, pkg_config) end end -- 通知LSP配置更新 client.notify("workspace/didChangeConfiguration") end end)) return true end
几个优化和注意事项:
- 所有回调都用
vim.schedule_wrap包裹,确保 Neovim 核心API调用运行在主线程,避免线程安全问题 - 把原有的grep逻辑移到Lua层实现,减少额外子进程开销,执行效率更高
- 异步逻辑不会阻塞on_init回调返回,LSP可以正常启动,配置更新完成后会自动生效
内容的提问来源于stack exchange,提问作者ddd111
相关产品推荐
相关产品推荐

