键值副作用

键值副作用

在我的一个宏中,我想将某个宽度设置为两列或单列宽度。在其他宏中我确实使用了 key width,因此我想将请求的宽度存储在该 key 中。所以我的第一次尝试是

    \setkeys{MEMacros}{wide=false,#1}% 
    \par 1: wide=\ME@wide\par % Test point 1
\expandafter\ifstrequal\expandafter{\ME@wide}{true}
    {\setkeys{MEMacros}{width=\textwidth}}%
    {\setkeys{MEMacros}{width=\columnwidth}}%
    \par 2: wide=\ME@wide\par % Test point 2

但是,第二个测试点的\ME@wide值与第一个测试点的值不同。我猜这个问题是由\setkeys第一个测试点之后引起的。事实上,如果我用

\expandafter\ifstrequal\expandafter{\ME@wide}{true}
    {\def\mywidth{\textwidth}}
    {\def\mywidth{\columnwidth}}

然后一切正常。因此,看起来使用\setkeys...{width...}会改变键的值wide

我做错了什么,或者为什么\setkeys在这种情况下使用会产生改变另一个键值的副作用?或者,设置不是来自第一个参数的键是非法的?下面是一个完整的 MWE。

\documentclass{book}
\usepackage{xkeyval}
\usepackage{etoolbox}
\usepackage{ifthen}

    \makeatletter
    \define@key{MEMacros}{wide}[true]{\def\ME@wide{#1}}
    \define@key{MEMacros}{width}[3cm]{\def\ME@width{#1}}
    \presetkeys{MEMacros}{wide=false}{}%
    \presetkeys{MEMacros}{width=3cm}{}%

\newcommand\Table[2][]{%
    \setkeys{MEMacros}{wide=false,#1}% 
    \par 1: wide=\ME@wide, \par
    \expandafter\ifstrequal\expandafter{\ME@wide}{true}
        {\setkeys{MEMacros}{width=\textwidth}}%
        {\setkeys{MEMacros}{width=\columnwidth}}%
    \par 2: wide=\ME@wide, 
    }
\makeatother

\begin{document}
This is my table, wide:

\Table[wide]{A wide table}

\end{document}

结果是

This is my table, wide:
1: wide=true,
2: wide=false,

答案1

你没有做错什么。你所做的就是使用,\presetkeys这是你明显问题的原因。以下内容\presetkeysxkeyval 文档(部分6 个预设键,第 15 页):

\presetkeys[<prefix>]{<family>}{<head keys>}{<tail keys>}
\gpresetkeys[<prefix>]{<family>}{<head keys>}{<tail keys>}

\presetkeys将保存<head keys>\XKV<prefix><family>preseth<tail keys>\XKV<prefix><family>presett保存由 本地完成\presetkeys,由 全局完成\gpresetkeys(比较\savekeys和, [...])。保存的宏将在定义时\gsavekeys使用,只要的参数中使用。头键将在设置用户键之前设置,尾键将在之后设置。但是,如果某个键出现在用户输入中,则任何预设键都不会设置此特定键。\setkeys<family><families>\setkeys

所以,既然你有

\presetkeys{MEMacros}{wide=false}{}

作为 的一部分<head keys>,将在每次调用 时先wide=false进行设置。\setkeys{MEMacros}{<keys>}

进一步来说,

\setkeys{MEMacros}{wide=false,#1}

将设置widefalse(作为子句的结果\presetkeys{MEMacros}{wide=false}{}),然后它将再次设置widefalse(因为它在\setkeys子句内部提供。最后,由于被设置wide而被设置为。在后续条件中,另一个调用使(再次由于子句)。true#1\setkeyswide=false\presetkeys

如果你希望的默认值widefalse

\gsetkeys{MEMacros}{wide=false}

就可以了,而不是使用。或者,在每次调用 时\presetkeys在宏中设置默认键。\Table\setkeys

当然,上述讨论也适用于其他\presetkeyswidth在本例中)。

答案2

不确定这如何适合您的更大计划,但您可以这样做:

\documentclass{book}
\usepackage{xkeyval}
\usepackage{etoolbox}
\usepackage{ifthen}

\makeatletter
\define@key{MEMacros}{wide}[true]{\def\ME@wide{#1}}
\define@key{MEMacros}{width}[3cm]{\def\ME@width{#1}}
\presetkeys{MEMacros}{wide=false}{}%
\presetkeys{MEMacros}{width=3cm}{}%

\newcommand\Table[2][]{%
  \setkeys{MEMacros}{#1}%
  \par 1: wide=\ME@wide, \par
  \expandafter\ifstrequal\expandafter{\ME@wide}{true}
  {\setkeys{MEMacros}{#1,width=\textwidth}}%
  {\setkeys{MEMacros}{#1,width=\columnwidth}}%
  \par 2: wide=\ME@wide,
}
\makeatother

\begin{document}
  This is my table, wide:

  \Table[wide]{A wide table}

\end{document}

两个真

相关内容