2

The first answer to this question describes a method for highlighting all identifiers starting with an at sign. I want to do the same thing, just with an underscore instead. I've modified the code given there accordingly

\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]
# This is an example
@Blueword(foo) _Blueword bar
\end{lstlisting}
\end{document}

However, this code gives me the following errors:

! Improper alphabetic constant.
<to be read again> 
                   \lst@um_ 
l.62 @Blueword(foo) _Blueword 
                              bar
? 
! Missing = inserted for \ifnum.
<to be read again> 
                   \char 
l.62 @Blueword(foo) _Blueword 
                              bar
? 
! Missing number, treated as zero.
<to be read again> 
                   \char 
l.62 @Blueword(foo) _Blueword 
                              bar
? 
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] (./t.aux) )
(\end occurred when \ifnum on line 62 was incomplete)
(\end occurred when \iftrue on line 62 was incomplete)
(\end occurred when \ifnum on line 62 was incomplete)
(\end occurred when \iffalse on line 62 was incomplete)
(\end occurred when \ifnum on line 62 was incomplete)
(\end occurred when \iftrue on line 62 was incomplete)
(\end occurred when \ifnum on line 62 was incomplete)
(\end occurred when \iftrue on line 62 was incomplete)
(\end occurred when \ifnum on line 61 was incomplete)
(\end occurred when \iftrue on line 61 was incomplete)
(\end occurred when \ifnum on line 61 was incomplete)
(\end occurred when \iffalse on line 61 was incomplete)
(\end occurred when \ifnum on line 61 was incomplete)
(\end occurred when \iffalse on line 61 was incomplete)
(\end occurred when \ifnum on line 61 was incomplete)
(\end occurred when \iffalse on line 61 was incomplete)
  • Have you tried one of the other solutions? The linked answer doesn't seem to work well even in its original version, at least with the latest listings version. – siracusa Jun 24 at 13:31
  • The other solution requires that a trailing space be included after every number which won't work for the language I'm working with. There is apparently just an issue with interacting with underscores that I can't understand, which is what I'd like an answer to. – Kevin Keith Jun 24 at 13:52
2

Here's another approach that redefines the style for all identifiers, i.e. character sequences starting with a letter, @, $ or _, followed by more of these characters or digits. We set a special identifier style \@identifierstyle which dynamically decides what actual style should be applied for the current identifier.

If the first token of \lst@token equals \lst@um_, the internal macro used to denote _ in listings, we change the style to red color in this example; all other identifiers are typeset in blue color. Note that this hook doesn't interfere with the style for keywords, which are a special type of identifiers in listings (in green color here).

The full example:

\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}

\makeatletter

\lstdefinestyle{mybash}
{%
  language = bash,
  basicstyle   = \ttfamily,
  keywordstyle = \color{green},
  identifierstyle = \@identifierstyle,
}[keywords,strings,comments]

\def\@headtoken#1#2\end{\noexpand#1}

\def\@identifierstyle{%
    \edef\@tempa{\expandafter\@headtoken\the\lst@token\end}%
    \edef\@tempb{\expandafter\noexpand\csname lst@um_\endcsname}%
    \ifx\@tempa\@tempb
        % apply special style for identifies staring with '_'
        \color{red}%
    \else
        % normal identifier style
        \color{blue}%
    \fi
}

\makeatother

\begin{document}
\begin{lstlisting}[style=mybash]
# This is an example for _Blueword
@Blueword(foo) _Blueword bar
'_Blueword in string'
if _cond then __this__ else __that__
\end{lstlisting}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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