如何使用 {} 在 \tl_set_rescan:Nnn 中替换 \scantokens?

如何使用 {} 在 \tl_set_rescan:Nnn 中替换 \scantokens?

该问题与以下方面相关:更改 \tl_set_rescan:Nnn 中的转义字符) 和 (https://tex.stackexchange.com/a/496258/7832) 但并不相同。

我尝试改变这一点:

    \exp_args:NNx \_scontents_append_contents:nn \l_scontents_name_seq_tl 
      {
       \exp_not:N \scantokens \exp_after:wN { \l_tmpa_tl } %
      }

以这样的expl3方式使用其他的东西:\tl_set_rescan:Nnn

    \exp_args:NNx \_scontents_append_contents:nn \l_scontents_name_seq_tl 
      {
       < use \tl_set_rescan:Nnn over \l_tmpa_tl to obtain the same effect >
      }

但我无法获得相同的效果,我不知道要输入什么{<setup>}才能获得所需的结果。MWE 文件:

\documentclass{article}
\usepackage{filecontentsdef}[2019/04/20]
\usepackage{xparse}
\usepackage{fvextra} 
\setlength{\parindent}{0pt} % just for the example
\ExplSyntaxOn

\keys_define:nn { scontents }
  {
    save-env  .tl_set:N   = \l_scontents_name_seq_tl,
    save-env  .initial:n  = contents,
    show-env  .bool_set:N = \l_scontents_show_env_bool,
    show-env  .initial:n  = false  
  }

% Adapted from https://tex.stackexchange.com/a/215571/7832
\cs_new_protected:Npn \_scontents_append_contents:nn #1 #2
  {
    \seq_if_exist:cF { g_scontents_seq_name_#1_seq }
      {
        \seq_new:c { g_scontents_seq_name_#1_seq }
      }
    \seq_gput_right:cn { g_scontents_seq_name_#1_seq } { #2 }
  }

\cs_new_protected:Npn \_scontents_getfrom_seq:nn #1 #2
  {
    \seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
  }

\ProvideExpandableDocumentCommand{\getstored}{ O{1} m }
  {
    \_scontents_getfrom_seq:nn { #1 } { #2 }
  }

% Define scontents (wrap \filecontentsdefmacro) whit [key=val] Delaying
% Adapted from https://tex.stackexchange.com/a/487746/7832
\ProvideDocumentEnvironment{ scontents }{}
  {
    \char_set_catcode_active:N \^^M
    \scontents_start_environment:w
  }
  {
    \scontents_stop_environment:
    \scontents_atend_environment:
  }

\cs_new_protected:Npn \scontents_environment_keys:w [#1]
  {
    \keys_set:nn { scontents } { #1 }
  }

% Star environment
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \scontents_start_environment:w #1 ^^M
  {
    \tl_if_blank:nF { #1 } { \scontents_environment_keys:w #1 }
    \group_begin: % open group for env
    \use:c { filecontentsdefmacro } { \l_tmpa_tl } ^^M 
  }
\group_end:

% Stop environment
\cs_new_protected:Nn \scontents_stop_environment:
  {
    \endfilecontentsdefmacro 
    \group_end:  % close group for env
  }

% A variant to replace \^^M for \^^J (need by Verb{..} from fvextra)
% https://tex.stackexchange.com/a/8971/7832
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nxx } 

% Expand \l_tmpa_tl and pass to seq
\cs_gset_protected:Nn \_scontents_macro_to_seq:
  { 
    \regex_replace_all:nnN { \^^M } { \^^J } \l_tmpa_tl
    \cs_log:N \l_tmpa_tl
    \exp_args:NNx \_scontents_append_contents:nn \l_scontents_name_seq_tl 
      {
       \exp_not:N \scantokens \exp_after:wN { \l_tmpa_tl } %
      }
  }

% Code after scontent environment 
\cs_new_protected:Nn \scontents_atend_environment:
  {
    \_scontents_macro_to_seq:
    \bool_if:NT \l_scontents_show_env_bool
      {
        \_scontents_getfrom_seq:nn { -1 }{ \l_scontents_name_seq_tl }
      }
    \cs_undefine:N \l_tmpa_tl
  }
\ExplSyntaxOff
\begin{document}
\section*{Test environment}
Test \verb+\begin{scontents}+ no \verb+[key=val]+\par

\begin{scontents}
Using \verb+scontents+ env no \verb+[key=val]+, save in \verb+contents+ 
with index $1$\footnote{AND footnotes !!}.%

Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+

\begin{Verbatim}
(A) verbatim environment                                               %
many space here and percent at end of line                             %
                                many space                   
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
\end{scontents}

Test \verb+\begin{scontents}[save-env=other]+\par

\begin{scontents}[save-env=other]
    Now Using \verb+scontents+ env with \verb+[save-env=other]+, save in  
\verb+other+ with index $1$.

\begin{verbatim*}
      (B) verbatim environment

      kkkkkkkkkkkkkkkkkkkkkkkk
\end{verbatim*}
Show a space. 
\end{scontents}

\section*{Show stored contents}
XX\getstored[1]{contents}NO space here :)\par

YY\getstored[1]{other}A space here :)

\end{document}

问候。

答案1


2020 年 1 月 1 日:您好,Pablo,祝您和大家新年快乐!祝您平安健康!


问题的主题是:

如何使用来替换?{⟨setup⟩}\tl_set_rescan:Nnn\scantokens


\tl_set_rescan:Nnn是基于\scantokens/\tex_scantokens:D但两者的目的不同:

\tl_set_rescan:Nnn ⟨tl var⟩ {⟨setup⟩} {⟨tokens⟩}打算在特定的类别代码机制下,传递一系列重新标记(但没有进一步处理/消化)的标记作为标记列表变量的值/内容。

\tl_rescan:nn {⟨setup⟩} {⟨tokens⟩}打算在特定的类别代码机制下,传递一系列重新标记(但没有进一步处理/消化)的标记到 TeX 消化道中的标记队列进行进一步消化。

\scantokens{⟨tokens⟩}打算在当前类别代码制度下初始化一段 .tex 输入的重新消化。
标记化只是 TeX 消化 .tex 输入的一个方面/阶段。

使用这两个命令,重新标记/重新消化的 .tex-input 源是模拟⟨tokens⟩对某些模拟的空外部文本文件的未扩展写入的结果。


\tl_set_rescan:Nnn ⟨tl var⟩ {⟨setup⟩} {⟨tokens⟩} 执行以下操作:

  • 收集三个参数(在当前类别代码制度下)。
  • 根据 更改当前的类别代码机制⟨setup⟩。这将影响后续 .tex 输入的标记方式。这可能会影响控制序列标记到外部文本文件的未扩展写入。(更改类别代码可能会导致单字母控制序列不再被视为控制字标记,而是被视为控制符号标记,反之亦然。当未扩展写入控制字标记时,TeX 会附加一个空格字符。当未扩展写入控制符号标记时,TeX 不会附加空格字符。)
  • \newlinechar=\endlinechar
  • 模拟将结果未扩展写入某些模拟的外部文本文件。\detokenize{⟨tokens⟩}
  • 读取并标记(在此遵循更改的类别代码制度)整个模拟外部文本文件,如下所示:
    TeX 不会停止查看模拟外部文本文件并生成标记并累积它们(而不是消化它们),直到它看到/处理了模拟外部文本文件中包含的所有字符。当 TeX 看到/处理了模拟外部文本文件中包含的所有字符时,累积的标记将存储在 中⟨tl var⟩
    请注意,在此过程中较早产生的标记不会影响模拟的外部文本文件的后续字符的标记方式。在此过程中较早产生的标记不会影响模拟的外部文本文件的后续字符如何被标记,因为较早产生的标记不会被 TeX 消化而是会被累积。
  • 撤消当前类别代码制度的更改并撤消的更改\newlinechar

\tl_rescan:nn {⟨setup⟩} {⟨tokens⟩}几乎与 类似\tl_set_rescan:Nnn。唯一的区别是累积的标记不存储在 中⟨tl var⟩。当所有内容都累积起来并且对类别代码机制的更改被撤消时,所有标记都会立即插入 TeX 的消化道(扩展发生的地方)中的标记队列中,以便进一步消化。

\scantokens⟨general text⟩/ → 执行以下操作:\tex_scantokens:D⟨general text⟩
  ⟨general text⟩⟨filler⟩{⟨balanced text⟩⟨right brace⟩

  • 模拟将未扩展的标记写入⟨balanced text⟩某些模拟的外部文本文件。
  • 处理模拟的外部文本文件,就像它是通过 -primitive 加载的外部文本文件一样\input
    处理模拟的外部文本文件是发起与开始执行\scantokens/时当前的类别代码机制一致\tex_scantokens:D
    由此产生的标记不会累积以供以后存储。每个标记都会立即通过 TeX 的消化道。因此,每个标记都会像往常一样被 TeX 消化。消化标记的结果可能是类别代码机制的改变,这反过来又会影响模拟外部文本文件中的后续字符如何被标记化。

现在你可能会有这样的印象

\tl_rescan:nn {⟨setup⟩} {⟨tokens⟩}

就像

⟨setup⟩\scantokens{⟨tokens⟩}

模拟了将内容扩展\tl_rescan:nn或未 \scantokens扩展的文本写入外部文本文件的情况。⟨tokens⟩

细微的差别在于如何读回和标记模拟的外部文本文件:

模拟的外部文本文件的所有行/字符都会\tl_rescan:nn被一次性标记。生成的标记集会“一次性”插入到 TeX 管道中的标记队列中。

.tex 输入文件的消化\scantokens过程照常进行:
只有当嘴巴需要字符来生成标记时,才会从模拟的外部文本文件中读取和标记字符。
只有当食道(扩展机器)需要标记时,嘴巴才会生成标记。当
胃需要标记时,例如生成盒子、执行任何任务,食道就会将标记发送到胃。

因此

\scantokens\expandafter{\string\verb+text+}

该标记\verb已被消化。\verb导致标记化并“查看”下一个标记(预计是字符标记),在本例中为字符标记,并且(通过一些技巧)使相应字符(在本例中为)处于活动状态并在 verbatim-catcode-régime 下读取/标记化/处理后续字符,直到标记了一个活动的字符,表示 的参数的结束。+12\lowercase++\verb

但随着

\exp_args:Nno \tl_rescan:nn {} {\token_to_str:N \verb+text+}

令牌\verb不会立即被消化。相反,它会像其他东西一样被积累起来。
最后,令牌序列

\verbcontrol word token+12t11e11x11t11+12

被积累起来并插入到 TeX 喉咙里的令牌队列中。

问题是:\verb在这种情况下,将 的类别代码切换为+active ,并保持 TeX 在 verbatim-catcode-régime 下对事物进行标记,直到标记了 active- +。但是 TeX 不会对 active- 进行标记,+因为序列中的第二个已经用类别代码 12(其他)进行了标记。无法找到 的参数+结尾。\verb


如果我理解正确的话,在您的代码中,宏的\_scontents_macro_to_seq:目的是用换行符替换标记列表变量中的所有结束符\l_tmpa_tl,并将序列附加到变量。\scantokens{total expansion of the content of the token-list-variable \l_tmpa_tl}\l_scontents_name_seq_tl

由于就读回/摘要模拟的外部文本文件而言,各种摘要操作发生的时间顺序对于\scantokens/\tex_scantokens:D\tl_rescan:nn/不同\tl_set_rescan:Nnn,因此无法使用或进行模拟。\scantokens{⟨tokens⟩}\tl_rescan:nn\tl_set_rescan:Nnn

相关内容