![收集两个宏之间的内容并传递给第三个宏](https://linux22.com/image/448256/%E6%94%B6%E9%9B%86%E4%B8%A4%E4%B8%AA%E5%AE%8F%E4%B9%8B%E9%97%B4%E7%9A%84%E5%86%85%E5%AE%B9%E5%B9%B6%E4%BC%A0%E9%80%92%E7%BB%99%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%AE%8F.png)
是否可以定义这样的两个宏\mymodule_start_collecting:
,\mymodule_stop_collecting:
并将它们之间的内容作为参数传递给第三个(给定的)宏?
动机:我想要两个宏来修剪它们之间内容两侧的空格。例如,\MacroOne Te xt \MacroTwo
应该表现得像Te xt
。我的想法是收集内容并将其传递给\tl_trim_spaces:n
,因此有这个问题。
答案1
如果要防止周围牙套的脱落:
\cs_new:Npn \MacroOne
{ \mymodule_start_collecting:w \prg_do_nothing: }
\cs_new:Npn \mymodule_start_collecting:w #1 \MacroTwo
{ \exp_args:No \tl_trim_spaces:n {#1} }
如果你不关心周围的括号,那么它会简单得多:
\cs_new:Npn \MacroOne #1 \MacroTwo
{ \tl_trim_spaces:n {#1} }
注意\mymodule_start_collecting:
要有签名w
。
答案2
答案3
如果你\MacroOne
的总是接下来\MacroTwo
,你只需这样做
\NewExpandableDocumentCommand{\MacroOne}{}
{
\mymodule_start_collecting:w
}
\cs_new:Npn \mymodule_start_collecting:w #1 \MacroTwo
{
\tl_trim_spaces:n { #1 }
}
请注意,您必须拥有明确地 \MacroTwo
在定义中,因为 TeX 在吸收参数(分隔或非分隔)时不会扩展标记。
如果你的用例包括类似
\MacroOne { Te xt} \MacroTwo
并且你想保留括号后的空间,那么使用
\NewExpandableDocumentCommand{\MacroOne}{}
{
\mymodule_start_collecting:w \prg_do_nothing:
}
\cs_new:Npn \mymodule_start_collecting:w #1 \MacroTwo
{
\exp_args:No \tl_trim_spaces:n { #1 }
}
(中的第一个项#1
是\prg_do_nothing:
,其扩展为空)。
如果你还想\MacroTwo
执行该操作,请将其添加回末尾
\NewExpandableDocumentCommand{\MacroOne}{}
{
\mymodule_start_collecting:w
}
\cs_new:Npn \mymodule_start_collecting:w #1 \MacroTwo
{
\tl_trim_spaces:n { #1 } \MacroTwo
}
(或保留大括号的修改)。
答案4
Phelype Oleinik 和 egreg 提供了 的保留大括号变体\MacroOne ... \MacroTwo
。
使用这些变体,如果存在显式空格标记序列,则会在形成 -delimited 参数的标记集的左侧和右侧删除它们\MacroTwo
。如果可以将生成的标记集视为由最外层一对匹配的花括号包围的一组标记,则该对匹配的花括号将保留在原处,花括号内的显式空格标记序列也将保留在原处。
因此,可以使用一对匹配的花括号来防止删除空格。
但是,如果存在这对用于防止删除空格的匹配花括号,则它们将保留在原处。
我可以想到这样的情况:使用一对匹配的花括号来防止删除里面有内容的空格是可取的,但您更喜欢将用于防止删除空格的花括号去掉,因为当完成空格删除后,花括号已经完成了它们的使命,不再需要它们,从而防止删除花括号内的空格。
以下代码提供了一种变体,其中,如果存在分隔参数\MacroA...\MAcroB
左侧和右侧的空格标记\MacroB
,以及之后的空格标记(如果存在),则删除围绕该参数的所有其他标记的最外层一对匹配的花括号,但保留最外层一对匹配的花括号内内容的空格(如果存在)。
这样,在任何情况下,参数的“包围除前导和尾随空格之外的所有内容”的一级花括号都被视为“空格标记删除阻止器”,无论如何,该阻止器都会在过程中被剥离。
由于\romannumeral
/\exp:w
扩展,可以通过在 上触发两个扩展步骤来获得结果\MacroOne
。
\ExplSyntaxOn
\cs_new:Npn \MacroOne
{
\exp:w \__mymodule_start_collecting:w \prg_do_nothing:
}
\cs_new:Npn \__mymodule_start_collecting:w #1 \MacroTwo
{
\exp_args:Ne \__mymodule_RemoveSurroundungBraces:n { \tl_trim_spaces:o { #1 } }
}
\cs_new:Nn\__mymodule_RemoveSurroundungBraces:n
{
\tl_if_blank:nTF { #1 }
{ \exp_end: #1 }
{
\exp_args:No \tl_if_empty:nTF { \use_none:n #1 }
{ \use:nn {\exp_end:} #1 }
{ \exp_end:#1 }
}
}
%----------------------------------------------------------------------------------
% \InsertSpacesAndCallMacroOne{<Argument>} defines the macro \test from the result
% of triggering two expansion-steps on \MacroOne<Argument>\MacroTwo and shows the
% meaning of \test on the console. Instances of #1 within <Argument> are replaced
% by explicit tokens before expanding \MacroOne.
%
\cs_new:Npn \InsertSpacesAndCallMacroOne #1#2
{
\cs_gset:Npn \InsertSpacesAndCallMacroOne ##1
{
\cs_set:Npn \test ####1
{
\exp_args:NNf \cs_set:Npn \test {
\exp_after:wN \exp_after:wN \exp_after:wN |
\MacroOne##1\MacroTwo|~is~the~result~of~|#1##1#2|
}
\tex_show:D \test
}
\test{~}
}
}
\exp_args:Noo \InsertSpacesAndCallMacroOne{\token_to_str:N \MacroOne}{\token_to_str:N \MacroTwo}
\ExplSyntaxOff
% #1 within the argument of \InsertSpacesAndCallMacroOne denotes space token
\InsertSpacesAndCallMacroOne{#1#1#1{#1Te#1xt#1}#1#1#1}%
\InsertSpacesAndCallMacroOne{{#1Te#1xt#1}#1#1#1}%
\InsertSpacesAndCallMacroOne{#1#1#1{#1Te#1xt#1}}%
\InsertSpacesAndCallMacroOne{#1#1#1#1Te#1xt#1#1#1#1}%
\InsertSpacesAndCallMacroOne{#1#1#1{#1Te}#1xt#1#1#1#1}%
\InsertSpacesAndCallMacroOne{#1#1#1{#1{#1Te}#1xt#1}#1#1#1}%
% For this minimal example, no document environment was needed and
% therefore not loaded. So now we end the LaTeX run with the
% "sledgehammer method", i.e., with the command \stop:
\stop
控制台输出摘录:
| Te xt | is the result of |\MacroOne { Te xt } \MacroTwo|.
| Te xt | is the result of |\MacroOne{ Te xt } \MacroTwo|.
| Te xt | is the result of |\MacroOne { Te xt }\MacroTwo|.
|Te xt| is the result of |\MacroOne Te xt \MacroTwo|.
|{ Te} xt| is the result of |\MacroOne { Te} xt \MacroTwo|.
| { Te} xt | is the result of |\MacroOne { { Te} xt } \MacroTwo|.