Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help with xkeyval

59 views
Skip to first unread message

Leo

unread,
Nov 22, 2009, 7:19:07 PM11/22/09
to
Hi,

In myclass.cls, I want to create an option with xkeyval so that, for
example,

\documentclass[xcolor={monochrome,dvipsnames}]{myclass}

will pass the xcolor options to xcolor package which is loaded in
myclass.cls.

I'm new to xkeyval and I tried the following with no luck:

\define@key[cu]{kkk}{xcolor}[{dvipsnames}]{\PassOptionsToPackage{#1}{xcolor}}

Thanks.

Leo

Joseph Wright

unread,
Nov 23, 2009, 1:52:18 AM11/23/09
to

What exactly fails? Can you post a minimal example?
--
Joseph Wright

Leo

unread,
Nov 23, 2009, 3:55:47 AM11/23/09
to

xkv.tex:

\documentclass[xcolor={monochrome,dvipsnames}]{myclass}
\begin{document}
\textcolor{red}{demo1}
\end{document}

myclass.cls:

\NeedsTeXFormat{LaTeX2e}

\ProvidesClass{myclass}[2009/11/23 a class for me]
\RequirePackage{xkeyval}


\define@key[cu]{kkk}{xcolor}[{dvipsnames}]{\PassOptionsToPackage{#1}{xcolor}}

\ProcessOptionsX[cu]<kkk>

\LoadClass{article}
\RequirePackage{xcolor}

I'm getting this:

......
l.7

! You can't use `macro parameter character #' in horizontal mode.
\@removeelement #1#2#3->\def \reserved@a ##1,#1,##
2\reserved@a
{##1,##2\rese...
l.7

Runaway argument?
{##1,##2\reserved@b }\def \reserved@b ##1,\reserved@b ##2\reserved@b
\ETC.
! Paragraph ended before \reserved@a was complete.
<to be read again>
\par
l.7
......

> -- Joseph Wright

Thanks.

Leo

Joseph Wright

unread,
Nov 23, 2009, 5:35:06 AM11/23/09
to

Something seems to be up here: what you've done looks fine to me.
Everything is okay when using xkyeval for a package using a modified
version of the same (miss out the class lines and save as a .sty file
to see this). Perhaps report the issue to the xkeyval author?
--
Joseph Wright

Joseph Wright

unread,
Nov 23, 2009, 8:22:05 AM11/23/09
to
On Nov 23, 10:35 am, I wrote:
> Something seems to be up here: what you've done looks fine to me.
> Everything is okay when using xkyeval for a package using a modified
> version of the same (miss out the class lines and save as a .sty file
> to see this). Perhaps report the issue to the xkeyval author?

I've reported this to the package author. Hopefully we'll here what is
up soon enough!
--
Joseph Wright

Claas Hemig

unread,
Nov 23, 2009, 8:35:03 AM11/23/09
to
Hi Leo,

What about

> \documentclass[xcolor={monochrome,dvipsnames}]{myclass}
--> \documentclass[{xcolor=monochrome,dvipsnames}]{myclass}

I did not dive into the option list of xcolor deeply, but I think, the
result is the intended. And no error message is thrown.

Best, Claas

Leo

unread,
Nov 23, 2009, 9:32:06 AM11/23/09
to

Thanks. But I think {xcolor=monochrome,dvipsnames} is less intuitive
than xcolor={monochrome,dvipsnames}, which is common in a few packages.

Best,
Leo

--
Emacs uptime: 62 days, 5 hours, 44 minutes, 32 seconds

Leo

unread,
Nov 23, 2009, 9:32:19 AM11/23/09
to

Thank you for this.

> -- Joseph Wright
>

--
Emacs uptime: 62 days, 5 hours, 46 minutes, 59 seconds

Claas Hemig

unread,
Nov 23, 2009, 9:47:03 AM11/23/09
to
Hi Leo,

> Thanks. But I think {xcolor=monochrome,dvipsnames} is less intuitive
> than xcolor={monochrome,dvipsnames}, which is common in a few packages.

Full ack, I came across this more or less accidently :-)

Best, Claas

Joseph Wright

unread,
Nov 23, 2009, 12:35:12 PM11/23/09
to
On Nov 23, 1:22 pm, Joseph Wright <joseph.wri...@morningstar2.co.uk>
wrote:

> I've reported this to the package author. Hopefully we'll here what is
> up soon enough!

There is obviously a difference in how keyval packages handle class
options. A similar idea to what you want to achieve is pretty easy
using the keys system in expl3 (with the accompanying l3keys2e from
the xpackages):

\begin{filecontents}{test.cls}
\RequirePackage{expl3}
\ProvidesExplClass{test}{2009/11/23}{0.0}{test class}
\LoadClass{article}
\RequirePackage{l3keys2e}
\keys_define:nn{test}
{ xcolor .code:n = \PassOptionsToPackage {#1} { xcolor } }
\ProcessKeysOptions{test}
\RequirePackage{xcolor}
\end{filecontents}

\documentclass[xcolor={monochrome,dvipsnames}]{test}


\begin{document}
\textcolor{red}{demo1}
\end{document}

I suspect the same will work using kvoptions, as the code in l3keys2e
for handling options is based on that in kvoptions.
--
Joseph Wright

Pluto

unread,
Nov 24, 2009, 2:49:54 PM11/24/09
to
On Nov 23, 8:55 am, Leo <sdl....@gmail.com> wrote:
> Leo- Hide quoted text -
>
> - Show quoted text -

Please try the following, if you like it. It worked on my system.

\documentclass{myclass}
\myclassoptions{xcolor={monochrome,dvipsnames}}

\begin{document}
\textcolor{red!75}{Demo}
\end{document}

% myclass.cls:

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}[2009/11/23 v1.0 A minimal class]
\RequirePackage{xkeyval}
\define@key[KV]{myclass}{xcolor}[dvipsnames]{\PassOptionsToPackage{#1}
{xcolor}}
\ProcessOptionsX[KV]<myclass>\relax
\long\def\myclassoptions#1{\setkeys[KV]{myclass}{#1}}
\LoadClass{article}
\RequirePackage{xcolor}

% You also need a way of passing unknown options.


Joseph Wright

unread,
Nov 24, 2009, 3:59:27 PM11/24/09
to
Right, I know what is up. This problem is seen with xkeyval but not with
kvoptions (or any derivatives thereof) because of the way class keys are
handled. In the kvoptions code, something like:

xcolor={monochrome,dvipsnames}

is first parsed just using the key name. If the key is defined for the
class, then the option is added to the "to do" list, otherwise it's
added to the "not used" list directly. So at no point is the option
removed from any lists: it's only added. To do this, kvoptions
overwrites the kernels \@unusedoptions with its own.

In contrast, xkeyval uses a modified parser to both check the validity
of keys and processes them at the same time. It does this by first
processing the option, then removing it from \@unusedoptions using
\@removeelement. However, the way \@removeelement is defined only works
for arguments not containing braces. So this is where the odd errors are
appearing.

Now, who's bug this is is a good question. Clearly, xkeyval could use
the same approach as kvoptions to bypass the issue, but at the same time
\@removeelement should behave better. I'll report this as a LaTeX bug, I
think, and leave it to the author of xkeyval to decide how to handle the
issue at his end (LaTeX bugs don't necessarily get resolved very quickly).
--
Joseph Wright

Leo

unread,
Nov 24, 2009, 4:32:25 PM11/24/09
to

Thank you for looking into this.

I just learnt that \RequirePackage{xkvltxp} also fixes the problem.

Leo

Leo

unread,
Nov 24, 2009, 4:33:45 PM11/24/09
to
On 2009-11-24 19:49 +0000, Pluto wrote:
> Please try the following, if you like it. It worked on my system.

Thank you for this. I think this is the best solution without loading
xkvltxp.

Leo

Leo

unread,
Nov 24, 2009, 5:21:38 PM11/24/09
to
On 2009-11-24 19:49 +0000, Pluto wrote:
> % You also need a way of passing unknown options.
>

I tried using:
\DeclareOptionX*{%
\PassOptionsToClass{\CurrentOption}{memoir}%
}

But it didn't work. Ideas?

Leo

Leo

unread,
Nov 26, 2009, 6:40:56 AM11/26/09
to
On 2009-11-24 19:49 +0000, Pluto wrote:
> Please try the following, if you like it. It worked on my system.
>
> \documentclass{myclass}
> \myclassoptions{xcolor={monochrome,dvipsnames}}
>
> \begin{document}
> \textcolor{red!75}{Demo}
> \end{document}
>
> % myclass.cls:
>
> \NeedsTeXFormat{LaTeX2e}
> \ProvidesClass{myclass}[2009/11/23 v1.0 A minimal class]
> \RequirePackage{xkeyval}
> \define@key[KV]{myclass}{xcolor}[dvipsnames]{\PassOptionsToPackage{#1}
> {xcolor}}
> \ProcessOptionsX[KV]<myclass>\relax
> \long\def\myclassoptions#1{\setkeys[KV]{myclass}{#1}}
> \LoadClass{article}
> \RequirePackage{xcolor}
>
> % You also need a way of passing unknown options.

I just realised there's a flaw in this as (it seems)
PassOptionsToPackage is only for future RequirePackage and thus it won't
work after the package xolor has been loaded, which is the case in the
code above.

Leo


--
Emacs uptime: 65 days, 2 hours, 51 minutes, 51 seconds

Pluto

unread,
Nov 26, 2009, 10:59:11 AM11/26/09
to
> Emacs uptime: 65 days, 2 hours, 51 minutes, 51 seconds- Hide quoted text -

>
> - Show quoted text -

The solution using \myclassoptions can't be used to pass options to
packages, because the packages are loaded by the class file before
\myclassoptions is invoked. If you must really pass options to
packages via \documentclass, you need to use \RequirePackage{xkvltxp}
on the top of \documentclass statement or use another scheme, which
submits the options to packages individually (option by option) via
\documentclass. The latter scheme requires that you load the packages
(eg, xcolor) in the class file after assemblying the options within
the class file. If you're interested in the latter approach, I can
provide a sample.

> \DeclareOptionX*{%
> \PassOptionsToClass{\CurrentOption}{memoir}}

> But it didn't work. Ideas?

Which errors did you get?


Joseph Wright

unread,
Nov 26, 2009, 11:55:39 AM11/26/09
to

Or use kvoptions to do the processing, where it works.
--
Joseph Wright

Leo

unread,
Nov 26, 2009, 12:15:52 PM11/26/09
to
On 2009-11-26 15:59 +0000, Pluto wrote:
>> \DeclareOptionX*{%
>> \PassOptionsToClass{\CurrentOption}{memoir}}
>> But it didn't work. Ideas?
>
> Which errors did you get?

It was a mistake. It works as expected.

Leo

Leo

unread,
Nov 26, 2009, 3:17:59 PM11/26/09
to
On 2009-11-26 16:55 +0000, Joseph Wright wrote:
> Or use kvoptions to do the processing, where it works.

I re-read your keyval.pdf;)

I stick with xkeyval as it seems it is the most popular package widely
used in many packages.

I haven't installed any LaTeX3 packages yet as I am not sure it will
happen (sorry to sound pessimistic).

Leo

Joseph Wright

unread,
Nov 26, 2009, 3:49:12 PM11/26/09
to
On 26/11/2009 20:17, Leo wrote:
> I stick with xkeyval as it seems it is the most popular package widely
> used in many packages.

I have to say that I wouldn't choose xkeyval if I was writing any of my
packages "from scratch". It's caused me no end of trouble in achemso. I
think of the LaTeX2e solutions, I'd go with kvoptions + kvsetkeys (both
in Heiko Oberdiek's bundle, and therefore widely available). While I
like pgfkeys, there are some bugs (such as not being babel safe) that
put me off.

> I haven't installed any LaTeX3 packages yet as I am not sure it will
> happen (sorry to sound pessimistic).

No problem :-) At least as far as expl3 goes, things do work, and the
code is in TeX Live 2009. So that at least will be available. (I'm using
expl3 for version 2 of siunitx: one reason is that this means I do get a
keyval system that works and is pretty flexible. But then I wrote most
of the keyval system for expl3, so I would say that.)
--
Joseph Wright

Leo

unread,
Nov 27, 2009, 12:03:27 PM11/27/09
to
On 2009-11-26 20:49 +0000, Joseph Wright wrote:
>> I stick with xkeyval as it seems it is the most popular package
>> widely used in many packages.
>
> I have to say that I wouldn't choose xkeyval if I was writing any of
> my packages "from scratch". It's caused me no end of trouble in
> achemso. I think of the LaTeX2e solutions, I'd go with kvoptions +
> kvsetkeys (both in Heiko Oberdiek's bundle, and therefore widely
> available). While I like pgfkeys, there are some bugs (such as not
> being babel safe) that put me off.

I will migrate my .cls to kvoptions. Thanks for the info.

Leo


--
Emacs uptime: 66 days, 8 hours, 17 minutes, 38 seconds

Pluto

unread,
Dec 11, 2009, 8:16:03 AM12/11/09
to
On Nov 26, 3:59 pm, Pluto <a.m...@rocketmail.com> wrote:
> Which errors did you get?- Hide quoted text -

>
> - Show quoted text -

I have found a way to use \myclassoptions to pass options to packages
(without deploying 'xkvltxp' and 'kvoptions-patch' packages). See
below. The trick is to delay the loading of the packages (to which you
want to pass options) until \myclassoptions is fired. For obvious
reasons, instead of using the \AtBeginDocument hook from the LaTeX
kernel, I have used the \AtEndPreamble hook from etoolbox.sty.
Disclaimer: I have conducted only limited tests on some larger in-
house class files.

What are the risks in using this approach? I don't know. But one
limitation is that you can't use the resources from the deferred
packages in your class file.

To avoid deferring package loading, I tried another approach which
also worked. I wrote all the \PassOptionsToPackage statements to a
special auxiliary file (call it .pop file, for 'Pass Options To
Package'), which is loaded early enough, unlike the .aux file). This
approach requires that the document is compiled at least twice, a pre-
requisite to get references right, anyway. On the first run, when
\PassOptionsToPackage statements haven't yet been written in the .pop
file, the run is neatly aborted as soon as all of them have been
written. I prefer this latter method, but it is slightly more
complicated.

You can restrict within the class file the options that can appear in
\myclassoptions. For example, you can instruct it not to accept
a4paper, 10pt, twocolumn, etc, which should instead appear in
\@classoptionslist.

By using toggles below, the packages are loaded only if indicated/
needed by the calling document. This makes sense only because the
loading of the packages is delayed.


%%%%%% Class file %%%%%%%
\ProvidesClass{myclass}[2009/12/10 v1.0 A minimal class]
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{etoolbox}
% You can use kvoptions.sty & kvsetkeys.sty instead
% of xkeyval (as you've agreed to follow the suggestion of Joseph).
\RequirePackage{xkeyval}
\newtoggle{xcolor}
\newtoggle{natbib}
\AtEndPreamble{%
\iftoggle{xcolor}{\RequirePackage{xcolor}}{}%
\iftoggle{natbib}{\RequirePackage{natbib}}{}%
}
\define@key[KV]{myclass}{xcolor}[dvipsnames]{%
\toggletrue{xcolor}%
\PassOptionsToPackage{#1}{xcolor}%
}
\define@key[KV]{myclass}{natbib}[numbers]{%
\toggletrue{natbib}%
\PassOptionsToPackage{#1}{natbib}%
}
\DeclareOptionX*{\PassOptionsToClass{\CurrentOption}{memoir}}
\ExecuteOptionsX[KV]<myclass>{}
\ProcessOptionsX*[KV]<myclass>\relax


\def\myclassoptions#1{\setkeys[KV]{myclass}{#1}}

\LoadClass{memoir}
\endinput


%%%%%%%%% Example document %%%%%%%%%
\documentclass[a4paper]{myclass}
\myclassoptions{xcolor={table,dvipsnames},natbib=
{numbers,sort&compress}}
\begin{document}
% Without the 'table' option to 'xcolor' package above,
% LaTeX will complain about the commands below:
\rowcolors[\hline]{3}{green!25}{yellow!50}
\arrayrulecolor{red!75!gray}
\begin{tabular}{ll}
test & row \number\rownum\\
test & row \number\rownum\\
test & row \number\rownum\\
test & row \number\rownum\\
\arrayrulecolor{black}
test & row \number\rownum\\
test & row \number\rownum\\
\rowcolor{blue!25}
test & row \number\rownum\\
test & row \number\rownum\\
\hiderowcolors
test & row \number\rownum\\
test & row \number\rownum\\
\showrowcolors
test & row \number\rownum\\
test & row \number\rownum\\
\multicolumn{1}%
{>{\columncolor{red!12}}l}{test} & row \number\rownum\\
\end{tabular}

\end{document}

0 new messages