1

I'm using the listings package to typeset some Haskell and Scala code in my document, and I've defined a simple style named ttt. I set comments to be displayed in red for contrast, but the problem remains even for simpler styles that don't involve colors.

Whether I use Scala or Haskell in the lstlistings environment does not matter. I get the same problem anyway, which is that if a comment contains specific operators of the corresponding language, then the comment style does not apply to them. For (a kinda minimal) example, suppose I want to comment whole lines of code, as below (nonsensical code, for illustration).

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

\lstloadlanguages{Scala, Haskell}
\lstdefinestyle{ttt}
               {basicstyle=\ttfamily,
               columns=flexible,
               commentstyle=\color{red},
               frame=single}

\begin{document}    
    \begin{lstlisting}[style=ttt, language=Scala, caption=Scala]
      // def addone : Int => Int = x => x + 1
      val z = 1       // def f[a](x:a) : a = g[a](x)
      // val v2 = g[Int](z)
    \end{lstlisting}

    \begin{lstlisting}[style=ttt, language=Haskell, caption=Haskell]
    -- addone :: Eq a => a -> Bool
    -- addone x = x + 1
    \end{lstlisting}
\end{document}

The above is typeset like this:

result

The = and => symbols are special operators in Haskell and Scala.

What I expect (and want to achieve) is that in Listing 1, lines 1 and 3 should be entirely red and in line 2 everything should be red after the // comment delimiter. Similarly, in Listing 2, line 1 should also be entirely red.

Have I hit a bug? Is there a solution?

2
  • As always on the site you are much more likely to get any help if you provide small complete self contained examples instead of sniplets like this. The small examples can be copied and testes as is. Here for sniplets we have to add document class, preamble etc.
    – daleif
    Feb 24 at 14:04
  • 1
    @daleif Thanks for the advice! I'll edit my question.
    – frabala
    Feb 24 at 14:05
1

The issue seems to be that => and = are defined as otherkeyword in the Scala and Haskell definitions, and these are processed even when the keyword is in comments. This seems to be a bug.

As a workaround you can use the system of hooks that listings provides. There are a number of hooks to execute code in specific circumstances. A list can be found in the Developer's Guide on page 69. One of the hooks is AfterBeginComment which is executed at the start of a comment. You can use this hook to set the text color to red. This seems redundant if the comment color is already red, but the color specification in this hook sets the general color (as opposed to the comment color specifically). The color is reset automatically at the end of a comment.

The command to set the hook \lst@AddToHook contains an @ sign, therefore the call must be surrounded by \makeatletter and \makeatother.

MWE:

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

\lstloadlanguages{Scala, Haskell}
\lstdefinestyle{ttt}
               {basicstyle=\ttfamily,
               columns=flexible,
               commentstyle=\color{red},
               frame=single}

\makeatletter
\lst@AddToHook{AfterBeginComment}{\color{red}}
\makeatother

\begin{document}    
    \begin{lstlisting}[style=ttt, language=Scala, caption=Scala]
      // def addone : Int => Int = x => x + 1
      val z = 1       // def f[a](x:a) : a = g[a](x)
      // val v2 = g[Int](z)
    \end{lstlisting}

    \begin{lstlisting}[style=ttt, language=Haskell, caption=Haskell]
    -- addone :: Eq a => a -> Bool
    -- addone x = x + 1
    \end{lstlisting}
\end{document}

Result:

enter image description here

0

With my little knowledge I've found a patchy solution that requires modifying the code written within the lstlisting environments. This solution uses the literate option of the package. It would be nice to see a cleaner solution, though, that does not require modifications in the code. The behaviour I describe in the question still feels like a bug.

Instead of using the problematic = and => symbols in the comments, I use c=c and c=>c, respectively, and then use literate to translate them to their normal counterparts.

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

\lstloadlanguages{Scala, Haskell}
\lstdefinestyle{ttt}
               {basicstyle=\ttfamily,
               %columns=flexible,
               commentstyle=\color{red},
               frame=single,
               literate={c=c}{=}1 {c=>c}{=>}2}

\begin{document}

    \begin{lstlisting}[style=ttt, language=Scala, caption=Scala]
      // def addone : Int => Int c=c x c=>c x + 1
      val z = 1       // def f[a](x:a) : a c=c g[a](x)
      // val v2 = g[Int](z)
    \end{lstlisting}

    \begin{lstlisting}[style=ttt, language=Haskell, caption=Haskell]
    -- addone :: Eq a c=>c a -> Bool
    -- addone x = x + 1
    \end{lstlisting}

\end{document}

Unfortunately, if columns=flexible is specified, spacing will be incorrect in the printed code, but patchy adjustments in the literate entries can recover from that:

literate={c=c}{= }2 {c=>c}{=> }3

The above latex code with columns=flexible not-commented and with the adapted literate option, gives the following:

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.