1

Say my LaTeX package defines only \MyMarvelousCommand. In my package documentation, I have many different listings typeset with minted. \MyMarvelousCommand should appear in red inside each listing.

Here is my actual solution:

  1. use minted's escapeinside||
  2. In all my listings, replace \MyMarvelousCommand by |\MyMarvelousCommand|
  3. Redefine \MyMarvelousCommand at the beginning of the minted environment using hooks.
\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}

enter image description here

This is far from optimal:

  1. I must parse the code by myself
  2. It breaks MWE with spurious characters, which is very annoying
  3. it does not work on listing+output examples (like in tcblisting)

Is there another approach

1 Answer 1

1

Here I add two options to minted

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

minted is also patched to execute python3 <script.py> <hash.pygtex> <more_arg> before input a <hash.pygtex> file each time. Here <hash.pygtex> represents the (intermediate) output tex file of pygments. You can think it as the cached _mint-<main>/<hash.pygtex>.

Then your need can be served by a simple python script which replaces \MyMarvelousCommand to a wrapped form, like \wrapper{\MyMarvelousCommand}. Since we are handling the pygments output, \<cmd> is actually \PYGZbs{}<cmd>.

Since pygments is itself a python library, executing a python script will not add any extra dependencies. Also the following script is more or less a proof-of-concept, so you can extend the script to make it more flexible.

#!/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}
3
  • 1
    Works as is on OSX. I reverted the order of arguments #2 and #3 such that I could add \MySecondCommand, \MyThirdCommand` as arguments #4, #5, ... to the process. Commented Nov 25, 2021 at 7:11
  • You can make #3 accept a list of csnames, like "MySecondCommand, MyThirdCommand, ...". Parsing a list is much easier in python than in tex. For a more flexible example, python3 highlightcmd.py xxx.pygtex --red "cmd1, cmd2" --blue "cmd3,cmd4". Commented Nov 25, 2021 at 8:55
  • As I do not need such flexibility, I just replaced python assignment cmd=sys.arg[2] by for cmd in sys.argv[3:]: and indent next instructions appropriately. Commented Nov 25, 2021 at 9:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .