历史遗留问题

我喜欢用 org-mode 来记笔记和写文章,而不是用 markdown 的一个原因是 org-mode 的支持更友好,可以直接使用 $\LaTex$ 这种方式直接输入,也可以直接使用 \begin{cases}\end{cases} 这种方式来直接开始一段跨行的公式输入。除了输入方便, org-mode 更是支持在 emacs 中直接预览输入的数学公式,wysiwyg。但在配置之后我遇到了点小问题,在我使用 org-mode 做一些经济学笔记的时候,我遇到了这样一个公式:

得到的结果是下面这样的:

这是什么情况? 难道不支持中文?我又试着使用 org-export 将整个文档输出成 PDF 看看情况,好家伙,全是方框,不支持中文实锤了。经过一番查证,最后确定问题出现在 org-mode 默认使用的是 pdflatex 来生成最终文档,不支持中文的。解决方案是将默认的使用的 compiler 切换到了 xelatex ,另外添加了一些导出PDF是需要添加的 Headers,终于 PDF 可以正常导出了。但问题没有结束,PDF 中的一般中文没有问题,但是在数学公式中的中文依然像上面一样无法显示。嗯,像不像在修 bug 的你,明明在修一个 bug,却先把另外一个 bug 修好了,原来那个 bug 还在对你微笑。😂

我又继续查了一些资料,但是 org-mode 中用 ,并且还有中文的人实在有点儿少,要不就是有点儿老。没有找到解决方案,我也发现将文件转换为 html,使用 LaTeX.js 来渲染并没有问题,所以这个问题就暂时搁置了下来。

问题的解决

因为最近在使用 brew upgrade 来升级一下系统中的各种工具的时候报了一个错,是在 brew cleanup 的过程中有些文件没有权限删除,我仔细一看,这文件不是 ghostscript 的么,是在捣腾 环境的时候通过安装 MacTex 的时候一起安装的,pkg 的安装程序默认用的用户是 root,homebrew 确实没有权限删除,于是我又想起了 org-mode 中还有 preview 无法显示中文公式的 bug,决定这一次把它们一起解决了。

删除原来的 MacTex

上次捣腾的时候,为了方便,我直接安装了一个完整的 MacTex,大概有 5G 左右,很多东西都用不上,而且现在和 homebrew 冲突了,所以我决定这次删掉 MacTex,然后通过 homebrew 安装一个精简的 BasicTex。MacTex 的删除不是那么容易,主要分成两个步骤:

  1. 删除 latex 相关程序和 app,可以参考 MacTex 网站的说明,在这里 Uninstalling MacTex

  2. 删除 ghostscript, 这个相对麻烦一点。因为要删除 ghostscript 的相关文件,首先你需要知道有哪些 ghostscript 的相关文件,于是需要重新下载一遍 MacTex 的 pkg 安装包,再从安装包中提取获取到具体安装了哪些文件。有人分享了一段 shell,但是我实际使用的时候发现已经不太一样了,这里是我修改的一个版本:

    uninstall_ghostscript () {
        bom_usr_local=$(pkgutil --bom $1 | grep -F Ghostscript)
        lsbom -s -f $bom_usr_local | grep -F -v ghostscript | sed 's_^\.__' | while read filename; do
    	if [[ -e $filename ]]; then
    	    command mv - "$filename" ~/.Trash
    	fi
        done
        command mv -v /usr/local/share/ghostscript ~/.Trash
    }
     
    uninstall_ghostscript $1

通过 homebrew 安装 BasicTex

在经历了上面的 MacTex 的删除过程,才能更深的体会到使用 homebrew 来管理软件的方便,直接使用 brew install baisctex ,翘着二郎腿等着结束就完成了。

解决 org-mode preview 无法显示中文的问题

在又经过了一番搜索和试错之后,我确定这个问题要分成两个部分解决。

第一个问题是 latex 本身的问题, xelatex 中在公式环境中插入中文默认都是无法显示的,需要使用 \mbox{} 来处理,所以我之前的笔记中的公式是不对的,需要在公式中出现中文的地方,都使用 \mbox{} 来包围才能正常显示,拿文章开头的例子来说明。

