lsp-mode 快速参考卡全解:核心命令速查与 PDF 再生成指南

原创2026-10-12 12:46:021,677 阅读
文章标签:开发工具

lsp-mode 快速参考卡全解:核心命令速查与 PDF 再生成指南

lsp-mode 是 Emacs 下的 Language Server Protocol 客户端/库,其功能命令数量庞大且分散在多个前缀组合中。为了帮助用户快速上手,仓库提供了一个单页 PDF 形式的“快速参考卡”(Quick Reference Card),浓缩了使用 lsp-mode 最需要记住的核心命令。本文以 refcard/README.md 为骨架,完整讲解参考卡的内容、从 TeX 源文件重新生成 PDF 的方法,并结合 lsp-mode.el 的源码揭示这些按键绑定背后的实现原理。读完本文,你将能看懂参考卡上的每一个组合键,能自行修改并重新生成属于你自己的速查卡,也能理解哪些命令依赖额外的 lsp-ui / lsp-treemacs 扩展包。

什么是 lsp-mode Quick Reference Card

lsp-mode 的快速参考卡是一份单页 PDF,位于 refcard/lsp-refcard.pdf,它只收录“有效使用 lsp-mode 所必需的关键命令”(the essential commands one needs to know to use lsp-mode effectively)。项目文档 refcard/README.md 中给出了相当直白的建议:

You're encouraged to print it, laminate it and keep it on your desk.

即:把它打印出来、塑封好、放在桌面上随时查阅。这份参考卡的设计目标就是在不翻文档的前提下,快速找到“跳转到定义”“重启语言服务器”“触发代码操作”等高频操作的按键。它不追求穷尽 lsp-mode 的全部 100 余条命令,而是精选出日常开发中最常用的部分,按功能域分组排版成双栏。

参考卡的排版布局定义在 refcard/lsp-refcard.tex 中。这是一个 LaTeX 源文件,内容分为以下功能分组:

  • Programming > Change Server State:服务器生命周期管理
  • Toggle Actions:各类显示特性的开关
  • GoTo:符号跳转导航
  • Workspace:工作区文件夹管理
  • Peek:内联预览(依赖 lsp-ui)
  • Find Actions:悬停描述、签名帮助等查询
  • Refactor:重命名、整理导入
  • Code Actions:代码操作与符号高亮

修改与再生成:从 .tex 到 .pdf

参考卡是文本可维护的:PDF 并非手工绘制,而是由 LaTeX 源文件 refcard/lsp-refcard.tex 编译生成。若想增删按键、调整分组或修改标题,应先编辑 .tex 源文件,再重新编译出 PDF,而不是直接修改 PDF 文件本身。

重新生成 PDF 的命令极其简单(在 refcard/ 目录下执行):

$ pdflatex lsp-refcard.tex

运行后会在同一目录下生成(或覆盖)refcard/lsp-refcard.pdf。

需要注意以下几点前提:

  1. 安装 pdflatex:README 明确指出“you might have to install pdflatex first”。pdflatex 是 TeX 发行版提供的编译命令,常见发行版包括 TeX Live(Linux/macOS/Windows)、MacTeX(macOS)与 MiKTeX(Windows)。例如在 Debian/Ubuntu 系系统上安装 texlive 相关软件包、在 macOS 上安装 MacTeX、在 Windows 上安装 MiKTeX,即可获得 pdflatex 可执行文件。安装完成后可用 pdflatex --version 验证。
  2. 宏包依赖:lsp-refcard.tex 头部加载了 geometry、multicol、menukeys、enumitem、xcolor、xparse、calc、tcolorbox 等宏包(见 refcard/lsp-refcard.tex)。其中 menukeys 用于渲染键盘按键外观(如 s-l w s 的键帽样式),tcolorbox 用于绘制顶部“Getting Help for lsp-mode”提示框,multicol 实现双栏排版。建议安装完整的 TeX 发行版,以免因缺少宏包导致编译报错。
  3. 排版细节:文档类为 a4paper,10pt 的 article,页边距 1cm,无页码(\pagestyle{empty}),双栏间距 1cm,并在中栏位置使用 \columnbreak 强制分栏(见 refcard/lsp-refcard.tex),保证双栏内容均衡。

参考卡命令全览:前缀约定

