![键值副作用](https://linux22.com/image/304001/%E9%94%AE%E5%80%BC%E5%89%AF%E4%BD%9C%E7%94%A8.png)
在我的一个宏中,我想将某个宽度设置为两列或单列宽度。在其他宏中我确实使用了 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
这是你明显问题的原因。以下内容\presetkeys
在xkeyval
文档(部分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}
将设置wide
为false
(作为子句的结果\presetkeys{MEMacros}{wide=false}{}
),然后它将再次设置wide
为false
(因为它在\setkeys
子句内部提供。最后,由于被设置wide
而被设置为。在后续条件中,另一个调用使(再次由于子句)。true
#1
\setkeys
wide=false
\presetkeys
如果你希望的默认值wide
是false
\gsetkeys{MEMacros}{wide=false}
就可以了,而不是使用。或者,在每次调用 时\presetkeys
在宏中设置默认键。\Table
\setkeys
当然,上述讨论也适用于其他\presetkeys
(width
在本例中)。
答案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}