列表:突出显示以单引号开头的前缀关键字

列表:突出显示以单引号开头的前缀关键字

这是关于 Rust 及其生命周期符号:

\documentclass[crop,varwidth]{standalone}
\usepackage{listings}

\usepackage{xparse}
\usepackage{expl3}
\usepackage[svgnames]{xcolor}

\def\noprint#1{}

\ExplSyntaxOn
\NewDocumentCommand \lifetime { }
{
  \tl_set:No \l_demo_tl {\the\use:c{lst@token}}
  \regex_replace_all:nnN { ([\'\:][a-zA-Z]+[^\'\:]) } { \c{textcolor}\cB{ Violet \cE}\cB{ \1 \cE} } \l_demo_tl
  \tl_use:N \l_demo_tl
  \noprint
}
\ExplSyntaxOff
\lstset{
  basicstyle=\ttfamily,
  alsoletter={':},
  identifierstyle=\lifetime
}

\begin{document}
\begin{lstlisting}
struct Foo<'a, 'b>{} // highlight 'a and 'b -- doesn't work
struct Foo<:a, :b>{} // highlight :a and :b -- works
'a' // not highlighted
:a: // not highlighted
\end{lstlisting}
\end{document}

我尝试从这个问题调整解决方案[1] 但不知何故,正则表达式与单引号不匹配——如果我用冒号替换单引号,它就会按预期突出显示。

  • keywordsprefix对我来说没用
  • moredelim亮点太多

平均能量损失

答案1

您的版本似乎不起作用,因为'不仅仅是一个简单的字符,listings而是一个内部调用的宏\lst@um'。显然,这是用来在正常和直立引号字符之间进行选择的。我不知道如何使正则表达式包匹配这个,所以这里有一个使用传统方法的版本。

这个想法与正则表达式版本基本相同。首先,我们制作'一个字母,使其成为所有标识符名称的一部分。然后我们的\lifetime宏挂接到标识符打印中,并\lst@token在应用适当的样式打印之前扫描标记列表(存储标识符标记)。我不会在这里详细解释扫描,请随意手动扩展几个示例以确保您能正常工作。:)

通过扫描,我们可以区分三种情况,每种情况都可以分配一种单独的样式:

  • 不以'( \@normalstyle) 开头的标识符,
  • 以 ( ) 开头'但不以'( \@lifetimestyle) 结尾的标识符,以及
  • '以( )开头和结尾的标识符\@charlitstyle

请注意,\unskip在应用样式时使用的 ,\@setlststyle用于吞噬一些虚假的粘连,否则会在输出中添加不必要的空间。如果使用其他列格式,可能需要删除它们。

\documentclass{article}

\usepackage{listings}
\usepackage[svgnames]{xcolor}

\lstset{
    basicstyle=\ttfamily\small,
    alsoletter={'},
    identifierstyle=\lifetime,
    morecomment=[l][\color{gray}]{//},
}

\makeatletter
\def\@normalstyle{\color{blue}}
\def\@lifetimestyle{\color{red}}
\def\@charlitstyle{\color{green}}

\def\@setlststyle#1{%
    \edef\lt@temp{{\unskip\bgroup\noexpand#1}\the\lst@token{\unskip\egroup}}%
    \lst@token=\expandafter{\lt@temp}%
}

\begingroup
\catcode`\'=11

\gdef\lifetime{%
    \expandafter\lifetime@\the\lst@token\lst@um'\@end
}
\gdef\lifetime@#1\lst@um'#2\@end{%
    \if\relax\detokenize{#1}\relax
        \lifetime@'#2\@end
    \else
        \@setlststyle\@normalstyle
    \fi
}
\gdef\lifetime@'#1\lst@um'#2\@end{%
    \if\relax\detokenize{#2}\relax
        \@setlststyle\@lifetimestyle
    \else
        \@setlststyle\@charlitstyle
    \fi
}
\endgroup
\makeatother

\begin{document}
\begin{lstlisting}
 a    abc   // normal identifier
 a'   abc'  // normal identifier
'a   'abc   // timelife identifier
'a'  'abc'  // character literal
struct Foo<'a, 'b>{} // highlight 'a and 'b
\end{lstlisting}

\end{document}

在此处输入图片描述

答案2

在 @siracusa 发布他的解决方案后,我再次查看了这个问题,确实如他指出的那样,这'是一个宏,而不是扩展为正则表达式中可以使用的“正常”符号。幸运的是,正则表达式包允许我们使用宏——而不是'\'则表达式\c{lst@um'}用来匹配的或'lst@um宏必须用于所有“不可打印或难以打印”的字符(_$*-......)——请参阅列表文档。

\documentclass[crop,varwidth]{standalone}
\usepackage{listings}

\usepackage{xparse}
\usepackage{expl3}
\usepackage[svgnames]{xcolor}

\def\noprint#1{}

\ExplSyntaxOn
\NewDocumentCommand \lifetime { }
{
  \tl_set:No \l_demo_tl {\the\use:c{lst@token}}
  \regex_replace_all:nnN { ([\c{lst@um'}\:][a-zA-Z]+[^\c{lst@um'}\:]) } { \c{textcolor}\cB{ Violet \cE}\cB{ \1 \cE} } \l_demo_tl
  \tl_use:N \l_demo_tl
  \noprint
}
\ExplSyntaxOff
\lstset{
  basicstyle=\ttfamily,
  alsoletter={':},
  identifierstyle=\lifetime
}

\begin{document}
\begin{lstlisting}
struct Foo<'a, 'b>{} // highlight 'a and 'b -- works
struct Foo<:a, :b>{} // highlight :a and :b -- works
'a' // not highlighted
:a: // not highlighted
\end{lstlisting}
\end{document}

工作代码

相关内容