Markdown 语言服务器简介
2022 年 8 月 16 日,作者:Matt Bierner,@MattBierner
Markdown 支持是我在 2016 年加入 Visual Studio Code 时掌握的第一个功能。哇,真的已经过去六年了吗?不过,这是一场很棒的比赛。我使用 Markdown 的时间足够长了,经常发现自己满怀希望地在 Twitter、Outlook 以及光标所在的几乎每个文本框中输入反引号和星号。多年来,增加 VS Code 的内置 Markdown 支持是非常值得的。了解我们的 Markdown 扩展如何直接和间接塑造 webview 和笔记本等核心功能。
这就是为什么我很高兴分享一个我在过去半年里一直默默致力于的项目,我认为这个项目代表了 VS Code 的 Markdown 工具的下一步:Markdown 语言服务器。借助此语言服务器,我们可以将 VS Code 的大部分内置 Markdown 语言工具(从文档大纲、智能折叠到路径补全)提供给其他编辑器和工具。我们的目标是通过与编程语言相关的智能类型来推动 Markdown 工具的发展。
Markdown 语言服务器的工作分为两个新的(名称类似!)开源库:
-
Markdown 语言服务- 一个 TypeScript 库,提供使用 Markdown 的工具。
-
Markdown 语言服务器-使用语言服务构建的 Markdown语言服务器。
虽然这些库仍处于早期阶段,但 VS Code 1.70+ 已在使用它们(希望您从未注意到:-))。我们甚至看到了这种切换的一些好处,例如将 Markdown 工具移至单独的进程,这样它就不会阻止其他扩展。
但在我言过其实之前,也许您想知道:为什么需要 Markdown 语言服务器?说实话,我自己花了六年时间才意识到这一点。这也记录了我从将 Markdown 简单地视为带有一些星号、括号和井号以使事情变得生动起来的纯文本,到将 Markdown 理解为一种标记语言,并且可以从我们提供的许多相同工具中受益的演变适用于 TypeScript 或 Python 等编程语言。
使用 Markdown 工具
在我发现 VS Code 之前,我主要使用简单的文本编辑器进行编码。这意味着我必须记住符号名称,并在每次想要使用它们时将其键入。如果我想重命名一个变量,我会执行文本查找/替换,并希望我的单元测试能够捕获名称输入错误或损坏的不可避免的情况。这是一种缓慢且不可靠的工作方式,但我很满意,因为我不知道事情会变得更好。当我最终掌握了更智能的工具后,我才真正意识到我的工作流程是多么原始。
我最近对 Markdown 也有同样的认识。多年来,我一直习惯使用 VS Code 相对简单的 Markdown 编辑器。我对语法突出显示和内置的 Markdown 预览感到满意。文档大纲和可点击的编辑器链接只是额外的好处。我已经习惯了手写链接。我开始接受这样的事实:如果我更改了标题名称,我将需要进行文本搜索来更新该标题的所有链接。因为我认为 Markdown 只不过是花哨的纯文本,所以我什至无法想象还有更好的方法。
但有一天,在感觉第一百次输错图像路径后,我终于意识到:这不好玩!为什么我要浪费生命手动输入并验证这些链接?这就是工具的用途!我知道我不想要任何工具,我想要一个能够帮助我以文本形式阅读和编写 Markdown 的工具,而不是将 Markdown 源代码隐藏在一些所见即所得式的 UI 魔法后面。这非常符合 VS Code 的精神以及我们对编程语言支持的看法。为什么我们为传统编程语言提供的许多相同智能不能也适用于 Markdown?第二天我就开始了链接完成的工作。
链接完成是帮助您编写指向当前文件中的标题或工作区中其他文件的链接的建议。我什至添加了对完成其他 Markdown 文件中标题链接的支持。整洁的!这是一个小小的补充,但对我的工作效率产生了巨大的影响。很快我就无法想象没有它我该如何生活。
我对 Markdown 完成的成功感到头晕,想象着接下来我可以将哪些其他语言智慧带入 Markdown。我想象自己可以自信地在标题上按 F2 来安全地重命名它们。我梦想着红色的波浪线在黑暗的文本海洋中发光,以帮助识别无效链接。一切看起来都是那么明显!为什么我几年前就没有想到这一点?我开始将 Markdown 理解为结构化文本而不仅仅是纯文本,并且更好的 Markdown 工具的可能性似乎是无穷无尽的。
Markdown 语言特性
我不会让您厌烦每个新功能背后的故事,也不会深入探讨它们是如何实现的所有血淋淋的细节。可以说,我采取了一种渐进的方法,这使得我可以在有限的时间内投入 VS Code 的 Markdown 支持来完成所有的工作。例如,我没有直接跳转到构建重命名支持,而是首先启动并运行了一个可靠的“查找所有引用”版本(因为如果您想重命名一个符号,您首先需要知道引用它的所有位置)。增量工作并在彼此之上构建每个功能也帮助我在实现新功能时测试旧功能。例如,对链接实施重命名帮助我通过链接检测发现了大量错误。(这种方法的唯一缺点是意识到您已经在一些非常毛茸茸的正则表达式之上构建了“哦,如此优雅”的塔)。
当春末推出对报告无效文件/图像链接的实验性支持时,我退后一步审视我的工作。Markdown 语言功能集现在包括:
- 文件大纲
- 工作区符号
- 文档链接
- 智能折叠
- 智能选择
- 竣工数量
- 改名
- 查找所有参考文献
- 转到定义
- 诊断损坏的链接
- 更新文件移动/重命名的链接
我知道这些新工具将使 Markdown 工作变得更快、更安全。但当我回顾编程语言的常见功能列表时,一个想法一直困扰着我。几个月前,我还认为它很荒谬,但现在,当我再次思考时,我意识到可能终于到了使用 Markdown 语言服务器的时候了。
正在为您服务吗?
到 2022 年春末,VS Code 的所有 Markdown 工具仍在正常扩展 API上运行。虽然我想探索将所有这些工具转移到适当的语言服务器,但进行更改将产生真正的工程成本。我需要确保这是值得的。
我就这个问题来来回回了一个多月了。尽管现有代码状况良好,但仍有很多未知因素。如果我完成了一部分却发现它行不通怎么办?我以前从未认真研究过语言服务器。
当我争论这一切时,我通过重构 Markdown 扩展源代码让自己忙碌起来,就好像它将被移动到语言服务器一样。我尝试隔离对 VS Code 扩展 API 的依赖关系,将更多逻辑切换为使用服务注入,并确保测试不依赖于文件系统。这样,即使我从未尝试过语言服务器,至少我正在清理代码库。
一些考虑因素最终让我相信 Markdown 语言服务器是正确的下一步。首先是一个相当平常的问题:我发现有效地实现 Markdown 文件的链接诊断非常具有挑战性。在大型 Markdown 工作区(例如vscode-docs )上,我不断意外地阻塞扩展主机几百毫秒。不好。另一方面,语言服务器作为其自己的进程运行。不仅如此,语言服务器现在还有一个新的诊断拉模型,我很高兴尝试一下。
然后还有更崇高的理由。例如,Markdown 语言服务器对其他编辑器和工具很有用。这包括 VS Code 团队提供的另一个编辑器:Monaco!更不用说像 Markdown CLI 工具这样的可能性了。如果我没有时间自己构建这样的工具,也许其他人可以以语言服务器作为起点。我在 VS Code 的 Markdown 工具上投入了大量的工作,如果所有这些工作也能让其他人受益,那就太好了。
通过提供新的语言服务器,我也许还能够围绕改进 Markdown 工具启动共同努力。VS Code 是开源软件的多产生产者和用户,我已经看到了这些类型的项目提供的明显好处。开源 Markdown 语言服务器可以帮助其他编辑器,但反过来也会邀请贡献者,最终帮助 VS Code!语言服务器可以将开发人员聚集在一起,共同开发一个让每个人受益的更大项目,而不是让每个编辑器/工具重复工作来实现自己的 Markdown 支持。
如果没有如何实际构建语言服务器的计划,所有这些宏伟的想法都是无关紧要的。即使在我进行了所有重构之后,将代码移动到语言服务器仍然是一项艰巨的工作!这似乎令人难以承受,直到我意识到我不必一次性完成所有事情。我可以逐步构建服务器,一次将一项功能从 VS Code Markdown 扩展迁移到新的 Markdown 语言服务器。如果我做对了,我可以检查每个小的增量迁移,以便用户可以在构建新语言服务器时对其进行测试。理想情况下,用户永远不会注意到功能何时从扩展移至语言服务器。
也许这是显而易见的,但我已经成为这种用于大型代码更改的增量方法的忠实信徒。没有数十万个 LOC PR 或大量功能分支会持续数月(或数年!)。相反,对main
. 如果一切按计划进行,那么结束所有这些工作的提交应该是反气候的。这是我们在整个 VS Code 代码库中逐步使用严格的空检查所采取的方法,这就是我认为可以将 VS Code 的所有 Markdown 工具快速移动到新语言服务器的方式,并且尽可能减少戏剧性。
剧透警告:它成功了!我一次移动了一个语言特性。我边走边学,并在明确需要时进行重构。诊断是最后一个要移动的功能,因为我不仅将它们移动到语言服务器,而且还重写了它们以使用语言服务器的新拉式诊断模型。整个工作的最后一次提交主要从 Markdown 扩展中删除了现在未使用的代码。因此,今天,如果您使用 VS Code 1.70+,几乎所有 Markdown 语言功能都使用新的语言服务器。
一起构建更好的 Markdown 工具
在许多方面,过去六个月中 VS Code 的 Markdown 工具取得的进步比我在该领域工作的过去六年还要多。今天,我们发布了许多新工具,其中一些工具以前无法用于 Markdown。其中许多功能有利于 Markdown 的大多数临时读者和作者,而其他功能则只有高级用户才会欣赏。然而,对于所有这些进展,我知道我们才刚刚开始探索 Markdown 工具的可能性。
Markdown 语言服务器真正让我兴奋的是,现在该项目不仅仅是 VS Code。通过使我们的 Markdown 工具易于使用,我希望我们能够帮助推动 Markdown 工具为每个人所用。这些开源项目邀请大家共同构建 Markdown 工具的未来。如果您有兴趣做出贡献,请查看新项目并看看您可以使用它们创建什么。您可以提交错误报告和功能请求,甚至可能是 PR!有大量的智能 Markdown 语言功能是我做梦也想不到的。让我们一起构建它们!
如果您有兴趣查看源代码或做出贡献,可以在 GitHub 和 npm 上找到 Markdown 语言服务和服务器:
-
Markdown 语言服务- 一个 TypeScript 库,提供使用 Markdown 的工具。
-
Markdown 语言服务器-使用语言服务构建的 Markdown语言服务器。
快乐编码!
马特·比尔纳,@MattBierner