$\LaTeX{}$之minted使用技巧

本文介绍了如何在\(\LaTeX{}\)中使用minted宏包实现代码高亮效果。


介绍

minted 使用 Pygments 库提供语法高亮功能。它还提供自定义高亮源代码输出的选项,包括用 Python 实现的功能,例如使用正则表达式选择代码片段。

由于 minted 使用了 Pygments 和其他 Python 软件,因此它能够提供比纯粹用 LATEX 实现的语法高亮包(例如 listings)更丰富的高亮功能。过去,这种对外部软件的依赖带来了一些缺点,例如需要单独安装 Pygments。从 minted 版本 3 开始,所有 Python 软件(包括 Pygments)在使用 TEX 包管理器安装 minted时都会与 LATEX 包捆绑在一起,无需单独安装任何依赖项。


安装

1
2
tlmgr install minted # TeX Live
mpm --admin --install=minted # MiKTeX

两种方法:第一种直接安装minted,自动包含python相关的库文件;第二种先安装minted,pip安装latexminted(自动包含Pygments),将python的环境变量path路径放在texlive上面。具体如下:

  1. 安装 minted 软件包后,它将包含 latexminted Python 可执行文件以及所有必需的 Python 库(包括 Pygments)。为了使这些库正常运行,必须安装 Python 3.8+ 并在运行 latexminted 可执行文件时将其添加到 PATH 中。

  2. 请注意,如果您计划使用 Pygments 插件包(这里应该是使用通过pip单独安装的python里面的Pygments包),则需要在 Python 安装中安装 latexminted Python 包及其依赖项(包括 Pygments)。TEX 包管理器在 TEX 安装中安装的 Python 库与插件包不兼容。在 Python 安装中安装 latexminted 后,请确保其 latexminted 可执行文件在 PATH 中具有优先权(python的环境变量path路径在texlive上面)(个人觉得直接使用minted自带的应该就可以了)。


基本用法

latexminted 和 -shell-escape

minted 软件包的运行方式是将代码传递给 latexminted Python 可执行文件,后者会执行语法高亮,并以 LATEX 格式返回高亮的代码。latexminted 的设计符合受限 shell 转义的安全要求。对于 TeX Live 2024+ 的最新安装,-shell-escape 选项不再是必需的。latexminted Python 可执行文件已添加到 TeX Live 的受信任可执行文件列表中。

对于 2024 之前的 TeX Live 版本以及 MiKTeX,latexminted 需要特殊权限才能运行。这可以通过在运行 LATEX 时使用 -shell-escape 选项(TeX Live)或 -enable-write18 选项(MiKTeX)来实现。请注意,使用 -shell-escape-enable-write18 选项允许 LATEX 在您的系统上运行潜在的任意命令。这些选项应仅在必要时使用,并且用于来自可信来源的文档。另一种方法是手动将 latexminted 指定为可信可执行文件。

最小示例

默认缓存目录名称现在为 _minted。目录中的所有文件现在共享同一个缓存,而不是每个文档都拥有单独的缓存。

可以编译之前,在当前工作目录新建_minted文件夹避免报错。

1
2
3
4
5
6
7
8
9
10
11
\documentclass{article}
\usepackage{minted}
\usepackage[svgnames]{xcolor}
\begin{document}
\begin{minted}[bgcolor=Beige, bgcolorpadding=0.5em]{c}
int main() {
printf("hello, world");
return 0;
}
\end{minted}
\end{document}

image-20250530152046131

格式化源代码

minted

minted环境突出显示代码段

image-20250530152445921

环境接受一些以 key=value 格式传入的可选参数。这些参数在 6.2 节中描述。

要使用 Pygments 不支持的语言来使用 minted,或者只是禁用突出显示,请将语言设置为文本:\begin{minted}{text}

对于单行源代码,您可以使用 \mint 作为 minted 的简写:

image-20250530153051999

