
Вэтотответ egreg использовал макросы \DeclareTextSymbol
, \DeclareTextCommandDefault
и \UndeclareTextCommand
там, где я ранее (и безуспешно) пробовал простое \newcommand
или \let
.
Может ли кто-нибудь пояснить правильное использование этих команд и разницу со стандартом \newcommand
и т. д.?
решение1
Некоторые команды могут выбирать свое действие на основе текущей кодировки вывода.
Самый простой пример — акценты. Хочется, чтобы они \"
вели себя по-разному, когда выходная кодировка (соответствие между доступными глифами и их положением в шрифте) — OT1 или T1.
В первом случае \"u
будет сформирован вывод из ударения и символа, в то время как в случае с T1 он будет напрямую набирать предварительно составленный символ (это различие очень важно при рассмотрении переносов).
Таким образом, вместо того, чтобы поддерживать список команд для изменения определения при переключении кодировок, можно определить команду с помощью \DeclareTextSymbol
или подобных функций.
Давайте рассмотрим \textborn
. Он не определен в базовом LaTeX, но textcomp
дает его определение:
% textcomp.sty, line 225
\DeclareTextCommandDefault{\textborn}{\tc@check@symbol2\textborn}
Неважно знать, что должен делать заменяющий текст, но это определяет \textborn
как
\?-cmd \textborn \?\textborn
(три токена, последний — одиночный токен, расширением которого является приведенный выше текст замены, \tc@check@symbol2\textborn
и к которому можно получить доступ, выполнив \csname ?\string\textborn\endcsname
).
Позже, когда ts1enc.def
будет загружен, поскольку textcomp.sty
неявно вызывается \usepackage[TS1]{inputenc}
), LaTeX найдет
\DeclareTextSymbol{\textborn}{TS1}{98}
который будет делать тот же трюк, что и раньше, определяя \textborn
как
\TS1-cmd \textborn \TS1\textborn
(снова три жетона). Это самая важная часть. Как работает такая команда?
При расширении \textborn
, если LaTeX находится в месте, где ожидается набор символа, текущая выходная кодировка будет проверена на соответствие TS1. Если это так, то будет использоваться только глиф номер 98 текущего шрифта; в противном случае группа открывается, кодировка переключается на TS1, символ 98 набирается и группа закрывается.
Такая команда всегда надежна, то есть если она обнаружена в перемещаемых аргументах, она будет создана сама собой, а не расширяться при выполнении операций записи.
Это должно объяснить ваше недоумение при выполнении
\let\oldtextborn\textborn
до загрузки kpfonts
и затем не видим разницы между выводом, созданным \textborn
и \oldtextborn
. kpfonts
Пакет не переопределяет \textborn
, а скорее связывает новый шрифт с кодировкой TS1 на основе выбранного имени семейства шрифтов. Так что \oldtextborn
и \textborn
остаются теми же.
При определении \textborn
использования cmr
семейства нужно быть осторожным, потому что такая стратегия, как
\let\oldtextborn\textborn
\renewcommand\textborn{{\fontfamily{cmr}\selectfont\oldtextborn}}
не гарантируется безопасность. Например, если \textborn
появляется в движущемся аргументе, скажем, в заголовке раздела или подписи, .aux
файл будет содержать
\@writefile{toc}{\contentsline {section}{\numberline {1}{\fontfamily {cmr}\selectfont {\fontfamily {cmr}\selectfont \textborn }}}{1}}
где команда, по-видимому, расширяется несколько раз. В других обстоятельствах это может даже привести к бесконечным циклам.
Стратегия, включающая в себя, \UndeclareTextCommand
определенно безопаснее.