%3F.png)
Рассмотрим этот MWE, модифицированный изifthenelse сравнение равных строк не удается:
\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}
Если вы скомпилируете это с помощью pdflatex test.tex
, вы увидите следующий вывод в терминале:
test: macro:->german\relax , curentry: macro:->german\relax
unequal
Теперь, в связанном посте объясняется, почему это так:
происходит следующее: \string применяется к первому увиденному токену, в данном случае к g. Сравнивая два результата, можно заметить, что они не совпадают: в одном есть одна небуква и пять букв, во втором — шесть букв.
Однако, предположим, я пытаюсь проверить некоторую ситуацию в пакете, где я не знаю, как определены макросы. Поэтому я \typeout
решаю\meaning
- и я получаюточно такой жесодержимое печатается, а условие все равно не срабатывает. Что я могу сделать, чтобы отладить такую ситуацию?
Другими словами, есть ли какая-то функция, которую я мог бы использовать, которая (похожа наГенерация таблицы catcode в Latex (с \typeout в терминал)?) выведет для приведенных выше макросов, скажем:
% \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 ?)
... чтобы у меня была возможность самому сделать вывод, почему равенство «строки» (макроса) не выполняется?
(Кстати, подвопрос: может ли макрос/команда/токен/управляющая последовательность (то есть то, что начинается с \
) иметь кокод или нет?)
решение1
Команда \tl_analysis_show:N
выполняет то, что вы просите.
\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}
На терминале вы получите:
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}
(Для выпусков до TeX Live 2017 вам понадобится \usepackage{l3tl-analysis}
дополнительно \usepackage{xparse}
для работы и \tl_show_analysis:N
, теперь не рекомендуется)
решение2
Моему решению не нужен внешний пакет. Он \showcat\macro
реализован. После
\def\test{ger{$##m}a~n \relax \foo}
\edef\curentry{\string german \relax}
\showcat\test
\showcat\curentry
получаем результат:
\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)
И реализация:
\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{}
Конечно, токены с категориями 0, 5, 9, 14, 15 никогда не встречаются в теле макроса. А управляющие последовательности (токены без категории) выражены здесь как категория 16 для простого использования \showcatG
в \ifnum
тестах.