如何突出显示紧跟等号的所有形式为 [0-9][A-Za-z0-9]* 的单词?

如何突出显示紧跟等号的所有形式为 [0-9][A-Za-z0-9]* 的单词?

我正在使用 Latex Listings 包将代码包含在文档中。我需要实现类似于在标准 IDE 中看到的语法高亮。

我已经能够为评论、关键字和字符串分配颜色,但在弄清楚如何正确地为数字着色方面遇到了一些困难。

以下是其外观的示例:

所需输出

如您所见,只要等号后面的单词以数字开头,则所有后续字符(直到(但不包括)下一个分号或空格))都会被着色。当单词以数字开头时,单词中的所有字符都应被着色,即使它们不是数字。否则,所有数字都不会被着色。

截至目前,我无法想到等号前的单词以数字开头的情况,因此找到一种为所有以数字开头的单词着色的解决方案可能是可以接受的。

在这种情况下,数字是:0-9。

这是 Latex 中的 MWE,但正如您所见,它没有任何数字的颜色。

在此处输入图片描述

\documentclass[pdftex]{report}
\usepackage{listings}
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}

\definecolor{Code}{rgb}{0,0,0}
\definecolor{Keywords}{rgb}{255,0,0}
\definecolor{Strings}{rgb}{255,0,255}
\definecolor{Comments}{rgb}{0,0,255}
\definecolor{Numbers}{rgb}{255,128,0}

\lstdefinestyle{mycode}{
  language=C,
  % Comments
  commentstyle=\color{Comments}\slshape,
  % Strings
  stringstyle=\color{Strings},
  % keywords
  keywordstyle={\color{Keywords}\bfseries}
}

\begin{document}

\begin{lstlisting}[style=mycode]
int main ()
{
    //this is an example
    a1 = 0;
    a2 = a1;
    a3 = 16hxFF;
    a4 = 16 + a1;
    return 0;
}
\end{lstlisting}

\end{document}

答案1

以下是改编使用 listing 包对数字进行着色

在此处输入图片描述

笔记:

进一步增强:

  • 这确实不是如果数字中有非数字,则有效。因此16hxFF无法正确显示,但16x(带有尾随空格)可以。

代码:

\documentclass[pdftex]{report}
\usepackage{listings}
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}

\definecolor{Code}{rgb}{0,0,0}
\definecolor{Keywords}{rgb}{255,0,0}
\definecolor{Strings}{rgb}{255,0,255}
\definecolor{Comments}{rgb}{0,0,255}
\definecolor{Numbers}{rgb}{255,128,0}

\usepackage{etoolbox}
\newtoggle{AfterEqualSign}% Are we supposed to be coloring digits or not
\togglefalse{AfterEqualSign}% Wait until first equal sign
\newtoggle{AlreadyColoring}% Are we already coloring digits or not
\togglefalse{AlreadyColoring}% Start off with not coloring.

