5

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}
3
  • I would not use \@ifnextchar because it ignores spaces
    – user182849
    Mar 6 at 18:54
  • 1
    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
    – user182849
    Mar 6 at 19:01

2 Answers 2

5

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}

enter image description here

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}
1
  • 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}} }
    – user182849
    Mar 7 at 3:52
4

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}

enter image description here

0

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.