我有一个宏\a
。我想定义一个宏\b
,其替换文本T
将满足以下要求:
- 每个 token 的 catcode
T
都在 10-12 范围内。 - 忽略 catcodes,
T
逐个标记都等于\a
的最终扩展。
例如,
\def\z{12pt}%
\def\a{\noindent\fontsize{10pt}{\z}\selectfont}%
\def\b{???}%
\b
应排版:
\noindent\fontsize{10pt}{12pt}\selectfont
如果这不可能,也可以,如果\b
扩大一切递归地,直到没有什么可以扩展为止。
最后,下面的例子也足够好了:
\def\a{\noindent\fontsize{10pt}{\a}\selectfont}%
\def\b{???}%
\b
应排版:
\noindent\fontsize{10pt}{\a}\selectfont
答案1
不扩展和\a
,而是\meaning
:
\documentclass{article}
\begin{document}
\def\z{12pt}%
\def\a{\noindent\fontsize{10pt}{\z}\selectfont}%
\makeatletter
\edef\b{\expandafter\strip@prefix\meaning\a}
\makeatother
\texttt{\b}
\end{document}
命令名称后的空格由 TeX 插入。
使用 e-TeX 的 \detokenize 的变体:
\edef\b{\detokenize\expandafter{\a}}
在这两种情况下,定义文本中的标记\b
具有类别代码 12(其他),而空格具有类别代码 10(空格)。
如果知道 的内容\a
或多或少,则可以通过将不应扩展的宏重新定义为 的含义来防止扩展\relax
:
\documentclass{article}
\begin{document}
\def\z{12pt}%
\def\a{\noindent\fontsize{10pt}{\z}\selectfont}%
\begingroup
\let\fontsize\relax
\let\selectfont\relax
\edef\x{\a}
\xdef\b{\detokenize\expandafter{\x}}
\endgroup
\texttt{\b}
\end{document}
的完全展开\a
仅适用于某些宏,其结果或多或少有用:
\documentclass{article}
\begin{document}
\def\z{12pt}%
\def\a{\noindent\fontsize{10pt}{\z}\selectfont}%
\edef\tmp{\a}
\edef\b{\detokenize\expandafter{\tmp}}
\endgroup
\texttt{\b}
\end{document}
microtype
例如,添加包将得到一个\a
通过以下方式硬扩展中断的宏\edef
:
! Argument of \MT@res@a has an extra }.
<inserted text>
\par
l.7 \edef\tmp{\a}
LaTeX 的保护机制可供较软的 所用\protected@edef
。然后, 定义的命令\DeclareRobustCommands
和 带有可选参数的命令不会扩展太多:
\documentclass{article}
\usepackage{microtype}
\begin{document}
\def\z{12pt}%
\def\a{\noindent\fontsize{10pt}{\z}\selectfont}%
\makeatletter
\protected@edef\tmp{\a}
\makeatother
\edef\b{\detokenize\expandafter{\tmp}}
\texttt{\b}
\end{document}