[Tex/LaTex] How to highlight all identifiers starting by ‘@’

highlightinglistings

I would like to highlight any expression made of letters and that starts with one @. The use of moredelim=*[s][\color{blue}]{@}{\ } works only in case like @name is followed by one space. The following code nearly works except that I do not want the parenthesis to be colored in case like @decorator(x=3, y='some text') because that is @decorator( which is caught.

moredelim=[s][\bfseries\color{gray}]{@}{\ },
moredelim=[s][\bfseries\color{gray}]{@}{(},

The use of moredelim=[s][\bfseries\color{gray}]{@}{(} is not a good solution because the search is done on several lines… 🙁

Best Answer

I followed the same approach as in my answer to Can the listings package highlight by regexp?.

enter image description here

\documentclass{article}

\usepackage{xcolor}
\usepackage{listings}

\makeatletter

% ``state variables''
\newif\ifincomment\incommentfalse
\newif\ifinstring\instringfalse

% language and style definition
\lstdefinestyle{mybash}
{%
  language = bash,
  basicstyle   = \ttfamily,
  keywordstyle = \color{blue},
}[keywords,strings,comments]

% --- patch to automatically highlight identifier starting by @
% (only outside strings and comments, though) ---
\lst@AddToHook{Output}{\@ddedToOutput}
\lst@AddToHook{Endgroup}{\incommentfalse\instringfalse}

% local variables
\newif\if@identifierStartsByAt@
\newcount\currentchar

\def\splitfirstchar#1{\@splitfirstchar#1\@nil}
\def\@splitfirstchar#1#2\@nil{\gdef\@testChar{#1}}

\def\@testChar%
{%
  % copy the first token in \the\lst@token to \@testChar
  \expandafter\splitfirstchar\expandafter{\the\lst@token}%
  %
  % reset switch
  \@identifierStartsByAt@false
  %
  % equality test
  \expandafter\ifnum\expandafter`\@testChar=`@%
    \@identifierStartsByAt@true % if equality, set switch to true
  \fi
  %
  % apply class style if not within string or comment
  \if@identifierStartsByAt@
    \ifincomment
  \else
    \ifinstring
      \else
        \def\lst@thestyle{\lst@keywordstyle}%
      \fi
    \fi
  \fi
}
\let\@ddedToOutput\@testChar
\makeatother

\begin{document}
\begin{lstlisting}[style=mybash]{text.txt}
# This is an example
@Blueword(foo) @Blueword bar
\end{lstlisting}
\end{document}