3

I am using a loop to define keys with the xkeyval package, as well as to actually read out the keys inside some self-defined command. Everything works perfectly - but for some reason, as soon as I include hyperref, everything breaks:

! Incomplete \ifnum; all text was ignored after line 47.
<inserted text> 
            \fi 

Please consider the following MWE:

\documentclass{article}
\usepackage{xkeyval}
\usepackage{hyperref} % <-- comment this line to make it work

\makeatletter

\count@=0
\loop
  \advance\count@ 1
  \begingroup\edef\x{\endgroup
    \noexpand\define@key{mycmd}{KEY\the\count@}[]{%
      \noexpand\@namedef{mycmdKEY\the\count@}{####1}%
    }% end of \define@key
  }% end of \edef
  \x % execute \x
\ifnum\count@<6
\repeat
\presetkeys{mycmd}{KEY1=0,KEY2=0,KEY3=0,KEY4=0,KEY5=0,KEY6=0,%
}{}

\newcount\mycount%
\newcounter{mycnt}

\newcommand*\mycmd[2][]{%
\setkeys{mycmd}{#1}{
  \begin{enumerate}
  \mycount=0%
  \loop%
  \advance\mycount 1%
  \setcounter{mycnt}{\csname mycmdKEY\the\mycount\endcsname}%
  \ifnum\value{mycnt}>0%
    \item[item \the\mycount] text
  \fi%
  \ifnum\mycount<6\repeat%
  \end{enumerate}
}%
}%
\makeatother

\begin{document}

\mycmd[
  KEY1=200,
  KEY2=200,
  KEY3=500,
  KEY4=1000,
]{}

\end{document}

Here are my observations:

  • If I remove the dependency on hyperref, it works.
  • If I remove the enumerate environment and replace the call to \item with its argument, it also works.
  • If I remove the call to setkeys and replace the string \csname mycmdKEY\the\mycount\endcsname with 1, it also works.

All of this seems pretty weird to me. If anybody could tell me what I am doing wrong here and what I can do to fix it, that would be great!

PS: If you are wondering how I came up with this code in the first place: This question is a follow-up issue based on an earlier question of mine: Defining xkeyval keys within a loop

1
  • 1
    hyperref redefines \item. However, to fix it all you need is to use \ifnum\value{mycnt}>0\relax – John Kormylo Oct 19 '14 at 22:02
6

You have several bad % in your code. Always leave a space after a constant (or add \relax. In particular the bad one is at

\ifnum\value{mycnt}>0%
  \item[item \the\mycount] text
\fi%

When TeX wants to perform this check, it expands \item to see if some more digits come along. In the case hyperref is loaded, the first level expansion of \item is

\@hyper@itemfalse\if@nmbrlist\@hyper@itemtrue\fi\H@item

but TeX doesn't stop expanding and finds

\let\if@hyper@item\iffalse

which adds two conditionals in the input stream. At this point, though, TeX determines that the number is actually zero. If mycnt is bigger than zero, \let\if@hyper@item\iffalse becomes part of the false text, and the \fi is matched with \iffalse, leaving \ifnum unfinished.

Correct code:

\documentclass{article}
\usepackage{xkeyval}
\usepackage{hyperref}

\makeatletter

\count@=0
\loop
  \advance\count@ 1
  \begingroup\edef\x{\endgroup
    \noexpand\define@key{mycmd}{KEY\the\count@}[]{%
      \noexpand\@namedef{mycmdKEY\the\count@}{####1}%
    }% end of \define@key
  }% end of \edef
  \x % execute \x
\ifnum\count@<6
\repeat
\presetkeys{mycmd}{KEY1=0,KEY2=0,KEY3=0,KEY4=0,KEY5=0,KEY6=0,%
}{}

\newcount\mycount%
\newcounter{mycnt}

\newcommand*\mycmd[2][]{%
\setkeys{mycmd}{#1}{%
  \begin{enumerate}
  \mycount=0
  \loop
  \advance\mycount 1
  \setcounter{mycnt}{\csname mycmdKEY\the\mycount\endcsname}%
  \ifnum\value{mycnt}>0
    \item[item \the\mycount] text
  \fi
  \ifnum\mycount<6
  \repeat
  \end{enumerate}
}%
}%
\makeatother

\begin{document}

\mycmd[
  KEY1=200,
  KEY2=200,
  KEY3=500,
  KEY4=1000,
]{}

\end{document}

See Where are the necessary places to be appended with % to remove unwanted spaces? and When is it harmful to add percent character at end of lines in a \newcommand, or similar

Your Answer

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

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