我的动机基于包listings
(也是我的包mdframed
)。该包允许通过定义样式\lstset{foo}{options}
。现在我想创建一个宏来扩展样式foo
。例如\Apptolstset{foo}{more options}
。
我创建了以下示例。
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{testpackage.sty}
\ProvidesPackage{testpackage}
\RequirePackage{etoolbox,kvoptions}
\SetupKeyvalOptions{family=test,prefix=test@}
\DeclareStringOption[\bfseries]{font}
\DeclareStringOption[\normalsize]{size}
\ProcessKeyvalOptions*\relax
\newcommand\testsetup{\setkeys{test}}
\define@key{test}{loadstyle}{%
\ifcsundef{test@style@#1}{}%
{\expandafter\testsetup\expandafter{\csname test@style@#1\endcsname}}%
}
\newrobustcmd*\teststyle[2]{%
\csdef{test@style@#1}{#2}%
}
\newrobustcmd*\apptodefinestyle[2]{%
\ifcsundef{test@style@#1}%
{}%
{\csappto{test@style@#1}{,#2}}%
}
\newrobustcmd*\testresult[1]{{\test@font\test@size #1}}
\end{filecontents}
\usepackage{testpackage}
\begin{document}
Hello World!
\testresult{Hello World!}
\teststyle{new}{font=\bfseries\itshape}
\apptodefinestyle{new}{size=\Large}
\testsetup{loadstyle=new}
\testresult{Hello World!}
\end{document}
本例的错误之处在于:
! Missing \endcsname inserted.
<to be read again>
\protect
l.35 \testsetup{loadstyle=new}
The control sequence marked <to be read again> should
not appear between \csname and \endcsname.
如果我使用组合
\define@key{test}{loadstyle}{%
\ifcsundef{test@style@#1}{}%
{\csuse{test@style@#1}}%
}
\newrobustcmd*\teststyle[2]{%
\csdef{test@style@#1}{\testsetup{#2}}%
}
一切都会正常。但是对于这种组合,我不知道如何定义\apptoteststyle
应该扩展当前样式的命令。
我希望问题清楚了。
答案1
宏\setkeys
不会扩展其第二个参数。如果您有一个包含键的宏,则需要先将其扩展。请注意,这\csuse
会增加一个扩展步骤(就像任何宏一样),因此您应该使用底层\csname ... \endcsname
。这必须扩展两次,一次根据其名称创建宏,然后扩展宏本身。
所以:
\expandafter\expandafter\expandafter
\testsetup\expandafter\expandafter
\expandafter{\csname test@style@#1\endcsname}