[R Markdown] 为什么我放弃了用LaTex写作业文档

发布于 2020-03-25  263 次阅读


在长久以来用LaTex写作业的日子里, 我逐渐意识到了一个问题. 在我写作业文档的过程中, 绝大部分时候是在写数学公式和插入图片, 而不是玩弄LaTex的排版技巧. 那么, 为什么我需要为了最长不过十余页的作业文档不停地敲击复杂的, 不直观的, 无法直接预览的LaTex文件呢? 杀鸡焉用牛刀? 为什么不用一些简单但是更高效的工具呢? 抱着这种怀疑, 我搜索到了R Markdown.

为什么我需要 R Markdown?

LaTex的确很强, 功能很完善, 但是"功能强大"也同时意味着它复杂. 即使有很优秀的自动补全(比如VSC里面的LaTex Workshop), 我仍然需要输入大量额外的字符. 并且LaTex插入图片尤其烦人. 再者, LaTex的编译系统不是很友好, 报错完全报不准. 在长期的使用过程中我感觉到使用LaTex编写小文档是一件实际上很浪费时间的事情.

其实之前我就考虑过使用Markdown来写作业, 因为它语法简介直观, 而且大部分Markdown编辑器都可以实时预览. 但是我在Markdown上的尝试受到了两个强大的阻力:

  • Markdown(尤其是带了数学公式的Markdown)转PDF文件不方便
  • 页眉页脚无法自定义

对于这两个问题, 我曾经试图使用过Pandoc, 我之前的文章也提到过, Pandoc参数设置复杂, 简单直接的命令行调用带来的文档转换效果并不理想. 但是, 总归是有人早就想到了这些问题, 于是有了R Markdown.

R Markdown也是利用Pandoc来进行文档转换的, 它的语法以Markdown语法为基础, 支持一些扩展语法, 同时支持直接内嵌LaTex(可以让hardcore LaTex Player 愉♂悦地玩弄他们那些可有可无的排版技巧). 经过我这几天的实际尝试, 效果非常好, 而且在 Visual Studio Code 中可以直接利用Markdown的实时预览功能.

安装 R Markdown 环境

Linux用户不用教.

注意! 原本的(推荐用 scoop 安装 MikTex 的)方法经过我自己一段时间的使用之后, 出现了在 pandoc, miktex 升级之后造成的编译异常. 在经过多方尝试之后, 转向 tinytex, 这是一个精简版的 TexLive, 很小巧 (150Mb on macOS/Linux and 220Mb on Windows) .

对于Windows平台, 如果你使用scoop, 你可以直接在 Power Shell 中运行如下的命令

scoop install r pandoc

这会分别安装 R, Pandoc. (什么? 你不用scoop? 那你可以手动去网站上下载安装)

安装好之后需要打开 R 的交互式 Terminal(如果通过scoop安装, 在Power Shell中需要使用r.ps1来启动, 因为r在PS里面是显示上一条命令), 安装rmarkdown 与 tinytex.

install.packages('rmarkdown')
install.packages('tinytex')
tinytex::install_tinytex()

虽然 R Markdown 的官网上竭尽一切向你推荐 R Studio, 但是我实际使用的体验就是, 那玩意很不好用. 所以我还是选择了我最爱的 Visual Studio Code.

在VSC中安装如下的两个插件:

其中第一个用于调用 R, Pandoc 和 LaTex 来生成PDF文档, 第二个用于Markdown的语法高亮和 Tab 补全.

使用效果展示

比如这样一个常见的文件.

---
title: "测试文件"
header-includes:
  - \usepackage{ctex}
output:
  pdf_document:
    latex_engine: xelatex
    number_sections: true
    keep_tex: true
---

# 这是一个中文标题

这是一段py代码

```Python
if __name__ == "__main__":
    print("Hello World!")
```

这是一段C代码

```C
#include 

int main(int argc, char **argv){
    if(argc == 1){
        printf("One!");
    }
    return 0;
}
```

## 这是一个子标题

这是Markdown数学$e^{i\pi}$环境

$$
\begin{aligned}
    test &= \Omega \Delta \Gamma\cdot \beta_{\phi_{0}} \\
         &= f(0) \\
         &= something
\end{aligned}
$$

# This is an English heading

接下来是一段内嵌LaTex

\begin{align*}  
    \alpha &= \delta_{\beta} + \Omega \\  
           &= RUA  
\end{align*}  

## 接下来是图片

![测试图片$\beta$](Snipaste_2020-03-25_23-05-45.png)

接下来是一些废话

- Bullet List
- RUA!
- RUA~
- RUE~~

1. Numbered List
2. RUA!
   1. RUE~
3. Another One!
上面的文件在VSC编辑时的实时预览效果

可以看到内嵌的LaTex无法实时预览, 但是 Markdown 数学环境可以. 另外就是图片不要指定网络图片(尽管Markdown支持, 但是LaTex不支持), caption 会在产生PDF文件时自动生成, 当然也可以指明不要caption.

编译该文档, 直接按 Ctrl+Shift+P 调出VSC命令, 输入r:knit rmd to pdf 找到对应的命令(输了前几个字母就能看见了), 然后等待执行就可以得到PDF文件.

一些小技巧

正常显示中文, 需要在最开始的注释里面写明\usepackage{ctex}

插入的图片名字不能太诡异, 例如我曾经使用过的3.29.dfa.png就会转换异常, 估计是点点太多了.

如果图片插入错位了, 而你希望所有图片都出现在它在文字中出现的位置, 可以想办法让所有的LaTex图片环境增加[h]参数. 该方法来自于StackOverflow上的某个答案. 新建一个.tex文件, 假设名为preamble-latex.tex, 它包含以下内容

\usepackage{float}
\let\origfigure\figure
\let\endorigfigure\endfigure
\renewenvironment{figure}[1][2] {
    \expandafter\origfigure\expandafter[H]
} {
    \endorigfigure
}

然后把.md文件开头的注释中output部分修改如下

output:
  pdf_document:
    latex_engine: xelatex
    number_sections: true
    includes:  
      in_header: preamble-latex.tex

至于添加自定义的页眉页脚什么的, R Markdown 都可以利用 LaTex 轻松地做到, 自己搜搜就OK了.


终有一日, 仰望星空