[Tex/LaTex] Listings: color numbers only out of keywords

colorlistings

With the listings package, I would like to color the integers out of strings and comments and out of keywords too. The question for coloring numbers has been asked several times. Some answer handle the numbers occurring within comments, strings or barewords, but no solution given work when a keyword contain a number. Which is annoying because C and C++ have a lot of types with a number in them, like uint32_t.

Here is a small example.

\documentclass{standalone}
\usepackage{xcolor}
\usepackage{listings}

\definecolor{darkgreen}{rgb}{0.18,0.54,0.34}
\definecolor{maroon}{rgb}{0.64,0.16,0.16}
\definecolor{darkpink}{rgb}{0.75,0.25,0.5}

\lstdefinestyle{myc++}{
    language=[ISO]C++,
    keywordstyle=\color{darkgreen}\bfseries,
    commentstyle=\color{blue}\textit,
    stringstyle=\color{darkpink}\ttfamily,
%
    literate=*
    {0}{{{\textcolor{red}0}}}1
    {1}{{{\textcolor{red}1}}}1
    {2}{{{\textcolor{red}2}}}1
    {3}{{{\textcolor{red}3}}}1
    {4}{{{\textcolor{red}4}}}1
    {5}{{{\textcolor{red}5}}}1
    {6}{{{\textcolor{red}6}}}1
    {7}{{{\textcolor{red}7}}}1
    {8}{{{\textcolor{red}8}}}1
    {9}{{{\textcolor{red}9}}}1,
    escapeinside={|}{|},
%
    morekeywords={int32_t}
}

\begin{document}

\begin{lstlisting}[style=myc++]
// In comment: 42
int32_t in_keyword = 80085;
char *in_identifier|2| = "And in string 1337\n";
\end{lstlisting}

\end{document}

And the result:

LaTeX result.

The star for literate avoid to coloring the digits inside comments or strings. The escapeinside avoid coloring the digits inside a bareword when specifically marked. But I have yet to find how to color int32_t as a keyword.

Best Answer

I know that the question is nearly three years old now, but I am dealing with the same problem at the moment. I have searched the internet and the same or closley related questions have been asked a lot of times without 100% satisfying answers to me because I am looking for a solution like the one that was desired here. As I have found one which is not perfect, but quite good, I want to share it in case someone else comes across here. But generally I would agree with @Jubobs, it's really a pain in the neck doing this in listings.

