Emacs 31 的 markdown-ts-mode 非官方使用指南

Emacs 31 的 markdown-ts-mode 非官方使用指南 图片 1
Emacs 31 的 markdown-ts-mode 非官方使用指南 图片 2
Emacs 31 的 markdown-ts-mode 非官方使用指南 图片 3
Emacs 31 的 markdown-ts-mode 非官方使用指南 图片 4

介绍

所以,Emacs 31已经发布了,很多闪亮的新内容都在这里,随时准备让我们玩味。

你可能听说过这个新markdown-ts-mode于是决定去看看。你猜怎么着?在Emacs版本上31,这被标记为实验模式。这意味着什么?你应该用它还是不要?

准备好了吗?这只是一个模式的草图吗?

把这篇文章当作快速指南,帮助你启动并帮助你找到这些问题的答案。

功能方面怎么样?

这是实验模式,对吧?你需要选择加入,所以可能还不会所有功能都完美无缺,还需要更多测试和反馈。

话虽如此,不要被这款游戏误导。这并不意味着该模式的功能为时过早。正如你将看到的,这是一个功能非常丰富的模式。这个模式已经涵盖了所有https://commonmark.org/spec,以及大部分https://github.github.com/gfm/,还有一些额外的内容,比如代码块,即使是非——ts-modes,比如elisp目录工具,以及与外部转换器的接口,例如:pandoc以及gfm.

在自己深入操作之前,你可能需要一些帮助,才能简单地开启这个模式。树木看护者很棘手。这甚至可能是你第一次使用树木看护者,所以我们计划快速做一个“安装指南”。

它在哪里?我需要安装这个模式吗?

实验模式意味着Emacs默认不会启用该模式,所以它不会等着你打开一个.md归档或称呼M-x markdown-ts-mode RET.你需要加载这个库。

一如既往,在Emacs上,我非常喜欢各种操作方式use-package所以我倾向于用它来整理我的init文件。这是我建议的初始设置:

