[Tex/LaTex] How to avoid background / frame break in code listings with math / mathescape

backgroundsframedinline()listingsmath-mode

I have lots of C++ sources with LaTeX formulas in the comments. Ideal for using the listings packages to pretty print the source. However, most of the formulas break either, the background or the frame lines when the formula is "tall" (e.g. contains an integral or a sum) as seen in the following working example and preview. The question is: how can I force listing not to break the frame on tall lines produced by tall math equations?

\documentclass{article}
\usepackage[]{listings}
\usepackage{xcolor}
 \lstset{
        backgroundcolor=\color[gray]{0.9},
        frame=single,
        mathescape=true,
}
\lstset{language=C++}
\begin{document}

\begin{lstlisting}
for(i = 0; i < 10; i++)
{
// gratuitious equation $\mathcal{D}_3(x) = \frac{x^n}{n} \int_{0_0}^{x^2} \frac{t^n}{e^t-1}dt$ 
*p++ = i;
House h = new house();
int romms = h.getRooms():
}
\end{lstlisting}

\end{document}

enter image description here

Note: If this is an intrinsic limitation of listings packages, then the real question could be how can equations be force to use the normal vertical space as much as possible in math mode. For example to force integrals and sums to be even shorter than inline math model.

I am also aware of this other question: listings with background color and mathescape broken, but that only solved for a particular math symbol.

Best Answer

You have at least two options to correct for this behaviour.

  1. If your mathematical equations (contained within the escaping $...$) is fairly simple and usually only contains a one line, and perhaps even does not have any other code above/below it, then you can \smash the escaped content:

    \documentclass{article}
    \usepackage{listings}% http://ctan.org/pkg/listings
    \usepackage{xcolor}% http://ctan.org/pkg/xcolor
    \begin{document}
    \lstset{%
      backgroundcolor=\color[gray]{0.9},%
      frame=single,%
      mathescape=true,%
    }
    \lstset{language=C++}%
    
    \begin{lstlisting}
    for(i = 0; i < 10; i++)
    {
    // gratuitious equation $\smash{\mathcal{D}_3(x) = \frac{x^n}{n} \int_{0_0}^{x^2} \frac{t^n}{e^t-1}dt}$ 
    *p++ = i;
    House h = new house();
    int romms = h.getRooms():
    }
    \end{lstlisting}
    
    \end{document}
    

    enter image description here

    However, as you can see, even from this small example, the bottom part of the equation is overwritten with the background colour. This is because the algorithm is typeset sequentially, overwriting anything with a depth below the baseline. So this option is very restrictive, and typically only works if your mathematical expression does not drop below the baseline. Pretty restrictive...

  2. You can use a different environment to draw the frame and background. The mdframed package does an excellent job of this:

    \documentclass{article}
    \usepackage{listings}% http://ctan.org/pkg/listings
    \usepackage{xcolor}% http://ctan.org/pkg/listings
    \usepackage[framemethod=TikZ]{mdframed}% http://ctan.org/pkg/mdframed
    \begin{document}
    \lstset{%
    %  backgroundcolor=\color[gray]{0.9},
    %  frame=single,
      mathescape=true,
    }
    \lstset{language=C++}%
    
    \begin{mdframed}[backgroundcolor=black!15,outerlinewidth=0.25pt,outerlinecolor=black,%
      innerleftmargin=5pt,innerrightmargin=5pt,innertopmargin=0pt,innerbottommargin=0pt]
    \begin{lstlisting}
    for(i = 0; i < 10; i++)
    {
    // gratuitious equation $\mathcal{D}_3(x) = \frac{x^n}{n} \int_{0_0}^{x^2} \frac{t^n}{e^t-1}dt$ 
    *p++ = i;
    House h = new house();
    int romms = h.getRooms():
    }
    \end{lstlisting}
    \end{mdframed}
    
    \end{document}
    

    enter image description here

    In the above example, mdframed uses tikz to draw the frame. It is possible to automate this process of using mdframed in conjunction with listings. For this, the etoolbox package provides hooked to add code before the beginning and after the end of an environment (lstlisting in this case). For this, the macros \BeforeBeginEnvironment and \AfterEndEnvironment is helpful. It is crucial to add code in this manner, since lstlisting modified catcodes for formatting:

    \documentclass{article}
    \usepackage{listings}% http://ctan.org/pkg/listings
    \usepackage{xcolor}% http://ctan.org/pkg/listings
    \usepackage[framemethod=TikZ]{mdframed}% http://ctan.org/pkg/mdframed
    \usepackage{etoolbox}{% http://ctan.org/pkg/etoolbox
    
    \mdfdefinestyle{listingstyle}{%
      backgroundcolor=black!15,outerlinewidth=0.25pt,outerlinecolor=black,%
      innerleftmargin=5pt,innerrightmargin=5pt,innertopmargin=0pt,innerbottommargin=0pt%
    }
    
    \begin{document}
    
    \lstset{mathescape=true,language=C++}%
    
    \BeforeBeginEnvironment{lstlisting}{\begin{mdframed}[style=listingstyle]}
    \AfterEndEnvironment{lstlisting}{\end{mdframed}}
    
    \begin{lstlisting}
    for(i = 0; i < 10; i++)
    {
    // gratuitious equation $\mathcal{D}_3(x) = \frac{x^n}{n} \int_{0_0}^{x^2} \frac{t^n}{e^t-1}dt$ 
    *p++ = i;
    House h = new house();
    int romms = h.getRooms():
    }
    \end{lstlisting}
    
    \end{document}
    

In the above modification, a new mdframed style listingstyle is defined and used as style=listingstyle in the option argument to the mdframed environment. The output is similar to the previous example.

Related Question