我需要一个接收控制序列作为参数的宏来测试这个控制序列是否真的是一个\outer
宏。我可以自己编写代码,如下所示。
\documentclass{minimal}
\usepackage{expl3}
\ExplSyntaxOn
\group_begin:
\char_set_lccode:nn { `\; } { `\: }
\char_set_lccode:nn { `\Z } { `\t }
\char_set_lccode:nn { `\T } { `\T }
\char_set_lccode:nn { `\F } { `\F }
\tl_map_function:nN { O U Z E R M A C R ; } \char_set_catcode_other:N
\tl_to_lowercase:n
{
\group_end:
\prg_new_conditional:Nnn \cs_if_outer_macro:c { p, T , F , TF }
{
\exp_last_unbraced:Nf \cs_if_outer_macro_aux:w
\cs_meaning:c {#1} OUZER ~ MACRO ; \q_stop
}
\cs_new_nopar:Npn \cs_if_outer_macro_aux:w #1 OUZER ~ MACRO ; #2 \q_stop
{
\prg_case_str:xxn { #1 ~ }
{
{ \token_to_str:N \ }
{ \prg_return_true: }
{ \token_to_str:N \long \token_to_str:N \ }
{ \prg_return_true: }
{ \token_to_str:N \protected \token_to_str:N \ }
{ \prg_return_true: }
{ \token_to_str:N \protected \token_to_str:N \long \token_to_str:N \ }
{ \prg_return_true: }
}
{ \prg_return_false: }
}
}
\cs_new_eq:NN \IfOuterMacroTF \cs_if_outer_macro:cTF
\ExplSyntaxOff
\long\outer\protected\def\fooa{}
\outer\def\foob{}
\def\fooc{}
\def\food{outer macro:}
\typeout{It's \IfOuterMacroTF{fooa}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{foob}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{fooc}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{food}{}{NOT }an outer macro.}
\typeout{It's \IfOuterMacroTF{relax}{}{NOT }an outer macro.}
它受到l3token
包的启发。测试是可扩展的。我在xeCJK
包中使用过它。但是,它只接收计算机名称而不是控制序列。而且,我认为它有点慢。
我认为这是一个好问题并且希望看到其他可能的方法。
答案1
这不是可扩展的,但也许可以修改测试如下:
\documentclass{article}
\usepackage{expl3,l3regex}
\ExplSyntaxOn
\cs_new_protected:Npn \isouter { \exp_after:wN \checkouter:w \token_to_meaning:N }
\cs_new:Npn \checkouter:w #1 \relax
{
\regex_match:nnTF { outer .* macro .* :-> } { #1 }
{ \typeout{OUTER~MACRO} }
{ \typeout{NON~OUTER~TOKEN} }
}
\ExplSyntaxOff
\outer\def\bye{bye}
\isouter\bye\relax
\stop
但是,由于 Joseph Wright 提到的规则,此测试不能用于其他宏的参数。