[Tex/LaTex] Highlight function in minted with background color

mintedtikz-pgf

I would like to highlight a function in minted by giving it a background color in order to make the connection to a visualization better visible.

I used to put the functions to be highlighted in a separate minted environment and specify a background color for the entire environment (in minted v1.7):

% minted 2011/09/17 v1.7

\documentclass{article}

\usepackage{minted}
\newminted{c}{linenos, tabsize=4, gobble=2}

\makeatletter
\newenvironment{mintedBlock}{%
    % I can not use frame=topline|bottomline because that is inside of colored box
    % copied from /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty line 918 in \def\FV@SingleFrameLine
    \noindent
    \FancyVerbRuleColor{\vrule \@width\linewidth \@height\FV@FrameRule}%
}{%
    \FancyVerbRuleColor{\vrule \@width\linewidth \@height\FV@FrameRule}%
}
\makeatother

\newcommand{\colorMain}{green!10}%
\newcommand{\colorSum}{yellow!20}%

\begin{document}

\begin{mintedBlock}
    % I am using old package versions which are buggy, so firstnumber=last gives wrong numbering.
    \begin{ccode*}{frame=none, bgcolor=white}
        #include <stdio.h>
    \end{ccode*}
    \begin{ccode*}{frame=none, firstnumber=2, bgcolor=white}
    \end{ccode*}
    \begin{ccode*}{frame=none, firstnumber=3, bgcolor=\colorSum}
        int sum(int summand1, int summand2)
        {
            return summand1 + summand2;
        }
    \end{ccode*}
    \begin{ccode*}{frame=none, firstnumber=7, bgcolor=white}
    \end{ccode*}
    \begin{ccode*}{frame=none, firstnumber=8, bgcolor=\colorMain}
        int main()
        {
            int summand1 = 1;
            int summand2 = 2;
            printf("%d + %d = %d\n", summand1, summand2, 
                sum(summand1, summand2));
        }
    \end{ccode*}
\end{mintedBlock}

\end{document}

with minted v1.7 using separate environments

The spacing of the rules was not perfect but apart from that it was good enough in minted 1.7.
However I have recently upgraded to the newest version (minted 2.4.2dev) and now there are big spaces between the seperate minted environments.

I have tried to remove them with

\renewcommand{\vspace}{\@ifnextchar*\@gobbletwo\@gobble}%

which makes it a lot better but still leaves too big spaces.


Therefore I have tried it with a new approach: using escapeinside to insert tikz nodes with remember picture and drawing a rectangle around them later on.

% minted 2017/02/10 v2.4.2dev

\documentclass{article}

\usepackage{minted}
\newminted{c}{linenos, frame=lines, tabsize=4, gobble=1}

\usepackage{tikz}
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=(#1.base)] \node (#1) {\vphantom{I}};}

\newcommand{\colorMain}{green!10}%
\newcommand{\colorSum}{yellow!20}%

\begin{document}
\begin{ccode*}{breaklines, escapeinside=~~}
    #include <stdio.h>

    ~\tikzmark{sumtop}~int sum(int summand1, int summand2)
    {
        return summand1 + summand2;
    ~\tikzmark{sumbottom}~}

    ~\tikzmark{maintop}~int main()
    {
        int summand1 = 1;
        int summand2 = 2;
        printf("%d + %d = %d\n", summand1, summand2, sum(summand1, summand2));
    ~\tikzmark{mainbottom}~}
\end{ccode*}

\begin{tikzpicture}[remember picture, overlay]
    \path[overlay, fill=\colorSum] (sumtop.north) rectangle ([xshift=\linewidth]sumbottom.south);
    \path[overlay, fill=\colorMain] (maintop.north) rectangle ([xshift=\linewidth]mainbottom.south);
\end{tikzpicture}
\end{document}

with minted v2.4.2dev using escapeinside and tikz

Unfortunately the tikz picture is above the minted code.

How can I put the tikzpicture behind the text?

Also, I am not a hundred percent happy with this approach because I will run into problems if the code happens to move across a pagebreak.
Does someone have a better idea?

Best Answer

You have to add the picture on the page background layer, for example using eso-pic. This obviously cannot break across pages.

\documentclass{article}

\usepackage{minted}
\newminted{c}{linenos, frame=lines, tabsize=4, gobble=1}

\usepackage{tikz}
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=(#1.base)] \node (#1) {\vphantom{I}};}

\newcommand{\colorMain}{green!10}%
\newcommand{\colorSum}{yellow!20}%

\usepackage{eso-pic}

\begin{document}
\begin{ccode*}{breaklines, escapeinside=~~}
#include <stdio.h>

~\tikzmark{sumtop}~int sum(int summand1, int summand2)
{
    return summand1 + summand2;
~\tikzmark{sumbottom}~}

~\tikzmark{maintop}~int main()
{
    int summand1 = 1;
    int summand2 = 2;
    printf("%d + %d = %d\n", summand1, summand2, sum(summand1, summand2));
~\tikzmark{mainbottom}~}
\end{ccode*}

\AddToShipoutPictureBG*{%
  \begin{tikzpicture}[remember picture, overlay]
    \path[overlay, fill=\colorSum] (sumtop.north) rectangle ([xshift=\linewidth]sumbottom.south);
    \path[overlay, fill=\colorMain] (maintop.north) rectangle ([xshift=\linewidth]mainbottom.south);
  \end{tikzpicture}%
}
\end{document}

enter image description here