定义将下划线字符排版为 _ 的宏时遇到问题

定义将下划线字符排版为 _ 的宏时遇到问题

我想定义一个宏,用打字机字体排版其参数,并允许其参数中有下划线字符。在一个组中,我将其_激活,定义\_为排版为下划线,然后插入文本。

这种方法很有效外部我的宏定义,但是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}

相关内容