前言

最近做集创赛要写论文,需要插入很多很多代码。

之前 试过Listings,但是Listings的高亮很糟糕,而且支持的语言也很少。之前还给他们提交了一个RISCV的语法高亮方案。

有没有比Listings更方便的代码高亮方案呢?有的兄弟有的,那就是minted

minted使用Pygments作为语法高亮方案,支持更多的高亮特性,且得益于Python后端的原因,可以轻松自定义语法高亮方案。

使用

依赖导入

1
\RequirePackage{minted}

嵌入代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
\begin{minted}{cpp}
// 继电器闭合
void CBIT_Control(int num, bool on)
{
if (num < 0)
{
cout << "Invalid CBIT index: " << num << endl;
return;
}
const string cbitName = "CBIT" + to_string(num);

if (on)
{
cbit.Signal(cbitName).SetOn();
}
else
{
cbit.Signal(cbitName).SetOff();
}

sys.DelayUs(DELAY_LONG);
cbit.Signal(cbitName).GetStatus(CBIT_RESULT);

for (size_t count = 0; count < CBIT_RESULT.size(); count++)
{
cout << "Signal Name : " << CBIT_RESULT[count].strSigName << endl;
cout << "Site id : " << CBIT_RESULT[count].ulSite << endl;
cout << "value : " << CBIT_RESULT[count].dbValue << endl;
}
}
\end{minted}

引用文件内代码

1
2
3
\inputminted[
fontsize=\xiaowu,
]{cpp}{code/Test.cpp}

自用代码格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
\setminted{
style=default,
bgcolor=white,
fontsize=\xiaowu,
fontfamily=tt,
linenos,
baselinestretch=1.36,
breaklines,
breakanywhere,
breaksymbolleft={},
breaksymbolright={},
breakanywheresymbolpre={},
breakanywheresymbolpost={},
tabsize=4,
frame=single,
framerule=0.6pt,
framesep=0.6em,
rulecolor=\color{black},
numbersep=0.6em,
xleftmargin=2em
}

\makeatletter
\newcommand{\atelog@patch@pygments@escape}[2]{%
\ifcsname\minted@styleprefix#1\endcsname
\expandafter\def\csname\minted@styleprefix#1\endcsname##1{#2}%
\fi
}
\newcommand{\atelog@patch@pygments@ligatures}{%
% 允许 > < 的连字符
\atelog@patch@pygments@escape{Zlt}{\char`\<}%
\atelog@patch@pygments@escape{Zgt}{\char`\>}%
\atelog@patch@pygments@escape{Zhy}{\char`\-}%
}
\apptocmd{\minted@patch@PygmentsStyledef}{\atelog@patch@pygments@ligatures}{}{}
\renewcommand*\verbatim@nolig@list{}
\makeatother

以及字体定义中要指定好等宽字体的斜体与粗体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
\setmonofont[
AutoFakeBold=false,
Ligatures = Common,
CharacterVariant={1,62},
StylisticSet={3,7},
Path = ./fonts/,
UprightFont = Maple.ttf,
ItalicFont = MapleItalic.ttf,
FontFace = {b}{n}{MapleBold.ttf},
FontFace = {bx}{n}{MapleBold.ttf}
]{Maple}
\setCJKmonofont[
AutoFakeBold=false,
Ligatures = Common,
CharacterVariant={1,62},
StylisticSet={3,7},
Path = ./fonts/,
UprightFont = Maple.ttf,
ItalicFont = MapleItalic.ttf,
FontFace = {b}{n}{MapleBold.ttf},
FontFace = {bx}{n}{MapleBold.ttf}
]{Maple}
\DeclareFontSeriesDefault[tt]{bf}{bx}

看看效果:

默认主题的代码高亮,看起来还不错?

本地自定义语法高亮

开启许可后,lexer可执行任意Python代码。请勿在未审查的LaTeX模板仓库内开启此功能。

开启任意lexer执行权限

在用户目录或 TEXMFHOME.latexminted_config 里启用:

1
2
3
4
5
{
"security": {
"enable_cwd_config": true
}
}

自定义Lexer高亮

写一个mylexer.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pygments.lexer import RegexLexer
from pygments.token import Text, Keyword, Name

class CustomLexer(RegexLexer):
name = "MyLang"
aliases = ["mylang"]

tokens = {
"root": [
(r"\b(if|else|end)\b", Keyword),
(r"[a-zA-Z_]\w*", Name),
(r"\s+", Text),
(r".", Text),
]
}

默认类名应为 CustomLexer。如果类名不是这个,比如 MyLexer,在 LaTeX 里要写成 mylexer.py:MyLexer

然后算下HASH:

1
python -c "import hashlib, pathlib; p=pathlib.Path('mylexer.py'); print(hashlib.sha256(p.read_bytes()).hexdigest())"

项目内配置

同样在项目内创建 .latexminted_config

1
2
3
4
5
{
"custom_lexers": {
"mylexer.py": "0d000721..." // 填写上面自定义lexer的HASH
}
}

LaTeX内使用

如果类名是默认的 CustomLexer

1
2
3
4
5
6
7
8
9
10
11
12
\documentclass{article}
\usepackage{minted}

\begin{document}

\begin{minted}{./mylexer.py}
if foo
bar
end
\end{minted}

\end{document}

如果类名是 MyLexer

1
\inputminted{./lexers/mylexer.py:MyLexer}{example.my}

新版 minted 允许把自定义 lexer 文件直接放在内置 lexer 名称的位置,例如 \inputminted{lexer.py}{<file>}\inputminted{./path/lexer.py:LexerClass}{<file>}

编译

新版的minted v3已经不强制要求-shell-escape参数了。正常编译即可。