如何在宏中将 @ 设为字母

如何在宏中将 @ 设为字母

我定义了一个宏,它本质上是一个用于\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由于分组,这没有必要。)不用说,这是行不通的,否则我就不会发布这个问题了:-)

我的问题:

  1. 为什么这不起作用?
  2. 我怎样才能定义如我所愿的行为\whatis\whatis{\MacroNameWith@InIt}

答案1

关键是要\makeatletter在参数命中宏之前调用。因此,在这里,我将参数吸收移到\whatisaux\makeatletter在调用之后\whatis

\documentclass{article}
\makeatletter
\def\whatis{\makeatletter\whatisaux}
\def\whatisaux#1{{\ttfamily\string#1: \meaning#1}\makeatother}
\makeatother
\begin{document} 
\whatis\MacroNameWith@InIt
\end{document} 

在此处输入图片描述

答案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}

相关内容