这使用命令而不是环境来排版一行代码,因此可以节省一些输入,但其输出与 minted 环境的输出相同。 代码由一对相同的字符分隔,类似于 \verb 的工作方式。

完整的语法为 \mint[〈options〉]{〈language〉}〈delim〉〈code〉〈delim〉,其中 代码分隔符可以是几乎任何标点符号。〈code〉 也可以使用成对的花括号 {} 分隔,只要 〈code〉 本身不包含未成对的花括号即可。 请注意,\mint 命令不适用于行内使用。相反,当只有一行代码时,它是 minted 的快捷方式。

\mintinline 命令适用于行内使用。

\mintinline

image-20250530153840449

语法为 \mintinline[〈options〉]{〈language〉}〈delim〉〈code〉〈delim〉。分隔符可以是单个重复字符,就像 \verb 一样。它们也可以是一对 花括号 {}。当 \mintinline 用于可移动参数(例如 \section)时,需要使用花括号。

\verb 不同,\mintinline 通常可以在其他命令中使用。主要例外是代码包含百分号 % 或井号 #,或者不成对的花括号时。例如,\mintinline 通常可以在 \footnote\section 中使用!请注意,某些文档类或包(例如 memoir)会重新定义 \section,或者包含一些选项,这些选项会以与 \mintinline 不兼容的方式对其进行修改。如果您在 \section 内部或其他可移动参数中使用 \mintinline,则应进行实验以确保它与您的文档配置兼容。您也可以考虑使用 fvextra\Verb\EscVerb 作为替代方案。

\mintinline 的代码排版基于 fvextra\Verb。有关功能和限制的更多详细信息,请参阅 fvextra 关于 \Verb 的文档。

\inputminted

最后,还有一个 \inputminted 命令用于输入外部文件。其语法为\inputminted[〈options〉]{〈language〉}{〈filename〉}

使用不同的风格

除了使用默认的高亮样式,您还可以选择 Pygments 提供的其他样式。有两种等效的方法可以做到这一点:

1
2
\usemintedstyle{name}
\setminted{style=name}

\setminted 方法的优势在于它也能接受其他 minted 选项;而 \usemintedstyle 则仅限于修改样式。完整语法为 \usemintedstyle[〈language〉]{〈style〉}\setminted[〈language〉]{〈key=value〉}。 样式可以设置为整个文档(未指定语言),也可以仅为特定语言设置。请注意,样式也可以通过每个命令和环境的可选参数来设置。

pygments.org/styles 提供了样式高亮示例。您可以使用 pygments.org/demo 上的在线演示预览不同样式下的代码。 您也可以通过运行命令 pygmentize -L style 列出可用的样式。 您也可以创建自己的样式。请参阅 Pygments 网站上的说明。minted 仅支持与正则表达式 ^[0-9A-Za-z_-]+$ 匹配的样式名称。

支持语言

Pygments 支持数百种不同的编程语言、模板语言和其他标记语言。当前支持的语言列表。您也可以运行 pygmentize -L lexers 命令。


浮动 listings

minted 提供了一个 listing 环境,可用于包裹代码块。这会将代码放置在类似于图形或表格的浮动框中,默认位置为 tbp。 您还可以提供 \caption\label

image-20250530161050482

默认列表位置可以轻松修改。当包选项 newfloat=false(默认)时,float 包用于创建列表环境。可以通过重新定义 \fps@listing 来修改位置。例如,

1
2
3
\makeatletter
\renewcommand{\fps@listing}{htp}
\makeatother

newfloat=true 时,将使用功能更强大的 newfloat 包来创建列表环境。在这种情况下,可以使用 newfloat 命令来自定义列表:

\SetupFloatingEnvironment{listing}{placement=htp}

\listoflistings 宏将 \listoflistings 插入文档中所有(浮动)列表的列表:

image-20250530162056012

个性化 listing 环境

默认情况下,列表环境使用 float 包创建。在这种情况下,可以使用下文描述的 \listingscaption\listoflistingscaption 宏来自定义标题和列表。如果 minted 加载了 newfloat 选项,则列表环境将使用功能更强大的 newfloat 包创建。newfloatcaption 的一部分,caption 提供了许多自定义标题的选项。