参考卡上所有命令都遵循同一个前缀约定:s-l(super 键 + l 键),随后再按功能分组字母与操作键。例如 s-l w s 表示“按 super-l 后,再按 w 再按 s”,启动语言服务器。

这一约定在源码中由自定义变量 lsp-keymap-prefix 定义,默认值为字符串 "s-l"(见 lsp-mode.el):

(defcustom lsp-keymap-prefix "s-l"
  "LSP-mode keymap prefix."
  :group 'lsp-mode
  :type 'string
  :package-version '(lsp-mode . "6.3"))

也就是说,参考卡中的 s-l 前缀并非写死的常量,而是可以整体替换的:若你的 super 键不顺手,可通过 setq lsp-keymap-prefix "C-l" 之类的配置改为 C-l 前缀,参考卡上的所有组合键随之整体平移。绑定本身在 lsp-mode.el 中完成:

(when lsp-keymap-prefix
  (define-key map (kbd lsp-keymap-prefix) lsp-command-map))

即当 lsp-keymap-prefix 非 nil 时,把前缀键映射到 lsp-command-map(一个稀疏键表)。注意区分大小写:参考卡上 w d(Describe session)与 w D(Disconnect buffer)是不同命令,G g 的大写 G 是 Peek 分组的专属前缀。

参考卡左上角还有一个提示框 “Getting Help for lsp-mode”,强调:所有 lsp 命令都以该前缀命令开始——记住了 s-l,就等于掌握了进入整个命令体系的入口。

服务状态管理(Change Server State)

这一组命令管理语言服务器的生命周期,对应源码中 lsp-command-map 的 w* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l w s 启动语言服务器(Start server) lsp 始终可用
s-l w r 重启语言服务器(Restart server) lsp-workspace-restart 已有活动 workspace
s-l w q 关闭语言服务器(Shutdown server) lsp-workspace-shutdown 已有活动 workspace
s-l w d 描述当前会话(Describe session) lsp-describe-session 始终可用
s-l w D 将当前 buffer 与语言服务器断开(Disconnect buffer from LS) lsp-disconnect 已有活动 workspace

其中 lsp-describe-session(见 lsp-mode.el)会打开一个会话描述 buffer,展示各 workspace 的状态、已连接客户端与服务器信息,是排查“服务器到底起没起、连没连上”的首选诊断命令。

开关类操作(Toggle Actions)

T 分组集中了 lsp-mode 的显示特性开关,对应源码 T* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l T l 切换 Code Lens(Toggle lenses) lsp-lens-mode 服务器支持 textDocument/codeLens
s-l T L 切换 I/O 日志(Toggle log I/O) lsp-toggle-trace-io 始终可用
s-l T h 切换符号高亮(Toggle symbol highlighting) lsp-toggle-symbol-highlight 服务器支持 textDocument/documentHighlight
s-l T S 切换 Sideline(需 lsp-ui,红色标记) lsp-ui-sideline-mode 已加载 lsp-ui-sideline
s-l T d 切换文档弹窗(需 lsp-ui,红色标记) lsp-ui-doc-mode 已加载 lsp-ui-doc
s-l T s 切换签名自动激活(Toggle signature) lsp-toggle-signature-auto-activate 服务器支持 textDocument/signatureHelp
s-l T f 切换输入时格式化(Toggle on Type Formatting) lsp-toggle-on-type-formatting 服务器支持 textDocument/onTypeFormatting

参考卡源文件中,T S 与 T d 两项以红色印刷(refcard/lsp-refcard.tex),提示用户这两项依赖独立的 lsp-ui 扩展包。源码中的可用条件也印证了这一点:(featurep 'lsp-ui-sideline) 与 (featurep 'lsp-ui-doc)。

lsp-toggle-on-type-formatting 的实现(见 lsp-mode.el)会在 after-change-functions 中挂钩,在每次输入后请求服务器执行按需格式化,属于“边打字边自动排版”的能力开关。

跳转导航(GoTo)

g 分组是日常使用频率最高的一组导航命令,对应源码 g* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l g g 查找定义(Find Definitions) lsp-find-definition textDocument/definition
s-l g r 查找引用(Find References) lsp-find-references textDocument/references
s-l g i 查找实现(Find Implementations) lsp-find-implementation textDocument/implementation
s-l g t 查找类型定义(Find Type Definition) lsp-find-type-definition textDocument/typeDefinition
s-l g d 查找声明(Find Declarations) lsp-find-declaration textDocument/declaration
s-l g h 显示调用层次(需 lsp-treemacs,蓝色标记) lsp-treemacs-call-hierarchy 服务器支持 callHierarchy/incomingCalls 且已加载 lsp-treemacs
s-l g e Treemacs 错误列表(需 lsp-treemacs,蓝色标记) lsp-treemacs-errors-list 已加载 lsp-treemacs
s-l g a 在工作区查找符号(Find Symbol in Workspace) xref-find-apropos workspace/symbol

这组命令在源码中均为 cl-defun 定义的异步跳转函数,例如 lsp-find-definition(见 lsp-mode.el)、lsp-find-references(见 lsp-mode.el)。参考卡中以蓝色标记的 g h 与 g e 两项,从源码条件可以看出它们依赖 lsp-treemacs 包(fboundp 'lsp-treemacs-call-hierarchy、fboundp 'lsp-treemacs-errors-list)。

工作区管理(Workspace)

F 分组管理 workspace 文件夹,对应源码 F* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l F a 向 workspace 添加文件夹 lsp-workspace-folders-add 始终可用
s-l F r 从 workspace 移除文件夹 lsp-workspace-folders-remove 始终可用
s-l F b 将文件夹移出 workspace 黑名单 lsp-workspace-blocklist-remove 始终可用

这三项与源码条件均为 t(无条件可用),它们操作的是 lsp-mode 的 workspace 会话模型:语言服务器通常以整个 workspace(根目录树)为单位提供服务,而黑名单机制用于排除不需要纳入管理的目录。

Peek 内联预览

G(大写)分组提供 lsp-ui 的 peek 内联预览功能,全部以红色标记(依赖 lsp-ui),对应源码 G* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l G g Peek 定义(内联预览) lsp-ui-peek-find-definitions 支持 textDocument/definition 且已加载 lsp-ui-peek
s-l G r Peek 引用 lsp-ui-peek-find-references 支持 textDocument/references 且已加载 lsp-ui-peek
s-l G i Peek 实现 lsp-ui-peek-find-implementation 支持 textDocument/implementation 且已加载 lsp-ui-peek
s-l G s Peek 工作区符号 lsp-ui-peek-find-workspace-symbol 支持 workspace/symbol 且已加载 lsp-ui-peek

与 g 组的“跳转到目标位置”不同,peek 是在当前窗口内弹出内联预览列表,选中后才会真正跳转,适合快速浏览而不丢失当前编辑上下文。

查询与帮助(Find Actions)

h 分组提供符号查询与帮助,对应源码 h* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l h h 描述光标处符号(Describe Symbol at Point) lsp-describe-thing-at-point 服务器支持 textDocument/hover
s-l h s 签名帮助(Signature Help) lsp-signature-activate 服务器支持 textDocument/signatureHelp
s-l h g lsp-ui 文档速览(Glance,红色标记) lsp-ui-doc-glance 已加载 lsp-ui-doc 且支持 textDocument/hover

其中 lsp-describe-thing-at-point(见 lsp-mode.el)把 LSP 的 hover 信息以富文本形式展示出来;lsp-signature-activate(见 lsp-mode.el)激活当前函数调用的参数签名提示,并可用 M-n / M-p 在多个重载签名间切换(见 lsp-mode.el)。

重构(Refactor)

r 分组是重构操作,对应源码 r* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l r r 重命名符号(Rename) lsp-rename 服务器支持 textDocument/rename
s-l r o 整理导入(Organize Imports) lsp-organize-imports 服务器支持 textDocument/codeAction

lsp-rename(见 lsp-mode.el)会要求输入新名称并调用 textDocument/rename,由服务器计算整个项目范围内的重命名编辑;lsp-organize-imports 则通过 codeAction 请求服务器清理未使用的导入语句。

代码操作(Code Actions)

a 分组提供代码操作入口,对应源码 a* 绑定(见 lsp-mode.el):

按键 功能 源码绑定 可用条件
s-l a a 执行代码操作(Code actions) lsp-execute-code-action 服务器支持 textDocument/codeAction
s-l a h 高亮符号(Highlight Symbol) lsp-document-highlight 服务器支持 textDocument/documentHighlight

lsp-execute-code-action(见 lsp-mode.el)会请求服务器返回当前光标位置可用的 code actions(如快速修复、生成实现等)并以交互方式让用户选择执行;lsp-document-highlight(见 lsp-mode.el)则高亮当前符号在文档中的所有出现位置,便于目视追踪。

源码视角:条件按键绑定的实现原理

参考卡上的命令之所以“该出现时出现、不该出现时消失”,源于 lsp-command-map 采用了一种条件按键绑定机制。其核心定义位于 lsp-mode.el,而机制本身由宏 lsp-define-conditional-key 实现(见 lsp-mode.el)。

该宏与 define-key 类似,区别在于多了一个 COND 条件参数:

(defmacro lsp-define-conditional-key (keymap key def desc cond &rest bindings)
  "In KEYMAP, define key sequence KEY as DEF conditionally.
This is like `define-key', except the definition disappears
whenever COND evaluates to nil."
  ...)

实现上,它把每个绑定展开为带 :filter 的 menu-item:

`((define-key ,keymap ,key
    '(menu-item
       ,(format "maybe-%s" def)
       ,def
       :filter
       (lambda (item)
         (when (with-current-buffer (or (when (buffer-live-p lsp--describe-buffer)
                                          lsp--describe-buffer)
                                        (current-buffer))
                 ,cond)
           item))))

menu-item 的 :filter 会在按键被查询时求值 COND:条件成立则返回该菜单项(按键可用),条件不成立则返回 nil(按键从键表中“消失”)。这样,s-l g g(Find Definitions)只有在当前语言服务器声明支持 textDocument/definition 时才有效;若当前 buffer 未启用任何语言服务器,整组 g* 命令都会自动失效,从而避免误触。这也解释了参考卡上每个命令旁“可用条件”一栏的来源——它们直接对应源码中 lsp-command-map 里各绑定的条件表达式。

此外,lsp-define-conditional-key 在定义绑定时会同时把 (key desc) 对追加到 lsp--binding-descriptions 列表(见 lsp-mode.el),为 which-key 集成提供描述数据。参考卡上每个命令旁边的英文说明(如 “start server”“toggle lenses”)正是这些描述,它们与 which-key 弹层中显示的提示文本同源。

参考卡之外的扩展:完整命令表与 which-key

参考卡是精选子集,并非完整清单。lsp-command-map(lsp-mode.el)中还包含若干未印上参考卡的命令,例如:

  • 格式化:s-l = =(lsp-format-buffer 格式化整个 buffer)、s-l = r(lsp-format-region 格式化选中区域),对应源码 =* 绑定(见 lsp-mode.el)。
  • 更多开关:s-l T D(modeline 诊断显示)、s-l T T(lsp-treemacs 同步)、s-l T a(modeline 代码操作计数)、s-l T b(headerline 面包屑),以及 s-l a i(接受 inlay hint)、s-l a l(avy 跳转 lens)等(见 lsp-mode.el)。

如果你使用的是 which-key 插件,可以调用 lsp-enable-which-key-integration(见 lsp-mode.el)为当前 major-mode(或传 t 时为所有模式)注册按键描述:

(lsp-enable-which-key-integration)   ; 当前 major-mode
(lsp-enable-which-key-integration t) ; 所有模式

该函数把 lsp--binding-descriptions 中的描述信息配合分组说明(w → workspaces、F → folders、T → toggle、g → goto、h → help、r → refactor、a → code actions、G → peek,见 lsp-mode.el)注入 which-key,按下 s-l 后即可看到分组提示——相当于把参考卡“搬进了” Emacs 交互界面,且能随服务器能力动态增减条目。参考卡与 which-key 描述同源,二者互为补充:纸质卡适合全局概览,which-key 弹层适合即时提示。

小结

快速参考卡是 lsp-mode 高频命令的“一页纸”浓缩:以 s-l 前缀为入口,w(服务器状态)、T(开关)、g(跳转)、F(工作区)、G(peek)、h(帮助)、r(重构)、a(代码操作)八大分组覆盖了日常开发的核心操作。参考卡本身是可持续维护的 LaTeX 产物,修改 refcard/lsp-refcard.tex 后执行 pdflatex lsp-refcard.tex 即可重新生成 refcard/lsp-refcard.pdf。而所有按键背后的条件绑定机制、可用能力判断与 which-key 描述,都可以在 lsp-mode.el 的 lsp-command-map 定义中逐一验证——这正是从“背按键”走向“理解 lsp-mode 命令体系”的进阶路径。

登录后查看全文
lsp-mode