1137 字

用 minted 宏包实现语法高亮

LaTeX; LaTeX; 语法高亮; Highlight;

listings 的麻烦

在 LaTeX 中实现语法高亮的老牌方案是 listings,然而这种方案用起来非常麻烦:

  1. 默认的字体效果很糟糕,居然是 Serif 系列的;
  2. 定义一种新语言需要先耗费大量时间了解帮助手册,还可能需要了解很多奇怪的规则;
  3. 代码跨页时需要一些额外的工作
  4. 代码中的单引号,双引号问题
  5. 中文支持问题1
  6. 甚至对 LaTeX 的语法高亮支持也需要做许多额外工作

当然,不是说 listings 包的功能不够强大,从《给语法高亮内容中的部分内容进行高亮标识》这个方案可以看到,利用 escape character 除了可以解决中文的问题外,还可以实现更多自定义的效果,比如《在代码中添加公式》。如果是英文文档,定义一个类似于 \verb|.| 的命令,实现 inline code 式的命令也很容易2

因此,虽然 listings 包理论上可以满足我们的需求,但是要解决特定的问题往往需要耗费相当的精力和时间,对初学者并不算太友好。

minted 宏包需要的支持

LaTeX 中的 minted 宏包实际上是调用 Python 的 pygments 来完成语法高亮的,高亮效果好,支持的语法充分,可以实现代码内的公式3,通过 \mintinline 命令实现行内代码的同时4可以指定语言的名称5,需要的额外配置少,唯一目前要做就是在安装完 Python 后,通过下面的命令安装 pygments

pip install pygments

之后编译时用下面的命令:

xelatex -shell-escape demo.tex

lualatex -shell-escape demo.tex

对于使用 WinEdt 或者 Sublime Text 界面接口的用户,可能选项 -shell-escape 会比较麻烦一些,但由于自己是直接调用 bat 文件来处理编译问题,因此这个选项完全不是问题。

现在 knitr 转成 pdf 的语法高亮应该也是由 pygments 完成的,并且完全不需要用户干预(不确定在 knitrpygments 是否需要提前安装。)。

可能的麻烦

提醒:尝试在 CTeX 2.9.2 下面直接将最新版minted 相关文件复制到相应的目录,但结果出错,说找不到 fvextra 宏包,然而添加了该宏包之后仍然会有其它错误,估计是相关的依赖包没有更新的原因,因此推荐使用最新版的 TeXLive 或者将整个 CTeX 套装的宏包都进行更新来解决这个问题,但是在线更新 MikTeX 之后,再更新相关宏包时,同样会出现各种各样的奇怪问题,像 picins 这要的宏包甚至会认为是过时的而直接删除,导致其它很多麻烦,最终放弃更新 CTeX。

好像更新新的 ctex 宏包后,ctexsetup 命令也不再推荐使用。

简单例子

这个例子来自 https://zhuanlan.zhihu.com/p/27996164

\documentclass[a4paper]{article}
\usepackage{minted}
\usepackage{xcolor}
\definecolor{bg}{rgb}{0.95,0.95,0.95} 
\usepackage[margin=2.5cm]{geometry}
\begin{document}

\begin{minted}[bgcolor=bg]{rust}
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
    // Do stuff with `v1` and `v2`.
    // Hand back ownership, and the result of our function.
    (v1, v2, 42)
}

let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];

let (v1, v2, answer) = foo(v1, v2);
\end{minted}

\begin{minted}[bgcolor=bg]{go}
import "math"

type Shape interface {
    Area() float64
}

type Square struct { // Note: no "implements" declaration
    side float64
}

func (sq Square) Area() float64 { return sq.side * sq.side }

type Circle struct { // No "implements" declaration here either
    radius float64
}

func (c Circle) Area() float64 { return math.Pi * math.Pow(c.radius, 2) }
\end{minted}

\end{document}

下面是实际的高亮效果:

`minted` 语法高亮


  1. 中文支持后期已经基本解决,参考 CTeX #76123CTeX #77046
  2. 中文里面还有 bug,参见 GitHub #282 以及《语法高亮:在 lstinline 中给行内代码添加背景颜色 z》。
  3. 参见帮助文档。
  4. 可进一步参考 Stack Exchange #45756
  5. 参考 Stack Exchange #45756,这个功能需要 minted 2.0 以上版本,CTeX 2.9.2 套装默认的版本不行。