使用 newfloat 创建列表环境时,应使用 newfloat\SetupFloatingEnvironment 命令进行自定义。例如,可以使用以下命令将标题中的字符串“Listing”更改为“Program code”

\SetupFloatingEnvironment{listing}{name=Program code}

并且“List of Listings”可以更改为“List of Program Code”,

\SetupFloatingEnvironment{listing}{listname=List of Program Code}

请参阅 newfloat 和 caption 文档以获取更多信息。

自定义列表 \listingscaption 标题中的字符串“Listing”。此功能仅在包选项 newfloat=false 时有效。例如:

\renewcommand{\listingscaption}{Program code}

自定义列表标题“List of Listings”。此功能仅在包选项 newfloat=false 时有效。例如:

\renewcommand{\listoflistingscaption}{List of Program Code}


选项(使用texdoc minted查看说明文档)

宏包选项

\usepackage[options]{minted}

  • chapter 要控制 LATEX 如何计算浮动列表的章节数,您可以在加载 minted 包时传递 chaptersection 选项。

  • cache=true 缓存源代码选项。默认情况下处于启用状态。cache 选项会在文档根目录中创建一个 _minted 目录(可以使用 cachedir 选项自定义)。高亮代码的文件存储在此目录中,以便以后无需再次高亮代码。不再使用的缓存文件会被自动删除。在大多数情况下,缓存可以显著加快文档的编译速度。

  • cachedir=_minted 缓存文件的存储目录。默认值:_minted,路径应使用正斜杠,即使在 Windows 下也是如此。

  • debug=false 提供额外的信息以辅助调试。这会保留用于生成高亮代码的临时文件,并将额外的信息写入日志。

  • frozencache=false 使用冻结(静态)缓存。当frozencache=true时,Python和Pygments不再需要,并且任何通过\inputminted访问的外部文件也不再需要。如果缓存文件丢失,则会报告错误,并且不会尝试生成丢失的缓存文件。 当使用带有 -output-directory 选项的frozencache时,应使用 cachedir 包选项指定缓存的完整相对路径(例如,cachedir=./<output_directory>/_minted)。

  • hightlightmode=fastfirst 确定何时高亮代码。这仅在 cache=true 时有效。默认值为 fastfirst。如果文档缓存存在,则立即高亮代码。如果文档缓存不存在,则排版占位符而非代码,并在文档末尾高亮所有代码。这需要在排版代码之前进行第二次编译,但由于所有代码会一次性高亮,因此开销较小,对于包含大量代码片段的文档,所需的总时间会显著减少。备选方案包括 fast(始终在文档末尾高亮,需要第二次编译)和 immediate(始终立即高亮,因此无需第二次编译)。当使用 fast 或 fastfirst 在文档末尾高亮显示代码时,任何错误和警告消息都将指向文档末尾的位置,而不是原始代码位置,因为高亮发生在文档末尾。

  • inputlexerlinenos=false 这将启用 lexerlinenos,并使其除了应用于 minted 环境和 \mint命令(以及基于它们的自定义环境/命令)之外,还应用于 \inputminted(以及基于它的自定义命令)(默认值:false)。 常规 lexerlinenos 选项将文档 .tex 文件中的所有代码视为每种语言都拥有一组行号,然后将每个输入的源文件视为拥有各自独立的行号。inputlexerlinenos 为每个词法分析器定义一个单独的编号,无论代码源自何处。

  • lexerlinenos=false 这允许所有 minted 环境和 \mint 命令(以及基于它们的自定义环境/命令)在firstnumber=last 时,针对给定词法分析器(语言)共享行号,以便每个后续命令/环境都具有从前一个延续的行号。这不适用于 \inputminted(以及基于它的自定义命令)。minted 在后台使用 fancyvrb 包进行代码排版。fancyvrb 提供了一个选项 firstnumber,允许指定环境的起始行号。为了方便起见,还有一个选项 firstnumber=last,允许从上次中断的地方继续行号。lexerlinenos 选项使 firstnumber 在所有 minted\mint 用法中分别适用于每个词法分析器(语言)。例如,请考虑下面的代码和输出。

  • newfolat=false 默认情况下,列表环境使用 float 包创建。newfloat 选项会改为使用 newfloat 创建列表环境。这可以更好地与 caption 包集成。

  • placeholder=false 无需排版代码,只需插入占位符即可。使用 PGF/TikZ 外部化功能时,此功能会自动启用。

