我想定义一个宏,用打字机字体排版其参数,并允许其参数中有下划线字符。在一个组中,我将其_
激活,定义\_
为排版为下划线,然后插入文本。
这种方法很有效外部我的宏定义,但是Missing $ inserted
如果我尝试将一些包含下划线字符的文本作为参数传递给相关宏,TeX 会报错。发生了什么?
\documentclass{article}
\newcommand\allowsforunderscores[1]%
{%
\begingroup
\ttfamily
\catcode`\_=\active
\let\_\textunderscore%
#1%
\endgroup
}
\begin{document}
%\allowsforunderscores{Bertrand_Russell} % if uncommented, this generates an error
% However, the following compiles just fine.
{
\ttfamily
\catcode`\_=\active
\let\_\textunderscore
Bertrand_Russell%
}
\( 4_4 \) % sanity check
\end{document}
答案1
你的策略有三个错误。
第一个错误:\let\_=\textunderscore
没有对活动的 做任何事情_
。
第二个错误:即使你输入\let_=\textunderscore
这个也不会起作用,因为_
在执行定义时不活动,所以令牌_
仍然有类别代码 12,并且\let_=\textunderscore
在宏调用时是非法的。请注意,你能用于\_
表示下划线的字符代码,例如
\catcode`\_=\active
但这并不意味着您可以用\let\_=...
它赋予活动下划线以含义。
第三个错误:除非使用,否则您不能更改已经吸收的参数中的标记的类别代码\scantokens
。
\documentclass{article}
\makeatletter
%% A macro used in both strategies
%% At definition time the token `_` must be active
\begingroup
\catcode`_=\active
\gdef\activate@us{%
\let_\textunderscore
\catcode`\_=\active
}
\endgroup
%%% Alternative definition of \activate@us not requiring \gdef
%\begingroup\lccode`\~=`\_
%\lowercase{\endgroup
% \def\activate@us{\let~\textunderscore\catcode`\_=\active}}
% First strategy
\newcommand{\allowforunderscoresA}{%
\begingroup
\activate@us
\@allowforunderscores
}
\newcommand{\@allowforunderscores}[1]{%
\ttfamily
#1%
\endgroup
}
% Second strategy
\newcommand{\allowforunderscoresB}[1]{%
\begingroup\activate@us\ttfamily
\scantokens{#1\endinput}%
\endgroup
}
\makeatother
\begin{document}
X\allowforunderscoresA{Bertrand_Russell}X
X\allowforunderscoresB{Bertrand_Russell}X%
\footnote{\allowforunderscoresB{Bertrand_Russell}}
\end{document}
请注意,第一个宏不能出现在另一个命令的参数中,而\allowforunderscoresB
可以。
答案2
传递给宏的不是字符序列,而是标记序列。Catcode 更改对标记没有影响,它们只会更改从字符生成标记时使用的映射。这正是您不能\verb
在宏参数中使用的原因。
最简单的解决方案是使用url
包和(它使用数学模式而不是 catcode 更改来完成其工作,或者您可以在更改 catcodes 后\url{Bertrand_Russell}
使用重新标记该参数。\scantokens
答案3
但\allowsforunderscores
不能在另一个宏的参数内使用。在某些环境中可以毫无问题地使用它。除了那些收集其内容的讨厌的宏(这种情况很少见)。
\documentclass{article}
\catcode`_ 13
\newcommand\allowsforunderscores
{%
\bgroup
\ttfamily
\let_\textunderscore
\catcode`\_=\active
\let\next=%
}%
\catcode`_ 8
\begin{document}\thispagestyle{empty}
\allowsforunderscores{Bertrand_Russell}
Hello $H_{ij}$
\end{document}