检测 \global、\long、\outer、\protected

检测 \global、\long、\outer、\protected

有没有办法检测下一个赋值是否是\global\long\outer\protected?也就是说,是否可以编写一个命令\detectmodifiers,使得代码如下

\def\otherdef{%
  \detectmodifiers
  preprocessing
  \ifglobal\expandafter\global\fi
  \iflong\expandafter\long\fi
  \ifouter\expandafter\outer\fi
  \ifprotected\expandafter\protected\fi
  \def
}

做正确的事情(定义一个\otherdef与 操作相同的命令\def,但首先进行一些预处理)?

答案1

您可以在宏的开头创建一个虚拟宏,它将受到上述任何修饰符的影响。然后,您可以测试修饰符以构建 -switches 。您可以在包含、和修饰符的虚拟宏\def上使用,这些修饰符可以提取出来并再次使用 转换为宏。一个挑战是:您需要在组中进行分配,并检查组后它是否仍然相同。\detectmodifiersif\meaning\outer\long\protected\scantokens\global

您应该使用您已有的 -tree ,if而是定义一个宏\themodifiers,然后将其放在前面\def
\def\themodifiers{\protected\global}...。\themodifiers\def...


这里有一些概念验证代码。我记得“修饰符”称为前缀,所以我更改了宏名称。前缀存储在宏中\theprefixes,可以在前面使用\def\global但是前缀很特殊,不能像这样读取。我尝试\dummy在组内定义宏并使用,\global\let\gdummy\dummy以便我可以测试组结束后两者是否仍然相同。问题是:在:-(之前不允许使用\begingroup{\def\dummy

您应该更改一些宏的名称以防止名称冲突。

\documentclass{article}

\makeatletter
\def\macroother{macro}
\@onelevel@sanitize\macroother
\makeatother

\expandafter
\def\expandafter\returnprefixes\expandafter#\expandafter1\macroother#2\relax{%
    \scantokens{\def\theprefixes{#1}}%
}

\def\detectprefixes{%
    \def\dummy{}%
    \expandafter\returnprefixes\meaning\dummy\relax
}

\def\otherdef{%
    \detectprefixes
    % other code
    \theprefixes\def
}

\global\long\outer\protected\otherdef\mymacro{mystuff}
\show\mymacro


\begin{document}


\end{document}

答案2

您可以通过构建一系列条件来检测差异。

\def\Z{This}
\global\def\X{This}
\outer\def\Y{This}

\ifx\Z\Y true \else false \fi

\ifx仅当两个标记都是宏,并且它们在\long和方面具有相同的状态\outer,并且它们都具有相同的参数和“顶级”扩展时, 才会返回 true。根据条件,您可以使用 构建命令csname

答案3

想法:不要编写一个命令来做一些有趣的事情来检测\global之前是否有另一个前缀,而是进行修改\global等以提前查看并使用协议来通知相应的宏,它将自己视为前缀。

以下不是工作代码,旨在提出一种方法

\let\ea\expandafter
\makeatletter

\let\@global\global
\let\@long\long
% etc
\let\@def\def
\let\@edef\edef
% etc
\let\@let\let

\@def\@prefixables{%
    \def%
    \edef%
    % etc
    \let%
}

\@def\newprefixable#1{
    \@def\prefixable@def@reset{
        \ea\@def\csname prefixable@#1@global\endcsname{0}
        \ea\@def\csname prefixable@#1@long\endcsname{0}
        % etc
    }
    \@def\prefixable@def@reset
    \@edef\@prefixables{%
        \expandonce{\@prefixables}%
        \expandonce{\csname#1\endcsname}%
    }
}

\def\global{%
    % Pseudocode
    If the next token is in \@prefixables:
        \@def\prefixable@<the token>@global{1}
    End if
}

\newprefixable{def}
% Showing only treatment of \global
\@def\def#1#2{%
    \if\prefixable@def@global1%
        \@global\@def#1#2%
    \else%
        \@def#1#2%
    \fi%
    \prefixable@def@reset%
}
\newprefixable\otherdef % The macro in the question

\makeatother

其他注意事项:如果命令前有多个前缀,则需要工作,例如如果\long\global\otherdef发生类似情况。上面的方法无法处理这种情况

相关内容