%3F.png)
Betrachten Sie dieses MWE, modifiziert vonifthenelse - Vergleich gleicher Zeichenfolgen schlägt fehl:
\documentclass{article}
\edef\test{german\relax}
\edef\curentry{\string german\relax}
\typeout{test: \meaning\test, curentry: \meaning\curentry}
\ifx\curentry\test
\typeout{ equal}
\else
\typeout{ unequal}
\fi
\begin{document}
\end{document}
Wenn Sie dies mit kompilieren pdflatex test.tex
, sehen Sie diese Ausgabe im Terminal:
test: macro:->german\relax , curentry: macro:->german\relax
unequal
Der verlinkte Beitrag erklärt nun, warum das so ist:
was passiert, ist, dass \string auf das erste Token angewendet wird, das es sieht, in diesem Fall ein g. Beim Vergleich der beiden Ergebnisse sind sie nicht gleich: Das eine hat einen Nicht-Buchstaben und dann fünf Buchstaben, das zweite hat sechs Buchstaben.
Nehmen wir jedoch an, ich versuche, eine Situation in einem Paket zu untersuchen, bei dem ich nicht wirklich weiß, wie die Makros definiert wurden. Also entscheide ich mich für \typeout
die \meaning
Makros - und ich erhalte diegenau das gleicheInhalt wird gedruckt, aber die Bedingung schlägt immer noch fehl. Was kann ich tun, um diese Art von Situation zu debuggen?
Mit anderen Worten, gibt es eine Funktion, die ich verwenden könnte, die (ähnlich wieGenerieren einer Catcode-Tabelle in Latex (mit \typeout zum Terminal)?) würde für die obigen Makros beispielsweise Folgendes ausgeben:
% \typeoutComponents{\test}
g (catcode 11)
e (catcode 11)
r (catcode 11)
m (catcode 11)
a (catcode 11)
n (catcode 11)
\relax (catcode ?)
% \typeoutComponents{\curentry}
g (catcode 12)
e (catcode 11)
r (catcode 11)
m (catcode 11)
a (catcode 11)
n (catcode 11)
\relax (catcode ?)
... damit ich selbst herausfinden kann, warum eine „String“-(Makro-)Gleichheit fehlschlägt?
(Übrigens eine Unterfrage: Kann eine Makro-/Befehls-/Token-/Steuersequenz (also das, was mit beginnt \
) einen Catcode haben oder nicht?)
Antwort1
Der Befehl \tl_analysis_show:N
führt das aus, was Sie verlangen.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\checktokenbytoken}{sm}
{
\IfBooleanTF{#1}
{
\tl_show_analysis:n { #2 }
}
{
\tl_show_analysis:N #2
}
}
\ExplSyntaxOff
\edef\xgerman{\string german\relax}
\checktokenbytoken{\xgerman}
\checktokenbytoken*{german\relax}
Sie erhalten auf dem Terminal
The token list \xgerman contains the tokens:
> g (the character g)
> e (the letter e)
> r (the letter r)
> m (the letter m)
> a (the letter a)
> n (the letter n)
> \relax (control sequence=\relax).
<recently read> }
l.19 \checktokenbytoken{\xgerman}
?
The token list contains the tokens:
> g (the letter g)
> e (the letter e)
> r (the letter r)
> m (the letter m)
> a (the letter a)
> n (the letter n)
> \relax (control sequence=\relax).
<recently read> }
l.20 \checktokenbytoken*{german\relax}
(Für Versionen vor TeX Live 2017 benötigen Sie \usepackage{l3tl-analysis}
zusätzlich zu \usepackage{xparse}
und , damit dies funktioniert \tl_show_analysis:N
, mittlerweile veraltet)
Antwort2
Meine Lösung benötigt kein externes Paket. Das \showcat\macro
ist implementiert. Nach
\def\test{ger{$##m}a~n \relax \foo}
\edef\curentry{\string german \relax}
\showcat\test
\showcat\curentry
erhalten wir das Ergebnis:
\test ->
the letter g (catcode 11)
the letter e (catcode 11)
the letter r (catcode 11)
begin-group character { (catcode 1)
math shift character $ (catcode 3)
macro parameter character # (catcode 6)
the letter m (catcode 11)
end-group character } (catcode 2)
the letter a (catcode 11)
the token ~ (catcode 13)
the letter n (catcode 11)
blank space (catcode 10)
the token \relax (catcode 16)
the token \foo (catcode 16)
\curentry ->
the character g (catcode 12)
the letter e (catcode 11)
the letter r (catcode 11)
the letter m (catcode 11)
the letter a (catcode 11)
the letter n (catcode 11)
blank space (catcode 10)
the token \relax (catcode 16)
Und die Umsetzung:
\def\showcat#1{\immediate\write16{\string#1 -> }\expandafter\showcatA#1\showcatA}
\def\showcatA{\futurelet\tmp\showcatB}
\def\showcatB{\let\next=\showcatE
\ifx\tmp\bgroup \let\next=\showcatC \fi
\ifx\tmp\egroup \let\next=\showcatC \fi
\expandafter\ifx\space\tmp \let\next=\showcatC \fi
\ifx\tmp\showcatA \let\next=\showcatF \fi
\next
}
\def\showcatC{\afterassignment\showcatD \let\tmp= }
\def\showcatD{\showcatE\tmp}
\def\showcatE#1{\edef\next{\string#1}%
\immediate\write16{\space\space
\ifnum\showcatG<13 \meaningtmp \else the token \next
\fi \space (catcode \showcatG)}%
\showcatA
}
\def\meaningtmp{\meaning\tmp}
\def\showcatF#1{}
\def\showcatG{\showcatH\bgroup1\showcatH\egroup2\showcatH$3\showcatH&4%
\showcatH##6\showcatH^7\showcatH_8\showcatH{ }{10}%
\showcatH A{11}\showcatH/{12}\showcatH~{13}16}
\def\showcatH#1#2{\ifcat\noexpand\tmp\noexpand#1#2\expandafter\showcatI\fi}
\def\showcatI#116{}
Natürlich kommen die Token mit den Kategorien 0, 5, 9, 14, 15 nie im Makrokörper vor. Und die Kontrollsequenzen (Token ohne Kategorie) werden hier als Kategorie 16 ausgedrückt, um die Verwendung \showcatG
in \ifnum
Tests zu vereinfachen.