Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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}
share|improve this question
2  
    
Thanks for linking those threads. However, neither addresses the issue of coloring numbers only after the equals sign. I've tried the solutions in both threads, but they still color numbers that occur to left of the = sign, which is not what I want. –  Lyn Nov 6 '12 at 21:19
    
So just to clarify: you want the entire text of anything that starts with a digit following an equal sign (with possible a leading space) to be colored up until the closing semi-colon. No other digits are to be colored. So, can it be assumed that the "digits" that are to be colored restricted to [a-fA-F0-9h]? Are there other characters that may show up here? –  Peter Grill Nov 6 '12 at 21:35
1  
You shoudl also adjust the text: "if the first digit after the equals sign is a number, all following digits until (but not including) the next semicolon are colored". Also can you provide a list of all the characters that are digits. You example include h. Any other characters? –  Peter Grill Nov 6 '12 at 21:52
1  
There is also an issue with your comment: "...that starts with a digit", and since you include a in this list, then doesn't that mean that the a1 should be colored? I think I know what you mean, but you should review to make sure that you have all the cases properly specd. –  Peter Grill Nov 6 '12 at 21:55
show 1 more comment

2 Answers 2

up vote 8 down vote accepted

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}
share|improve this answer
    
Thank you. This answer works well for my code! –  Lyn Nov 8 '12 at 7:30
add comment

Review of Peter Grill's approach

Peter's approach has its merits, but suffers from three limitations.

  1. Any non-digit within a number breaks the highlighting of this number (as reported by Peter).
  2. Numbers get partially highlighted within strings, which seems to be a bug; I guess numbers shouldn't be highlighted at all in strings.
  3. listings is unable to recognise (and properly highlight) an identifier if the latter contains any character subject to a literate replacement. Here, for instance, return is not recognised as a keyword (and therefore not highlighted in red) because it contains the character e, which is subject to a literate replacement.

Peter-Grill-approach

An alternative approach

Here is a similar but more robust approach, which remedies all three of the limitations discussed above. The only obvious problem is code duplication. Edit: see egreg's answer for a much leaner approach!

enter image description here

\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{`k}\lsts@myl{\lsts@myl\processletter}
  \lst@DefSaveDef{`k}\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@myN\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}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.