5

I am not a TeX/LaTeX specialist, recently I wrote a package concerning 'problems' and 'solutions' which is intended to be displayed at the end of the document, however it is not restricted to that purposes. In order to achieve that behaviour, amongst other features, I used the xkeyval package, with a lot of key macros and boolean keys also.

I want to provide a better version and get rid of dozens of key macro definition lines and boolean key definitions basically looking alike but just setting some flags, replacing the tedious entering of LaTeX code by some short commands like

\GenerateBoolKey[true]{SomeKeys}{DummyBoolKey}

This should define the boolean key DummyBoolKey belonging to family SomeKeys as if one would have written

\define@boolkey{SomeKeys}{DummyBoolKey}[true]{%
\ifKV@SomeKeys@DummyBoolKey%
%Do something if true%
\else%
%Do something different if false%
\fi%
}%

The xkeyval documentation (version 2.6b) says on page 7 that there is defined a macro \ifKV@fam@key as \newif

Well, I failed in writing the above command and using the \ifKV macro, here is a minimal (non) working example, which fails during compiling with error message

     ! Too many }'s.

Here's a minimal example

\documentclass{minimal}
\usepackage{xkeyval}

\makeatletter

\providecommand{\GenerateBoolKey}[3][false]{%
\define@boolkey{#2}{#3}[#1]{%
\csname ifKV@#2@#3 \endcsname%
\typeout{true}%  % Do something if true
\else%
\typeout{false}%   % Do something different if false
\fi%
}% End of  \define@boolkey
}% End of \providecommand

\makeatother

% Key Family is called SomeKeys
% Use a fake command for testing purposes

\providecommand{\DummyCommand}[1][false]{%
\setkeys{SomeKeys}{#1}%

% Do something useful inside this command...

}%

\begin{document}

\GenerateBoolKey{SomeKeys}{DummyBoolKey}%
\DummyCommand[DummyBoolKey=true]%

\end{document}

How can I provide the \newif command on the fly with my 'wrapper' code in order to provide the \ifKV boolean test?

  • You seem to have an extra space in the \csname line, which should be \csname ifKV@#2@#3\endcsname (or \@nameuse{ifKV@#2@#3}). Does altering that fix your issue? – Joseph Wright Jan 1 '14 at 11:52
  • @JosephWright I have already tested whether the extra space in that line is to blame, however it did not remove the errors. I did not know of \@nameuse -- I will test it. Thank you so far. – user31729 Jan 1 '14 at 11:56
  • @JosephWright: I tested both removing the extra space and \@nameuse -- neither worked. – user31729 Jan 1 '14 at 12:24
4

This looks like a problem with conditional nesting. The best approach here seems to me to be to force expansion of the name 'up front' so that you have a definition indentical to that you'd get 'by hand'.

\documentclass{article}
\usepackage{xkeyval}

\makeatletter

\providecommand{\GenerateBoolKey}[3][false]{%
  \begingroup
  \edef\x{\endgroup
    \noexpand\define@boolkey{#2}{#3}[#1]{%
      \expandafter\noexpand\csname ifKV@#2@#3\endcsname%
        \noexpand\typeout{true}%  % Do something if true
      \noexpand\else%
        \noexpand\typeout{false}%   % Do something different if false
      \noexpand\fi%
    }% End of  \define@boolkey
  }% End of defintion of \x
  \x
}% End of \providecommand

\makeatother

% Key Family is called SomeKeys
% Use a fake command for testing purposes

\providecommand{\DummyCommand}[1][false]{%
\setkeys{SomeKeys}{#1}%

% Do something useful inside this command...

}%

\begin{document}

\GenerateBoolKey{SomeKeys}{DummyBoolKey}%
\DummyCommand[DummyBoolKey=true]%

\end{document}

This works by defining \x inside a group which is closed when we use \x, and which forces the expansion of the name without expanding anything else (hence lots of \noexpands).

  • Thanks a lot, Joseph, this was actually was I was looking for -- it works!!! I understand, that I have to dig deeper into TeX/LaTeX internals. After analysing your provided solution I see the crux of the matter but I could not have found the solution by myself. – user31729 Jan 2 '14 at 9:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy