[Tex/LaTex] minted: Hiding comments in code

minted

Is there anyway to have minted hide code comments completely? This is related to How to strip a listing of all (line and block) comments without leaving white space?

But that question is about the listings package.

Best Answer

The following code creates a new environment, mintednc, that strips comments completely. You can add it to the preamble. I've tested it with both C and Python. It's possible that it will need a few tweaks to deal with additional languages.

This code works by creating a custom version of \minted@pygmentize. In this customized version, the highlighted Pygments output is opened via a \write18 Python command, and any line beginning with \PY{c}, \PY{c+cm}, or \PY{c+c1} is discarded. These are the Pygments highlighting commands with arguments that indicate comments. This approach completely eliminates any line that begins with a comment. But inline comments that follow code would be left intact.

Edit in response to question in comments: Adding support for \inputminted is just a matter of creating a wrapper command (\inputmintednc) that uses the customized \minted@pygmentize. I've added this at the end of the code.

Edit in response to error messages in comments: It looks like you are using the development version of minted. The patch only works for minted 1.7. I've added code that works (for now, anyway) with the development version.

Code for minted 1.7 (which is in current TeX distros)

\makeatletter
\newcommand{\minted@pygmentize@stripcomments}[2][\jobname.pyg]{
  \def\minted@cmd{pygmentize -l #2 -f latex -F tokenmerge
    \minted@opt{gobble} \minted@opt{texcl} \minted@opt{mathescape}
    \minted@opt{startinline} \minted@opt{funcnamehighlighting}
    \minted@opt{linenos} -P "verboptions=\minted@opt{extra}"
    -o \jobname.out.pyg #1}
  \immediate\write18{\minted@cmd}
  % For debugging, uncomment:
  %\immediate\typeout{\minted@cmd}
  \ifthenelse{\equal{\minted@opt@bgcolor}{}}
   {}
   {\begin{minted@colorbg}{\minted@opt@bgcolor}}
  % add command to strip comments
  \immediate\write18{\detokenize{python -c "f = open(\"}\jobname\detokenize{.out.pyg\");
    txt = f.readlines(); f.close();
    txt = [line for line in txt if not line.lstrip().startswith(\"\\PY{c}\") and not line.lstrip().startswith(\"\\PY{c+c1}\") and not line.lstrip().startswith(\"\\PY{c+cm}\")];
    f = open(\"}\jobname\detokenize{.out.pyg\", \"w\");
    f.write(\"\".join(txt)); f.close();"}}
  % end
  \input{\jobname.out.pyg}
  \ifthenelse{\equal{\minted@opt@bgcolor}{}}
   {}
   {\end{minted@colorbg}}
  \DeleteFile{\jobname.out.pyg}}

\newenvironment{mintednc}[2][]{%
  \VerbatimEnvironment
  \let\minted@pygmentize\minted@pygmentize@stripcomments
  \begin{minted}[#1]{#2}}{\end{minted}}
\newcommand{\inputmintednc}[3][]{%
  \begingroup
  \let\minted@pygmentize\minted@pygmentize@stripcomments
  \inputminted[#1]{#2}{#3}%
  \endgroup}
\makeatother

Code for current development version of minted

\makeatletter
\newcommand{\minted@inputpyg@stripcomments}{%
  \ifthenelse{\equal{\minted@optcmd@bgcolor}{}}%
    {}%
    {\begin{minted@colorbg}{\minted@optcmd@bgcolor}}%
  % add command to strip comments
  \immediate\write18{\detokenize{python -c "from io import open;
    import re;
    pattern = re.compile(r\"\\PYG([a-z]+)\");
    f = open(\"}\minted@outputdir\minted@infile\detokenize{\", encoding=\"}\minted@encoding\detokenize{\");
    txt = f.read(); f.close();
    p = pattern.search(txt).groups()[0];
    p1 = \"\\PYG\"+p+\"{c}\";
    p2 = \"\\PYG\"+p+\"{c+c1}\";
    p3 = \"\\PYG\"+p+\"{c+cm}\";
    txt = [line for line in txt.splitlines(True) if not line.lstrip().startswith(p1) and not line.lstrip().startswith(p2) and not line.lstrip().startswith(p3)];
    f = open(\"}\jobname\detokenize{.out.pyg\", \"w\", encoding=\"}\minted@encoding\detokenize{\");
    f.write(\"\".join(txt)); f.close();"}}
  % end
  \input{\jobname.out.pyg}%
  \ifthenelse{\equal{\minted@optcmd@bgcolor}{}}%
    {}%
    {\end{minted@colorbg}}%
}
\newenvironment{mintednc}[2][]{%
  \VerbatimEnvironment
  \let\minted@inputpyg\minted@inputpyg@stripcomments
  \begin{minted}[#1]{#2}}{\end{minted}}
\newcommand{\inputmintednc}[3][]{%
  \begingroup
  \let\minted@inputpyg\minted@inputpyg@stripcomments
  \inputminted[#1]{#2}{#3}%
  \endgroup}
\makeatother