6

I would like to create a lstlisting language for a syntax that highlights namespaces for readability. Here's what I want to achieve:

\documentclass{standalone}
\usepackage{listings}
\usepackage{xcolor}

\definecolor{gray}{rgb}{0.4,0.4,0.4}
\definecolor{darkblue}{rgb}{0.0,0.0,0.6}
\definecolor{cyan}{rgb}{0.0,0.6,0.6}

\lstset{
    basicstyle=\ttfamily,
    columns=fullflexible,
    showstringspaces=false,
    commentstyle=\color{gray}\upshape
}

\lstdefinelanguage{turtle}
{
    stringstyle=\color{black},
    identifierstyle=\color{darkblue},
    keywordstyle=\color{cyan},
    moredelim=[is][\color{orange!80!black}]{!}{!},
    moredelim=[l][\color{orange!80!black}]{\ }{:} % my best guess: does not work
}

\begin{document}
\lstset{language=turtle}
\begin{lstlisting}
 !a!:b !c!:d !e!:f .
\end{lstlisting}
\end{document}

desired output

However, I would like to avoid having to put ! explicitly in the input to wrap the namespaces. The command moredelim=[l][\color{orange!80!black}]{\ }{:} has no effect unless I put a space directly before and after each :.

badroit
  • 7,557

1 Answers1

7

You can insert color codes into the identifiers using a regular expression with expl3 (see also https://tex.stackexchange.com/a/238832/89417) as follows:

  1. include the prefix in the identifier tokens with alsoletter{:}
  2. define a new command as identifierstyle to which the tokens are passed by lstlisting
  3. expand the current token (using the o argument specifier)
  4. add the color commands with a regex (using the syntax for building commands with \c{} and \cB{,\cE}) on the two matching groups \1 and \2
  5. print the replaced token
  6. return a command to identifierstyle which will be applied to the current token by lstlisting, define this command such that nothing is printed.

Note that it would be cleaner to modify c{lst@token} in-place (instead of step 5 and 6), but due to my lack of knowledge about expl3 I didn't do that :)

MWE:

\documentclass{article}
\usepackage{listings,xparse}
\usepackage{expl3}
\usepackage{xcolor}
\definecolor{darkblue}{rgb}{0.0,0.0,0.6}
\colorlet{orangeb}{orange!80!black}
\def\noprint#1{}

\ExplSyntaxOn
\NewDocumentCommand \namespaces { }
{
    \tl_set:No \l_demo_tl {\the\use:c{lst@token}}
    \regex_replace_all:nnN { ([a-zA-Z]*):([a-zA-Z]*) } { \c{textcolor}\cB{ orangeb \cE}\cB{ \1 \cE}:\c{textcolor}\cB\{ darkblue \cE\}\cB{ \2 \cE} } \l_demo_tl
    \tl_use:N \l_demo_tl
    \noprint
}

\ExplSyntaxOff

\lstset{
    basicstyle=\ttfamily,
    alsoletter={:},
    columns=fullflexible,
    identifierstyle=\namespaces
}

\begin{document}

\begin{lstlisting}
a:b c:d e:f .
\end{lstlisting}

\end{document}

Result:

enter image description here

Marijn
  • 37,699