[Tex/LaTex] Problem highlighting listings in beamer

beamerlistings

I'm using listings inside beamer to typeset some Octave code. Because I want to apply overlay specifications to parts of the listing as I go through the slides (for highlighting purposes), I'm applying the method laid out in How to make overlay still work inside lstlisting environment?

However, I've noticed that the overlay doesn't apply to one-line comments at the end of a line of normal code. If I place the delimiter on the next line, it works, but it yields an undesired extra space, and using emptylines=1 does not rid me of the latter.

enter image description here

Is there a way to also highlight the comments that are on the same line as normal code?

Heree is a MWE:

\documentclass[dvipsnames,cmyk]{beamer}

\usepackage{arev}
\usepackage{listings}

% remove navigation symbols 
\setbeamertemplate{navigation symbols}{}

\lstdefinestyle{highlight}{
  keywordstyle=\color{red},
  commentstyle=\color{green},
}

\lstdefinestyle{base}{
language=Octave,
emptylines=1,
breaklines=true,
basicstyle=\tiny\ttfamily\color{black!40},
keywordstyle=\color{red!40},
commentstyle=\color{green!40},
moredelim=**[is][\only<+>{\color{black}\lstset{style=highlight}}]{@}{@},
}

\begin{document}

\begin{frame}[fragile]%{Listings overlay}
\begin{lstlisting}[style=base, gobble=0]
@% This comment will be highlighted; it is also bigger than the frame size so it is expected that line is breaked into at least two. Note that unwanted empty line may be generated
@

@a = 2@ % aaa
@b = 1 % aaa @
@c = 1 % aaa @
@c = 1 % aaa
@

\end{lstlisting}
\end{frame}

\end{document}

As you can see, comments in code (a=… % comment) is not highlighted. How can I do it, without generating extra lines (@ in next line)?

Best Answer

Better late than never :)

As stated by Qrrbrbirlbel in his comment, the problem is that, because % is a (one-line) comment delimiter in the Octave language, listings treats your closing overlay delimiter @ as part of the comment.

One workaround is to undefine % as a comment delimiter, but use literate to apply the comment style when that character is encountered anyway. You also need to reset the style at the beginning of each line.

enter image description here

Two caveats of this approach:

  • any % character that occurs within a string literal will mess up the highlighting,
  • keywords get highlighted even in comments.

\documentclass[dvipsnames,cmyk]{beamer}

\usepackage{arev}
\usepackage{listings}

% remove navigation symbols 
\setbeamertemplate{navigation symbols}{}

\lstdefinestyle{highlight}{
  keywordstyle=\color{red},
  commentstyle=\color{green},
}

\makeatletter

\lstdefinestyle{base}{
    language      = Octave,
    emptylines    = 1,
    breaklines    = true,
    basicstyle    = \tiny\ttfamily\color{black!40},
    keywordstyle  = \color{red!40},
    commentstyle  =\color{green!40},
    moredelim     = **[is][\only<+>{\color{black}\lstset{style=highlight}}]{@}{@},
    %
    % Undefine % as a comment delimiter, but still apply comment style when it's encountered.
    deletecomment =[l]\%,
    literate      ={\%}{{\lst@commentstyle\%}}1,
}

% Reset the style at the beginning of every ``true'' line
\lst@AddToHook{EveryPar}{\lst@basicstyle}

\makeatother

\begin{document}
\begin{frame}[fragile]%{Listings overlay}

\begin{lstlisting}[style=base, gobble=0]
@% This comment will be highlighted; it is also bigger than the frame size so it is expected that line is breaked into at least two. Note that unwanted empty line may be generated
@

@a = 2@ % aaa
@b = 1 % aaa @
@c = 1 % aaa @
@d = 1 % aaa @

\end{lstlisting}

\end{frame}
\end{document}
Related Question