同时阅读带星号和不带星号的列表

同时阅读带星号和不带星号的列表

我目前正在使用 listings 包编写语言定义。我的语言应按以下方式着色:

  • 所有评论都应该是完全绿色的,无一例外
  • 所有琴弦都应该是完全红色的,无一例外
  • 所有关键字都应为蓝色(关键字可以包含数字)
  • 标识符应该是黑色(标识符可以包含数字)
  • 数字应该是洋红色(但关键字或标识符中的数字不是)
  • 数学运算符、括号等应为青色

用这种方式给我的语言着色其实并不难。我通过将 basicstyle 设置为洋红色、keywordstyle 设置为蓝色、commentstyle 设置为绿色、stringstyle 设置为红色,然后使用 * 版本的 literate 将数学运算符设置为青色来实现这一点。一切都很顺利。但是,我的语言定义还必须允许在字符串或注释中使用像“ü”这样的德语变音符号。我们知道这有点棘手,因为列表和 utf8 编码会造成一些麻烦,但通常可以通过使用不带星号的 literate 版本来实现。

问题来了。正如你所见,我必须用 * 版本来标记一些内容,同时标记其他没有星号的内容。我发现理论上可以像这里一样做到这一点: 如何在列表环境中将星号(*)仅应用于少数识字者?

这有效,但并非在所有情况下都有效。我在尝试识读 = 符号和 时遇到了麻烦。问题似乎是我的注释的分隔符包含 =,而字符串本身中的 " 被 \ 转义了。有什么想法可以解决这个问题吗?

我创建了一个 MWE,并根据 MWE 中的评论做出了三项输出:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{xcolor}
\usepackage{listings}



\lstdefinelanguage{testlang}{
morekeywords={int32,string},
morecomment=[l]{\#},
morecomment=[n]{\#=}{=\#},
morestring=[b]{"}
}[keywords,comments,strings]




\makeatletter
\newcommand{\jPm}[1]{%
\ifnum\lst@mode=\lst@Pmode\relax%
{\color{cyan}#1}%
\else%
#1%
\fi%
}
\begin{document}


% defining the colors
\lstset{basicstyle={\color{magenta}\ttfamily}, keywordstyle={\color{blue}\bfseries},
commentstyle={\color{green}\textit}, stringstyle={\color{red}}, identifierstyle={\color{black}}}
% defining the literals
\lstset{extendedchars=true}
\lstset{literate={ü}{{\"u}}{1} {+}{{{\jPm{+}}}}{1} % the first result does not use the next two lines
%{\\}{{{\jPm{\textbackslash{}}}}}{1} % the second result does not use the next line
%{=}{{{\jPm{=}}}}{1} % the third result also uses this line
}
\lstset{language=testlang}




\begin{lstlisting}
#= A comment that is longer than one line,
and that contains the German word "Blüte". =#

# Single comment: We will calculate 5 + 2 \ 8

string mystr = "An \"escaped string\", a Blüte and 1 + 1 = 2."
int32 my2ndvar = 8
int32 myres = 5 + 2 \ my2ndvar
\end{lstlisting}

\end{document}

当只有ü和+时输出: 第一个输出

当ü、+、\为字母时输出: 第二个输出

当ü、+、\、= 为字母时输出: 第三个输出

答案1

在尝试了很多不同的方法、查看了 listings 包的文档和源代码以及搜索了互联网之后,我终于找到了一个解决方案,当然,我想与遇到同样问题的人分享。这可能不是最简单的解决方案,但它确实有效。

我所做的基本上是查看 listings 包的源代码,找出哪些命令定义了 literate 属性,将它们复制到我的源代码中并对其进行修改以创建一个新的 opliterate 属性,该属性的作用与 literate 属性相同。现在我可以使用 literate 属性来进行没有星号的文字识别,也可以使用 opliterate 属性来进行有星号的文字识别。

以下是代码:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{xcolor}
\usepackage{listings}



\lstdefinelanguage{testlang}{
morekeywords={int32,string},
morecomment=[l]{\#},
morecomment=[n]{\#=}{=\#},
morestring=[b]{"}
}[keywords,comments,strings]




\makeatletter
\def\lst@OpLiteratekey#1\@nil@{\let\lst@ifxopliterate\lst@if
                             \def\lst@opliterate{#1}}
\lst@Key{opliterate}{}{\@ifstar{\lst@true \lst@OpLiteratekey}
                             {\lst@false\lst@OpLiteratekey}#1\@nil@}
\lst@AddToHook{SelectCharTable}
    {\ifx\lst@opliterate\@empty\else
         \expandafter\lst@OpLiterate\lst@opliterate{}\relax\z@
     \fi}
\def\lst@OpLiterate#1#2#3{%
    \ifx\relax#2\@empty\else
        \lst@CArgX #1\relax\lst@CDef
            {}
            {\let\lst@next\@empty
             \lst@ifxopliterate
                \lst@ifmode \let\lst@next\lst@CArgEmpty \fi
             \fi
             \ifx\lst@next\@empty
                 \ifx\lst@OutputBox\@gobble\else
                   \lst@XPrintToken \let\lst@scanmode\lst@scan@m
                   \lst@token{#2}\lst@length#3\relax
                   \lst@XPrintToken
                 \fi
                 \let\lst@next\lst@CArgEmptyGobble
             \fi
             \lst@next}%
            \@empty
        \expandafter\lst@OpLiterate
    \fi}




\begin{document}


% defining the colors
\lstset{basicstyle={\color{magenta}\ttfamily}, keywordstyle={\color{blue}\bfseries},
commentstyle={\color{green}\textit}, stringstyle={\color{red}}, identifierstyle={\color{black}}}
% defining the literals
\lstset{extendedchars=true}
\lstset{literate={ü}{{\"u}}{1}}
\lstset{opliterate=*{+}{{{\color{cyan}+}}}{1} {\\}{{{\color{cyan}\lstum@backslash}}}{1} {=}{{{\color{cyan}=}}}{1}}
\lstset{language=testlang}




\begin{lstlisting}
#= A comment that is longer than one line,
and that contains the German word "Blüte". =#

# Single comment: We will calculate 5 + 2 \ 8

string mystr = "An \"escaped string\", a Blüte and 1 + 1 = 2."
int32 my2ndvar = 8
int32 myres = 5 + 2 \ my2ndvar
\end{lstlisting}

\end{document}

输出如下: 在此处输入图片描述

相关内容