lsp.vim 开发者 API 指南:用 rpc() 与 rpc_a() 调用任意 LSP 方法

发布时间:2026/8/20 21:08:16
lsp.vim 开发者 API 指南:用 rpc() 与 rpc_a() 调用任意 LSP 方法 lsp.vim 开发者 API 指南用 rpc() 与 rpc_a() 调用任意 LSP 方法【免费下载链接】lspLanguage Server Protocol (LSP) plugin for Vim9项目地址: https://gitcode.com/gh_mirrors/lsp/lsplsp.vim 是 Vim9 环境下流行的 Language Server ProtocolLSP客户端插件内置的补全、跳转、悬停提示等功能覆盖了绝大多数场景。但当你想调用某个语言服务器特有的扩展方法时就需要直接操作 RPC 接口。本指南将手把手教你使用rpc()与rpc_a()两个核心 API在 lsp.vim 中发送任意 LSP 请求让你的 Vim 开发环境解锁更多能力。rpc() 与 rpc_a() 有什么区别先看核心概念lsp.vim 与语言服务器之间通过 JSON-RPC 消息通信。插件把这一层封装成了两个极易上手的接口rpc(method, params, opts)同步请求。发送后阻塞等待服务器回复直接返回结果适合在函数里顺序取值的场景。rpc_a(method, params, Cbfunc)异步请求。发送后立即返回请求 ID服务器回复时再回调你的函数不阻塞Vim 界面适合交互频繁的操作。两者的第一个参数都是 LSP 方法名如textDocument/signatureHelp第二个参数是请求参数。这就是调用任意 LSP 方法的全部秘诀——只要 LSP 规范里存在的方法你都可以用这两个函数原样发送。第一步用 lsp.Server() 拿到服务器对象调用 RPC 前必须先获取当前缓冲区对应的服务器对象import autoload lsp/lsp.vim def g:MyRpcDemo() var s lsp.Server() if s-empty() return endif 现在就可以调用 s.rpc() / s.rpc_a() 了 enddeflsp.Server()返回空字典表示当前缓冲区没有关联语言服务器定义见 lsp.vim 中的Server()函数所以做一次判空是良好的防御习惯。此外它还能顺便提供getPosition()、getTextDocPosition()等辅助方法帮你把光标位置自动转成 LSP 要求的坐标结构省去手工换算的麻烦。同步调用实战用 rpc() 获取函数签名假设你想实现一个括号内也能显示签名的自定义快捷键用同步rpc()是最直白的写法。官方文档lsp.txt 的 Custom LSP Requests 章节给出了完整范例def g:FindSig() var s lsp.Server() if s-empty() return endif var sig s.rpc(textDocument/signatureHelp, s.getTextDocPosition(false)) if sig.result-empty() var save winsaveview() normal! F( if getline(.)[charcol(.) - 1] ( sig s.rpc(textDocument/signatureHelp, s.getTextDocPosition(false)) endif winrestview(save) endif echon \r\r if sig.result-empty() echon No signature found else echon sig.result.signatures[0].label endif enddef nnoremap C-k :call g:FindSig()CR三个要点值得注意返回结构rpc()返回整个 LSP 回复字典结果在result字段里出错时返回空字典。智能坐标getTextDocPosition(false)自动生成TextDocumentPositionParams无需自己拼 JSON。超时控制rpc()还支持可选参数opts例如s.rpc(method, params, {timeout: 5000})可自定义等待时长源码见 lspserver.vim 的Rpc()实现。异步调用实战用 rpc_a() 不阻塞界面同步请求在服务器响应慢时会卡住 Vim而rpc_a()能优雅解决。看同样的签名查询用异步怎么写def FindSigReply(s: dictany, sig: any) echon \r\r if sig-empty() echon No signature found else echon sig.signatures[0].label endif enddef def g:FindSigAsync() var s lsp.Server() if s-empty() return endif s.rpc_a(textDocument/signatureHelp, s.getTextDocPosition(false), FindSigReply) enddef nnoremap C-k :call g:FindSigAsync()CRrpc_a()的回调函数签名为Cbfunc(lspserver, result, error)第一个参数是服务器对象第二个是请求结果第三个是错误信息。若旧代码使用了两参数回调Cbfunc(lspserver, result)插件会自动做向后兼容见 lspserver.vim 的AsyncRpcCb()迁移成本几乎为零。进阶技巧利用返回的请求 ID 取消请求rpc_a()的返回值是本次请求的消息 ID出错时返回 -1。这个 ID 并非摆设——它可以在必要时取消请求。设计交互类功能如高频触发的悬停提示时你可以保存 ID在用户快速移动光标后取消尚未完成的旧请求避免过期结果覆盖新内容让插件体验更跟手。更省事的方案LspRequestCustom() 一键发自定义请求如果不想手写回调插件还内置了g:LspRequestCustom({name}, {method}, {params})函数定义见 lspserver.vim。它按服务器名称找到当前缓冲区的实例异步发送自定义方法并把回复交给统一的处理器适合快速验证某个服务器扩展接口是否可用。比如:call g:LspRequestCustom(tsserver, workspace/executeCommand, {command: myCustomCommand})什么时候该用哪个选型建议一次性查询、逻辑线性选rpc()代码短、易读适合脚本和一次性命令。高频触发、需要流畅交互选rpc_a()不阻塞界面配合请求 ID 可做取消控制。快速验证服务器扩展接口优先LspRequestCustom()无需自己写回调。掌握rpc()与rpc_a()后lsp.vim 就不再只是一个开箱即用的客户端而是完全可编程的 LSP 开发平台。无论是调用textDocument/prepareRename、workspace/executeCommand还是各家服务器私有扩展方法你都能信手拈来把编辑器真正打造成自己的效率工具。【免费下载链接】lspLanguage Server Protocol (LSP) plugin for Vim9项目地址: https://gitcode.com/gh_mirrors/lsp/lsp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