设置命令和环境的选项

所有生成的突出显示命令和环境都接受相同的选项集。选项被指定为以逗号分隔的键值对列表。

通过设置\setminted[〈lexer〉]{key=value,...}为整个文档或整个词法分析器设置选项,lexer特定选项会覆盖文档范围内的选项。单个命令和环境选项会覆盖特定于lexer的选项。

您可能希望为\mintinline设置单独的选项,无论是整体文档或特定词汇(语言)。这可以通过\setmintedinline实现。

语法是 \setmintedinline[<lexer>]{key=value,...}。Lexer特定选项覆盖文档范围内的选项。单个命令选项会覆盖特定于lexer的选项。 所有用\setmintedinline指定的设置都会覆盖用\setminted设置的设置。也就是说,内联设置总是比常规设置具有更高的优先级。

命令和环境选项

以下是可用选项的完整列表。几个选项被简单地传递给Pygments、fancyvrb和fvextra进行处理。在这些情况下,这些软件包的文档中可能会提供更多详细信息。

  • autogobble=false 从代码中删除所有常见的前导空格。从本质上讲,这是一种自动决定应该删除哪些内容。适用于最初没有缩进,但在粘贴到LATEX文档后手动缩进的代码。

autogobblegobble一起使用时,效果是累积的。首先autogobble删除所有常见的缩进,然后应用gobble

  • baselinestretch

  • beameroverlays

  • bgcolor 命令和环境背后的背景颜色。

  • bgcolorpadding=none 设置bgcolor时填充。

  • bgcolorvphantom=\vphantom{\"Apgjy}

  • breakafter=none 当breaklines=true时,在指定字符后换行,而不仅仅是空格处。赋予breakafter的特殊字符应进行反斜杠转义。有关替代方案,请参阅breakbefore。当breakbefore和breakafter用于同一字符时,breakbeforeinrun和breakaftereinrun必须具有相同的设置。

  • breakafterinrun=false 使用换行符时,在相同字符的行内插入换行符。如果为false,则将相同字符的序列视为一个不能包含断点的单元。当breakbefore和breakafter用于同一字符时,breakbeforeinrun和breakafterenrun必须具有相同的设置。

  • breakaftersymbolpost

  • breakanywherebreaklines=true时,在任何地方换行,而不仅仅是在空格处。

    image-20250602104657610

  • 未完待续……


定义快捷方式

包含多个列表的大型文档可能使用相同的词法分析器和相同的选项集对于大多数列表。因此,minted定义了一组命令,允许您定义突出显示命令和环境的快捷方式。每个快捷方式都是特定的一个lexer。

  • \newminted \newminted为minted环境定义了一个新别名:

    image-20250602110057221

    如果你想动态提供额外的选项,或者覆盖现有的默认选项,你也可以这样做:

    image-20250602110255573

    环境的默认名称是<lexer>code。如果此名称与另一个环境,或者如果你想选择一个不同的名称,你可以使用可选的参数:newminted[environment name]{lexer}{options}

  • \newmint newmint[macro name]{lexer}{options}

    image-20250602111126529

  • \newmintinline 这创建了个性化版本的mintinline。语法和\newmint语法相同。

    image-20250602111633405

  • newmintedfile 这创建了个性化版本的inputminted。语法是newmintedfile[macro name]{lexer}{options},如果macro name未指定,则使用<lexer>file