# Expandable, very specific keyval processing

I am having a hard time trying to come up with an fully expandable keyval parsing macro which deals only with specific keys/values. I wouldn't even attempt this in full generality, that's way beyond me. Here is as far as I've got:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{ifthen}
\begin{document}

\makeatletter
\def\foo@bar{value}

\def\thing@i#1{%
\thing@ii#1&}

\def\thing@ii#1=#2&{%
\ifthenelse{\equal{#1}{form}}
{#2}
{}}

\catcode\==11
\csuse{foo@\thing@i{form=original}}

\end{document}


Aside from the problem of having to catcode "=" (and then somehow having to catcode it back again later when "=" doesn't mean "=" any more), This doesn't work due to some expansion issue with the \ifthen it seems. I am a bit numb looking at this now, I've tried using \ifx etc. but no luck. There seems to be no way to get fully expandable keyval processing and so I'm reduced to doing something which hard-codes the possible keys etc. I have to have this because I will have macros with keyval args which need fully expanding to construct csnames.

• The \ifthenelse tests are not expandable. – egreg Apr 24 '13 at 10:42

The \ifthenelse tests are not expandable. You can use \pdfstrcmp for the comparison (and \pdf@strcmp is better because it's engine independent):

\documentclass{article}
\usepackage{etoolbox,pdftexcmds}
\begin{document}

\makeatletter
\def\foo@bar{value}

\def\thing@i#1{%
\thing@ii#1&}

\def\thing@ii#1=#2&{%
\ifnum\pdf@strcmp{#1}{form}=\z@
#2%
\fi}

\def\foo@original{ORIGINAL} % provide a definition for testing
\csuse{foo@\thing@i{form=original}}

\end{document}


You can also strip spaces (but note that this will strip also "internal spaces", so no options with a space in the name):

\documentclass{article}
\usepackage{etoolbox,pdftexcmds}
\begin{document}

\makeatletter
\def\foo@bar{value}

\def\thing@i#1{%
\thing@ii#1&}

\def\thing@ii#1=#2&{%
\ifnum\pdf@strcmp{\zap@space#1 \@empty}{form}=\z@
\zap@space#2 \@empty
\fi}

\def\foo@original{ORIGINAL} % provide a definition for testing
\csuse{foo@\thing@i{form=original}}

\csuse{foo@\thing@i{form =original}}

\csuse{foo@\thing@i{form = original}}

\csuse{foo@\thing@i{ form = original }}

\end{document}

• Many thanks - it is rather annoying that I tried exactly this after fearing that the \ifthen stuff wasn't expandable but now realise I had a typo when I tried it. This at least confirms that it's the right way to do it ... – PLK Apr 24 '13 at 11:23
• One question - is there an expandable way you know of of stripping spaces from the beginning/end of strings? The strings to compare with \pdf@strcmp` may come with leading/trailing spaces. – PLK Apr 24 '13 at 12:20
• @PLK I was expecting this. ;-) – egreg Apr 24 '13 at 12:22
• I'm embarrassingly glad to hear it :-) – PLK Apr 24 '13 at 12:25
• @PLK Solution ready. ;-) – egreg Apr 24 '13 at 12:26