# use \ref{#1}c instead of \cref{#1} (using \futurelet)

I would like to use \ref{#1}c instead of \cref{#1} for some autocompletion issues.

I have been trying to implement this using the following code:

\let\oldref\ref
\def\ref{\futurelet\@nexttoken\myref}
\def\myref#1{\if c\@nexttoken\creftemp{#1}\else\oldref{#1}\fi}
\def\creftemp#1c{\cref{#1}}


But the result doesn't change. What's wrong?

MWE:

\documentclass[10pt]{article}
\usepackage{hyperref}
\usepackage{amsthm}
\usepackage{cleveref}
\newtheorem{theorem}{Theorem}

\makeatletter
\let\oldref\ref
\def\ref{\futurelet\@nexttoken\myref}
\def\myref#1{\if c\@nexttoken\creftemp{#1}\else\oldref{#1}\fi}
\def\creftemp#1c{\cref{#1}}
\makeatother

\begin{document}

\begin{theorem}[sdfs] \label{sdf} asfa \end{theorem}

\cref{sdf} = theorem 1

\ref{sdf}c = theorem 1

\ref{sdf} c = 1 c

\end{document}

• I would not use \@ifnextchar because it ignores spaces Mar 6 at 18:54
• Can you edit your question to provide a minimum working example so that we don't each have to create all the necessary filling that your question lacks? Mar 6 at 18:57
• @StevenB.Segletes Sure Mar 6 at 19:01

There are several shortcomings in your definition. You need to first absorb the argument to \ref and only after it check whether a c follows.

Also the conditional should end before calling the “gobbling” macro.

Finally, \ref gets redefined by hyperref at begin document, so your own redefinition should be delayed.

Another small issue is the usage of \let with the \ref command that hyperref makes robust; here I use \NewCommandCopy that's been available for more than a year; if your TeX distribution is older, use \LetLtxMacro from the letltxmacro package.

\documentclass[10pt]{article}

\usepackage{amsthm}
\usepackage{hyperref}
\usepackage{cleveref}

\newtheorem{theorem}{Theorem}

\makeatletter
\AtBeginDocument{%
\NewCommandCopy{\old@ref}{\ref}%
\def\ref#1{\def\temp@ref{#1}\futurelet\@nexttoken\new@ref}%
}
\def\new@ref{%
\if c\noexpand\@nexttoken
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\cref@eatc{\temp@ref}}%
{\old@ref{\temp@ref}}%
}
\def\cref@eatc#1c{\cref{#1}}
\makeatother

\begin{document}

\begin{theorem}[sdfs] \label{sdf} asfa \end{theorem}

\cref{sdf} = theorem 1

\ref{sdf}c = theorem 1

\ref{sdf} c = 1 c

\end{document}


Why \noexpand? Because you don't want to expand the following token which might be a macro or ~.

You may appreciate an expl3 version of the same, which is easier to implement, but not conceptually different.

\documentclass[10pt]{article}

\usepackage{amsthm}
\usepackage{hyperref}
\usepackage{cleveref}

\newtheorem{theorem}{Theorem}

\ExplSyntaxOn

\AtBeginDocument
{
\NewCommandCopy{\__refc_saved_ref:n}{\ref}
\cs_set_eq:NN \ref \__refc_new_ref:n
}

\tl_new:N \l__refc_arg_tl

\cs_new_protected:Nn \__refc_new_ref:n
{
\tl_set:Nn \l__refc_arg_tl { #1 }
\peek_charcode_remove:NTF c
{
\exp_args:NV \cref \l__refc_arg_tl
}
{
\exp_args:NV \__refc_saved_ref:n \l__refc_arg_tl
}
}

\ExplSyntaxOff

\begin{document}

\begin{theorem}[sdfs] \label{sdf} asfa \end{theorem}

\cref{sdf} = theorem 1

\ref{sdf}c = theorem 1

\ref{sdf} c = 1 c

\end{document}

• Thanks. Based on your answer, I could further simplify it: \AtBeginDocument{% \NewCommandCopy{\old@ref}{\ref} \def\ref#1{\ltx@ifnextchar@nospace c{\cref@eatc{#1}}{\old@ref{#1}}} \def\cref@eatc#1c{\cref{#1}} } Mar 7 at 3:52

Here I use a token cycle to obtain the result. For proper behavior with hyperref, the redefinition of \ref must be placed \AtBeginDocument.

\documentclass{article}
\usepackage{hyperref}
\usepackage{amsthm}
\usepackage{cleveref}
\newtheorem{theorem}{Theorem}

\let\oldref\ref
\usepackage{tokcycle}
\newcommand\tcpushliteral[1]{\tcpush{\noexpand#1}}
\stripgroupingtrue

\AtBeginDocument{\renewcommand\ref[1]{%
\tokencycle
{\ifx c##1\tcpush{\cref{#1}}\else\tcpush{\oldref{#1}##1}\fi
\tcpushliteral{\endtokcycraw}}
{\tcpushliteral{\truncatenow{##1}}}
{\ifx\truncatenow##1\else
\tcpush{##1}\fi\tcpush{\oldref{#1}}%
\tcpushliteral{\endtokcycraw}}
{\tcpush{\oldref{#1}##1}\tcpushliteral{\endtokcycraw}}%
}}

\begin{document}

\begin{theorem}[sdfs] \label{sdf} asfa \end{theorem}

\cref{sdf} = theorem 1

\ref{sdf}c = theorem 1

\ref{sdf} c = 1 c

\ref{sdf}x = 1x

\ref{sdf}\today = 1\today

\ref{sdf}{\itshape d}x = 1{\itshape d}x
\end{document}