3

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?

4

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

1

I have found a solution for the first approach, using separate minted environments, which has the advantage that it works across page breaks.

Unfortunately the distances from the code to the surrounding text do not match those of a regular minted environment. I would appreciate hints on how to fix that.

Please note that the breaklines option is important here, it somehow influences the distance between the lines.

% minted 2017/02/10 v2.4.2dev

\documentclass{article}

\usepackage{minted}

\newminted{c}{
    linenos, 
    frame=lines, 
    tabsize=4, 
    autogobble,
}

\newif\ifFirstMintedPart
\makeatletter
\newenvironment{mintedBlock}{%
    \par
    \medskip%TODO
    \begingroup
        \setlength{\parskip}{0pt}%
        \setlength{\baselineskip}{0pt}%
        \setlength{\lineskip}{0pt}%
        \let\originalVspace=\vspace
        \renewcommand{\vspace}{\@ifnextchar*\@gobbletwo\@gobble}%
        \setlength{\fboxsep}{0pt}%
        \FirstMintedParttrue
        \noindent\FancyVerbRuleColor{\vrule \@width\linewidth \@height\FV@FrameRule}%
        \originalVspace{2pt}%TODO
        \par
}{%
        \par
        \originalVspace{2pt}%TODO
        \noindent\FancyVerbRuleColor{\vrule \@width\linewidth \@height\FV@FrameRule}%
        \par
    \endgroup
    \medskip%TODO
}
\makeatother

\newenvironment{cpart}[1]{%
    \VerbatimEnvironment
    \ifFirstMintedPart
        \newcommand\currentLineNumber{firstnumber=1}%
    \else
        \newcommand\currentLineNumber{firstnumber=last}%
    \fi
    \newcommand{\beginCCode}{\begin{ccode*}}%
    \expandafter\beginCCode\expandafter{%
        \currentLineNumber, 
        frame=none, 
        bgcolor=white, 
        breaklines, % this is important!
        #1
    }%
}{%
    \end{ccode*}%
    \global\FirstMintedPartfalse
}

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


\begin{document}

\begin{mintedBlock}
    \begin{cpart}{}
        #include <stdio.h>
    \end{cpart}
    \begin{cpart}{}
    \end{cpart}
    \begin{cpart}{bgcolor=\colorSum}
        int sum(int summand1, int summand2)
        {
            return summand1 + summand2;
        }
    \end{cpart}
    \begin{cpart}{}
    \end{cpart}
    \begin{cpart}{bgcolor=\colorMain, escapeinside=~~}
        int main()
        {
            int summand1 = 1;
            int summand2 = 2;
            printf("%d + %d = %d\n", summand1, summand2, ~\linebreak~sum(summand1, summand2));
        }
    \end{cpart}
\end{mintedBlock}

\end{document}

screenshot

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.