chuxinyuan dead-sky 这两周我把工作推到了一边,大力投入 litedown 的开发,已经看到曙光。本来我只是想重写一下 knitr 和 rmarkdown 就算了,但写着写着发现在我目前的架构上,其实 bookdown 和 blogdown 已经是唾手可得,所以在不久的未来,你们应该就可以看见一整套极度精简版的 R Markdown 系统,即:
litedown = knitr + evaluate + rmarkdown
+ bookdown + blogdown + pagedown + xaringan + tufte
- Pandoc - Hugo
它仅有两个依赖包,就是 commonmark 和 xfun,不依赖外部系统软件。前提是我会去掉一些功能,比如重点支持 HTML 输出,次要支持 LaTeX,而所有其它格式都不支持。默认情况下一切都是极简风,比如网站会是类似 hugo-xmin 那种令人生无可恋的主题(要是用户有本事折腾算我输)。当然,扩展性肯定还是会留的。
过去十二年开发和维护 knitr 让我对其中的一些设计深感懊悔(当年还是太年轻,不会拒绝),这次重新设计,终于一吐胸中闷气,把很多拥堵的节点都打通了,还衍生出一些非常奇葩的功能。随便剧透几个例子,比如 litedown 可以准确识别 Markdown 元素,所以代码块或注释中的代码将不再会被解析到:
````markdown
下面的代码块不会被运行:
```{r}
1 + 1
```
行内代码 `r pi` 也不会。
````
<!--
注释随便你注,我要是碰了你的注释算我输。
```{r}
1 + 1
```
-->
knitr 对这两个问题的解决方案堪称恶心,它发明了两个新引擎,得写成这种鬼样子(简直该陈列到“不自然博物馆”里去):
````{verbatim, lang='markdown'}
代码。
````
````{comment}
注释掉的内容。
````
行内代码我设计了一种新语法 `{lang} code`
,这里的语言 lang
不再局限于 r
,可以是其它语言(尽管我还决定好如何支持其它语言),而且 {}
里可以像代码块一样写选项,比如 `{r, eval=FALSE} code`
。
再比如代码和文本的运行顺序可以通过一个选项任意指定,不一定非得是从头到尾按顺序执行,你可以先运行第二段代码,再运行第一段文本,再运行第五段代码,等等。这是为了解决一个长久以来的痛点,就是有时候文本中需要用到后面代码段中的变量(比如文首摘要中需要插入文末结论部分中计算的数值),knitr 的解决方案也很恶心,我都不知道我是如何能有勇气把它写在书中的,而 litedown 则完美允许非线性的运行顺序。不过我估计有人听说了这个逆天的功能会排队来刺杀我,而有人会排队来给我送花。
knitr 的缓存设计也让我感到如鲠在喉多年。今年在瑞士再保险看别人的文档编起来辣么慢,而我也不是很有底气让人用 cache = TRUE,于是此事终于给了我一道强刺激让我把那个糟糕的缓存系统重写了一遍,以后要是再推荐别人启用缓存就不需要找那个宁夏人梁静茹借勇气了。
还有 HTML 预览将会支持源文档和输出文档在左右栏同步滚动,这样写文档的时候可以左边写哪儿、右边就预览哪儿,不需要一会儿左边拖拖拖、一会儿又右边滚滚滚。类似 Typst 那样实时增量更新预览也是有可能的,即写哪儿就只编译哪一块而不必编整个文档,但到这里就碰到我的技术短板了,可能不是那么容易能做出来,可以留作后话。