使用 \ref{#1}c 代替 \cref{#1} (使用 \futurelet)

使用 \ref{#1}c 代替 \cref{#1} (使用 \futurelet)

我想使用\ref{#1}c而不是\cref{#1}来解决一些自动完成问题。

我一直在尝试使用以下代码来实现这一点:

\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}}

但结果没有改变。哪里出了问题?

梅威瑟:

\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}

答案1

你的定义有几个缺陷。你需要先吸收论证,\ref然后再检查是否c符合。

条件也应该结束调用“gobbling”宏。

最后,\ref在文档开始时被重新定义hyperref,因此您自己的重新定义应该被延迟。

另一个小问题是使用\let命令\refhyperref使其更强大;在这里我使用\NewCommandCopy已经可用一年多了;如果你的 TeX 发行版较旧,请使用包\LetLtxMacro中的命令letltxmacro

\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}

在此处输入图片描述

为什么\noexpand?因为你不想扩展下面的标记,它可能是宏或~

您可能会欣赏expl3相同的版本,它更易于实现,但在概念上并没有什么不同。

\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}

答案2

这里我使用一个标记循环来获取结果。为了使 的行为正确hyperref,必须将 的重新定义\ref放在\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}

在此处输入图片描述

相关内容