我有一个项目,其中大量使用了出色的 xkeyval 包。但是,我仍然在为一些更奢侈的事情而苦苦挣扎。例如,我想使用枚举键(key1
to keyN
,其中N
是某个任意整数)。为了避免复制粘贴工作,我想到了一个主意,即使用循环来进行所有调用\define@key
- 但是,这并不像我预期的那样有效。
请考虑以下 MWE。您将观察到文档包含字符串“test”,但不包含我期望出现的以下字符串“something”。这是否有效似乎取决于命令的确切定义\index
。
\documentclass{article}
\usepackage{xkeyval}
\makeatletter
\count@=0
\loop
\advance\count@ 1
%\edef\index{1}% <-- uncomment this line
\edef\index{\@arabic\count@}% <-- and comment this one to make it work
\expandafter\def\csname KV@family@key\index\endcsname ##1{\expandafter\def\csname familykey\index\endcsname{##1}}
%\define@key{family}{key\index}{\expandafter\def \csname familykey\index\endcsname{#1}}% <- using this line instead of the above doesn't make a difference
\ifnum\count@<6
\repeat
\makeatother
\begin{document}
test
\setkeys{family}{key1=something}{
\csname familykey1\endcsname
}
\end{document}
将该线与的定义进行交换的事实\index
产生了差异,这使我得出结论,即参数扩展出现了问题,但我似乎无法弄清楚如何使其发挥作用。
有什么建议么?
答案1
问题是\define@key
没有扩展其参数;也\index
应该在定义时在的替换文本中扩展\define@key
,而不是在运行时。
使用\index
不是必需的,\the\count@
效果相同(或者\@arabic\count@
,如果你愿意的话。\index
无论如何,这是一个糟糕的选择名称:尝试为您的文档建立一个索引以了解原因。
\documentclass{article}
\usepackage{xkeyval}
\makeatletter
\count@=0
\loop
\advance\count@ 1
\begingroup\edef\x{\endgroup
\noexpand\define@key{family}{key\the\count@}{%
\noexpand\@namedef{familykey\the\count@}{####1}%
}% end of \define@key
}% end of \edef
\x % execute \x
\ifnum\count@<6
\repeat
\makeatother
\begin{document}
test
\setkeys{family}{key1=something1}
\setkeys{family}{key2=something2}
\setkeys{family}{key3=something3}
\setkeys{family}{key4=something4}
\setkeys{family}{key5=something5}
\setkeys{family}{key6=something6}
\csname familykey1\endcsname
\csname familykey2\endcsname
\csname familykey3\endcsname
\csname familykey4\endcsname
\csname familykey5\endcsname
\csname familykey6\endcsname
\end{document}
为什么是####1
必要的?我们在定义 ( \edef
) 中,但也\loop
执行了\def
,因此#1
也应该因此而加倍。两次加倍得到####1
。