minted icon indicating copy to clipboard operation
minted copied to clipboard

weird interaction between formatting commands like \textbf and \mintinline

Open jendrikw opened this issue 4 years ago • 3 comments

Take this code as an example:

\documentclass{article}
\usepackage{minted}
\begin{document}
\mintinline[escapeinside=~~]{text}{abc ~\textit{abc}~}

\textbf{\mintinline[escapeinside=~~]{text}{abc ~\textit{abc}~}}
\end{document}

The result I get is:

image

I'm wondering why there are two spaces in the second line, and the def in the second line is not italics. Can anyone explain?

jendrikw avatar May 29 '20 13:05 jendrikw

Workaround

Use

\mintinline[escapeinside=||, fontseries=b]{text}{abc |\textit{abc}|}

and do not use \mintinline in argument of any command.

Weak and incomplete explanation

\textbf{\mintinline[escapeinside=~~]{text}{abc ~\textit{abc}~}}

results in a .pygtex file containing

\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}]
abc \PYG{esc}{\textit {abc}}
\end{Verbatim}

and since at the time \PYG expands the category code of space character after \textit is not 10, \textit {abc} is equivalent to \textit{ }{abc}. Therefore there are two spaces in the output and abc is not italic.

Wrapping \mintinline[arg1]{arg2}{arg3} in other command means the arguments of \mintinline is tokenized before \mintinline is expanded. I believe this causes the extra space after \textit (Maybe at the stage of \scantokens used by \minted@inline@iii, an internal macro of \mintinline).

muzimuzhi avatar May 29 '20 14:05 muzimuzhi

Thank you for the explanation. In reality, the \textbf of the question is an \item of a description environment. I'll see if I can find another way to typeset what I want.

jendrikw avatar May 29 '20 15:05 jendrikw

Short answer: This is a tokenization issue due to the wrapping \textbf, as @muzimuzhi pointed out. The examples shown are not using syntax highlighting, so if that is indeed not necessary, it might be easier to use verbatim commands instead. One option would be

\textbf{\Verb[commandchars=\\\{\}]{abc \textit{abc}}}

Another possibility would be to use \EscVerb from fvextra, which is meant to be used inside other commands;

\textbf{\EscVerb{abc }\textit{\EscVerb{abc}}}

Normally, \mintintline reads its argument in verbatim mode, so it sees \texttt as just a sequence of characters. When \textbf wraps everything, then \mintinline's argument is not read in verbatim mode (everything is tokenized before \mintintline receives it), so it gets \texttt as a command sequence. \mintinline detokenizes its argument as part of the highlighting process, and when a command sequence is detokenized, a space is inserted after it. So the command sequence "\texttt" becomes the character sequence "\texttt " after detokenization, and then the inserted space appears in the final output.

I created a custom retokenization routine in fvextra a while back, and that may fix cases like this if I get a chance to rework \mintintline to use that.

gpoore avatar May 29 '20 15:05 gpoore

The example document given in this issue now works as expected without any workarounds. minted version 2.7 (Dec 12, 2022) reimplemented \mintintline using fvextra, so \mintintline is now more robust to being used inside other commands.

gpoore avatar Jul 15 '23 19:07 gpoore