1

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{%
    \thm@notefont{}% same as heading font
    \itshape % body font
}
\def\th@definition{%
    \thm@notefont{}% same as heading font
    \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}

enter image description here

  • 1
    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
3

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

instead.

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.

  • Could you explain the difference between these two? and possibly a recommendation about which solution? – oliversm Jun 26 '18 at 12:01
  • @oliversm There should be no difference (though I would not be too surprised if I am proven wrong on that). My gut instinct prefers the second solution (that's why I updated my other answer with that), but I don't have a good Texnical reason to think it is better. – moewe Jun 26 '18 at 12:09
  • +1 for outstanding use of the term "thrice". :-) – Mico Jun 26 '18 at 12:09
  • 1
    tex.stackexchange.com/q/7703/35864 might be of interest to understand all the \expandafters – moewe Jun 26 '18 at 12:15

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.