测试宏变化

测试宏变化

在我正在编写的一个包中,我有一个宏(称为\foo),默认情况下,它接受一个参数,并且相当于\relax。在某些情况下,用户可能希望\foo在他们的文档中重新定义,以便它仍然接受一个参数,但现在打印该参数并应用一些格式。包需要能够检测到这种重新定义并在发生时执行不同的代码。

在下面的 MWE 中,我弄清楚了如果格式是字体属性(系列、形状或系列)的更改,该如何执行此操作。但是,当我尝试更改字体大小时,测试中断,并抱怨超出 TeX 容量。我该如何重写测试,使其在这种情况下也能正常工作?

\documentclass[11pt]{article}

\def\foo#1{\relax}

\begin{document}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\bfseries #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\ttfamily #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\itshape #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\small #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\end{document}

上下文(以防有帮助):最初\foo定义为将一些默认格式应用于其参数并打印它。用户将重新定义它以更改该格式。但是,这种更改应用于某些文本的格式的方法在包中已被弃用。我想做的是检测何时有人使用旧方法,以便我可以警告他们他们正在使用弃用的语法并将他们指向新语法。因此,在我的用例中,代码true将使用新方法格式化文本,而代码false将使用旧方法并引发警告或错误。定义\foo为默认等同\relax于是我认为我可能能够检测到这种变化的方式。

答案1

您不想\foo直接进行测试,而不是通过中间定义吗\test

\documentclass[11pt]{article}

\def\foo#1{\relax}
\let\svfoo\foo
\def\testfoo{\ifx\svfoo\foo true\else false\fi}

\begin{document}
\testfoo

\renewcommand{\foo}[1]{{\bfseries #1}}
\testfoo

\renewcommand{\foo}[1]{{\ttfamily #1}}
\testfoo

\renewcommand{\foo}[1]{{\itshape #1}}
\testfoo

\renewcommand{\foo}[1]{{\small #1}}
\testfoo

\def\foo#1{\relax}
\testfoo
\end{document}

在此处输入图片描述

答案2

有些宏是强壮的,而其他人则脆弱的。健壮的宏可以在某些条件下保护自己免于扩展,而脆弱的命令则不能,这就是导致当前问题的原因。

针对您的情况,\small它不够强大,在e扩展的definition 中使用时会出现问题。相反,使用

\makeatletter
\protected@edef\test{\foo{a}}
\makeatother

在大多数应用程序中,这应该足够安全。或者,如果您知道在 中可能使用的内容\foo,则可以\robustify借助etoolbox





\documentclass{article}

\def\foo#1{\relax}
%\usepackage{etoolbox} ...or use this:
%\robustify\small

\begin{document}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\bfseries #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\ttfamily #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\renewcommand{\foo}[1]{{\itshape #1}}
\edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi

\makeatletter
\renewcommand{\foo}[1]{{\small #1}}
\protected@edef\test{\foo{a}}
\expandafter\ifx\test\relax true \else false \fi
\makeatother

\end{document}

相关内容