6

I am wondering if it is still possible to print characters chosen to be moredelim in \lstdefinestyle. It turns out that since I've defined a character as moredelim, it can only be used inside quotes or comments with no obvious way to escape it. Here is some code to help understanding what I mean:

% !TEX encoding = UTF-8 Unicode
\documentclass{article}
\usepackage{listings,xcolor}
\usepackage[T1]{fontenc}
\usepackage{verbatim}

\newcommand{\listingsfont}{\fontfamily{courier}}

\lstdefinestyle{test}{
    language={sh},
    moredelim=**[is][\color{red}]{~}{~},
    basicstyle=\ttfamily, 
}

\begin{document}

I want to highlight first two command arguments in the following code:
\begin{verbatim}
$ ./my-command some-dir some-dir2 some-other-argument
$ ./my-command ~/Desktop ~/Documents some-other-argument
\end{verbatim}


What I get:
\begin{lstlisting}[style=test]
$ ./my-command ~some-dir~ ~some-dir2~ some-other-argument
$ ./my-command ~"~/Desktop"~ ~~./Documents~ some-other-argument
# ~ is not shown before ./Documents because of being used in moredelim,
# but it can be still printed in comments / inside strings.
\end{lstlisting}
\end{document}

Escape moredelim in lstlisting

Of course, in my simple example I can overcome the problem by using some other characters instead of ~, but when it comes to a document with several hundred pages and lots of listings, it's good to know that whatever moredelims you choose, you won't put yourself into a trap.

How can I keep ~ (or any other character) as moredelim, but still be able to print it when needed?

  • You want to have you cake and eat it too :) How is listings supposed to know when ~ should be printed or act as a delimiter? Choose your delimiters carefully, ones that have no chance of appearing in your code. You can even choose exotic sequences of characters for moredelim , such as <<@<< and >>@>> to reduce that risk. – jub0bs Jan 21 '14 at 19:49
  • 1
    I was thinking of taking this approach, it's fine as long as you don't want to use your moredelim too often. But if you want to highlight something frequently, your code becomes unreasonably cluttered. – Alexander Kachkaev Jan 21 '14 at 20:23
5

Looks like I got the solution to my own problem now. It’s in using literate when defining \lstdefinestyle:

% !TEX encoding = UTF-8 Unicode
\documentclass{article}
\usepackage{listings,xcolor}
\usepackage[T1]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage{verbatim}

\newcommand{\listingsfont}{\fontfamily{courier}}

\lstdefinestyle{test}{
    language={sh},
    moredelim=**[is][\color{red}]{~}{~},
    moredelim=**[is][\color{blue}]{<}{>},
    basicstyle=\ttfamily, 
    literate={\\~}{{\textasciitilde}}1
        {\\<}{{\unichar{"003C}}}1 
        {\\>}{{\unichar{"003E}}}1
}

\begin{document}

\textasciitilde, > or < can be escaped using \texttt{literate}, and still be used as \texttt{moredelim}:
\begin{lstlisting}[style=test]
$ ./my-command ~some-dir~ ~some-dir2~ some-other-argument
$ ./my-command ~"~/Desktop"~ ~\~./Documents~ some-other-argument
$ ls \~ > /dev/null
$ <ls \~ \> /dev/null>  
\end{lstlisting}
\end{document}

moredelim can be escaped in lstlisting by using literate when defining lstdefinestyle

You can prepend your moredelim character with backslash and replace this sequence with a pure character. The trick is in using a corresponding latex command for the character or its unicode definition. If you type {\\~}{{~}}1 instead of {\\~}{{\textasciitilde}}1, this won’t work as latex will end up with a death loop.

With such workaround you can have very short and simple moredelims, but won’t have to limit yourself in what you print in your listings.

  • 1
    If your own answer satisfies you, feel free to accept it, so it be removed from the "unanswered" pile :) – jub0bs Jan 24 '14 at 20:40

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.