在宏中激活角色

在宏中激活角色

我以为我很聪明,所以我把此代码本地允许将内联数学中的中断放入宏中:

\documentclass{article}
\def\MakeCommaBreakable{%
    \def\OldComma{,}
    \catcode`\,=13
    \def,{%
        \ifmmode%
        \OldComma\discretionary{}{}{}%
        \else%
        \OldComma%
        \fi%
    }%
}
\begin{document}
    \MakeCommaBreakable
    $xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx$
\end{document}

现在,失败了;第一个错误:

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
l.14    \MakeCommaBreakable

什么原因导致此错误?

答案1

诀窍是让逗号数学活跃

这样,命令\MakeCommaBreakable就可以正确执行里面公式,因此数学激活的效果受到限制。

\documentclass{article}
\usepackage{amsmath}

\newcommand{\MakeCommaBreakable}{%
  \mathchardef\normalcomma=\mathcode`,
  \begingroup\lccode`~=`,\lowercase{\endgroup\let~}\BreakableComma
  \mathcode`,="8000
}
\newcommand{\BreakableComma}{%
  \normalcomma\mspace{0mu plus 6mu}\penalty0
}

\begin{document}

$\MakeCommaBreakable xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx$

\end{document}

在此处输入图片描述

你的代码有什么问题?

首先,即使它是固定的,你也会在外层使逗号处于活动状态,这不是好事。但这并不是主要原因:当 TeX 读取 的定义时\MakeBreakableComma,替换文本已被标记且,类别代码为 12,因此它无法跟随\def

使用这个\lowercase技巧,TeX 看到的是一个活动逗号,因为\lowercase不会改变类别代码。

可能使逗号处于活动状态,而不仅仅是数学处于活动状态,但我不建议这样做,因为如果它处于活动状态,则您无法在选项规范中使用它。数学活动字符仅在 TeX 检查数学代码时才会呈现“活动状态”。

为了完整起见,你也可以\MakeBreakableComma在外层放置全部数学公式中的逗号会变得易断:绝对不推荐,因为你不想破坏类似这样的东西f(x,y)

答案2

\def\MakeCommaBreakable在 的主体被扫描时,,中的\def,catcode 尚未设置为 13,而扫描之后 catcode 会被保存,因此不会受到定义主体内部 catcode 变化的影响,因此 TeX 会在 之后抱怨控制序列丢失/def。使用 Plain TeX 代替 LaTeX 可以给出更直观的错误信息:

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
<to be read again> 
                   ,
\MakeCommaBreakable ... {,} \catcode `\,=13 \def ,
                                                  {\ifmmode \OldComma \discr...
l.12 \MakeCommaBreakable

我假设您想要获取一个可拆分的命令,但仅使用 存在一些问题\discretionary{}{}{},即如果一行中没有可拉伸的空间(粘连),TeX 几乎总是会抱怨框太满。根据您的需要,您可能需要或不需要该粘连或更改其大小。

正确的方法可能是:

\bgroup
% make sure it is defined before catcode change to prevent infinite expand
\gdef\OldComma{,}
\catcode`\,=13
\gdef\MakeCommaBreakable{%
    \catcode`\,=13
    \def,{%
        \ifmmode
% You don't need to place % after control token, because
% TeX already ignores them.
% Also, consider use math glue to give some adjustable spacing, otherwise
% TeX would almost always report overfull box for a long line like this
        \OldComma\>\allowbreak
        \else
        \OldComma
        \fi
    }%
}
\egroup
\MakeCommaBreakable
    $xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx$
\bye

相关内容