0

I'm writing a small package and am using kvoptions to parse key-val options passed to it as:

\RequirePackage{kvoptions}
\SetupKeyvalOptions{family=my,prefix=my@}
\DeclareStringOption[bar]{foo}
\DeclareStringOption[5.75]{len}
...
\ProcessKeyvalOptions*

At this point (after \ProcessKeyvalOptions* is called) I'd like to get a list of all keys that are defined and do something to them in a loop, e.g. append the string " yes" to all of them. I know I could manually add \edef\my@<option>{\my@<option> yes} for each of them, but I'd like to automate that.

By "keys that are defined" I mean all keys that are declared using \Declare*Option, not just those that are passed to the package -- but I'd also appreciate input on how to do the latter.

I had a brief look at kvoptions.sty and it defines and uses \KVO@GetClassOptionsList but that seems to be empty after \ProcessKeyvalOptions* is called. There is \KVO@classoptionslist but that's the class' options. I can see the @for loop in the kvoptions code ... I should probably spend some time looking into it. Any expert help will be much appreciated.

Normadize
  • 278
  • When you say 'defined' do you mean 'given in the package options list' rather than 'declared as options': you presumably know the latter! – Joseph Wright Mar 03 '15 at 19:53
  • @JosephWright First, thanks for writing all the ton of helpful *tex packages for us .. and for still finding time to reply here. Re my question, you're right, I should have been more specific. Edited. I meant getting a list of all the options declared, not just the ones passed to the package (though I'd like how to do the latter too). – Normadize Mar 04 '15 at 02:24

1 Answers1

2

At the implementation level, keys are simply macros stored with a particular name pattern. As such, key lookup is a question of checking if a name is defined. TeX does not give us a way of asking 'list all defined macros with names matching pattern XXX', and so if a list of keys is needed that can be queried in this way it has to be done at the macro level.

As you are defining the keys yourself the most obvious way to do this would be to simply create a list manually

\newcommand*\my@options@list{foo,bar,...}

and to use this list to check (later) what is defined. That could be automated by creating a helper, for example

\newcommand*\my@options@list{}
\newcommand\my@declare@option[3][]{%
  \ifx\my@options@list\@empty
    \def\my@options@list{#2}%
  \else
    \edef\my@options@list{\my@options@list,#2}%
  \fi
  #3[#1]{#2}%
}
\my@declare@option[bar]{foo}\DeclareStringOption

(The syntax here could be set up to follow that of \DeclareStringOption, etc., directly with a bit more effort.)

Tracking which options have been given to be set is an entirely separate task. The most obvious way to do it is to add an appropriate piece of code to the key implementation. That could be done by setting up everything manually by creating keys using \newcommand rather than the kvoptions system, or we could use the fact that we know what the macros are that implement keys. For example, with the set up in the question the key macros are \KV@my@foo and \KV@my@bar, so we could patch them with etoolbox:

\SetupKeyvalOptions{family=my,prefix=my@}
\DeclareStringOption[bar]{foo}
\DeclareStringOption[5.75]{len}
\newcommand*\my@given@options{}
\RequirePackage{etoolbox}
\pretocmd\KV@my@foo{\edef\my@given@options{\my@given@options,#1}}{}{\ERROR}

or we could just do the job by hand

\newcommand\KV@my@len[1]{%
  \edef\my@given@options{\my@given@options,#1}%
  \def\my@foo{#1}%
}
Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • Many thanks. I admit I was hoping there is a more automatic way to do it, which does not require writing twice each option name manually (I had already implemented a similar solution myself using a macro called after \ProcessKeyvalOptions). \ProcessKeyvalOptions does parse all options that were declared automatically. Perhaps add this to a future version of kvoptions a macro like \ProcessKeyvalOptions which just spits a csv list of options that were declared, and another macro to spit the options that were set? I'd certainly like that. – Normadize Mar 04 '15 at 12:03
  • @Normadize Without knowing why you need the info it's hard to be more specific, but I'd note that kvoptions is really about giving a 'good' interface to the complex area of keyvals in LaTeX. It's deliberately focussed on certain common tasks. In any case, a feature request would have to go to the package author, Heiko Oberdiek. – Joseph Wright Mar 04 '15 at 13:50
  • My specific reason involves being able to pass options from the command line, e.g. pdflatex "\def\myfoo{newbar}\def\mylen{10ex}\input{file.tex}" to override any options set into the .tex file, without having to edit the .tex file. The way I thought of doing that was to add functionality in the package so that after the options were processed, I'd look for whether macros \myfoo, \mylen are defined and override the ones passed to the package. A for loop coupled with \ifcsname and \csname would be an easy solution and was hoping for an easy way to get the list of all declared options. – Normadize Mar 05 '15 at 00:22