我如何告诉列表包行注释仅影响包含我的分隔符的行?

我如何告诉列表包行注释仅影响包含我的分隔符的行?

我正在尝试使用该listings包来格式化自定义语言,但遇到了分隔符问题。

我需要将以“C”开头、后跟一个或多个空格的任何行标记为注释。以“C”开头且任何非空格字符的行都算作有效代码,不应被注释。

\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\lstset{%
basicstyle=\small\ttfamily,
frame=single,
morecomment=[f][\color{red}][0]{C\ },
}
\begin{document}
\begin{lstlisting}
C FM184 0.03827 100 51
C21 -0.95 -0.9 -0.85 -0.8 -0.75 -0.7  -0.65 -0.6 -0.55 -0.5 &
C   This is cos(theta) in one-degree increments from 180 to 0 degrees
C   
C    Error in previous computation - now corrected here  
C    -----------------------------------------------------------------
\end{lstlisting}
\end{document}

我的 MWE 让我接近,但无法注释掉仅包含分隔符本身的行,即使有多个尾随空格。

在分隔符中添加空格字符

但是,将我的分隔符切换为其他变体,例如

morecomment=[f][\color{red}][0]{C },
morecomment=[f][\color{red}][0]{C},

导致这些行被注释,但是任何以“C”开头的行都会被注释掉:

分隔符中无空格

我尝试在分隔符中添加换行符,但这会导致编译崩溃。我不希望通过在“C”行中添加字符来打断我的空白行,只是为了让它们被注释。有人能给我指出正确的方向吗?

答案1

有点晚了,但这里有一个解决方案,也可以修复空注释行。

当 TeX 从输入文件中读取一行时,它会删除行尾出现的所有显式空格字符(字符代码 32)。这是内部发生的,无法通过更改 catcode 或其他技巧来绕过。因此,您的输入行

C␣␣␣<newline>

将被listings视作

C<newline>

因此,您匹配的评论在C\这里不起作用。

literate然而,我们可以做的是为C<newline>(在 TeX 中)添加匹配项,如果它出现在输入行的第一列,则将C\^^M相应的颜色染成红色,否则仅输出正常内容。CC

这种方法的问题在于,listings然后就看不到行尾字符了,因为它被处理吞噬了literate,从而阻止了换行的正常工作。因此,每当找到匹配的空注释行时,我们都必须模拟换行。为了指示这种假换行,我们使用一个开关,\iflst@fakeEOL该开关在调用时设置,并在输出任何标记后literate在钩子中检查。如果设置,我们会发出,这是每次正常换行时发生的略微修改的版本。在钩子中,每次开始一行时都会重置开关。PostOutput\lst@fakeEOLInitVarBOL

完整示例代码:

\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}

\makeatletter

\newif\iflst@fakeEOL

\lst@AddToHook{PostOutput}{%
    \iflst@fakeEOL
        \aftergroup\lst@fakeEOL
    \fi
    \global\lst@fakeEOLfalse
}

\lst@AddToHook{InitVarBOL}{%
    \global\lst@fakeEOLfalse
}

\newcommand\lst@fakeEOL{%
    \lst@EOLUpdate \lsthk@InitVarsBOL
    \global\advance\lst@lineno\@ne
    \ifnum \lst@lineno>\lst@lastline
        \lst@ifdropinput \lst@LeaveMode \fi
        \ifx\lst@linerange\@empty
            \expandafter\expandafter\expandafter\lst@EndProcessListing
        \else
            \lst@interrange
            \lst@GetLineInterval
            \expandafter\expandafter\expandafter\lst@SkipToFirst
        \fi
    \else
        \expandafter\lst@BOLGobble
    \fi
}

\lstset{%
    basicstyle=\small\ttfamily,
    numbers=left,
    numberstyle=\ttfamily\footnotesize\color{gray},
    morecomment=[f][\color{red}][0]{C\ },
    literate=*{C\^^M}{\empty@line@comment}1
}

\newcommand\empty@line@comment{%
    \lst@CalcColumn
    \ifnum\@tempcnta>1
        C%
    \else
        \textcolor{red}{C}%
    \fi
    \global\lst@fakeEOLtrue
}

\makeatother

\begin{document}
%\tracingmacros=2
\begin{lstlisting}
C FM184 0.03827 100 51
C FM184 0.03827 100 51
C21 -0.95 -0.9 -0.85 -0.8 -0.75 -0.7  -0.65 -0.6 -0.55 -0.5 &
C   This is cos(theta) in one-degree increments from 180 to 0 degrees
C   
C    Error in previous computation - now corrected here  
C    -----------------------------------------------------------------

C
CC
C C
CCC C
\end{lstlisting}
\end{document}

输出

在此处输入图片描述

相关内容