So basically what I did is I colored everything with the color I want to have for the numbers using the basicstyle attribute. Then I colored the keywords, comments and strings as usal using the keywordstyle, commentsytle and stringstlye attributes. Now the trick is to use the identifierstyle to color all variable names in the actual basic color. What is left concerning the basic style then is all digits as well as all operators, brakets and so on like ( + - * ... After that you obviously only have to color the operators, and breakets and so on with the basic color to get your result. This can be done with the literate attribute.

I will add a few lines of code from my Julia style that I am creating right now to illustrate what I mean. Notice that in my case I wanted to color the numbers with the same color as the strings, but you can obiously simply create a new one for that job.

% julia language definition

\lstdefinelanguage{julia}{%
morekeywords=[1]{end,export,finally},%
morekeywords=[2]{true,false,ARGS},%
morekeywords=[3]{ANY,AbstractArray,AbstractChannel},%
morecomment=[l]{\#},%
morecomment=[n]{\#=}{=\#},%
morestring=[b]{"},%
morestring=[m]{'},%
}[keywords,comments,strings]



% defining the colors for
\definecolor{jlbase}{HTML}{444444}                       % julia's base color
\definecolor{jlkeyword}{HTML}{444444}                    % julia's keywords
\definecolor{jlliteral}{HTML}{78A960}                    % julia's literals
\definecolor{jlbuiltin}{HTML}{397300}                    % julia's built-ins
\definecolor{jlcomment}{HTML}{888888}                    % julia's comments
\definecolor{jlstring}{HTML}{880000}                     % julia's strings



% basic font
\def\lstbasicfont{\color{jlstring}\fontfamily{pcr}\selectfont\scriptsize}

% defining the styles for
\lstset{keywordstyle={[1]\color{jlkeyword}\bfseries}}    % julia's keywords
\lstset{keywordstyle={[2]\color{jlliteral}}}             % julia's literals
\lstset{keywordstyle={[3]\color{jlbuiltin}}}             % julia's built-ins
\lstset{commentstyle={\color{jlcomment}}}                % julia's comments
\lstset{stringstyle={\color{jlstring}}}                  % julia's strings
\lstset{identifierstyle={\color{jlbase}}}        % variables


% coloring the operators with the basecolor
% and . in floating point numbers with the desired number color
\lstset{extendedchars=false}
\lstset{literate=*
{\\}{{{\color{jlbase}\textbackslash{}}}}{1} {\{}{{{\color{jlbase}\{}}}{1} {\}}{{{\color{jlbase}\}}}}{1}
{!}{{{\color{jlbase}!}}}{1} {\%}{{{\color{jlbase}\%}}}{1} {&}{{{\color{jlbase}\&}}}{1}
{(}{{{\color{jlbase}(}}}{1} {)}{{{\color{jlbase})}}}{1} {*}{{{\color{jlbase}*}}}{1}
{+}{{{\color{jlbase}+}}}{1} {,}{{{\color{jlbase},}}}{1} {-}{{{\color{jlbase}-}}}{1}
{.}{{{\color{jlbase}.}}}{1} {/}{{{\color{jlbase}/}}}{1} {:}{{{\color{jlbase}:}}}{1}
{;}{{{\color{jlbase};}}}{1} {<}{{{\color{jlbase}<}}}{1} {=}{{{\color{jlbase}=}}}{1}
{>}{{{\color{jlbase}>}}}{1} {?}{{{\color{jlbase}?}}}{1} {[}{{{\color{jlbase}[}}}{1}
{]}{{{\color{jlbase}]}}}{1} {^}{{{\color{jlbase}\^{}}}}{1} {|}{{{\color{jlbase}|}}}{1}
{~}{{{\color{jlbase}\textasciitilde{}}}}{1}
{.0}{{{\color{jlstring}.0}}}{2} {.1}{{{\color{jlstring}.1}}}{2} {.2}{{{\color{jlstring}.2}}}{2}
{.3}{{{\color{jlstring}.3}}}{2} {.4}{{{\color{jlstring}.4}}}{2} {.5}{{{\color{jlstring}.5}}}{2}
{.6}{{{\color{jlstring}.6}}}{2} {.7}{{{\color{jlstring}.7}}}{2} {.8}{{{\color{jlstring}.8}}}{2}
{.9}{{{\color{jlstring}.9}}}{2}}



% activating the julia style
\lstset{language=julia}

Ok, I guess this is what you consider a MWE:

\documentclass{standalone}
\usepackage{xcolor}
\usepackage{listings}

\definecolor{darkgreen}{rgb}{0.18,0.54,0.34}
\definecolor{maroon}{rgb}{0.64,0.16,0.16}
\definecolor{darkpink}{rgb}{0.75,0.25,0.5}

\lstdefinestyle{myc++}{
    language=[ISO]C++,
    keywordstyle=\color{darkgreen}\bfseries,
    commentstyle=\color{blue}\textit,
    stringstyle=\color{darkpink}\ttfamily,
    basicstyle={\color{red}},
    identifierstyle={\color{black}}, 
%
    literate=*
    {*}{{{\color{black}*}}}{1}
    {=}{{{\color{black}=}}}{1}
    {;}{{{\color{black};}}}{1}
    {.7}{{{\color{red}.7}}}{2},%
%
morekeywords={int32_t}
}

\begin{document}

\begin{lstlisting}[style=myc++]
// In comment: 42
int32_t in_keyword = 80085.7;
char *in_identifier2 = "And in string 1337\n";
\end{lstlisting}

\end{document}

The result looks like:enter image description here

Note that with the approach you dont even need to escape the 2 in in_identifier2.