xkeyval `boolkey` 设置在宏调用中持久:范围泄漏?

xkeyval `boolkey` 设置在宏调用中持久:范围泄漏?

我认为keyval宏的参数应该限制在其宏范围内,但是以下代码:

\documentclass{report}

\usepackage{xkeyval}

% Define a custom command option using `boolkey`
\makeatletter
\define@boolkey{myCommand}[]{option}[true]{} % one boolean option
\newcommand{\myCommand}[2][]{%
    \setkeys{myCommand}{#1}%
    \ifoption%
        \textbf{#2}%
    \else%
        #2%
    \fi%
    }
\makeatother

\begin{document}

\myCommand{not bold} % default behaviour is not to bold

\myCommand[option]{bold} % explicitly set option to bold

\myCommand{not bold} % fail! default behaviour was expected!

\myCommand[option=false]{not bold} % workaround that makes the "default" concept useless

\end{document}

生成:

意外行为

为什么?我是不是漏掉了什么?
有没有办法让这个默认行为不管之前是否调用过宏都可以正常工作?

答案1

宏定义本身不会添加分组级别,因此您在宏代码中所做的一切都会“泄漏”并且只发生在调用宏的范围内。这个想法是,调用定义\somemacro\newcommand在该位置粘贴代码参数的内容相同(没有周围的括号)。

例如

\documentclass{article}
\usepackage{xcolor}

\newcommand*{\mygreen}[1]{%
  \color{green}#1}

\begin{document}
Not green

{\mygreen{this is green}

but so is this...}

again black
\end{document}

第一行和最后一行是黑色,第二行和第三行是绿色。

产生两行绿色文本,因为\mygreen没有范围限制,不会阻止它应用于下一行。最后一行超出了调用的范围\mygreen,所以它又是黑色的。

简单的解决方案是添加\begingroup...\endgroup以使您的设置本地化到宏调用。

\documentclass{report}
\usepackage{xkeyval}

% Define a custom command option using `boolkey`
\makeatletter
\define@boolkey{myCommand}[]{option}[true]{} % one boolean option
\newcommand{\myCommand}[2][]{%
  \begingroup
    \setkeys{myCommand}{#1}%
    \ifoption%
        \textbf{#2}%
    \else%
        #2%
    \fi%
  \endgroup
}
\makeatother

\begin{document}
\myCommand{not bold} % default behaviour is not to bold

\myCommand[option]{bold} % explicitly set option to bold

\myCommand{not bold} % fail! default behaviour was expected!

\myCommand[option=false]{not bold} % workaround that makes the "default" concept useless
\end{document}

不粗体,**粗体**,不粗体,不粗体

相关内容