这与 LaTeX3 和 TL2017 中引入的变化有关。
我正在定义一个构造框的命令,但我需要在框的开头放入一些内容。因此,我先查找左括号,从流中吸收它,执行我想要执行的额外操作,然后使用 来开始框\c_group_begin_token
。
这在 TL2016 中有效,但在 TL2017 中却有缺陷。
具体来说,如下代码:
\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\box_new:N \l__tmpa_box
\cs_new_nopar:Npn \dobox
{
\exp_after:wN \dobox_aux: \tex_let:D \l_peek_token =
}
\cs_new_nopar:Npn \dobox_aux:
{
\hbox_set:Nn \l__tmpa_box
\c_group_begin_token
in~the~box~
}
\cs_new_nopar:Npn \dobebox
{
\box_use:N \l__tmpa_box
}
\ExplSyntaxOff
\begin{document}
greetings
\dobox{hello world}
everyone
\dobebox
\end{document}
在 TL2016 中编译产生输出:
greetings everyone in the box hello world
但在 TL2017 中,我收到了一个投诉:
! Missing } inserted.
<inserted text>
}
l.32 \dobox
{hello world}
?
! Too many }'s.
l.32 \dobox{hello world}
?
产生的输出是:
greetings in the box hello world everyone
表明盒子构造被忽略了。
有没有办法来解决这个问题?
答案1
标准 TeX 代码的翻译:
\newbox\mybox
\def\dobox{%
\expandafter\doboxaux\let\mytoken =%
}
\def\doboxaux{%
\setbox\mybox=\hbox\bgroup in the box
}
\def\dobebox{%
\copy\mybox
}
请注意,这\expandafter
将什么也不做。当你调用
\dobox{hello world}
宏\doboxaux
立即被展开,你得到
\setbox\mybox=\hbox\bgroup in the box \let\mytoken={hello world}
被{
吞噬\let\mytoken=
,因此框将包含“hello world”。
结果是
盒子里的问候 大家好,世界
\hbox_set:Nn \l__tmpa_box
然而,非常不同于\setbox\mybox=\hbox
。后者接受\bgroup
(在expl3
术语中\c_begin_group_token
)而前者不接受,因为它是一个双参数函数,并且n
参数不能被 分隔\bgroup
。
过去可能存在的事实无关紧要。你滥用了expl3
。以下是\cs_show:N \hbox_set:Nn
结果
> \hbox_set:Nn=\protected\long macro:#1#2->\tex_setbox:D #1\tex_hbox:D
{\group_begin: #2\group_end: }.
因此您会看到 被#2
抓取为正常参数。您的(错误)宏过去之所以能工作#2
是因为\c_group_begin_token
。其效果与您在 LaTeX2e 中获得的效果非常相似,\mbox\bgroup foo\egroup
似乎可以工作,但实际上却不行。 的定义\hbox_set:Nn
已更改,并且(错误)混合物现在会引发错误。
你可能想做
\def\dobox{%
\afterassignment\doboxaux\let\mytoken=
}
\def\doboxaux{%
\setbox\mybox=\hbox\bgroup in the box
}
\def\dobebox{%
\copy\mybox
}
唉,expl3
没有提供接口\afterassignment
。