如何在修改后的环境下运行 scantokens,但在扫描的代码中使用正常环境?

如何在修改后的环境下运行 scantokens,但在扫描的代码中使用正常环境?

例如如果我运行

%! TEX program = lualatex
\documentclass{article}
\begin{document}


{% prepare a token list <a> (assume this is provided by user)
\catcode 13=12\relax  % 12:other
\global\def\a{line 1^^M^^Mline 2^^M^^Mnewlinechar=\the\newlinechar^^M}%
}

% scan \a, but with newlinechar=13...
\newlinechar=13\relax
\expandafter\scantokens\expandafter{\a}
% but then the code inside should still see newlinechar=10.

\end{document}

每个由 charcode 为 13 的字符分隔的部分将作为单独的行写出;然而里面的代码将看到 \newlinechar=13。

假设我希望里面的代码看到的值等于正常值,即 10。我该如何实现?(该命令似乎没有提供任何明显的方法来实现。)

(还假设里面的代码是任意的用户提供的内容,可能不应该被触碰,并且它可能包含应该遵守的 catcode 更改命令。)

答案1

好吧,我能找到几种方法。

修改输入以适应换行符

正如 Skillmon 所建议的那样。

\cs_generate_variant:Nn \tl_replace_all:Nnn { Nee }
\tl_replace_all:Nee \a { \char_generate:nn { 13 } { 12 } } { \char_generate:nn { \newlinechar } { 12 } }
\tl_set_rescan:Nno \a {} { \a }

问题\newlinechar:如果是 -1 或其他奇怪的值(例如) ,则会出现问题/,并且用户代码恰好/也有一个。

扩展\scantokens一次然后恢复 newlinechar

看起来的 o 扩展\scantokens与 的 o 扩展类似\@@input,将内容放在输入流的前面。

这将适用于问题中的示例。(执行之前先\endgroup展开\scantokens一次。另一个是展开\a。旁注,\scantokens是一个原语,它展开以下标记直到看到{,所以\expandafter之前的另一个是不必要的。)

%! TEX program = lualatex
\documentclass{article}
\begin{document}


{% prepare a token list <a> (assume this is provided by user)
\catcode 13=12\relax  % 12:other
\global\def\a{line 1^^M^^Mline 2^^M^^Mnewlinechar=\the\newlinechar^^M}%
}

% scan \a, but with newlinechar=13...
\begingroup\newlinechar=13\relax\expandafter\endgroup
\scantokens\expandafter{\a}
% but then the code inside should still see newlinechar=10.

\end{document}

使用活动字符恢复重新扫描的标记内的换行符

%! TEX program = lualatex
\documentclass{article}
\begin{document}


{% prepare a token list <a> (assume this is provided by user)
\catcode 13=12\relax  % 12:other
\global\def\a{line 1^^M^^Mline 2^^M^^Mnewlinechar=\the\newlinechar^^M}%
}

\begingroup
\catcode `\~\active
\let~\endgroup
\newlinechar=13\relax
\scantokens\expandafter{\expandafter~\a}

\end{document}

我认为这种方法没有任何缺点(如果的默认 catcode~未激活,它将在组关闭时重置,这\endlinechar无关紧要)。基本上

  • 开一个群
  • 使其~处于活动状态,并使其在执行时关闭组
  • \newlinechar
  • 传递~⟨content⟩\scantokens。当~执行重新扫描时,该组将被关闭。

相关内容