# Escaped percent sign is syntax-highlighted as comment by listings package

My code:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\lstset{
language=[latex]tex,
basicstyle=\ttfamily,
columns=fullflexible,
keepspaces=true,
upquote=true,
showstringspaces=false,
}
\begin{document}
\begin{lstlisting}
Foo % Comment 1
Bar % Comment 2
Baz \% Not a comment
\end{lstlisting}
\end{document}


Output:

Why is % Not a comment colored violet when it is not a comment? How can I fix this?

• Inside lstlisting environment, backslash character \  is just a normal character, so \% is not interpreted as a command anymore. What other contents will you use inside that lstlisting environment? Jun 6, 2020 at 1:00
• @muzimuzhiZ Isn't it a bug in lstlisting then? When I have mentioned [latex]tex as the language, shouldn't it use LaTeX grammar parsing rules for all content in lstlisting environment? I mean, Vim gets it right and does not highlight \% Not a comment as a comment. Shouldn't lstlisting do the same thing? Jun 6, 2020 at 7:18

you can try to setup the \% as a string:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\lstset{
language=[latex]tex,
basicstyle=\ttfamily,
columns=fullflexible,
keepspaces=true,
upquote=true,
showstringspaces=false,
morestring=[s]\\\%,
stringstyle=\color{red},
}
\begin{document}
\begin{lstlisting}
Foo % Comment 1
Bar % Comment 2
Baz \%abc\% Not a comment %still a comment
\end{lstlisting}
\end{document}


• According to the doc of option morecomment=[s]{<delim>}{<delim>}, morestring=[s]\\\% defines a string delimited by \\  and \%. Hence for input text \large % text, the characters \large % is recognized as a string. I tried options moretexcs={large} and texcsstyle=*<style>, it seems that the string tokenizer has higher precedence than texcs. Jun 7, 2020 at 22:34

(This only shows some failed attempts, hence is not a standard answer.)

As I commented under @UlfikeFischer's answer, morestring=[s]\\\% creates a string pattern which begins at \\ and ends with \%. Therefore for input text \large % text, \large % is recognized as a string and colored red. And this cannot be overwritten by morekeywords and keywordstyle.

I also tried listings aspect texcs and keyword, none of them succeeds.

• When comment=[l]\% is set (this is the default setting), control characters such as \# and \; can both be set and highlighted as texcs or keywords, but this fails on \%.
• When another character other than % is used as comment char, then \% can be set and highlighted as texcs or keyword.
\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}

% a texcs attempt
\lstset{
language=[latex]tex,
basicstyle=\ttfamily,
texcsstyle=*\color{orange}, % the star (*) means highlight the backslash
columns=fullflexible,
keepspaces=true,
upquote=true,
showstringspaces=false,
comment=[l], % clear comment setting
alsoletter={\#\;\%},
moretexcs={cmd, Foo, AtBeginDocument, \#, \;, \%}
}

\begin{document}
Use \verb|C| as comment character
\begin{lstlisting}[comment={[l]C}]
\cmd \Foo % Comment 1
\#\; Bar % Comment 2
Baz \% Not a Comment
\AtBeginDocument
\end{lstlisting}

Use \verb|\%| as comment character
\begin{lstlisting}[comment={[l]\%}]
\cmd \Foo % Comment 1
\#\; Bar % Comment 2
Baz \% Not a Comment
\AtBeginDocument
\end{lstlisting}
\end{document}


I think it is the precedence that matters. It looks like there is a precedence order like "string ~ comment > keyword ~ texcs".

Just use literate to replace the \% with %, as follows:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\lstset{
language=[latex]tex,
basicstyle=\ttfamily,
columns=fullflexible,
keepspaces=true,
upquote=true,
showstringspaces=false,
literate={\\\%}{\%}1, % Replace \% with %
}
\begin{document}
\begin{lstlisting}
Foo % Comment 1
Bar % Comment 2
Baz \% Not a comment
\end{lstlisting}
\end{document}