(use-package markdown-ts-mode
  :ensure nil
  :mode ("\\.md\\'" "\\.mdx\\'" "\\.markdown\\'")
  :config
  (require 'markdown-ts-mode-x))

或者如果你保持use-package从你的工具箱里拿出来:

(autoload 'markdown-ts-mode "markdown-ts-mode" nil t)

(dolist (re '("\\.md\\'" "\\.mdx\\'" "\\.markdown\\'"))
  (add-to-list 'auto-mode-alist (cons re 'markdown-ts-mode)))

(with-eval-after-load 'markdown-ts-mode
  (require 'markdown-ts-mode-x))

现在,既有模式,也包括x(额外内容)库已经加载,你可以直接访问你的Markdown文件。

如果你想在不动动自己配置的情况下尝试,可以这样做:

  1. 把上述内容保存到类似这样的文件中testing.el.
  2. 叫声emacs其中emacs -Q --load 'testing.el'.

这就是一个带着测试场地的裸Emacs会话。这就是我接下来的指南内容。

重要: 有不用了下载或添加到你的包管理器中。(现在非常旧且已归档)MELPA 仓库它拒绝安装Emacs 31版以后,功能非常非常差。如果你用的是这个,说明你没用到新的内置 markdown-ts-mode.右?继续吧。

打开我们的第一个 Markdown 文件

为了让你“看到我看到的”,我们需要一些图片。如果你是第一次使用基于树木的模式,我得提醒你:虽然树木看护非常棒、快速且功能丰富,但它也有一套任务需要完成,如果需要帮助,还可能需要调试技能。

我会尽量在这里介绍一些;其他的我肯定会遗忘。

在这个指南中,我将使用这个测试文件.

它托管的仓库是我们的实验室。记住,那里没有代码,所有代码都存在于Emacs内部。

现在,打开吧test.md档案。

重要此时,可能发生许多事情。如果你有markdown安装在你的系统中,文件已经打开了。不过,你可能会像我一样被提示写出这个:

这意味着Emacs还没找到markdown在我的系统里,在这里~/.emacs.d/tree-sitter/(这是我启动Emacs时的默认设置emacs -Q ...).Emacs 会提供安装,这意味着从已定义的仓库下载并编译markdown-ts-mode的源代码。

我们用 安装它y.Emacs 会克隆语法仓库,编译它,然后继续到第二个语法。是的,markdown使用两种语法:主语法和直排解析。我会允许Emacs安装第二个y.

成功了!

你应该看到的是什么:

如果没有,以下是你应注意的检查:

  1. Emacs 是用 tree-sitter 标志编译的吗?用途M-: (featurep 'treesit) RET并检查是否返回t.
  2. 你有用来“编译”语法的工具吗,比如make,gcc,还有其他人?
  3. 树木守护者需要在你的发行版中包含一个包,通常命名为tree-sitter-cli这提供了tree-sitter二进制,你可以用tree-sitter --version.

这是大家共同头疼的问题tree-sitter模式。很多人喜欢不是他们自己编译语法,而是使用他们信任的地方的编译文件,比如自己的发行版仓库,或者包含数百个预编译语法的包。

我不会深入探讨;获取语法有很多方法,本指南我会坚持“自己构建”。

你看,我有点骗你了。我告诉过你应该看到那个,但实际上,“你看到我看到的”应该是这样的:

我们提供完整文件给你,并且有几个默认主题,方便你比较你的设置是否完整。

那么,发生了什么?

这也是部分原因markdown-ts-mode是非常特别.

该模式不仅适用于markdown但对所有其他-ts-mode可获得!请记住;我们稍后会谈到代码块。现在,我们需要了解一些事情。

在你的test.md文件,我们有一个特殊的头部。非常常见的toml或yaml作为 的头部markdown文件。

这只小家伙:

---
title: The Official 'markdown-ts-mode.el' Feature Test File
author: Rahul Martim Juliato
date: 2026-03-18
version: 0.1.0
parsers needed: markdown, markdown-inline, yaml, toml, html, c, javascript, python, ruby, rust
---

需要别的东西Fontify(也就是用Emacs的颜色涂色)。你能找出缺失的是什么吗?如果你的答案是“我们需要YAML的语法!”,那就点赞!

每当某物字体化不正确时-ts-modeS,你可能漏掉了语法。作为markdown-ts-mode是为工作而设计的所有可用的 TS 模式,这次也不例外。

我们来安装我们的yaml与我们信赖的语法M-x treesit-install-language-grammar RET yaml.

你现在可能会看到我看到的:

我们就这样吧y.嗯,这次看起来出了点问题yaml-ts-mode尝试用treesit-install,因为没有建议。我们可以手动提供。但先确认一下。看看yaml-ts-mode.el,我们可以检查它在源代码中期望的语法:

;; from yaml-ts-mode.el
(add-to-list
 'treesit-language-source-alist
 '(yaml "https://github.com/tree-sitter-grammars/tree-sitter-yaml"
		:commit "b733d3f5f5005890f324333dd57e1f0badec5c87")
 t)

太棒了!我们只需评估那个模块,然后尝试重新安装语法。或者手动提供源代码https://github.com/tree-sitter-grammars/tree-sitter-yaml对我们已经开始的互动会议,这次我做了:

然后我们继续使用默认函数RET RET RET...直到图书馆安装完成。

之后,重新装弹markdown-ts-mode,或使用C-x x g或者重新打开你正在访问的档案。

我们访问源代码的方式非常罕见,而且大多数-ts-modeS会自动建议他们将从哪个仓库编译。很高兴能这样,我可以告诉你该怎么做。

现在怎么办?我们也得做同样的事M-x treesit-install-language-grammar对于每个字体化我们遇到的。如果你愿意,我们可以用来做测试文件C-x x f强制字体化并提示该文件中每一个缺失的语法。

到现在,你应该能看到整份文件字体化如同给你.和之前的图片一样:

关于语法的说明

A-ts-mode它取决于树上看护者的语法.这意味着所有-ts-mode需要不断跟进改进grammar,任何想要使用的编辑器或程序都共享tree-sitter去解析语言。

这也意味着我们在某个时刻,依赖在某些约束和特征上。几乎所有-ts-modeEmacs的代码充满了关于局限性的注释,以及为什么以及如何以这种方式对待某些晦涩事物。

Emacs 模式的作者和维护者总是试图建议语法和 SHA 提交ts-mode准备使用,无论是在注释中还是模式内的代码中,这与你看到的yaml建议。

维护的一部分ts-modeS正在跟进更新的语法版本变更。我们尽力保持最新版本,但我们测试过且应该能正常工作的,是模式源文件里的那个。

这就是为什么我认为自己用Emacs交互式编译是保证良好体验的最佳方式。

具体来说,是markdown-ts-mode,我们使用的是https://github.com/tree-sitter-grammars/tree-sitter-markdown这是最完整、最维护且被广泛采用的版本,无论是代码编辑器还是程序。

这并不意味着它没有错误或限制。我们同样尽力绕过这些限制,甚至为语法和核心树置库贡献问题。

我终于能打开一个Markdown文件了!

恭喜!接下来呢?我需要多久做一次这些?只要一次,第一次用-ts-mode或者如果你已经通过其他方式安装了语法,就永远不会。

现在让我们看看markdown-ts-mode已经提供了。

快速浏览一下markdown-ts-mode功能

我们(顺便说一句,这个模式由我和Stéphane Marks共同编写)提供了easy-menu功能可快速发现功能。

你可以点击以下内容访问Markdown在mode-line或者,如果你有menu-bar-mode启用、菜单栏,甚至是菜单栏Ctrl + Right click(无论Emacs将你的操作系统输入映射到哪种设备)在缓冲区上,使用markdown-ts-mode.

这实际上是本指南的简而言之;总结如果你现在想停下来自己探索,可以去探索(前面有剧透)。

剪辑

学习这个模式最快的方法就是每种内容都打一点。下面是速通:你写什么,哪个键帮你做。

标记(强调)

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**节目粗体.编辑时阅读非常方便,就像默认设置一样org-mode.

另一个建议:M-q即使在列表和报价内也能正确填写。

标题

类型:#,##, ...至多为######.文字标题(===以及---下划线)也被识别。

提升和降级,无需重新输入哈希值:

  • M-晋升(markdown-ts-promote)
  • M-降级(markdown-ts-demote)

然后移动整段,包括身体和孩子们:

  • M-(markdown-ts-move-subtree-up)
  • M-(markdown-ts-move-subtree-down)

TAB在一个标题上,其可见性循环(轮廓折叠)。该模式为outline-minor-mode公民,所以折叠就是行得通。S-TAB航向将循环显示所有航向的可见性。

重要:到现在,你可以看到这个模式尽可能地试图与org-mode,因此习惯于 Emacs 的用户在适应markdown.如果这些绑定不适合你,所有东西都可以定制。

列表(列表和复选框)

类型- 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的:

- [ ] not done
- [x] done

原始模式:

隐藏标记时:

注意你切换后看到的子弹和方框C-c C-x RET仅显示。缓冲区依然存在-以及[x].参见markdown-ts-unordered-list-marker,markdown-ts-checked-checkbox以及markdown-ts-unchecked-checkbox.

方块

C-c C-,(markdown-ts-insert-structure然后一个密钥:

  • `围栏代码块,语言提示
  • ~Tilde Fenced Code Block
  • q引用
  • d分隔器(主题切换)
  • t表格

如果区域处于激活状态,它会包裹该区域,而不是插入空块。

隐藏标记时:

代码块

这就是派对技巧。一个带有某种语言标签的围栏块会被该语言的模式字体化:

```python
def hello():
	return "world"
```

缺少颜色通常意味着语法缺失,情况与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.

非树木坐姿模式也行,elisp包含。旋钮:markdown-ts-code-block-modes,markdown-ts-default-code-block-mode,markdown-ts-fontify-code-blocks-natively.

一个生的例子:

隐藏标记时:

表格

插入一个C-c C-, t或M-x markdown-ts-table-insert-table,要求你指定要插入的行数和列数。

| Column 1 | Column 2 |
|----------|:---------|
| a        |        1 |

在你所在的桌子里markdown-ts-in-table-mode(打火机) [table]) 键位变化:

  • TAB/S-TAB下一格/上一个单元格(同时负责表格格式化)
  • RET/S-RET下一行/上一行
  • M-RET请在下方插入行
  • M-/M-移动排
  • M-/M-移动列
  • M-S-插入上方行,M-S-删除行
  • M-S-左侧插入列,M-S-删除列
  • C-c C-c把整张桌子对齐
  • C-c C-t a设置列对齐(左、中、右)
  • C-c C-t t换位表

此外,菜单中还包括:克隆行和列,导入区域的CSV/TSV,以及表格的CSV/TSV导出。

注意:目前处理表格有一些限制,主要是语法解析方式,所以你打字时可能会碰到未字体化的内容。不过根据GFM规范,所有有效的表格都应该没问题。

链接与图片

链接是常见的[text](url)以及[text][ref].片段链接如[intro](#intro)可以点击并跳转到缓冲区的标题,默认使用 GitHub 风格的 slug。

图像是内联渲染的。C-c C-x C-v切换它们(markdown-ts-toggle-inline-images).参见markdown-ts-image-max-width以及markdown-ts-display-remote-inline-images比如大小以及是否会获取远程 URL。

折扣:

之后C-c C-x C-v:

之后C-c C-x RET:

移动

  • TAB点处的循环折叠
  • C-c C-n/C-c C-p下一个 / 上一个标题
  • C-c C-u上到父标题
  • C-c C-f/C-c C-b下一个/上一个标题,同一层级
  • M-x imenu通过完成跳转到任意标题或命名代码块
  • C-c C-v n/C-c C-v p下一个 / 上一个代码块

markdown-ts-default-folding决定文件的开启方式:全部显示,还是折叠。

markdown-ts-视图模式

M-x markdown-ts-view-mode仅读模式,单键导航:n,p,u,f,b,TAB.适合不用担心打字就能阅读README。

附加内容

下面的一切都是markdown-ts-mode-x.el这也是我们重新加载它的原因。

目录

目录由HTML注释界定,因此在任何地方渲染时都能保存下来:

<!-- markdown-ts-toc: -->
<!-- markdown-ts-toc-end: -->
  • M-x markdown-ts-toc-insert-template插入这些标记,无论是基本还是完整(完整标记列出每个参数及其默认值)
  • M-x markdown-ts-toc-generate每次通话都填写并补充
  • M-x markdown-ts-toc-clear空的,markdown-ts-toc-clear-and-remove还能去除标记
  • M-x markdown-ts-toc-update-before-save-mode存档时会重生

参数在开篇评论中列出:min-depth,max-depth,candidates,from,style,indent,no-link,relative-depth,ignore.一个缓冲区可以容纳多个具有不同参数的表。

候选不仅是标题,列表项、文字头和命名代码块也可以为表提供信息。

Raw:

隐藏标记时:

出口

M-x markdown-ts-convert转换缓冲区,markdown-ts-convert-file一个文件。除非你设置markdown-ts-default-converter.开箱即用支持:

  • PDF 来源pandoc
  • HTML 通过pandoc,cmark,cmark-gfm,markdown,markdown.pl

使用前缀参数时,结果默认显示为eww.参见markdown-ts-convert-display-function而是在浏览器中打开。这就是你所谓的“实时”预览。

转换还不是(目前)自动的,未来可能会。

示例使用eww为本次演示手动制作的分割:

手头的规格

M-x markdown-ts-browse-commonmark-spec以及M-x markdown-ts-browse-gfm-spec打开规格,以备需要解决争论时使用。

实验eglot以及eldoc

这仍然是实验中的实验,所以别怪eglot如果出现问题,作者。发送错误报告到markdown-ts-mode反而。

如果你设置这个:

(setopt eglot-documentation-renderer #'markdown-ts-view-mode)

Eglot 会尝试用以下方式渲染文档(通常是 LSP 服务器提供的 Markdown 格式)markdown-ts-mode.

同样,我们还在削减一些粗糙的部分,结果可能会有所不同。不过请务必帮我们测试一下。

玩玩各种选项

M-x customize-group RET markdown-ts RET然后仔细看看。一些值得先了解的习俗:

  • markdown-ts显示用途:标记隐藏、省略号、项目符号、复选框、主题分隔和硬换行字符、内联图片、打开时折叠
  • 代码块:markdown-ts-code-block-modes,markdown-ts-default-code-block-mode,markdown-ts-enable-code-block-context-mode
  • 表格:markdown-ts-enable-table-mode,markdown-ts-table-auto-align,markdown-ts-table-default-column-width
  • markdown-ts-convert用于出口
  • markdown-ts-toc目录

面孔也可以自定义,每个Markdown元素一个。

你能帮忙的方式

你能帮忙的最好方式就是直接使用它。试试用你的Markdown文件,玩玩不同的功能,看看哪些需要改进,哪些会出问题。

如果你发现某些问题不正常,请报告为Emacs本身的bug。M-x report-emacs-bug RET.尽可能包含一个小示例,以复现问题。这对于涉及字体化、树置语法、表格、代码块或其他模式的交互。

我们还在完善这些粗糙的部分,因此非常欢迎反馈、反馈和实际测试。

我发现了一个bug,是因为markdown-ts-mode有bug吗?

使用时你可能会遇到一些惊喜markdown-ts-mode可能是模式,有些是语法问题,有些可能来自 Tree-sitter 如何集成到 Emacs,或者是整个 tree-sitter 生态系统的基础。

提前了解这些有助于理解调试的挑战。

语法是共享的外部资产

Emacs没有写语法。正是tree-sitter-markdown被其他编辑器和工具消耗,因此任何变更都是所有用户协商的。这对生态系统来说是好事,也意味着我们希望看到的修复可能需要一段时间才能实现,或者永远不会达到理想状态。

当这种情况发生时,我们会尽力在模式内绕过,并将问题报告上游。

所以,如果你发现看起来像模式漏洞,答案是“语法就是这样解析的”,那你就知道答案从哪里来了。无论如何,请务必报告,我们宁愿听到两次反馈,也不愿完全听不到。

构建语法也有其独特的特点。并非所有语法都用make以及仅一个C编译器:其中几个是从JavaScript定义生成的,因此它们的构建路径期望tree-sitterCLI,有时还要Node.js安装,才能提供。

这也是预编译语法包和发行版包如此受欢迎的一个重要原因。如前所述,我仍然更喜欢用Emacs交互式编译,但现在你知道为什么你的发行版可能比预期更受欢迎了。

间接缓冲

这点值得明确警告,因为它让人感到惊讶:树木保护者和间接缓冲者并不合得来。

  1. 解析器不与间接缓冲区共享。它们属于基础缓冲区,间接缓冲区从零开始。你要么手动复制它们,要么通过在间接缓冲区启用主模式重新实例化它们。
  2. 间接缓冲区中完全不支持字体锁定。这是 Emacs 本身的一个限制。

实际结果是(至少在本文撰写时)如果你使用一个将某个区域克隆到间接缓冲区的包,那里不会有字体化。这并非针对特定情况markdown-ts-mode,适用于所有-ts-mode这不是我们能从模式端解决的问题。

延伸阅读

如果这份指南让你感兴趣,网上有很多关于写作和使用树木看护模式的好材料。Stéphane Marks,我在这个模式的搭档,整理了下面的清单,实在太好了,我们自己藏着不说。

有些内容现在可能有点陈旧,树木看护者进展很快,但这些文章的理由是站得住脚的:

当然,还有那些将这些内容融入Emacs的作者——袁福和尤里·林科夫的笔记,这是我们目前最接近正史参考的部分:

这会不会超出experimental下次Emacs发布时要标记吗?

在这篇文章开头我写道:

这意味着什么?你应该用它吗?准备好了吗?这只是一个模式的草图吗?

现在你可能有更好的答案了。

experimental并不意味着markdown-ts-mode这只是草图,或者它缺少你对Markdown模式期望的基本功能。这意味着该模式仍在演进,我们还没准备好保证它的API、行为或部分功能不会改变。

那么,你应该使用它吗?是的!如果你对实验性标签感到满意,请试试。使用者越多,配合不同的Markdown文件、配置和工作流程,我们就越容易发现问题并修复。

它会被淘汰吗experimental在下一个Emacs版本中?也许吧,我们确实在朝这个方向努力!拭目以待。还有许多细节需要完善,限制需要克服,还有反馈需要处理,才能做出决定。

现在,把这当作你的邀请,去玩玩它。如果你发现什么奇怪的东西,不要只是绕开,告诉我们。这就是我们准备它的方式。

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论