Comment \ verb détecte-t-il les espaces qui ne devraient pas exister

Oct 09 2020

Considérez le MWE suivant:

\documentclass{article}

\usepackage{listings}
\lstset{basicstyle=\ttfamily}

\begin{document}

\lstinline |asdf|asdf asdfasdf

\verb |asdf|asdf asdfasdf

\end{document} 

Ma compréhension de ce à quoi il faut s'attendre ici a toujours été la suivante (laissez \cmdreposer l'un \verbou l' autre ou \lstinlinece qui suit):

  • Lorsque TeX a été tokenisé pour la première fois \cmd |, il engloutit l'espace qui le suit, ne laissant que le jeton \cmddans sa "bouche" (et |derrière lui dans le flux d'entrée).
  • Il se développe ensuite \cmd, ce qui conduit à une série de changements de code de catégorie, créant essentiellement tous les caractères spéciaux other, suivis d'une macro qui regarde le jeton suivant (dans ce cas, |).
  • Cette macro récupère ensuite tout jusqu'à la prochaine occurrence de ce jeton (étant alors jetée), applique une mise en forme et modifie les codes de catégorie.

Notamment, l'espace suivant \cmdest englouti pendant la tokenisation de cette séquence de contrôle, c'est-à-dire avant que tout code de catégorie ne soit changé.

Avec cette compréhension, je m'attendrais à ce que les deux lignes ci-dessus composent

asdfasdf asdfasdf

Mais j'obtiens la sortie suivante:

\lstinlinese comporte comme prévu, mais \verbconnaît en quelque sorte l'espace qui le suit.

Comment?? À ma connaissance, il n'aurait jamais dû y avoir de jeton d'espace derrière le \verbjeton.

Réponses

12 PhelypeOleinik Oct 09 2020 at 15:56

Au tout début, vous avez dit:

Quand TeX a été tokenisé pour la première fois \cmd |

mais c'est faux. TeX est un gentleman bien élevé et ne prend pas de l'avance sur lui-même en scannant un  et un |avant de savoir ce qu'il \cmdest censé faire. En ce qui concerne TeX, l'espace et le |et tout autre caractère pourraient tous signifier la même chose, et pourraient changer de sens, donc le pré-scan ne ferait que semer la confusion.

Lorsque TeX voit \cmd, la seule chose «spéciale» qu'il fait aux espaces vides est de définir state:=skip_blanks, de sorte que lorsque, disons, la composition, \TeX codeécrira

, en ignorant les espaces après la séquence de contrôle comme d'habitude. Vous pouvez vérifier par vous-même avec:

\def\test{\catcode`\ =12 \testx}
\def\testx{\futurelet\token\testy}
\def\testy{\show\token\afterassignment\testx\let\token = }
\test     x

et vous verrez qu'il montre 5 the character avant de montrer the letter x.


Revenons maintenant au problème actuel: mettez à jour votre LaTeX :-)

L'ancien comportement de \verbétait de regarder le jeton suivant, quel qu'il soit, et de l'utiliser comme délimiteur (à l'exception de {). Ce problème a maintenant été corrigé pour la version LaTeX 2020-10-01 (à partir du numéro 32 de LaTeX News ):

6 frougon Oct 09 2020 at 16:25

Je pense que ce qui se passe est le suivant:

  • \verbest d'abord tokenisé (le caractère d'espace, qui a le catcode 10 juste avant \verbest tokenisé, marque la fin de ce mot de contrôle mais n'est pas rejeté).

  • TeX passera à l'état S, puisqu'il \verbs'agit d'un mot de contrôle (séquence de contrôle dont le nom est composé uniquement de «lettres»), mais il ne saute pas encore les espaces.

  • \verbest développé et le code de son expansion est exécuté. Ce code donne d'abord aux espaces le catcode 12 (via \let\do\@makeother \dospecials), c'est important.

  • A la fin du \verbtexte de remplacement de, il y a \@ifstar\@sverb\@verb. Ceci \@ifstarregarde vers l'avant dans l'entrée, donc l'état S entre en jeu. Puisque les espaces ont le catcode 12 à ce stade, le caractère espace suivant \verbn'est pas ignoré. Il est symbolisé avec le catcode 12.

  • Puisque nous avons utilisé la forme sans étoile de \verbet \@verbest défini comme \def\@verb{\@vobeyspaces \frenchspacing \@sverb}, les espaces sont maintenant rendus actifs et \@sverbsont développés (ainsi, le délimiteur de fin sera un espace catcode-13, tandis que le délimiteur de début était un espace catcode-12).

  • \@sverbattrape le jeton d'espace catcode-12 comme son seul argument et définit les espaces actifs comme étant- \letégaux à \verb@egroup(s'ils \verb*avaient été utilisés, l' \@sverbaurait fait \@setupverbvisiblespace \@vobeyspacesaussi; ainsi, les espaces finissent par être actifs dans tous les cas). C'est ainsi que le texte textuel se terminera dans des conditions non erronées: \verb@egroupwill yield \egroup, qui terminera le groupe commencé par \verb(il y a un texte de remplacement \bgroupin \verb). Puisque la configuration spéciale du catcode a été effectuée localement dans ce groupe, cela met fin à la configuration spéciale du catcode.

Ainsi, la phrase de la question «Cette macro saisit alors tout jusqu'à la prochaine occurrence de ce jeton» n'est pas vraiment correcte: il n'y a pas de saisie du contenu textuel comme argument. Les jetons entre les délimiteurs de début et de fin sont simplement traités comme des jetons catcode-12, à l'exception des jetons d'espace qui sont toujours actifs à la fin de \@sverb, comme nous l'avons vu.

Note: comme Phelype Oleinik a souligné , le comportement \verba été modifié dans le format LaTeX à partir 01/10/2020. Mes commentaires ici sont basés sur LaTeX2e <2020-02-02> patch level 5.