
Некоторое время назадЯ спросилкак расширить 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: покопавшись в исходниках Minted, я увидел следующее:
\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 ;
не создает никаких выходных данных, поэтому весь вызов команды будет вести себя так, как будто этой части команды нет.