[Tex/LaTex] Inconsistent output for R language operators when using listings package

listingsr

A referee noticed that the <<- (assignment to a global) and %*% (matrix mult.) operators in a code listing I used were wrong.

I am using the standard listings package (version 1.4 dated 2007/02/22, from texlive 20120611 on Ubuntu 12.10). An example is below. In both cases the second use of < or % seems to use the correct font, the first one does not.

These operators are defined (in file lstlang3.sty) as

otherkeywords={!,!=,~,$,*,\&,\%/\%,\%*\%,\%\%,<-,<<-,_,/},%

In this short example, I even define a simple custom language definition. By defining %*% as an otherkeyword I have half the problem solved — but I cannot fix <<- and <- at the same time: once <- is added it match inside of <<-. This seems like a bug. Any TeXwizards who can chase it?

Code:

\documentclass[12pt]{article}
\usepackage{listings}           
\lstdefinelanguage{customR}{    % defined a new R entry
  keywords={t},
  otherkeywords={<<-,\%*\%},    %% cannot add <-
  keywordstyle=\bfseries
}
\lstdefinelanguage{customRtwo}{
  otherkeywords={<-,<<-,\%*\%},  %% cannot add <-
  keywordstyle=\bfseries
}

\begin{document} 

\lstset{language=R,caption={Standard R}}
\begin{lstlisting}[frame=tb]
    S <- H %*% t(pprd) %*% t(H) + R
    xest <<- xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\lstset{language=customR,caption={Custom R}}
\begin{lstlisting}[frame=tb]
    S <- H %*% t(pprd) %*% t(H) + R
    xest <<- xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\lstset{language=customRtwo,caption={Custom R (alt.)}}
\begin{lstlisting}[frame=tb]
    S <- H %*% t(pprd) %*% t(H) + R
    xest <<- xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\end{document}

Output (rendered to png here)

enter image description here

In summary:

  • In the default, both <<- and %*% are wrong
  • I managed to fix <<- and %*% but …
  • … I cannot seem to fix <<- and <-

Any help would be greatly appreciated.

Edit: The closing } is of course spurious, I initially had a longer example and forgot to remove those.

Best Answer

A possible manual approach is with the use of moredelim=**[is][\bfseries]{@}{@},

Can I also suggest a style? Below I have defined \lstdefinelanguage customRthree in conjunction with package courier. You can also try beramono. See for instance, Latex listings R: need mono-spaced font with bold keywords and correct caret (^).

\lstdefinelanguage{customRthree}{
    keywords={t},
    otherkeywords={<<-,\%*\%},    %% cannot add <-
    keywordstyle=\bfseries,
    moredelim=**[is][\bfseries]{@}{@}, % every character inside @ @ will be in bold face
    basicstyle=\ttfamily,
    commentstyle=\textsl,
}

Code

\documentclass[preview,border=5,convert]{standalone}

\usepackage{courier}

\usepackage{listings}           
\lstdefinelanguage{customR}{    % defined a new R entry
  keywords={t},
  otherkeywords={<<-,\%*\%},    %% cannot add <-
  keywordstyle=\bfseries,
  moredelim=**[is][\bfseries]{@}{@},
}
\lstdefinelanguage{customRtwo}{
  otherkeywords={<-,<<-,\%*\%},  %% cannot add <-
  keywordstyle=\bfseries,
  moredelim=**[is][\bfseries]{@}{@},
}

\lstdefinelanguage{customRthree}{
    keywords={t,R},
    otherkeywords={<<-,\%*\%},    %% cannot add <-
    keywordstyle=\bfseries,
    moredelim=**[is][\bfseries]{@}{@},
    basicstyle=\ttfamily,
    commentstyle=\textsl,
}

\begin{document} 

\lstset{language=R,caption={Standard R}}
\begin{lstlisting}[frame=tb]
    S <- H %*% t(pprd) %*% t(H) + R
    xest <<- xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\lstset{language=customR,caption={Custom R}}
\begin{lstlisting}[frame=tb]
    S @<-@ H %*% t(pprd) %*% t(H) + R
    xest @<<-@ xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\lstset{language=customRtwo,caption={Custom R (alt.)}}
\begin{lstlisting}[frame=tb]
    S <- H %*% t(pprd) %*% t(H) + R
    xest @<@<- xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\begin{lstlisting}[frame=tb,language=customRthree,caption={Custom R 3}]
    S @<-@ H %*% t(pprd) %*% t(H) + R
    xest @<<-@ xprd + kalmangain %*% (z - H %*% xprd)
}
\end{lstlisting}

\end{document}

Output

enter image description here

Related Question