7

In my \lstset{...} I have morecomment=[l][{\color[rgb]{0.1, 0.2, 0.8}}]{\#}, which I've seen used to give preprocessor commands colour. This works just fine but I'd like to get multi-line macros to be highlighted too, for example:

\begin{lstlisting}
#define MAX(a, b) \
    ((a)>(b)?(a):(b))
\end{lstlisting}

What's a good way to get listings to match multi-line macros?

[EDIT]
very well, here's a complete example with \documentclass etc... :P

\documentclass{article}
\usepackage{color}
\usepackage{listings}
\lstset{language=C,
    morecomment=[l][{\color[rgb]{0.1, 0.2, 0.8}}]{\#}
    }
\begin{document}
\begin{lstlisting}
#define MAX(a, b) \
    ((a)>(b)?(a):(b))
\end{lstlisting}
\end{document}

I'd like the second line of the macro to be blue too, based on a rule relating to the \.

enter image description here

4
  • Please add a minimal working example (MWE) that illustrates your problem. It will be much easier for us to reproduce your situation and find out what the issue is when we see compilable code, starting with \documentclass{...} and ending with \end{document}. Side-question: can you actually do line continuation with a backslash in C? Not to my knowledge...
    – jub0bs
    Feb 14 '14 at 9:35
  • @Jubobs done. not in C exactly, but most compilers provide a C preprocessor in which macros may escape newlines with a `\`. It's just a readability thing afaik.
    – jozxyqk
    Feb 14 '14 at 10:01
  • @Jubobs apologies for the delay. I wanted to give code a try first. Thanks for your time!
    – jozxyqk
    Mar 17 '14 at 9:58
  • No bother. Glad I was able to answer.
    – jub0bs
    Mar 17 '14 at 10:07
4

The listings package doesn't directly provide the means of highlighting a compiler directive that is continued over multiple lines. If you think that's a desirable feature, you might want to get in touch with the maintainer.

In the meantime, here is a possible implementation. It uses two switches with self-explanatory names to keep track of the context and patches listings in order to check, right before anything gets printed, whether we're still in a compiler directive; if so, the directive style is applied.

enter image description here

\documentclass{article}

\usepackage{etoolbox}
\usepackage{xcolor}
\usepackage{listings}

\lstloadaspects{directives}

% ---------- Beginning of ugly internals ----------
\makeatletter

% switches to keep track of context
\newif\if@LastCharWasBackslash
\newif\if@DirectiveContinued

% --- hooking into listings ---
\lst@AddToHook{OutputOther}%
{% 
  \ifx\lst@lastother\lstum@backslash%   % if the last character in
                                        % \the\lst@token is a backslash...
    \global\@LastCharWasBackslashtrue%
  \else
    \global\@LastCharWasBackslashfalse%
  \fi  
  \@condApplyDirectiveStyle             % Apply directive style if needed
}
\lst@AddToHook{Output}%
{%
  \global\@LastCharWasBackslashfalse%   % Reset switch
  \@condApplyDirectiveStyle%            % Apply directive style if needed 
}

% `listings' automatically exits CDmode at the EOL hook;
% we patch \lsthk@EOL so that it checks whether a compiler directive
% is continued on the next line and set the relevant switch accordingly.
\patchcmd{\lsthk@EOL}
  {\ifnum\lst@mode=\lst@CDmode \lst@LeaveMode \fi}
    {%
      \global\@DirectiveContinuedfalse%
      \ifnum\lst@mode=\lst@CDmode%
        \lst@LeaveMode
    \else
        \if@LastCharWasBackslash%
          \global\@DirectiveContinuedtrue%
        \fi
      \fi
    }
    {}{\@latex@error{\string\lsthk@EOL\space patch failed!}{}}

% --- two helper macros ---
\newcommand\@condApplyDirectiveStyle
{%
  \ifnum\lst@mode=\lst@CDmode%
    \@applyDirectiveStyle%
  \fi
  \if@DirectiveContinued%
    \@applyDirectiveStyle%
  \fi  
}

\newcommand\@applyDirectiveStyle{\let\lst@thestyle\lst@directivestyle}

\makeatother

% ---------- End of ugly internals ----------

\lstset
{
  language       = C,
  directivestyle = \color{blue},
}

\begin{document}
\begin{lstlisting}
#define MAX(a, b) \   
  ((a)>(b)?(a):(b))
#define \
  bar \
  baz
foo \ bar
baz
\end{lstlisting}
\end{document}
0

Not an answer, but a workaround...

\documentclass{article}
\usepackage{color}
\usepackage{listings}
\lstset{language=C,
    morecomment=[l][{\color[rgb]{0.1, 0.2, 0.8}}]{\#},
    moredelim=[il][{\color[rgb]{0.1, 0.2, 0.8}}]{@},
    }
\begin{document}
\begin{lstlisting}
#define MAX(a, b) \
@   ((a)>(b)?(a):(b))
\end{lstlisting}
\end{document}

Not sure if this is the right way to colour arbitrary lines, but the moredelim option with i hides the @ character in the macro and colours the rest of the line just like morecomment.

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.