如何正确指定 minted 的 pygmentize 外部命令的替代方案?

如何正确指定 minted 的 pygmentize 外部命令的替代方案?

不久以前我问如何扩展 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 ;不会产生任何输出,因此整个命令调用将表现得好像命令的这一部分不存在一样。

相关内容