8

I want code in parentheses and in brackets to appear in different colors. In the following document, the words brackets again appear in green as intended, and outside again is black as intended, but stretches into the margin of the page.

If I uncomment the line ,breaklines=true, the line is broken between brackets and again, however, these words and the following are red, i.e. as if a (-)-delimited section was detected but then the closing ) was ignored.

What is going on here?

Addition: The problem occurs also if there is no line break present, e.g. if I shorten all words in the text to their first letter. The problem goes away in any case if I pick any other kind of delimiter instead of (), e.g. {}.

\documentclass{article}
\usepackage{color}
\usepackage{listings}

\lstdefinelanguage{new}{
    moredelim=*[s][\color{red}]{(}{)},
    moredelim=*[s][\color{green}]{[}{]},
  }
\lstset{
  language=new
  %,breaklines=true
  }

\begin{document}

\begin{figure}
\begin{lstlisting}
outside(in paren) [in brackets (paren+brackets) brackets again] outside again
\end{lstlisting}
\end{figure}

\end{document}
siracusa
  • 13,411
arne.b
  • 451

2 Answers2

6

You might have come across a bug arising from the special treatment of the right parenthesis by the line-breaking algorithm of the listings package. In fact, when the SelectCharTable hook used by the listings package is executed and line breaking is enabled ) is defined as a macro, namely by

\lst@Def{`)}{\lst@breakProcessOther)}

where

\lst@Def=macro:
#1->\lccode `\~=#1\lowercase {\def ~}.

Unfortunately, this means that ) is not recognized as a delimiter any more, which eventually leads to your observation.

I’ve put some effort in finding a fix for this bug, but haven’t succeeded so far. (My TeX programming skills are still limited.) So, the only thing I can provide right now is a workaround in the form of a patch that simply cancels the special treatment of ) by the line-breaking algorithm:

\documentclass{article}

\usepackage{color}

\usepackage{listings}

\lstdefinelanguage{new}{
  moredelim=*[s][\color{red}]{(}{)},
  moredelim=*[s][\color{green}]{[}{]},
}

\lstset{
  language=new,
  breaklines=true
}

\usepackage{etoolbox}

\makeatletter

\patchcmd{\lsthk@SelectCharTable}{%
  \lst@ifbreaklines\lst@Def{`)}{\lst@breakProcessOther)}\fi
}{%
}{
}{
}

\makeatother

\begin{document}

\begin{lstlisting}
outside (in paren) [in brackets (paren+brackets) brackets again] outside again
\end{lstlisting}

\end{document}

The resulting output is:

mhp
  • 8,692
  • I don't fully understand the logic of that \lst@Def. Is there any reason why you use those \expandafter's and not \patchcmd{\lsthk@SelectCharTable}{...}{}{}{}? – egreg Oct 01 '12 at 11:01
  • @egreg: You’re right, \patchcmd{\lsthk@SelectCharTable} would be possible as well. I’ve used the alternative formulation since this is the way the control sequence name of the SelectCharTable hook is constructed by \lst@AddToHook. – mhp Oct 01 '12 at 11:21
  • @egreg: \lst@Def is completely mysterious to me. – mhp Oct 01 '12 at 11:26
  • There's no need to use such a complicated procedure once the control sequence has been built. – egreg Oct 01 '12 at 12:05
  • @egreg: You’ve convinced me; I’ve edited my answer. – mhp Oct 01 '12 at 12:16
3

A simple workaround would be, instead of using closing parenthesis ')', one can use another character e.g ']' and replace it with closing parenthesis ')'.

\begin{lstlisting[literate={(}{{\textbf{(}}}1                          
                           {]}{{\textbf{)}}}1]
(In text I'm closing using]
\end{lstlisting}
Onur
  • 31