错误的输入方式为:

$需求的价格弹性系数 = \frac{需求的变动率}{价格的变动率}$

正确的输入方式为:

$\mbox{需求的价格弹性系数} = \frac{\mbox{需求的变动率}}{\mbox{价格的变动率}}$

这一部分问题解决之后,使用 org-export 导出的PDF中的中文可以正常显示了,但是在 org-mode 中调用 org-latex-preview 函数依然无法获得正常的结果。

接着来解决第二个问题,需要修改控制 org-latex-preview 的两个变量:

  1. org-preview-latex-process-alist 这个变量是一个列表,列表中每一项都定义了一种 org-latex-prewiew 的处理过程,默认的过程中使用的都是 latex 命令来生成 dvi 文件,在转化为 png 或者 svg 在 emacs 中显示。

  2. org-preview-latex-default-process 这个变量定义了 org-latex-preview默认使用的处理过程,需要在 org-preview-latex-process-alist 变量中定义。

org-latex-prewiew 函数的大概处理流程为,先查询到当前buffer当前光标下公式开始与结尾,再通过 org-preview-latex-default-process 变量获取到需要使用的处理流程,再通过 org-preview-latex-process-alist 查到对应处理过程需要使用到的命令,最后把公式的插入到一个固定模板,在按照定义好的处理流程将 LaTeX 的代码转化为png或者svg显示在buffer当中。

明白了这个流程,我们就可以通过下面的设置,新建一个处理流程来解决公式中中文无法显示的问题,具体的代码如下:

(add-to-list 'org-preview-latex-process-alist '(xdvsvgm :progams
							("xelatex" "dvisvgm")
							:discription "xdv > svg"
							:message "you need install the programs: xelatex and dvisvgm."
							:image-input-type "xdv"
							:image-output-type "svg"
							:image-size-adjust (1.7 . 1.5)
							:latex-compiler ("xelatex -interaction nonstopmode -no-pdf -output-directory %o %f")
							:image-converter ("dvisvgm %f -n -b min -c %S -o %O")))
(setq org-preview-latex-default-process 'xdvsvgm)

这里要注意的是 image-input-type 这个字段的值不为 dvi,而应该是 xdv,xelatex 处理之后的文件后缀为 xdv,再通过 dvisvgm 处理成 svg。

这样我们终于成功的让 org-mode 支持实时显示含有中文的公式了。

配置 orgmode 的 LaTeX 环境的其他问题

Tex 环境的选择

目前应该有三种选择:

  1. 直接安装 MacTex,非常大,功能很全,但是很多用不上,删除也不容易,还和 homebrew 冲突。

  2. 通过 homebrew 安装 basictex,比起 MacTex,这个不到 100M,所以很多 package 都没有,安装之后还需要安装所需要的 package。具体来说为了能够使用 org-export 导出 PDF 文件,我还安装了如下的 package。

    sudo tlmgr nth
    sudo tlmgr install capt-of
    sudo tlmgr install wrapfig
     
    sudo tlmgr install nth
    sudo tlmgr install ulem xcolor environ letltxmacro enumitem stringenc trimspaces soul algorithm2e genmisc
    sudo tlmgr install epstopdf subfigure appendix
     
    sudo tlmgr install ifmtarg
    sudo tlmgr install multirow ifoddpage relsize titlesec
    sudo tlmgr install xifthen
  3. 使用 MikTex,这个我并没有了解,不太清楚使用的效果。

配置 org-export 使用 xelatex 来做 pdf 的生成

(setq org-latex-compiler "xelatex")
(setq org-latex-pdf-process '("xelatex %f"))
(add-to-list 'org-latex-default-packages-alist '("" "ctex" t ("xelatex")))

实时的预览 LaTeX 公式

org-latex-preview 这个函数不是自动调用的,需要使用一个插件 org-fragtog 来让我们离开公式输入的region之后自动调用这个函数生成预览。这里我直接使用 use-package 来管理包的安装。

(use-package org-fragtog
  :after org
  :hook
  (org-mode . org-fragtog-mode))

相关的一些链接