如何正確指定 pygmentize 外部指令的替代方法?

如何正確指定 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,而不是我自己的手動呼叫。 (我刪除了鑄造的緩存,切換到使用更新的 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}

無論哪種方式都會產生錯誤。我已確認 mybin/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 ;不會產生任何輸出,因此整個命令呼叫的行為就像命令的這一部分不存在一樣。

相關內容