Emacs 31: Markdown-ts-mode 非官方指南
摘要
一本关于在 Emacs 31 中设置和使用实验性的 Markdown-ts-mode 的非官方指南,涵盖其功能、安装和使用技巧。
暂无内容
查看缓存全文
缓存时间: 2026/08/27 15:21
# Emacs 31 中 markdown-ts-mode 的非官方指南
来源:https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31
## 简介
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#intro
`Emacs 31` 已经发布,带来了许多闪亮的新功能等待我们探索。你可能听说了这个新的 `markdown-ts-mode` 并决定尝试一下。猜怎么着?在 `Emacs 31` 版本中,它被标记为实验性模式。这意味着什么?你应该使用它吗?它已经准备好了吗?这只是一个模式的草图吗?将这篇文章视为快速指南,帮助你启动并运行此模式,并找到这些问题的答案。
## 功能方面进展如何?
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#where-is-it-in-terms-of-features
这是一个实验性模式,对吧?你需要主动选择启用,所以可能并非所有功能都能完美运行,它需要更多的测试和反馈。尽管如此,别被这个标题误导。这并不意味着该模式在功能上还不成熟。正如你将看到的,这是一个功能非常丰富的模式。该模式已经涵盖了所有 [CommonMark 规范](https://commonmark.org/spec),以及大部分 [GitHub Flavored Markdown 规范](https://github.github.com/gfm/),并包含一些额外功能,例如支持非 `-ts-mode`(如 `elisp`)的代码块、目录实用工具,以及与外部转换器(如 `pandoc` 和 `gfm`)的接口。在你深入探索之前,可能需要一些帮助来启动这个模式。Tree-sitter 有点复杂。这可能是你第一次接触 tree-sitter,因此我们的议程中包含一份快速“安装指南”。
## 它在哪里?我需要安装这个模式吗?
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#where-is-it-do-i-need-to-install-the-mode
实验性意味着 Emacs 默认不启用该模式,因此它不会在那里等着你打开 `.md` 文件或通过 `M-x markdown-ts-mode RET` 调用它。你需要加载这个库。正如在 Emacs 中一样,做任何事情都有不止一种方法,我非常喜欢 `use-package`,因此我倾向于用它来组织我的初始化文件。这是我建议的初始设置:
或者,如果你的工具包中没有 `use-package`:
(此处原文省略了具体代码,但根据上下文,应是指不依赖 use-package 的配置方式)
现在,模式和 `x`(不错的额外好东西)库都已加载,你可以直接用它来访问你的 Markdown 文件。如果你想在不修改自己配置的情况下尝试,请执行以下操作:
1. 将上述内容保存到一个文件中,例如 `testing.el`。
2. 使用 `emacs -Q --load 'testing.el'` 命令调用 `emacs`。
这样,你就拥有了一个纯净的 Emacs 会话,测试环境已设置好。本指南的剩余部分将使用此会话。
> **重要提示**:你*无需*下载此包或将其添加到你的包管理器中。(现已非常陈旧并已归档的)MELPA 仓库 (https://github.com/LionyxML/markdown-ts-mode) 将拒绝在 Emacs 31 及更高版本上安装,并且在功能方面非常非常匮乏。如果你在使用它,你就不是在用新的**内置** `markdown-ts-mode`,对吧?我们继续。
## 打开我们的第一个 markdown 文件
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#opening-our-first-markdown-file
为了让你“看到我所看到的”,我们需要一些图片。如果这是你第一次使用基于 tree-sitter 的模式,让我提醒你:尽管 tree-sitter 非常出色、快速且功能丰富,但它也有自己需要完成的一系列任务,如果遇到问题可能需要调试技能。我将尝试在这里涵盖一些;我肯定会忘记其他一些。本指南中,我将使用这个[测试文件](https://github.com/LionyxML/markdown-ts-mode-lab/blob/main/test.md)。托管它的仓库是我们的实验室。记住,那里没有代码,所有代码都在 Emacs 本身中。现在,打开 `test.md` 文件。
> **重要提示**:此时,可能会发生多种情况。如果你的系统中已经安装了 `markdown` 的语法,文件将直接打开。不过,你可能会像我一样被提示:
> (此处描述 Emacs 提示安装语法的场景)
> 这意味着 Emacs 在我的系统中没有找到 `markdown` 的语法,此处指 `~/.emacs.d/tree-sitter/`(这是用 `emacs -Q ...` 启动 Emacs 时的默认位置)。Emacs 会提供安装选项,这意味着从 `markdown-ts-mode` 源代码中已定义的仓库下载并编译它。让我们用 `y` 来安装。Emacs 将克隆语法仓库,编译它,然后继续处理第二个语法。是的,`markdown` 使用两个语法:主语法和一个用于*内联*解析的语法。我将用 `y` 允许 Emacs 安装第二个。成功了!你应该看到这个:
> (此处描述安装成功后的状态)
> 如果没有,以下是出错时你应该检查的内容:
> 1. Emacs 是否使用 tree-sitter 标志编译?使用 `M-: (featurep 'treesit) RET` 检查是否返回 `t`。
> 2. 你是否有用于“编译”语法的工具,如 `make`、`gcc` 等?
> 3. Tree-sitter 需要你发行版中的一个包,通常名为 `tree-sitter-cli`,它提供 `tree-sitter` 二进制文件,你可以用 `tree-sitter --version` 检查你是否拥有它。
> 这是所有 `tree-sitter` 模式的常见难题。许多人喜欢**不**自己编译语法,而是使用来自他们信任的地方(如自己的发行版仓库)的已编译文件,或者包含数百个预编译语法的包。我不打算深入探讨;获取语法的方法有很多,本指南我将坚持“自己构建”。看,我在这里有点骗了你。我告诉你应该看到那个,但实际上,“你看到我所看到的”应该像这样:
> (此处描述实际应有的显示效果)
> 我们在[这里](https://github.com/LionyxML/markdown-ts-mode-lab/blob/f3368384a92464607ddb189c580a92d1a9fd2a89/demo/demo-default-theme-raw.md)提供了完整文件,包含多种默认主题,以便你可以比较你的设置是否完整。那么,发生了什么?这部分解释了为什么 `markdown-ts-mode` **非常特别**。这个模式不仅可以与 `markdown` 一起工作,还可以与所有其他可用的 `-ts-mode` 一起工作!请记住这一点;我们稍后会谈到代码块。现在,我们需要理解几件事。在你的 `test.md` 文件中,我们有一个特殊的头部。在 `markdown` 文件中,以 `toml` 或 `yaml` 作为头部是非常常见的。这里的小东西:
> (此处指 YAML front matter)
> 需要其他东西来*字体化*(即被 Emacs 着色)。你能猜到缺少了什么吗?如果你的回答是“我们需要一个 YAML 的语法!”,那你就对了!当 `-ts-mode` 中的某些内容没有正确字体化时,你很可能缺少语法。由于 `markdown-ts-mode` 是为与**所有可用的 ts-modes** 配合工作而设计的,这也不例外。让我们用可靠的 `M-x treesit-install-language-grammar RET yaml` 安装我们的 `yaml` 语法。你现在可能看到我看到的:
> (此处描述安装 yaml 语法的提示)
> 让我们用 `y` 同意。嗯,看起来这次 `yaml-ts-mode` 试图用 `treesit-install` 注册其首选语法时出了点问题,因为没有建议。我们可以手动提供。但让我们先检查一下。查看 `yaml-ts-mode.el` 源代码,我们可以检查它期望使用哪个语法:
> (此处查看源码确定语法来源)
> 太棒了!让我们直接求值那个代码块,然后再次尝试安装语法。或者像我这次一样,手动提供源 `https://github.com/tree-sitter-grammars/tree-sitter-yaml` 给已启动的交互会话:
> (此处描述手动提供语法源的过程)
> 然后我们用 `RET RET RET...` 持续接受默认选项,直到库安装完成。之后,重新加载 `markdown-ts-mode`,或使用 `C-x x g`,或重新打开你正在访问的文件。我们通过查看源代码所做的在这里相当罕见,大多数 `-ts-mode` 会自动建议它们将从中编译语法的仓库。这次经历很好,这样我可以向你展示该怎么做。现在怎么办?对于每个我们遇到的没有*字体化*的块,我们都需要执行相同的 `M-x treesit-install-language-grammar` 操作。如果你愿意,对于我们的测试文件,我们可以使用 `C-x x f` 强制*字体化*,并提示此文件使用的每个缺失语法。到现在,你应该已经看到整个文档被*字体化*了,就像[这里](https://github.com/LionyxML/markdown-ts-mode-lab/blob/main/demo/demo-default-theme-raw.md)一样。与之前的图像相同:
> (此处再次展示完整字体化的图像)
## 关于语法的说明
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#a-note-on-grammars
**一个 `-ts-mode` 的好坏取决于其背后的 tree-sitter 语法**。这意味着每个 `-ts-mode` 都需要不断跟上 `grammar` 的改进,该语法被任何想要使用 `tree-sitter` 解析该语言的编辑器或程序共享。这也意味着我们在某些时候,会*依赖*语法来获得特定的约束和功能。Emacs 中几乎所有的 `-ts-mode` 代码都充满了关于局限性的说明,以及为何和如何处理某些晦涩内容的推理。Emacs 模式的作者和维护者总是尝试建议语法和 `ts-mode` 准备使用的 SHA 提交,无论是在注释中还是在模式内部的代码中,就像你为 `yaml` 建议看到的那样。维护 `ts-mode` 的一部分工作就是跟上新语法版本的变化。我们尽力保持其与最新版本同步,但我们测试过并应按预期工作的是模式源文件中的那个。这就是为什么我认为通过 Emacs 交互式地自行编译语法是保证良好体验的最佳方式。特别是对于 `markdown-ts-mode`,我们使用 [tree-sitter-grammars/tree-sitter-markdown](https://github.com/tree-sitter-grammars/tree-sitter-markdown) 提供的语法,因为这是最完整、维护最广泛且被代码编辑器和通用程序普遍采用的一个。这并不意味着它没有错误或局限性。同样,我们尽力绕过这些局限性,甚至向语法核心 tree-sitter 库提交问题。
## 我终于可以打开一个 markdown 文件了
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#i-can-finally-open-a-markdown-file
恭喜!现在呢?我需要多久做一次所有这些?只有一次,即你第一次使用 `-ts-mode` 时,或者如果你已经通过其他方法安装了语法,则永远不需要。现在让我们看看 `markdown-ts-mode` 已经提供了什么。
## 快速了解 `markdown-ts-mode` 的功能
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#a-quick-look-at-markdown-ts-mode-features
我们(顺便说一句,这个模式由我和 Stéphane Marks 编写)提供了一个 `easy-menu` 功能,以便快速发现功能。你可以通过点击 `mode-line` 中的 `Markdown`,或者(如果你启用了 `menu-bar-mode`)在菜单栏上,甚至在使用 `markdown-ts-mode` 的缓冲区上点击 `Ctrl + 右键单击`(无论 Emacs 将你的 OS 输入映射成什么)来访问它。
(此处描述菜单界面)
这实际上是本指南的*摘要(TL;DR)*,如果你想现在就停下来自己探索(前方剧透)。
## 编辑
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#editing
学习这个模式最快的方法是尝试所有内容。下面是一个快速演示:你写什么,哪个键为你完成。
### 标记(强调)
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#marks-emphasis
Markdown 是纯文本,所以你总是可以自己输入标记符:
| 你想要 | 你写什么 |
| :---------- | :-------------- |
| **粗体** | `**bold**` |
| 粗体(替代)| `__bold__` |
| *斜体* | `*italic*` |
| 斜体(替代)| `_italic_` |
| ***粗斜体*** | `***both***` |
| ~~删除线~~ | `~~gone~~` |
| `行内代码` | `` `code` `` |
或者让模式来做:`C-c C-x C-f`(`markdown-ts-emphasize`),然后按单个键:
- `b` 粗体,`B` 使用下划线的粗体
- `i` 斜体,`I` 使用下划线的斜体
- `a` 粗斜体
- `s` 删除线
- `c` 行内代码
- `SPC` 移除光标处的强调
如果选定了区域,格式会包裹该区域。如果没有区域,则包裹光标处的单词,或者插入这对标记并将光标放在中间。
(此处描述示例)
提示:`C-c C-x RET`(`markdown-ts-toggle-hide-markup`)可以隐藏标记符本身,因此 `**bold**` 显示为 **bold**。这在边编辑边阅读时非常棒,类似于默认的 `org-mode`。
(此处描述隐藏标记后的效果)
另一个提示:`M-q` 即使在列表和引用内也能正确填充。
### 标题
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#headings
输入它们:`#`,`##`,... 直到 `######`。Setext 标题(`===` 和 `---` 下划线)也会被识别。无需重新输入井号来提升或降低标题级别:
- `M-<` 提升(`markdown-ts-promote`)
- `M->` 降低(`markdown-ts-demote`)
并且移动整个部分(包括正文和子项):
- `M-^`(`markdown-ts-move-subtree-up`)
- `M-v`(`markdown-ts-move-subtree-down`)
在标题上按 `TAB` 会循环其可见性(大纲折叠)。该模式是 `outline-minor-mode` 的良好公民,因此折叠可以正常工作。在标题上按 `S-TAB` 会循环所有标题的可见性。
(此处描述折叠效果)
> **重要提示**:到目前为止,你可以看到这个模式尽可能地试图与 `org-mode` 建立相似之处,以便 Emacs 用户可以更容易地适应 `markdown`。如果这些绑定不适合你,所有内容都可以自定义。
### 列表(列表和复选框)
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#listings-lists-and-checkboxes
输入 `- item`,`+ item`,`* item` 或 `1. item`。
- `M-RET` 新的列表项(`markdown-ts-insert-list-item`)
- `RET` 很智能:`markdown-ts-newline` 会为你继续列表
- `M-<` / `M->` 提升/降低项目
- `C-c C-r` 重新编号有序列表(`markdown-ts-renumber-list`)
- `C-c C-c` 切换任务复选框(`markdown-ts-toggle-checkbox`)
- `M-q` 在项目内正确填充
任务列表是 GFM 的那种:
原始模式:
(此处描述原始任务列表)
隐藏标记后:
(此处描述隐藏标记后的任务列表)
注意,如果你切换了 `C-c C-x RET`,你看到的符号和框仅用于显示。缓冲区仍然保留 `-` 和 `[x]`。参见 `markdown-ts-unordered-list-marker`、`markdown-ts-checked-checkbox` 和 `markdown-ts-unchecked-checkbox`。
### 代码块
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#blocks
`C-c C-,`(`markdown-ts-insert-structure`),然后按一个键:
- `` ` `` 围栏代码块,提示输入语言
- `~` 波浪线围栏代码块
- `q` 块引用
- `d` 分隔线(主题分隔符)
- `t` 表格
如果选定了区域,则包裹该区域而不是插入空块。
(此处描述插入块后的效果)
隐藏标记后:
(此处描述隐藏标记后的效果)
### 代码块
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#code-blocks
这是派对技巧。带有语言标签的围栏块将由该语言自己的模式进行字体化:
(此处描述带语言高亮的代码块)
缺少颜色通常意味着缺少语法,与之前的 `yaml` 头部情况相同。比颜色更好的是:将光标放在块内,你就进入了 `markdown-ts-code-block-in-context-mode`(模式行中较轻的 `[code]`)。在里面:
- `TAB` 按照该语言的方式缩进
- `RET` 换行并按该语言的方式缩进
- `M-q` 按该语言的方式填充
- `M-.` 通过 `xref` 跳转到定义
使用 `C-c C-v n` 和 `C-c C-v p` 移动到下一个/上一个块。非 tree-sitter 模式也适用,包括 `elisp`。可配置项:`markdown-ts-code-block-modes`、`markdown-ts-default-code-block-mode`、`markdown-ts-fontify-code-blocks-natively`。
一个原始示例:
(此处描述原始代码块)
隐藏标记后:
(此处描述隐藏标记后的代码块)
### 表格
https://rahuljuliato.com/posts/markdown-ts-mode-emacs-31#tables
使用 `C-c C-, t` 或 `M-x markdown-ts-table-insert-table` 插入一个表格,它会要求你指定要插入的行数和列数。在表格内,你处于 `markdown-ts-in-table-mode`(模式行中较轻的 `[table]`),键位会改变:
- `TAB` / `S-TAB` 下一个 / 上一个单元格(同时格式化你的表格)
- `RET` / `S-RET` 下一行 / 上一行
- `M-RET` 在下方插入行
(注:由于原始文本在此处结束,翻译也到此为止。)
相似文章
Emacs 31 即将到来:我日常使用的变化
Emacs 31 即将到来,带来了更简单的 tree-sitter 配置和内置的 markdown-ts-mode 等改进。本文详细介绍了作者在开发分支中使用的一些特性,强调了配置工作量的减少。
我已在日常使用的 Emacs 31 变更
Emacs 31 引入了 tree-sitter 的改进,简化了语法安装,并新增了一个内置的 markdown-ts-mode。作者一直在开发分支上日常使用这些变更。
软件界的Emacs化
作者讲述了在终端中阅读 Markdown 的烦恼,并描述了如何使用 Claude 快速构建一个自定义的 macOS Markdown 查看器(MDV.app),展示了 AI 如何让人能够迅速创建个人软件工具。
@geekbb: 发现一个丝滑的 Markdown 编辑器,专为 AI 聊天上下文管理场景设计。 基于 Tauri + React + TypeScript 构建,跨平台支持 macOS / Windows / Linux。 左侧 CodeMirror 6…
marka.md is a cross-platform Markdown editor specialized for AI context management, built with Tauri, React, and TypeScript. It features live preview, Vim mode, themes, and a context tray to bundle notes for AI chats like Claude, ChatGPT, and Gemini.
基于Markdown的测试套件
作者解释了为EndBASIC的编译器和虚拟机切换到基于Markdown的测试套件的原因,目的是让这些测试作为LLM学习该语言独特特性的权威文档。