我怀疑我在要求魔法,但我还是会继续。假设我有一个命令,它接受任意大小的逗号分隔术语列表。我们都熟悉的一个命令是,\usepackage
尽管我们当然可以想出几十个。在的情况下\usepackage
,我们可以写:
\usepackage[opta,optb,optc]{pkgx,pkgy,pkgz}
IE,
\usepackage[ <comma-separated-options> ]{ <comma-separated-pkg-names> }
更一般地,我们可能会得到一个像这样使用的命令:
\command{ <comma-separated-list> }
我的问题是,是否有任何 TeX\LaTeX 向导可以构造以下命令:
\newcommand\mylist{
... possible wizardry ...
a,b,c
... possibly more wizardry ...
}
写作的效果
\command{\mylist}
和\command{a,b,c}
或者
\command{ ...code... \mylist ...code... }
和\command{a,b,c}
会一样吗?
换句话说,是否有可能构建一个可以在<comma-separated-list>
通常会被接受的编译中存在、扩展和接受的 TeX\LaTeX 命令?
动机:(除了学习新的 TeX 相关知识的巨大乐趣之外:))在很多场合,我必须将一个大型的非固定大小列表传递到几个地方,其中一些是打包的命令,由于它们的复杂性和它会施加的维护负担,我相当不愿意深入研究并重新定义。
编辑:
虽然已经提出了一些非常好的想法(特别感谢 TH 和 Will!),但这些解决方案并不完全符合要求。因此,为了使我的问题更明确,以下是我试图解决的案例的具体内容。作为背景,我的代码在多个位置使用相同的长值列表。虽然我可以在所有使用它的地方对列表进行硬编码,但出于良好和实际的原因,这样做的想法一点也不吸引人。我真的很想将它作为参数传递,就像我可以传递给任何其他正常值一样。使用列表的两个地方之一(假设)是命令, TH 和 Will 的重复完美地解决了这个问题。然而,另一个让我苦苦挣扎的情况是我在命令\command
中重复使用列表 ,尽管在任何其他共享相同类型模板的命令的情况下也会存在同样的问题。(仅供参考,我曾尝试破解 TH 的不错解决方案以适应,但进展并不快。)这是一个示例值列表以及我访问它们的情况:xkeyval
\define@choicekey
\newcommand*\mylist{a,b,c,...,l,m,n}
\define@choicekey{myfamily}{mykey}[]
\mylist% <-- how can I consume \mylist here?
[a]
{\renewcommand*\mynewkey{#1}}
\newcommand\anothercmd{
...
\command{\mylist}% <-- this problem is easily fixed with TH's nice solution
...
}
答案1
如果 \mylist 在 \define@choicekey 之前定义,则在调用 define@choicekey 之前扩展它相当容易。如果 \mylist 之后发生变化,您将不得不重新调用 \define@choicekey,并希望 xkeyval 进行所有必要的清理以删除 \mylist 以前内容的痕迹。
\documentclass[]{article}
\usepackage{xkeyval}
\begin{document}
\makeatletter
\newcommand\mylist{left,center,right}
\toks@=\expandafter{\mylist}
\edef\next{\unexpanded{\define@choicekey*{fam}{align}[\val\nr]}{\the\toks@}
\unexpanded{{%
\ifcase\nr\relax
raggedright
\or
centering
\or
raggedleft
\fi}}}%
\next
\setkeys{fam}{align=left}
\end{document}
答案2
如果我没记错的话,我认为你实际上是在寻求一种处理 keyval 输入的新方法。所有 keyval 处理包(keyval、xkeyval、kvoptions、l3keys 等)都非常小心地确保它们收到的逗号分隔条目是不是扩大。
理论上可以有如下代码
\innerclist\mylist{x,y,z}
\processclist{a,\foo,b,\mylist,c,\bar,d} % etc.
只扩展\mylist
为将x
、y
和z
插入到处理中,否则就\foo
不管\bar
它们,但 keyval 代码需要相当多的关心和注意才能编写。
另一种方法是始终完全扩展你的 keyval 参数(如果可能的话)。如果你只是写
\edef\temp{a,\foo,b,\mylist,c,\bar,d}
\expandafter\processclist\expandafter{\temp}
然后假设\foo
和\bar
是可扩展的,那么就没问题了。(这和 TH 之前写的一样。)
最后,如果你可以限制你的 clist-to-be-expanded 的位置,使得它只且总是出现在你的选项的开头,那么你可以简单地使用\expandafter
它,如下所示:
\def\innerclist{x,y,z}
\expandafter\processclist\expandafter{\innerclist,a,b,c,\foo}
您选择的解决方案(以及我们可以合理建议的解决方案)非常具体地针对您要解决的实际问题。
答案3
其他答案本身都很有趣,但这个问题的简短答案很简单不. 您不能\command
仅通过定义一种特殊的来改变 的行为\mylist
。
答案4
您可以使用键值包。它提供您想要的内容,此外您还可以定义键值参数。