我定义了一个宏,它本质上是一个用于\meaning
检查宏定义的包装器。
\def\whatis#1{{\ttfamily\string#1: \meaning#1}}
(我使用的实际形式更进一步,检查命令是否强大,但这与此无关。)通常,结果涉及一些包含标记的内部宏@
。如果我想检查这宏,然后我必须写类似
\makeatletter
\whatis\MacroNameWith@InIt
\makeatother
因为我很懒,:-)
我想\makeatletter
在的范围内激活\whatis
,所以我尝试了
\def\whatis#1{{\makeatletter\ttfamily\string#1: \meaning#1\makeatother}}
(实际上我猜\makeatother
由于分组,这没有必要。)不用说,这是行不通的,否则我就不会发布这个问题了:-)
我的问题:
- 为什么这不起作用?
- 我怎样才能定义如我所愿的行为
\whatis
?\whatis{\MacroNameWith@InIt}
答案1
答案2
对于特定用例,避免问题的一个更简单的方法是更改输入语法,使其不需要\
\def\whatis#1{\texttt{#1: \expandafter\meaning\csname #1\endcsname}}
\whatis{MacroNameWith@InIt}
对原方法的评论:
史蒂文展示了如何执行您所要求的操作,但请注意,生成的命令类似于\verb
并且不能在任何其他宏的参数中使用。
类似 的 catcode 更改\makeatletter
(即\catcode``\@=11
)会影响 catcode 表,该表仅用于将输入字符转换为标记。当您进入宏的替换文本时,传递的参数已#1
被标记化,因此 catcode 更改不起作用(除非您使用 ,\scantokens
这与将其写入文件然后读回字符相同,但使用内部缓冲区以提高效率)。
答案3
\def\whatis#1{{\tt % use \ttfamily in LaTeX
\string#1:
\begingroup\escapechar=-1 \expandafter\endgroup
\expandafter\meaning\csname\string#1\endcsname
}}
\catcode`@=11 % \makeatletter in LaTeX
\def\MacroNameWith@InIt#1{whatever}
\catcode`@=12 % \makeatother in LaTeX
\whatis{\sqrt}
\whatis{\MacroNameWith@InIt}% <-- braces are necessary!
\bye
如果愿意的话,您可以轻松地将其转换为 LaTeX。
如果你确定\whatis
宏永远不会是另一个命令的参数,你可以这样做(假定为 LaTeX)
\newcommand\whatis{\begingroup\makeatletter\whatisaux}
\newcommand\whatisaux[1]{\ttfamily\string#1: \meaning#1\endgroup}