![l3doc 中 @@ 替换的微妙之处](https://linux22.com/image/478159/l3doc%20%E4%B8%AD%20%40%40%20%E6%9B%BF%E6%8D%A2%E7%9A%84%E5%BE%AE%E5%A6%99%E4%B9%8B%E5%A4%84.png)
我正在尝试了解类@@
中替换的确切语义l3doc
。到目前为止,我从文档中收集到的信息如下:
%<@@=name>
在文档中出现声明之前没有发生替换。当发生替换时,将按照字符序列(从左到右)的顺序尝试并替换以下模式:
"@@@@" -> "@@" "__@@" -> "__" + name "_@@" -> "__" + name "@@" -> "__" + name
\cmd
替换发生在和的参数中\cs
,除非replace=false
在这些命令的可选参数中定义了。function
替换发生在和环境的第一个参数中列出的所有控制序列名称中macro
。- 替换发生在
\begin{macrocode}
和之间的所有行中\end{macrocode}
,除非该字符序列<@@=
出现在该行中。
我的问题:
- 还有其他地方可以进行替换吗?
- 是否有其他选项(全球性或本地性)对替换有影响?
%<@@=name>
如果在同一文档中出现多个声明,预期的替换行为是什么?
答案1
替换发生在两种情况下。第一种是 docstrip 步骤,即读取源代码并将源代码.dtx
复制到目标.sty
/.cls
文件;第二种是再次读取代码以排版文档和实现。
在文档删除步骤中l3docstrip.tex
使用代码,该代码\moduleOption
对原始代码进行了修补docstrip.tex
,以包含语法的可能性%<@@=...>
。这里docstrip.tex
逐行读取输入文件,如果%<@@=...>
发现,程序将设置活动模块名称,并对所有后续行使用进行替换\replaceModuleInLine
(否则将是一个空定义)。可以使用任意数量的%<@@=...>
,代码将更改为新的模块名称。这里替换总是会发生,无论任何设置如何,只要出现%<@@=...>
并且\replaceModuleInLine
没有被清除。
在排版步骤中,执行替换的命令是\__codedoc_replace_at_at:N
。第一个条件是,只有当\g__codedoc_module_name_tl
不为空时,即%<@@=name>
给出了 a 时,才会进行替换,正如您已经说过的。这是替换宏本身中应用的唯一替换条件,因此它是“最全局”的条件。其他条件则根据上下文应用。
其他出现\__codedoc_replace_at_at:N
于:
\__codedoc_cmd:nn
\cmd
,由、\cs
和所使用,并且仅当(即选项)为真\tn
时才会发生。选项中的默认为 false,因此您需要触发替换。\l__codedoc_cmd_replace_bool
replace
\tn
replace
\tn[replace=true]
\__codedoc_names_get_seq:nN
,由 和 两者使用,\__codedoc_function:nnw
而和 又由、和环境\__codedoc_macro:nnw
使用。替换发生在这些环境的强制参数中,即所描述的变量/函数/宏的列表。在其中任何一个中,如果(即选项) 设置为 false,则会发生替换,因此不会替换。variable
function
macro
\l__codedoc_names_verb_bool
verb
\begin{macro}[verb]{\@@_something:n}
\__codedoc_xmacro_code:n
由环境使用macrocode
。在此环境中,替换始终发生(假设%<@@=...>
在某处使用),但这里有两种不同的行为。第一种是如果%<@@=....>
环境中没有,则替换正常发生。第二种是如果环境中有。在这种情况下,将抓取%<@@=...>
到的代码,将其全部替换为当前模块名称,更新模块名称,然后继续扫描代码以查找下一个或环境的末尾。直到最近,如果在单个环境中发现 多个代码,代码就会中断(在单独的环境中仍可能出现任意多个代码)。这个问题已经修复(%<@@=...>
@@
%<@@=...>
%<@@=...>
macrocode
97daab8
) 及更新版本l3doc
(晚于 2019 年 6 月 27 日)应该具有与 相同的替换行为l3docstrip
。
l3doc
对于2019 年 6 月 27 日之前的版本:
当macrocode
环境包含时%<@@=...>
,它将全局更改 的值\g__codedoc_module_name_tl
,并且从那时起将使用新值,因此您可以%<@@=....>
在文档中任意使用多个 。例如,此源(假设%<@@=...>
之前未使用):
% \begin{macrocode}
\cs_new:Npn \@@_world:n {}
%<@@=hello>
\cs_new:Npn \@@_world:n {}
% \end{macrocode}
变成这样的代码:
\cs_new:Npn \@@_world:n {}
\cs_new:Npn \hello_world:n {}
%<@@=...>
但是每个环境预计只使用一次macrocode
,因此该来源:
% \begin{macrocode}
\cs_new:Npn \@@_world:n {}
%<@@=hello>
\cs_new:Npn \@@_world:n {}
%<@@=goodbye>
\cs_new:Npn \@@_world:n {}
% \end{macrocode}
中断 :-)
为:
! Missing { inserted.
<to be read again>
\sb
l.228 % \end{macrocode}
?
因为代码用 替换了@@
中%<@@=goodbye>
的__hello
,不知道这是名称空间的另一次更改,因此造成混乱。\__codedoc_xmacro_code:n
和的轻微更改使 的\__codedoc_xmacro_code:w
行为与替换 的行为l3cls
相同(放在您的序言中):l3docstrip
@@
\group_begin:
\char_set_catcode_letter:N \@
\char_set_catcode_active:N \<
\char_set_catcode_active:N \>
\let\tmpa\__codedoc_xmacro_code:n
\cs_gset_protected:Npn \__codedoc_xmacro_code:n #1
{
\tl_clear:N \l__codedoc_tmpa_tl
\tl_if_in:nnTF {#1} { < @ @ = }
{ \__codedoc_xmacro_code:w #1 < @ @ = \q_recursion_tail > \q_recursion_stop }
{
\tl_set:Nn \l__codedoc_tmpa_tl {#1}
\__codedoc_detect_internals:N \l__codedoc_tmpa_tl
\__codedoc_replace_at_at:N \l__codedoc_tmpa_tl
\tl_use:N \l__codedoc_tmpa_tl
}
}
\cs_gset_protected:Npn \__codedoc_xmacro_code:w #1 < @ @ = #2 >
{
\tl_set:Nn \l__codedoc_tmpb_tl {#1}
\__codedoc_detect_internals:N \l__codedoc_tmpb_tl
\__codedoc_replace_at_at:N \l__codedoc_tmpb_tl
\tl_put_right:NV \l__codedoc_tmpa_tl \l__codedoc_tmpb_tl
\quark_if_recursion_tail_stop_do:nn {#2}
{ \tl_use:N \l__codedoc_tmpa_tl }
\tl_gset:Nn \g__codedoc_module_name_tl {#2}
\tl_put_right:Nn \l__codedoc_tmpa_tl { < \text { \verbatim@font @ @ = #2 } > }
\__codedoc_xmacro_code:w
}
\group_end:
上述代码使得%<@@=...>
在一个macrocode
环境中拥有任意多个成为可能。