1

Here I use escapechar with listings to set the colour for an individual word in a listing. The text set with listings is set looser though, so this doesn't align. How can I get it to align?

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

\begin{document}
\lstset{language=Python,
  basicstyle=\ttfamily,
  keywordstyle=\textcolor{purple},
  escapechar=\@,
}
\begin{lstlisting}
def pass_fn(x):
    pass
\end{lstlisting}

\begin{lstlisting}
def @\textcolor{blue}{pass\_fn}@(x):
    pass
\end{lstlisting}

\end{document}

enter image description here

\textcolor is there as an example, but there is no special problem with that. I get the same problem with just @\ttfamily pass\_fn@ .

  • I don't use emph but I want this colour only here – not when the same function is called somewhere else. – pst Oct 14 '19 at 16:00
  • In the case of your MWE it suffices to add \usepackage[T1]{fontenc}…(assuming you are using pdflatex) – cgnieder Oct 14 '19 at 16:06
  • Really? For me (with a fairly updated texlive2019) it doesn't. – pst Oct 14 '19 at 16:14
  • Oh, yes, and: columns=fullflexible – cgnieder Oct 14 '19 at 16:18
  • Yes, that on the other hand changes the appearance (alone, not "and"). I don't want to change the general appearance of the listing, though. I want to get the same look at escaped text as I (already) have around it. – pst Oct 14 '19 at 16:47
2

When listings finds an escape character in the input, it temporarily switches back to normal input processing and typesetting mode. That means all characters read between @...@ in your example aren't aligned like the ones inside the listing. Escaping should only be used if your really need some LaTeX code (like math symbols) in your listing.

However, there are several ways to highlight individual parts of your code:

Emphasized identifiers

listings has some special groups of identifiers, e.g. keywords or emphasized identifiers. The latter are meant to be used for highlighting special words in the code. As with identifiers, you can declare differently numbered classes of emphasized identifiers:

emph      = [1]{pass_fn},
emphstyle = [1]{\color{blue}}

Advantage: No extra tags in code necessary.
Disadvantage: Only works for identifiers.

Delimited environments

Similar to escape environments you can define new delimited environments which do not escape to normal processing but still allow you to define special markup for the text between the delimiters. There are different delimiter types, most interesting here are two (s) invisible (i) delimiters:

moredelim = [is][\color{blue}]{\#}{\#}

Advantage: Can be used for arbitrary parts of the code, and also be nested.
Disadvantage: Requires extra tags in the code.

Literate processing

listings also provides a literate option to specify exact/literate code replacements. Note that each character of the replacement text is set in a single box, which prevents spanning formatting commands around the whole replacement text:

literate = {pass_fn}{{\textcolor{blue}{p}}
                     {\textcolor{blue}{a}}
                     {\textcolor{blue}{s}}
                     {\textcolor{blue}{s}}
                     {\textcolor{blue}{\char`\_}}
                     {\textcolor{blue}{f}}
                     {\textcolor{blue}{n}}}{7}

Advantage: Can be used without extra tags for arbitrary parts of the code.
Disadvantage: Very verbose definitions if replacement text is longer than a few letters.

Full example document:

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

\begin{document}
\parindent=0pt
\lstset{language=Python,
  basicstyle=\ttfamily,
  keywordstyle=\textcolor{purple},
  escapechar=\@,
}

\begin{lstlisting}
def pass_fn(x):
    pass
\end{lstlisting}

\bigskip
\begin{minipage}[t]{0.4\linewidth}
\texttt{escapechar:}
\begin{lstlisting}
def @\textcolor{blue}{pass\_fn}@(x):
    pass
\end{lstlisting}
\end{minipage}
%
\begin{minipage}[t]{0.4\linewidth}
\texttt{emph/emphstyle:}
\begin{lstlisting}[
    emph={[1]{pass_fn}},
    emphstyle={[1]{\color{blue}}}
]
def pass_fn(x):
    pass
\end{lstlisting}
\end{minipage}

\bigskip
\begin{minipage}[t]{0.4\linewidth}
\texttt{moredelim:}
\begin{lstlisting}[
    moredelim={[is][\color{blue}]{\#}{\#}}
]
def #pass_fn#(x):
    pass
\end{lstlisting}
\end{minipage}
%
\begin{minipage}[t]{0.4\linewidth}
\texttt{literate:}
\begin{lstlisting}[
    literate={pass_fn}{{\textcolor{blue}{p}}
                       {\textcolor{blue}{a}}
                       {\textcolor{blue}{s}}
                       {\textcolor{blue}{s}}
                       {\textcolor{blue}{\char`\_}}
                       {\textcolor{blue}{f}}
                       {\textcolor{blue}{n}}}{7}
]
def pass_fn(x):
    pass
\end{lstlisting}
\end{minipage}

\end{document}

outputs

enter image description here

|improve this answer|||||
  • moredelim is the answer I was looking for! The rest I can't use. In the example I gave it's about doing markup for the defined function, since listings lacks that category. That should not happen every time that function name appears! (I'm also interested in doing some special highlighting in just one place now and then.) – pst Oct 19 '19 at 6:19

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.