我正在尝试一下这个\tl_set_rescan:Nnn
功能(最初是为了让这个答案更简洁),但我正在努力使这个函数的哪怕非常简单的用法都能够发挥作用。
假设我们想让所有\
字符、字母和空格都具有其通常的 catcode。据我所知,以下代码应产生相同的输出:
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\group_begin:
\char_set_catcode_escape:N \~
~char_set_catcode_letter:N ~\
~char_set_catcode_space:n {32}
~tl_set:Nn ~l_tmpa_tl {<\verb|\LaTeX| \LaTeX>}
~tl_show:N ~l_tmpa_tl
~group_end:
%%%%%%%%%%
\tl_set_rescan:Nnn \l_tmpa_tl
{ \char_set_catcode_space:n {32} \char_set_catcode_letter:N \\ }
{<\verb|\LaTeX| \LaTeX>}
\tl_show:N \l_tmpa_tl
\ExplSyntaxOff
\end{document}
输出
> \l_tmpa_tl=<\verb|\LaTeX| \LaTeX>.
> \l_tmpa_tl=<\verb |\LaTeX |\LaTeX >.
第一个标记列表的结果是正确的,\
被设为字母字符,因此控制序列后没有输出多余的空格。然而,在重新扫描尝试中,控制序列仍然存在。还请注意第二个之后缺少的空格|
。
如何让第二个版本产生预期结果?或者可能更广泛一点,因为这些函数似乎不能很好地与逐字输入配合使用,它们的指定用例是什么?
答案1
在执行此操作时~tl_set:Nn ~l_tmpa_tl {<\verb|\LaTeX| \LaTeX>}
,您已经将 catcode 设置 \
为 11,并将空格字符的 catcode 设置为 10,因此在扩展时~tl_set:Nn
(抓取文本作为参数),伪控制序列是不是被标记为控制序列,因此 TeX 不会在它们后面添加任何空格,并且被标记的内容是:
<
12 \
11 v
11 e
11 r
11 11 12 11 11 11 11 11 b
11 12 10 11 11 11 11 11 11 12|
\
L
a
T
e
X
|
\
L
a
T
e
X
>
请注意,由于您没有在伪控制序列(\verb
和\LaTeX
)后插入任何空格,因此它们没有按预期显示。另外,空格位于第二个|
12之后,因为在扩展时~tl_set:Nn
没有忽略空格。
现在,你结束该组,一切恢复正常。当 TeX 扩展\tl_set_rescan:Nnn
并获取<\verb|\LaTeX| \LaTeX>
参数时,\
,是控制字符,空格是 catcode 9,IE,忽略。因此,当 TeX 看到它时,文本会立即被标记为 7 个标记:
<
12 \verb
|
12 \LaTeX
|
12 \LaTeX
>
12
请注意,后面的空格从|
一开始就不存在,还请注意,在三个控制序列\verb
、\LaTeX
和之后\LaTeX
,TeX 会插入通常的控制序列后空格。因此,在这种 catcode 机制中,TeX 实际上首先看到的是是 <\verb |\LaTeX |\LaTeX >
。现在\tl_set_rescan:Nnn
开始执行操作并将整个事物重新标记为:
<
12 \
11 v
11 e
11 r
11 b
11 10
|
12 \
11 L
11 a
11 T
11 e
11 X
10 12 11 11 11 11 11 10
|
12 11 11 11 11 11 10 12\
L
a
T
e
X
>
简而言之:问题在于您的两个输入从一开始就不同。