假设定义了一个宏\foo
:
\def\foo{\bar\space A hash {in {braces: \string##}\string##}}
扩展控制字标记/宏标记\foo可得到:
\bar\spaceA11␣10h11a11s11h11␣10{1i11n11␣10{1b11r11a11c11e11s11:12␣10\string#6}2\string#6}2
假定其中出现的控制序列标记均不是\outer
。
如何进行后处理以使每个哈希/类别 6/参数的每个显式字符标记加倍以获得?
\bar\spaceA11␣10h11a11s11h11␣10{1i11n11␣10{1b11r11a11c11e11s11:12␣10\string#6#6}2\string#6#6}2
反过来,这可以用作另一个宏的⟨替换文本⟩(的组成部分),该宏将通过\def
并且我不喜欢更改为通过定义\edef\AnotherMacro{\unexpanded{..}}
/我不喜欢更改为,\edef\AnotherMacro{\the\tokenregister}
因为执行\def
并且需要更改的代码来自不是我的宏包,我不知道用户是否依赖于不被更改/不被修补的东西。
(不幸的是,在许多 pgfkeys 宏的替换文本中,使用了类似的东西\edef\macro{\unexpanded{#1}}
来允许哈希作为参数 表示的参数的组成部分#1
。例如,在像和\def\macro{#1}
这样的处理程序的底层例程中似乎就是这种情况。如果这在最新的 pgfkeys 中已经得到纠正:我的一位同事仍然使用 TeX Live 2018,直到退休才会更新。).store in
.search also
我知道\meaning
、\write
和\scantokens
和\detokenize
双哈希,但使用这些,您会丢失有关字符标记类别的信息。 如果在 11 和其他字符之间翻转字符的类别代码,您也不知道哪些字符属于哪些控制序列的名称。 如果\escapechar
发生变化或不为正,您甚至根本不知道哪些字符属于控制序列的名称。
答案1
中有一些函数etl
可以搜索和替换宏参数标记。但它还有其他一些缺点(请参阅其文档,主要是关于一些不允许的内部标记、它将第 1 类和第 2 类标记规范化为{}
,以及某些标记无法以可扩展的方式相互区分)。
尽管如此,以下代码通过直接调用一个函数实现了哈希倍增,然后在一些伪设置宏中使用它作为 -internal 的示例pgfkeys
。我删除了\bar
,这样我就可以排版内容而无需进一步更改。
\documentclass{article}
\usepackage{etl}
\def\foo{\space A hash {in {braces: \string##}\string##}}
\ExplSyntaxOn
\cs_new:Npn \cattleya_double_hashes:n #1
{ \etl_token_replace_all_deep:nNn {#1} ## { #### } }
\cs_new_eq:NN \doublehashes \cattleya_double_hashes:n
\ExplSyntaxOff
% the other definition you don't have control over
\NewDocumentCommand\mysetupmacro{m}
{\def\macro{Stuff and #1 and stuff}}
\newcommand*\macro{} % initial value
\expanded{\noexpand\mysetupmacro{\expandafter\doublehashes\expandafter{\foo}}}
\begin{document}
\texttt{\meaning\macro}
\macro
\end{document}
答案2
我不确定这个令牌循环是否满足您的要求:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tokcycle,lmodern}
\tokcycleenvironment\showcats
{\ifcatSIX\addcytoks{\thistok{##1}{6}}\else\addcytoks{\catcomp{##1}}\fi}
{\addcytoks{\thistok{\{}{1}}\processtoks{##1}\addcytoks{\thistok{\}}{2}}}
{\addcytoks{\catcomp{##1}}\tctestifx{\par##1}{\addcytoks{\par}}{}}
{\ifimplicittok\addcytoks{\catcomp{##1}}\else
\addcytoks{\thistok{\textvisiblespace}{\number\catcode`##1}}\fi}
\newcommand\thistok[2]{#1$_{#2}$\,\allowbreak}
\makeatletter
\newcommand\catcomp[1]{%
\tctestifx{\implicitsixtok#1}{\expandafter\string#1$_{6}}{%
\string#1$_{%
\tctestifcatnx #1\relax{0}{%
\tctestifcatnx #1${3}{%
\tctestifcatnx #1&{4}{%
\tctestifcatnx #1^{7}{%
\tctestifcatnx #1_{8}{%
\tctestifcatnx #1\@sptoken{10}{%
\tctestifcatnx #1a{11}{%
\tctestifcatnx #11{12}{%
\tctestifcatnx #1~{13}{%
*%
}}}}}}}}}}%
}$\,\allowbreak%
}
\makeatother
\begin{document}
\let\foo\relax
\showcats\def\foo{\bar\space A hash {in {braces: \string##}\string##}}\endshowcats
\hrulefill
\def\foo{\bar\space A hash {in {braces: \string##}\string##}}
\detokenize\expandafter{\foo}
\expandafter\showcats\foo\endshowcats
\hrulefill
\newcommand\addhash{\cytoks\expandafter{\the\cytoks####}}
\resettokcycle
\Characterdirective{\ifcatSIX\addhash\addhash\else\addcytoks{#1}\fi}
\expandafter\tokcyclexpress\expandafter{\foo}
\expandafter\def\expandafter\food\expandafter{\the\cytoks}
\detokenize\expandafter{\food}
\expandafter\showcats\food\endshowcats
\end{document}
在第一个输出块中,如果在发生之前进行处理,则可以识别双重哈希值\def
,但这不是您所需要的。
在第二个块中,如果\def
首先出现,则根据的规则,双重哈希将丢失\def
。
在第 3 个块中,通过在预定义上操作给定的标记循环来恢复双重哈希,以使用循环标记 \foo
创建。我展示了去标记化,以及它的标记/分类代码细分。\food
\def
\food
我希望这可能正是您所要求的。