# Custom clever ref and and short captions giving error

I have been using the following modification of \Cref in my document to provide names to theorems and lemmas if one is given (as I think it reads nicer). As in the MWE (based on this answer to a previous question).

However, I just noticed that when I have a custom command in the short caption field I get the following error: Incomplete \iffalse; all text was ignored after line 68. I have commented this line out so it compiles for now, but I have several of these scattered throughout many short captions. Is there a fix?

MWE

(\caption[\oliver's short caption]{\oliver's figure} causes the issues.)

\documentclass[a4paper,10pt]{extarticle}

\usepackage{amsmath,mathtools,graphicx,etoolbox,nameref,amsthm,cleveref,xspace}
% Have theorems and lemmas be referenced by name if applicable.
\makeatletter
\renewrobustcmd{\cref}{\@osmcref{cref}}
\renewrobustcmd{\Cref}{\@osmcref{Cref}}
\def\@osmcref#1#2{%
\begingroup
\ifcsundef{r@#2}
{}
{\edef\@osmcref@name{%
\expandafter\expandafter\expandafter
\@thirdoffive\csname r@#2\endcsname}}%
\ifcsundef{r@#2@cref}
{}
{\cref@gettype{#2}{\@osmcref@type}}%
\ifboolexpr{not test {\ifdefvoid{\@osmcref@name}}
and (test {\ifdefstring{\@osmcref@type}{theorem}}
or test {\ifdefstring{\@osmcref@type}{lemma}})}
{\nameref{#2} (\@cref{#1}{#2})}
{\@cref{#1}{#2}}%
\endgroup
}
\makeatother
% Give bold names to definitions and similar environments.
\makeatletter
\def\th@plain{%
\itshape % body font
}
\def\th@definition{%
\normalfont % body font
}
\makeatother
% Giving correct theorem and lemma environments.
\newtheorem{theorem}{Theorem}[section]
\newtheorem{corollary}{Corollary}[theorem]
\newtheorem{lemma}[theorem]{Lemma}
% Naming these nicely.
\crefname{lemma}{lemma}{lemmas}
\Crefname{lemma}{Lemma}{Lemmas}
\crefname{theorem}{theorem}{theorems}
\Crefname{theorem}{Theorem}{Theorems}

\newcommand{\oliver}{Oliver\xspace}

\begin{document}
\section{Commands and short captions}
\label{sec}

\begin{lemma}\label{noname}
Extremely important lemma that has no name.
\end{lemma}

\begin{lemma}[Fatou's lemma]\label{boringLemma}
This is some boring statement.
\end{lemma}

\begin{theorem}[Fubini's Theorem]\label{awesomeTheorem}
This is a really awesome statement.
\end{theorem}

\Cref{fig} Doesn't work when I have \verb|\oliver| in the short caption.

\begin{figure}[htb]
\centering
Something interesting.
\caption[Oliver's short caption]{\oliver's figure}
%        \caption[\oliver's short caption]{\oliver's figure} % The troublesome line.
\label{fig}
\end{figure}

We have \Cref{boringLemma} and \Cref{awesomeTheorem}. Whereas \Cref{noname} doesn't have anything interesting.

\end{document}


• Is "Don't use \xspace" an acceptable answer? (tex.stackexchange.com/q/86565/35864) – moewe Jun 26 '18 at 11:39
• Not really, because sometimes I would like to follow the command with either a space or punctuation, and \xspace ensures this is formatted correctly. e.g. \oliver likes this figure would remove the space. – oliversm Jun 26 '18 at 11:42
• In that case you could write \oliver{} likes this figure if you don't use \xspace. I will have a look if I can find out how often exactly I need to expand the definition, but I can't promise anything. – moewe Jun 26 '18 at 11:43
• I have previously used the \oliver{} and \oliver/ variants but found these ugly, and then saw \xspace and until now I have been getting along happily with it. – oliversm Jun 26 '18 at 11:45

The unprotected \edef was a bit too eager. Try

\makeatletter
\newcommand\expandthrice{%
\unexpanded\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter}
\renewrobustcmd{\cref}{\@osmcref{cref}}
\renewrobustcmd{\Cref}{\@osmcref{Cref}}
\def\@osmcref#1#2{%
\begingroup
\ifcsundef{r@#2}
{}
{\edef\@osmcref@name{\expandthrice{%
\expandafter\expandafter\expandafter
\@thirdoffive\csname r@#2\endcsname}}}%
\ifcsundef{r@#2@cref}
{}
{\cref@gettype{#2}{\@osmcref@type}}%
\ifboolexpr{not test {\ifdefvoid{\@osmcref@name}}
and (test {\ifdefstring{\@osmcref@type}{thm}}
or test {\ifdefstring{\@osmcref@type}{lemma}})}
{\nameref{#2} (\@cref{#1}{#2})}
{\@cref{#1}{#2}}%
\endgroup
}
\makeatother


or this beauty

\makeatletter
\renewrobustcmd{\cref}{\@osmcref{cref}}
\renewrobustcmd{\Cref}{\@osmcref{Cref}}
\def\@osmcref#1#2{%
\begingroup
\ifcsundef{r@#2}
{}
{\expandafter\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\def
\expandafter\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\@osmcref@name
\expandafter\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter{%
\expandafter\expandafter\expandafter
\@thirdoffive\csname r@#2\endcsname}}%
\ifcsundef{r@#2@cref}
{}
{\cref@gettype{#2}{\@osmcref@type}}%
\ifboolexpr{not test {\ifdefvoid{\@osmcref@name}}
and (test {\ifdefstring{\@osmcref@type}{thm}}
or test {\ifdefstring{\@osmcref@type}{lemma}})}
{\nameref{#2} (\@cref{#1}{#2})}
{\@cref{#1}{#2}}%
\endgroup
}
\makeatother


I have updated my answer to Clever Ref to only give theorem names. with the seven \expandafters monster.
The first solution with \expandthrice expands the contents of \@osmcref@name three times by placing it in an \edef (which normally tries to expand as far as possible) but stopping the expansion after three steps with \expandthrice (essentially this is etoolbox's \expandonce but for three expansion steps). The second solution with the seven \expandafters immediately only expands the contents of \@osmcref@name three times before saving. I somehow feel that the second solution is a bit nicer because it does not define a new command and because it performs the necessary expansion steps explicitly, whereas the first solution stops an explicit full expansion in the right place.
• tex.stackexchange.com/q/7703/35864 might be of interest to understand all the \expandafters – moewe Jun 26 '18 at 12:15