minted+latex:每次出现给定命令时都会产生不同的颜色

minted+latex:每次出现给定命令时都会产生不同的颜色

假设我的 LaTeX 包仅定义\MyMarvelousCommand。在我的包文档中,我有许多使用 minted 排版的不同列表。\MyMarvelousCommand应该在每个列表内以红色显示。

这是我的实际解决方案:

  1. 使用 minted 的escapeinside||
  2. 在我的所有列表中,替换\MyMarvelousCommand|\MyMarvelousCommand|
  3. \MyMarvelousCommand使用钩子在铸造环境的开始处重新定义。
\documentclass{article}
\RequirePackage{minted}
\newcommand\MyMarvelousCommand[1]{Do marvelous things with #1}
\AtBeginEnvironment{minted}{
  \def\MyMarvelousCommand{{\color{red}\string\MyMarvelousCommand}}
}
\begin{document}
\begin{minted}[escapeinside=||]{latex}
\texttt{|\MyMarvelousCommand|{\LaTeX}}
\end{minted}
\texttt{\MyMarvelousCommand{\LaTeX}}
\end{document}

在此处输入图片描述

这远非最佳:

  1. 我必须自己解析代码
  2. 它使用虚假字符破坏了 MWE,这是非常恼人的
  3. 它不适用于列表+输出示例(例如在 tcblisting 中)

还有其他方法吗

答案1

在这里我添加了两个选项minted

  • post processor=<script.py>
  • post processor args=<more_args>

minted也被修补为每次python3 <script.py> <hash.pygtex> <more_arg>输入文件之前执行。这里表示的(中间)输出 tex 文件。您可以将其视为缓存的。<hash.pygtex><hash.pygtex>pygments_mint-<main>/<hash.pygtex>

然后,您可以通过一个简单的 Python 脚本来满足您的需求,该脚本替换\MyMarvelousCommand为包装形式,例如\wrapper{\MyMarvelousCommand}。由于我们正在处理pygments输出,\<cmd>实际上是\PYGZbs{}<cmd>

由于pygments它本身就是一个 Python 库,因此执行 Python 脚本不会添加任何额外的依赖项。此外,以下脚本或多或少是一个概念验证,因此您可以扩展该脚本以使其更加灵活。

#!/usr/bin/python3
import fileinput
import sys

# This is `highlightcmd.py`
# Usage: python3 highlightcmd.py xxx.pygtex MyCommandFirst

if len(sys.argv) < 4:
    raise ValueError(f'Need three args, given {len(sys.argv)}')

fin = sys.argv[1]
cmd = sys.argv[2]
wrapper = sys.argv[3]
# python highlighter of vscode accepts only uppercase `R` to represent raw string
# see https://github.com/MagicStack/MagicPython/issues/114
pattern_find = fR'{{\PYGZbs{{}}{cmd}}}'
pattern_sub = fR'{{\{wrapper}{{\PYGZbs{{}}{cmd}}}}}'

with fileinput.input(fin, inplace=True) as file:
    for line in file:
        print(line.replace(pattern_find, pattern_sub), end='')
\documentclass{article}
\usepackage{minted}
\newcommand\MyMarvelousCommand[1]{Do marvelous things with #1}

\makeatletter
\pretocmd\minted@inputpyg{%
  \minted@postprocesspyg
    {\minted@get@opt{post processor}{}}
    {\minted@outputdir\minted@infile}
    {\minted@get@opt{post processor args}{}}%
}{}{\fail}

\minted@def@opt{post processor}
\minted@def@opt{post processor args}

% #1 = name of the python script, e.g., "process.py"
% #2 = input ".pygtex" file, always be "\minted@outputdir\minted@infile"
% #3 = more args passed to the python script, possibly empty
\newcommand{\minted@postprocesspyg}[3]{%
  \ifstrempty{#1}{}{%
    % execute "python3 <script.py> <file.pygtex> <more_args>"
    \ShellEscape{python3 #1 #2 #3}%
  }%
}
\makeatother

\begin{document}
\setminted{
  autogobble,
  post processor=highlightcmd.py,
  post processor args=MyMarvelousCommand wrapper
}
\newcommand{\wrapper}[1]{\textcolor{red}{#1}}

\begin{minted}{latex}
  \MyMarvelousCommand{\LaTeX}
\end{minted}
\texttt{\MyMarvelousCommand{\LaTeX}}
\end{document}

相关内容