[Tex/LaTex] How to highlight all words of the form [0-9][A-Za-z0-9]* immediately following an equal sign

colorlistings

I am using the Latex Listings package to include code in a document. I need to implemented syntax highlighting similar to what you see in a standard IDE.

I've been able to assign colors to comments, keywords, and strings, but I am having some trouble figuring out how to color the numbers properly.

Here's an example of how it should look:

required output

As you can see, anytime a word after the equals sign starts with a digit, all following characters until (but not including) the next semicolon or space are colored. When a word starts with a digit, all characters in the word should be colored, even if they are not digits. Otherwise, none of the digits are colored.

As of right now, I cannot think of a case where a word before the equals sign would start with a digit, so it will probably be acceptable to find a solution that colors all words starting with a digit.

In this case, digits are: 0-9.

Here's an MWE in Latex, but as you can see it doesn't have any coloring for the numbers.

enter image description here

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

Best Answer

Here is an adaptation of Coloring digits with the listings package:

enter image description here

Notes:

  • I have used newtoggle from the etoolbox package as I prefer that syntax versus the \newif syntax. But if you don't want to include an additional package it should be pretty straightforward to adapt this to use \newif or some other conditional methods.

Further Enhancements:

  • This does not work if there is a non-digit within a number. So 16hxFF will not be properly displayed, but 16x (with trailing space) is fine.

Code:

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