\newcommand*{\ColorIfDigitsAfterEqualSign}[1]{%
    \iftoggle{AfterEqualSign}{\color{orange}#1}{#1}%
    \global\toggletrue{AlreadyColoring}%
}%
\newcommand*{\ColorIfAlreadyColoring}[1]{%
    \iftoggle{AlreadyColoring}{%
        \color{orange}#1%
    }{%
        \global\togglefalse{AfterEqualSign}%
        #1%
    }%
}%
\newcommand*{\DisableColoring}[1]{%
    #1%
    \global\togglefalse{AlreadyColoring}%
    \global\togglefalse{AfterEqualSign}%
}%
\newcommand*{\DisableColoringIfAlreadyColoring}[1]{%
    % Allows for a leading space after the =, but before the number
    #1%
    \iftoggle{AlreadyColoring}{%
        \global\togglefalse{AfterEqualSign}%
        \global\togglefalse{AlreadyColoring}%
    }{}%
}%
\lstset{literate=%
    {=}{{{\global\toggletrue{AfterEqualSign}{=}}}}1% Encountered equal sign
    {0}{{{\ColorIfDigitsAfterEqualSign{0}}}}1
    {1}{{{\ColorIfDigitsAfterEqualSign{1}}}}1
    {2}{{{\ColorIfDigitsAfterEqualSign{2}}}}1
    {3}{{{\ColorIfDigitsAfterEqualSign{3}}}}1
    {4}{{{\ColorIfDigitsAfterEqualSign{4}}}}1
    {5}{{{\ColorIfDigitsAfterEqualSign{5}}}}1
    {6}{{{\ColorIfDigitsAfterEqualSign{6}}}}1
    {7}{{{\ColorIfDigitsAfterEqualSign{7}}}}1
    {8}{{{\ColorIfDigitsAfterEqualSign{8}}}}1
    {9}{{{\ColorIfDigitsAfterEqualSign{9}}}}1
    {a}{{{\ColorIfAlreadyColoring{a}}}}1
    {b}{{{\ColorIfAlreadyColoring{b}}}}1
    {c}{{{\ColorIfAlreadyColoring{c}}}}1
    {d}{{{\ColorIfAlreadyColoring{d}}}}1
    {e}{{{\ColorIfAlreadyColoring{e}}}}1
    {f}{{{\ColorIfAlreadyColoring{f}}}}1
    {h}{{{\ColorIfAlreadyColoring{h}}}}1% Add other characters here if needed
    {A}{{{\ColorIfAlreadyColoring{A}}}}1
    {B}{{{\ColorIfAlreadyColoring{B}}}}1
    {C}{{{\ColorIfAlreadyColoring{C}}}}1
    {D}{{{\ColorIfAlreadyColoring{D}}}}1
    {E}{{{\ColorIfAlreadyColoring{E}}}}1
    {F}{{{\ColorIfAlreadyColoring{F}}}}1
    {\ }{{{\DisableColoringIfAlreadyColoring{\ }}}}1% Disable coloring at trailing space
    {;}{{{\DisableColoring{;}}}}1% Disable coloring at semi colon
}

\lstdefinestyle{mycode} {
language=C,
  % Comments
  commentstyle=\color{Comments}\slshape,
  % Strings
  stringstyle=\color{Strings},
   % keywords
   keywordstyle={\color{Keywords}\bfseries}
   }

 \begin{document}

 \begin{lstlisting}[style=mycode]
 int main ()
{
    //this is an example
    a1 = 0;
    a2 = a1;
    a3 = 16hFF;
    a4 = 16 + a1;
    return 0;
}
\end{lstlisting}

\end{document}

答案2

回顾 Peter Grill 的方法

彼得的方法有其优点,但也存在三个局限性。

  1. 数字中的任何非数字都会破坏该数字的突出显示(正如 Peter 所报告的)。
  2. 数字在字符串中被部分突出显示,这似乎是一个错误;我猜数字在字符串中根本不应该突出显示。
  3. listings如果标识符包含任何需要进行文字替换的字符,则无法识别(并正确突出显示)标识符。例如,此处的return不会被识别为关键字(因此不会以红色突出显示),因为它包含e需要进行文字替换的字符 。

彼得·格里尔方法

另一种方法

这是一个类似但更强大的方法,它弥补了上面讨论的所有三个限制。唯一明显的问题是代码重复。编辑: 看egreg 的回答采用更精简的方法!

在此处输入图片描述

\documentclass{article}

\usepackage{xcolor}
\usepackage{textcomp}
\usepackage{listings}

\definecolor{Code}{rgb}{0,0,0}
\definecolor{Keywords}{rgb}{255,0,0}
\definecolor{Strings}{rgb}{255,0,255}
\definecolor{Comments}{rgb}{0,0,255}
\definecolor{Numbers}{rgb}{255,128,0}

\makeatletter

\newif\iffirstchar\firstchartrue
\newif\ifstartedbyadigit
\newif\ifprecededbyequalsign

\newcommand\processletter
{%
  \ifnum\lst@mode=\lst@Pmode%
    \iffirstchar%
        \global\startedbyadigitfalse%
      \fi
      \global\firstcharfalse%
    \fi
}

\newcommand\processdigit
{%
  \ifnum\lst@mode=\lst@Pmode%
      \iffirstchar%
        \global\startedbyadigittrue%
      \fi
      \global\firstcharfalse%
  \fi
}

\lst@AddToHook{OutputOther}%
{%
  \lst@IfLastOtherOneOf{=}
    {\global\precededbyequalsigntrue}
    {}%
}

\lst@AddToHook{Output}%
{%
  \ifprecededbyequalsign%
      \ifstartedbyadigit%
        \def\lst@thestyle{\color{orange}}%
      \fi
    \fi
  \global\firstchartrue%
  \global\startedbyadigitfalse%
  \global\precededbyequalsignfalse%
}

\lstdefinestyle{mycode}
{
  language=C,
  commentstyle=\color{Comments}\slshape,
  stringstyle=\color{Strings},
  keywordstyle={\color{Keywords}\bfseries},
  alsoletter=0123456789,
  SelectCharTable=
  \lst@DefSaveDef{`0}\lsts@myzero{\lsts@myzero\processdigit}
  \lst@DefSaveDef{`1}\lsts@myone{\lsts@myone\processdigit}
  \lst@DefSaveDef{`2}\lsts@mytwo{\lsts@mytwo\processdigit}
  \lst@DefSaveDef{`3}\lsts@mythree{\lsts@mythree\processdigit}
  \lst@DefSaveDef{`4}\lsts@myfour{\lsts@myfour\processdigit}
  \lst@DefSaveDef{`5}\lsts@myfive{\lsts@myfive\processdigit}
  \lst@DefSaveDef{`6}\lsts@mysix{\lsts@mysix\processdigit}
  \lst@DefSaveDef{`7}\lsts@myseven{\lsts@myseven\processdigit}
  \lst@DefSaveDef{`8}\lsts@myeight{\lsts@myeight\processdigit}
  \lst@DefSaveDef{`9}\lsts@mynine{\lsts@mynine\processdigit}
  \lst@DefSaveDef{`a}\lsts@mya{\lsts@mya\processletter}
  \lst@DefSaveDef{`b}\lsts@myb{\lsts@myb\processletter}
  \lst@DefSaveDef{`c}\lsts@myc{\lsts@myc\processletter}
  \lst@DefSaveDef{`d}\lsts@myd{\lsts@myd\processletter}
  \lst@DefSaveDef{`e}\lsts@mye{\lsts@mye\processletter}
  \lst@DefSaveDef{`f}\lsts@myf{\lsts@myf\processletter}
  \lst@DefSaveDef{`g}\lsts@myg{\lsts@myg\processletter}
  \lst@DefSaveDef{`h}\lsts@myh{\lsts@myh\processletter}
  \lst@DefSaveDef{`i}\lsts@myi{\lsts@myi\processletter}
  \lst@DefSaveDef{`j}\lsts@myj{\lsts@myj\processletter}
  \lst@DefSaveDef{`k}\lsts@myk{\lsts@myk\processletter}
  \lst@DefSaveDef{`l}\lsts@myl{\lsts@myl\processletter}
  \lst@DefSaveDef{`m}\lsts@mym{\lsts@mym\processletter}
  \lst@DefSaveDef{`n}\lsts@myn{\lsts@myn\processletter}
  \lst@DefSaveDef{`o}\lsts@myo{\lsts@myo\processletter}
  \lst@DefSaveDef{`p}\lsts@myp{\lsts@myp\processletter}
  \lst@DefSaveDef{`q}\lsts@myq{\lsts@myq\processletter}
  \lst@DefSaveDef{`r}\lsts@myr{\lsts@myr\processletter}
  \lst@DefSaveDef{`s}\lsts@mys{\lsts@mys\processletter}
  \lst@DefSaveDef{`t}\lsts@myt{\lsts@myt\processletter}
  \lst@DefSaveDef{`u}\lsts@myu{\lsts@myu\processletter}
  \lst@DefSaveDef{`v}\lsts@myv{\lsts@myv\processletter}
  \lst@DefSaveDef{`w}\lsts@myw{\lsts@myw\processletter}
  \lst@DefSaveDef{`x}\lsts@myx{\lsts@myx\processletter}
  \lst@DefSaveDef{`y}\lsts@myy{\lsts@myy\processletter}
  \lst@DefSaveDef{`z}\lsts@myz{\lsts@myz\processletter}
  \lst@DefSaveDef{`A}\lsts@myA{\lsts@myA\processletter}
  \lst@DefSaveDef{`B}\lsts@myB{\lsts@myB\processletter}
  \lst@DefSaveDef{`C}\lsts@myC{\lsts@myC\processletter}
  \lst@DefSaveDef{`D}\lsts@myD{\lsts@myD\processletter}
  \lst@DefSaveDef{`E}\lsts@myE{\lsts@myE\processletter}
  \lst@DefSaveDef{`F}\lsts@myF{\lsts@myF\processletter}
  \lst@DefSaveDef{`G}\lsts@myG{\lsts@myG\processletter}
  \lst@DefSaveDef{`H}\lsts@myH{\lsts@myH\processletter}
  \lst@DefSaveDef{`I}\lsts@myI{\lsts@myI\processletter}
  \lst@DefSaveDef{`J}\lsts@myJ{\lsts@myJ\processletter}
  \lst@DefSaveDef{`K}\lsts@myK{\lsts@myK\processletter}
  \lst@DefSaveDef{`L}\lsts@myL{\lsts@myL\processletter}
  \lst@DefSaveDef{`M}\lsts@myM{\lsts@myM\processletter}
  \lst@DefSaveDef{`N}\lsts@myN{\lsts@myN\processletter}
  \lst@DefSaveDef{`O}\lsts@myO{\lsts@myO\processletter}
  \lst@DefSaveDef{`P}\lsts@myP{\lsts@myP\processletter}
  \lst@DefSaveDef{`Q}\lsts@myQ{\lsts@myQ\processletter}
  \lst@DefSaveDef{`R}\lsts@myR{\lsts@myR\processletter}
  \lst@DefSaveDef{`S}\lsts@myS{\lsts@myS\processletter}
  \lst@DefSaveDef{`T}\lsts@myT{\lsts@myT\processletter}
  \lst@DefSaveDef{`U}\lsts@myU{\lsts@myU\processletter}
  \lst@DefSaveDef{`V}\lsts@myV{\lsts@myV\processletter}
  \lst@DefSaveDef{`W}\lsts@myW{\lsts@myW\processletter}
  \lst@DefSaveDef{`X}\lsts@myX{\lsts@myX\processletter}
  \lst@DefSaveDef{`Y}\lsts@myY{\lsts@myY\processletter}
  \lst@DefSaveDef{`Z}\lsts@myZ{\lsts@myZ\processletter}
}

\makeatother

\begin{document}

\begin{lstlisting}[style=mycode]
int main ()
{
    printf("foo 3a a3")
    //this is an example
    a1 = 0;
    a2 = a1;
    a3 = 16hxFF;
    a4 = 16 + a1;
    // sanity check
    a5 =+ 16hFF /* 16hFF is not highlighted because it's not
                   immediately preceded by an equal sign */
    return 0;
}
\end{lstlisting}

\end{document}

相关内容