如何避免使用 math/mathescape 的代码列表中的背景/框架中断?

如何避免使用 math/mathescape 的代码列表中的背景/框架中断?

我有很多 C++ 源代码,注释中有 LaTeX 公式。非常适合使用 listings 包来漂亮地打印源代码。但是,当公式“很高”(例如包含积分或和)时,大多数公式都会破坏背景或框架线,如以下工作示例和预览所示。问题是:我如何才能强制 listing 不破坏由高数学方程式产生的高线条上的框架?

\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}

在此处输入图片描述

注意:如果这是 listings 包的固有限制,那么真正的问题可能是如何强制方程式在数学模式下尽可能多地使用正常的垂直空间。例如,强制积分和求和比内联数学模型更短。

我也知道另一个问题:背景颜色和 mathescape 损坏的列表,但这只能解决特定的数学符号。

答案1

您至少有两个选项可以纠正此行为。

  1. 如果你的数学方程式(包含在转义内$...$)相当简单并且通常只包含一行,甚至可能没有任何其他代码在其上方/下方,那么你可以\smash转义内容:

    \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}
    

    在此处输入图片描述

    但是,正如您所看到的,即使从这个小示例中,方程式的底部也会被背景颜色覆盖。这是因为算法是按顺序排版的,会覆盖深度低于基线的任何内容。因此,此选项非常严格,并且通常仅在您的数学表达式不低于基线时才有效。非常严格......

  2. 您可以使用不同的环境来绘制框架和背景。mdframed包裹在这方面做得很好:

    \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}
    

    在此处输入图片描述

    在上面的例子中,mdframed使用tikz绘制框架。可以mdframed结合使用listings.为此,etoolbox包裹提供挂钩以在环境开始之前和结束之后添加代码(lstlisting在本例中)。为此,宏\BeforeBeginEnvironment\AfterEndEnvironment很有用。以这种方式添加代码至关重要,因为lstlisting修改了 catcodes 以进行格式化:

    \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}
    

在上面的修改中,定义了一个新的mdframed样式,并将其用作环境的选项参数。输出与前面的示例类似。listingstylestyle=listingstylemdframed

相关内容