不久以前我问如何扩展 minted 以使用颜色突出显示我选择的关键词。大家一致同意“在外部 pygment 程序中进行更改”——所以我就这么做了。
变化很小,我修改后的 pygment 程序的输出似乎没问题。如果我在系统范围内安装新的 pygment 模块,我的文档就会正确编译,并且语法突出显示的更改也符合预期。
问题是我不想在整个系统范围内安装我的替换 pygment 模块,这太具侵入性了,而且我希望能够分发我的文档以便在其他人的计算机上进行编译。我有一个简单的 bash 脚本,bin/pygmentize.sh
它将新版本的 pygmentize 作为一组本地脚本调用。这个 bash 脚本已经过测试,可以作为全局程序的替代品pygmentize
。此外,当以如下所示的方式通过 latex/minted 调用它时,它会生成正确的标记,但文档无法编译。
下面是我修改后的 pygmentize 生成的标记与原始标记的比较:
前:
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{c+cp}{\PYGZsh{}include} \PYG{c+cpf}{\PYGZlt{}stdio.h\PYGZgt{}}
\PYG{k+kt}{void} \PYG{n+nf}{main} \PYG{p}{()}
\PYG{p}{\PYGZob{}}
\PYG{n+nf}{printf} \PYG{p}{(}\PYG{l+s}{\PYGZdq{}Hello, world!\PYGZdq{}}\PYG{p}{);}
\PYG{p}{\PYGZcb{}}
\end{Verbatim}
后:
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{c+cp}{\PYGZsh{}include} \PYG{c+cpf}{\PYGZlt{}stdio.h\PYGZgt{}}
\PYG{k+kt}{void} \PYG{n+nf}{main} \PYG{p}{()}
\PYG{p}{\PYGZob{}}
\PYG{n}{printf} \PYG{p}{(}\PYG{l+s}{\PYGZdq{}Hello, world!\PYGZdq{}}\PYG{p}{);}
\PYG{p}{\PYGZcb{}}
\end{Verbatim}
在这两种情况下,此代码均取自 minted 缓存目录,它是通过 latex 的调用生成的pygmentize
,而不是我自己的手动调用。(我删除了 minted 缓存,切换到使用我更新的 pygment,然后再次运行 pdflatex。)
生成的标记之间的唯一区别是\PYG{n}{printf}
变成了\PYG{n+nf}{printf}
这样,我期望文档的其余部分也能以相同的方式编译。事实并非如此
(/tmp/test/minted-cache/D855E0EC6A86300E2FD8FEE675873CCC2C2645CE96B6E2A989A9815
F3192183A.pygtex
! Undefined control sequence.
<argument> \PYG {c+cp}{\PYGZsh
{}include} \PYG {c+cpf}{\PYGZlt {}stdio.h\PYG...
l.2 ...ude} \PYG{c+cpf}{\PYGZlt{}stdio.h\PYGZgt{}}
! ==> Fatal error occurred, no output PDF file produced!
此错误发生在编译上述标记时。如果我没有看错的话,这是命令\PYGZsh
无法识别。这个错误让我感到非常奇怪——minted 显然正在加载和运行,而之前的\PYG
命令曾是被识别为控制序列,并且错误表现在未改变的代码段中。
下面是我如何调用修改后的 pygmentize:在挖掘源代码时,我看到了这一点:
\ifcsname MintedPygmentize\endcsname\else
\newcommand{\MintedPygmentize}{pygmentize}
\fi
过了一会儿
\MintedPygmentize\space -l #2 -f latex -P commandprefix=PYG -F tokenmerge (...etc)
看来,通过定义或重新定义,\MintedPygmentize
我应该能够调用不同的程序。
我在导入 minted 之前尝试过这样做
\newcommand{\MintedPygmentize}{bash bin/pygmentize.sh}
我在导入 minted 后尝试这样做
\renewcommand{\MintedPygmentize}{bash bin/pygmentize.sh}
无论哪种方式都会产生错误。我已确认我的bin/pygmentize.sh
被调用,并且它正在接收其输入并产生其输出。
我得出的结论是,重新定义\MintedPygmentize
已经引起了一些黑魔法的副作用。
那么,为了获得可移植编译的文档,我该如何告诉 minted 包使用我的外部脚本来生成标记,而不会导致出现这样的奇怪错误?
答案1
\renewcommand{\MintedPygmentize}{bash bin/pygmentize.sh}
它对您不起作用的原因在于pygmentize
检查是如何在 minted 中实现的。
这行在非 Windows 系统(例如 Linux、macOS)上执行检查的内容:
\immediate\write18{which #1 && touch \jobname.aex}
\IfFileExists{\jobname.aex}
{\AppExiststrue
\DeleteFile{\jobname.aex}}
{\AppExistsfalse}
\fi}
您的自定义命令将扩展为:
which bash bin/pygmentize.sh && touch \jobname.aex
它会找到 bash,但找不到bin/pygmentize.sh
。解决方案是要么使bin/pygmentize.sh
可执行文件 ( chmod u+x bin/pygmentize.sh
)which
不返回错误,要么完全绕过检查。您可以通过将命令声明为以下内容来绕过检查:
\renewcommand{\MintedPygmentize}{which ; bash bin/pygmentize.sh}
这将扩展为:which which; bash bin/pygmentize.sh && touch \jobname.aex
,从而通过检查。在实际调用时,which ;
不会产生任何输出,因此整个命令调用将表现得好像命令的这一部分不存在一样。