listings: how to colorize strings between angle brackets

I'd like to colorize the names of header files included in angle brackets (<>) in my C examples formatted by the listings package. In the MWE I'd like <brackets.h> to be orange too like "quotes.h". I don't want to do that manually with escapes in every listing but globally. I have tried various crude things including the use of keywordcommentsemicolon (which did not work at all because it is an undefined key although it is mentioned in the documentation... does it need to be enabled?). The most promising results were achieved by using morecomment=[s]{<}{>}. However, that would colorize everything following a <... which is not that uncommon in C ;) The solution should work independently from the documentclass, especially beamer should work, and preferably work with common listings options (i.e., not change the behavior of other formatting options such as identifierstyle.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{xcolor}
\definecolor{darkorange}{HTML}{C87B0F}

\usepackage{listings}
\lstset{language=C,captionpos=b}

\lstset{%
stringstyle=\color{darkorange},
identifierstyle={\color{blue}}.
}

\begin{document}

\begin{lstlisting}[gobble=4]
#include <stdlib.h>
#include "quotes.h"

int main(int argc, char **argv) {

if (argc <= 3)
return 0 > **argv;
return EXIT_SUCCESS;
}
\end{lstlisting}

\end{document}


Note: I'm making the assumption that the only angle-bracket strings you want colored are those that appear in lines containing a #. If there are other cases, I think my answer can be adapted.

(The code is below. You can skip the explanations if you like.)

You can't tell listings which of the strings starting with < should be colored and which shouldn't. But you can circumvent that using basic conditionals.

You started in the right direction. Let's use a delimiter on <>:

moredelim=[s][\coloroncondition]<>


with \coloroncondition a custom macro giving a new color depending on a custom condition \ifcoloranglebrackets:

\newcommand\coloroncondition{\ifcoloranglebrackets\color{darkorange}\fi}


If we assume we want to color brackets in lines containing a #, then we can set the condition to true in these particular lines thanks to a delimiter on #:

moredelim=**[l][\coloranglebracketstrue]\#


The ** makes listings cumulate the "style" of that delimiter and any delimiter inside, thus the style for angle-bracket strings whithin lines containing a # will be {\coloranglebracketstrue\coloroncondition} (which will be ultimately sort of expanded to \color{darkorange}), while the style for any other angle-bracket string will be {\coloroncondition} (which will be expanded to nothing).

Working example

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{xcolor}
\definecolor{darkorange}{HTML}{C87B0F}

\usepackage{listings}
\lstset{language=C,captionpos=b}

\newif\ifcoloranglebrackets
\coloranglebracketsfalse
\newcommand\coloroncondition{\ifcoloranglebrackets\color{darkorange}\fi}

\lstset{%
stringstyle=\color{darkorange},
moredelim=**[directive][\coloranglebracketstrue]\#,
moredelim=**[s][\coloroncondition]<>
}

\begin{document}

\begin{lstlisting}[gobble=4]
#include <brackets.h>
#include "quotes.h"
std::cout<<text
if a < b ...
\end{lstlisting}

\end{document}


Output:

About the directive option

I replaced l by directive when matching the # delimiter. That option is not clearly documented, but I found it in listings source code. Apparently, LaTeX uses it to emphasize keywords starting with a # in C (#include, etc.). l can be used instead, but that would erase the default behavior on such keywords (which is, in this case, to put them in bold font).

• Absolutely awesome, thank you! I'll forward a link to the current maintainer... maybe he wanna do something about the formatting itself or the documentation of directive – stefanct Jan 22 '18 at 13:21
• However, the solution quickly breaks in most real-world cases where an identifier style is used, e.g., identifierstyle={\color{blue}} (at least with the texlive version I am using right now. The first < stops highlighting of identifiers. :( – stefanct Jul 31 '18 at 18:25
• @stefanct You're right, I didn't take identifierstyle into consideration. I can't find a fix right now. I suggest you to either 1- un-accept my answer and edit your question with a MWE that includes identifierstyle, or 2- ask a (separate) follow-up question, linking to this one for context. It's up to you ;-) – SDF Jul 31 '18 at 20:15
• edited since I don't think a new question makes sense. i would have left the accepted flag as well but then nobody but you would look at the question. – stefanct Aug 1 '18 at 14:30