Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

My motivation bases on the package listings (also my package mdframed). The package allows to define a style via \lstset{foo}{options}. Now I want to create a macro to expand the style foo. For example \Apptolstset{foo}{more options}.

I created the followings example.

\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}

The error of this example is:

! 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.

If I use the combination

\define@key{test}{loadstyle}{%
  \ifcsundef{test@style@#1}{}%
        {\csuse{test@style@#1}}%
}
\newrobustcmd*\teststyle[2]{%
  \csdef{test@style@#1}{\testsetup{#2}}%
}

everything will work. But with this combination I don't know how to define the command \apptoteststyle which should be expand the current style.

I hope the question is clear.

share|improve this question
    
Usually you should start the question with a short explanation what you trying to achieve. Also, please always state what error you get. "Doesn't work without errors" isn't that helpful without the exact error you get. –  Martin Scharrer Nov 13 '11 at 13:55
    
The issue seems to be that you trying something like \setkeys{test}{\test@style@new} (because #1=new), i.e. feeding a macro to \setkeys. However it awaits keys instead. So use \setkeys{test}{style@#1} instead a define the style code using \define@key{test}{style@new}[]{<code>}. –  Martin Scharrer Nov 13 '11 at 14:00
    
In \define@key{test}{loadstyle}{...} you are calling \setkeys{test}{...} with an argument that's not in the form key=value. It's quite difficult to understand what you're trying to achieve. –  egreg Nov 13 '11 at 14:02
    
@egreg and @martinscharrer: The argument of \setkeys is saved in a macro in the form key=value. –  Marco Daniel Nov 13 '11 at 14:10
2  
@egreg: with that you still end up with \setkeys{test}{\test@style@new}. Should be \expandafter\expandafter\expandafter\testsetup\expandafter\expandafter\expandaf‌​ter{\csname test@style@#1\endcsname}, shouldn't it? –  Martin Scharrer Nov 13 '11 at 14:33
show 6 more comments

1 Answer

up vote 5 down vote accepted

The \setkeys macro doesn't expand its second argument. If you have a macro which holds the keys you need to expand it first. Note that \csuse adds one expansion step (as any macro does) so you should use the underlying \csname ... \endcsname directly. This must be expanded twice, once to create the macro from its name and then to expand the macro itself.

So do:

\expandafter\expandafter\expandafter
\testsetup\expandafter\expandafter
\expandafter{\csname test@style@#1\endcsname}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.