# Visible space character disappears in listings with xelatex

With TeX Live 2019 (manual install), this is my code:

\documentclass[french]{article}
\usepackage{ifxetex}
\ifxetex
\usepackage{fontspec}
\else
\usepackage{lmodern}
\fi
%
\usepackage{babel}
\usepackage{listings}
%
\begin{document}
\begin{lstlisting}[language=Python,showstringspaces=true,basicstyle=\ttfamily]
# un commentaire
i = 1
while i <= 5:
print(i)
i = i + 1
print('Fini !')
\end{lstlisting}
\end{document}


With pdflatex, the visible space before ! in 'Fini !' appears. With xelatex, it disappears...

On TeX Live 2015/dev/Debian, it appairs with both, pdflatex and xelatex...

How to obtain the visual space with xelatex on TeX Live 2019?

• @DavidCarlisle No, in this case it's listings that tries to use \char32, which in the OT font has no suitable glyph for the purpose. – egreg Nov 5 at 0:19
• thanks to egreg, i'll try his solution by this day. But why this difference between TL2015 and TL2019 ? – Christophe Poulain Nov 5 at 6:43
• Until 2018, fontspec redefined \lst@visiblespace, but the most recent version no longer does. – egreg Nov 5 at 7:48

The definition of \lst@visiblespace makes listings typeset \char32 when the font family is \ttdefault, but the OTF version of Latin Modern Mono hasn't a visible space there.

\documentclass[french]{article}
\usepackage{ifxetex}
\ifxetex
\usepackage{fontspec}
\else
\usepackage[T1]{fontenc} % <- don't forget
\usepackage{lmodern}
\fi

\usepackage{babel}
\usepackage{listings}

\ifxetex
\makeatletter
\def\lst@visiblespace{\lst@ttfamily{\char"2423}\textvisiblespace}
\makeatother
\fi

\begin{document}

\begin{lstlisting}[language=Python,showstringspaces=true,basicstyle=\ttfamily]
# un commentaire
i = 1
while i <= 5:
print(i)
i = i + 1
print('Fini !')
\end{lstlisting}

\end{document}


I use the same character used by \textvisiblespace, that is, U+2423 OPEN BOX.

With a recent version of LaTeX (October 2019), a better patch would be

\def\lst@visiblespace{\lst@ttfamily\verbvisible\textvisiblespace}


that doesn't even need to be conditionally performed.

Up to 2018, fontspec used to patch \lst@visiblespace, making it equal to \fontspec_visible_space:. The last version doesn't, but it's probably a mistake. Here's how to reinstate the better code:

\documentclass[french]{article}
\usepackage{ifxetex}
\ifxetex
\usepackage{fontspec}
\else
\usepackage{lmodern}
\fi

\usepackage{babel}
\usepackage{listings}

\ifxetex
\ExplSyntaxOn
\cs_set_eq:cN { lst@visiblespace } \fontspec_visible_space:
\ExplSyntaxOff
\fi

\begin{document}

\begin{lstlisting}[language=Python,showstringspaces=true,basicstyle=\ttfamily]
# un commentaire
i = 1
while i <= 5:
print(i)
i = i + 1
print('Fini !')
\end{lstlisting}

\end{document}

• It would be wrong to use \DeclareRobustCommand\verbvisiblespace{{\fontfamily{lmtt}\selectfont\char"2423}} \def\lst@visiblespace{\verbvisiblespace}? – Pablo González L Nov 5 at 2:51
• @PabloGonzálezL Yes: you'd be hard coding lmtt. – egreg Nov 5 at 8:30
• If the distribution is totally updated you can change the package ifxetex to iftex, from my point of view I think it is not always good to leave \verbvisiblespace\textvisiblespace, if you change the main font of the document (libertine for example), the character is very small, it is better to define directly \verbvisiblespace. – Pablo González L Nov 5 at 10:56
• thanks to egreg. It's word. – Christophe Poulain Nov 5 at 12:55