如何避免使用 crossreftools 包来处理定理注释?

如何避免使用 crossreftools 包来处理定理注释?

crossreftoolshyperref和一起使用cleveref,我可以获得交叉引用,如下面的输出所示,其中包括“命名定理”的名称或普通定理的注释字段:

使用 crossreftools 以下是来源:

\documentclass{memoir}

\usepackage{xstring}
\usepackage{suffix}

\usepackage{amsthm,thmtools}
\swapnumbers

\usepackage{hyperref}
\hypersetup{colorlinks,linkcolor=red}
\usepackage[nameinlink,noabbrev,capitalize]{cleveref}
\usepackage{crossreftools} % <--- how eliminate?

\makeatletter
\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  headpunct={\bfseries\sffamily.},
  postheadspace=0.5em,
  notefont=\sffamily\mdseries,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{thmstyle}

\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  postheadspace=0.5em,
  notefont=\bfseries\sffamily, 
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{namedthmstyle}
\makeatother

\declaretheorem[name=Theorem, style=thmstyle, numberwithin=chapter]{theorem}
\declaretheorem[name=Theorem, style=namedthmstyle, title={}, numberlike=theorem]{namedtheorem}

\crefname{theorem}{Theorem}{Theorems}
\Crefname{theorem}{Theorem}{Theorems}
\crefname{namedtheorem}{Theorem}{Theorems}
\Crefname{namedtheorem}{Theorem}{Theorems}

% --> HERE is where crossreftools is exploited <--
% Allow names in cross-reference to named theorems, etc.,...
% and optional argument names of theorems, etc:
\newcommand{\crefthm}[1]{%
  \IfStrEqCase*{\crtcrefcounter{#1}}{%
    {namedtheorem}{\crefthmname{#1}~(\ref{#1})}%   
    }%
    [\crefthmname{#1}~(\cref{#1})]%
}
\WithSuffix\newcommand\crefthm*[1]{%
  \IfStrEqCase*{\crtcrefcounter{#1}}{%
    {namedtheorem}{\crefthmname*{#1}~(\ref{#1})}%
    }%
    [\crefthmname*{#1}~(\cref{#1})]%
}
% For upper-casing, i.e., leave names as is:
\newcommand{\crefthmname}[1]{\hyperlink{\crtrefanchor{#1}}{\crtrefname{#1}}}
\WithSuffix\newcommand\crefthmname*[1]{\crtrefname{#1}}
\newcommand{\Crefthmname}[1]{\hyperlink{\crtrefanchor{#1}}{\crtrefname{#1}}}
\WithSuffix\newcommand\Crefthmname*[1]{\crtrefname{#1}}

\begin{document}

\mainmatter
\chapter{Math}

\begin{theorem}\label{thm:plain}
    $a + b = b + a$.
\end{theorem}

\begin{theorem}[basic arithmetic]\label{thm:simple}
    $1+1=2$.
\end{theorem}

\begin{namedtheorem}[Pythagorean theorem]\label{thm:pythag}
    The square upon the hypotenuse of a right triangle equals   
    the sum of the squares upon the other two sises.
\end{namedtheorem}

While \crefthm*{thm:simple} may seem simple,
the \crefthm{thm:pythag} is not.

Straightforward \verb!\cref! reference \cref{thm:plain} is OK, whereas \verb!\crefthm! gives: \crefthm{thm:plain}.

\end{document}

问题:如何才能完成同样的事情没有使用crossreftools(或从中重新创建相关代码)?

新的 LaTeX 发布 2023-11-01 \NewProperty/ RecordProperties/RefProperty机制会对此有所帮助吗?(请参阅 LaTeX 新闻,第 38 期,2023 年 11 月)

笔记:

  1. 与该 MWE 相反,在我的实际文档中还有“命名命题”、“命名引理”等,因此和的定义\crefthm在正文\crefthm*中包含了额外的替代方案\IfStrEqCase*
  2. 提出这个问题的原因是担心它crossreftools似乎没有得到积极维护,其当前版本可以追溯到 2020 年。

答案1

好的,那我会添加完整的答案。

方法 1cleveref:使用's获取类型/计数器\cref@gettype(参见https://tex.stackexchange.com/a/692754/105447) 以及其余refcount\getrefbykeydefault

\documentclass{memoir}

\usepackage{xstring}
\usepackage{suffix}

\usepackage{amsthm,thmtools}
\swapnumbers

\usepackage{hyperref}
\hypersetup{colorlinks,linkcolor=red}
\usepackage[nameinlink,noabbrev,capitalize]{cleveref}
% \usepackage{crossreftools} % <--- how eliminate?

\makeatletter
\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  headpunct={\bfseries\sffamily.},
  postheadspace=0.5em,
  notefont=\sffamily\mdseries,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{thmstyle}

\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  postheadspace=0.5em,
  notefont=\bfseries\sffamily,
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{namedthmstyle}
\makeatother

\declaretheorem[name=Theorem, style=thmstyle, numberwithin=chapter]{theorem}
\declaretheorem[name=Theorem, style=namedthmstyle, title={}, numberlike=theorem]{namedtheorem}

\crefname{theorem}{Theorem}{Theorems}
\Crefname{theorem}{Theorem}{Theorems}
\crefname{namedtheorem}{Theorem}{Theorems}
\Crefname{namedtheorem}{Theorem}{Theorems}

% --> HERE is where crossreftools is exploited <--
% Allow names in cross-reference to named theorems, etc.,...
% and optional argument names of theorems, etc:
\newcommand{\mytemptype}{}
\makeatletter
\newcommand{\crefthm}[1]{%
  \cref@gettype{#1}{\mytemptype}%
  \IfStrEqCase*{\mytemptype}{%
    {namedtheorem}{\crefthmname{#1}~(\ref{#1})}%
    }%
    [\crefthmname{#1}~(\cref{#1})]%
}
\WithSuffix\newcommand\crefthm*[1]{%
  \cref@gettype{#1}{\mytemptype}%
  \IfStrEqCase*{\mytemptype}{%
    {namedtheorem}{\crefthmname*{#1}~(\ref{#1})}%
    }%
    [\crefthmname*{#1}~(\cref{#1})]%
}
\makeatother
% For upper-casing, i.e., leave names as is:
\newcommand{\crefthmname}[1]{%
 \hyperlink{\getrefbykeydefault{#1}{anchor}{}}{\getrefbykeydefault{#1}{name}{}}}
\WithSuffix\newcommand\crefthmname*[1]{\getrefbykeydefault{#1}{name}{}}
\newcommand{\Crefthmname}[1]{%
  \hyperlink{\getrefbykeydefault{#1}{anchor}{}}{\getrefbykeydefault{#1}{name}{}}}
\WithSuffix\newcommand\Crefthmname*[1]{\getrefbykeydefault{#1}{name}{}}

\begin{document}

\mainmatter
\chapter{Math}

\begin{theorem}\label{thm:plain}
    $a + b = b + a$.
\end{theorem}

\begin{theorem}[basic arithmetic]\label{thm:simple}
    $1+1=2$.
\end{theorem}

\begin{namedtheorem}[Pythagorean theorem]\label{thm:pythag}
    The square upon the hypotenuse of a right triangle equals
    the sum of the squares upon the other two sises.
\end{namedtheorem}

While \crefthm*{thm:simple} may seem simple,
the \crefthm{thm:pythag} is not.

Straightforward \verb!\cref! reference \cref{thm:plain} is OK, whereas \verb!\crefthm! gives: \crefthm{thm:plain}.

\end{document}

在此处输入图片描述

方法 2:使用新ltproperties模块:

(概念证明。我自己会使用方法 1,因为不需要设置任何其他标签。数据已经存在了。)

\documentclass{memoir}

\usepackage{xstring}
\usepackage{suffix}

\usepackage{amsthm,thmtools}
\swapnumbers

\usepackage{hyperref}
\hypersetup{colorlinks,linkcolor=red}
\usepackage[nameinlink,noabbrev,capitalize]{cleveref}
% \usepackage{crossreftools} % <--- how eliminate?

\makeatletter
\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  headpunct={\bfseries\sffamily.},
  postheadspace=0.5em,
  notefont=\sffamily\mdseries,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{thmstyle}

\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  postheadspace=0.5em,
  notefont=\bfseries\sffamily,
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{namedthmstyle}
\makeatother

\declaretheorem[name=Theorem, style=thmstyle, numberwithin=chapter]{theorem}
\declaretheorem[name=Theorem, style=namedthmstyle, title={}, numberlike=theorem]{namedtheorem}

\crefname{theorem}{Theorem}{Theorems}
\Crefname{theorem}{Theorem}{Theorems}
\crefname{namedtheorem}{Theorem}{Theorems}
\Crefname{namedtheorem}{Theorem}{Theorems}

% --> HERE is where crossreftools is exploited <--
% Allow names in cross-reference to named theorems, etc.,...
% and optional argument names of theorems, etc:

\ExplSyntaxOn
\bool_new:N \l__murray_inside_thm_bool % or any kind of boolean you prefer
\AddToHookWithArguments{label}{
  \bool_if:NT \l__murray_inside_thm_bool
    { \RecordProperties{#1.thm}{counter,title,target} }
}
\AddToHook{env/theorem/begin}{ \bool_set_true:N \l__murray_inside_thm_bool }
\AddToHook{env/namedtheorem/begin}{ \bool_set_true:N \l__murray_inside_thm_bool }
% Add any other theorem environments you use here...
\ExplSyntaxOff
\newcommand{\crefthm}[1]{%
  \IfStrEqCase*{\RefProperty{#1.thm}{counter}}{%
    {namedtheorem}{\crefthmname{#1}~(\ref{#1})}%
    }%
    [\crefthmname{#1}~(\cref{#1})]%
}
\WithSuffix\newcommand\crefthm*[1]{%
  \IfStrEqCase*{\RefProperty{#1.thm}{counter}}{%
    {namedtheorem}{\crefthmname*{#1}~(\ref{#1})}%
    }%
    [\crefthmname*{#1}~(\cref{#1})]%
}
% For upper-casing, i.e., leave names as is:
\newcommand{\crefthmname}[1]{%
 \hyperlink{\RefProperty{#1.thm}{target}}{\RefProperty{#1.thm}{title}}}
\WithSuffix\newcommand\crefthmname*[1]{\RefProperty{#1.thm}{title}}
\newcommand{\Crefthmname}[1]{%
  \hyperlink{\RefProperty{#1.thm}{target}}{\RefProperty{#1.thm}{title}}}
\WithSuffix\newcommand\Crefthmname*[1]{\RefProperty{#1.thm}{title}}

\begin{document}

\mainmatter
\chapter{Math}

\begin{theorem}\label{thm:plain}
    $a + b = b + a$.
\end{theorem}

\begin{theorem}[basic arithmetic]\label{thm:simple}
    $1+1=2$.
\end{theorem}

\begin{namedtheorem}[Pythagorean theorem]\label{thm:pythag}
    The square upon the hypotenuse of a right triangle equals
    the sum of the squares upon the other two sises.
\end{namedtheorem}

While \crefthm*{thm:simple} may seem simple,
the \crefthm{thm:pythag} is not.

Straightforward \verb!\cref! reference \cref{thm:plain} is OK, whereas \verb!\crefthm! gives: \crefthm{thm:plain}.

\end{document}

在此处输入图片描述

选择: 使用zref-clever

因为评论中的讨论表明它可能会引起人们的兴趣。

事实证明,设置起来稍微简单一些,因为zref可以更直接地提取对不同属性的引用,并zref-clever允许使用可选参数提供更大的灵活性,因此我们不必手动处理超链接锚点。我还利用了ltcmd(以前的xparse)和删除了对和的expl3依赖。xstringsuffix

\documentclass{memoir}

\usepackage{amsthm,thmtools}
\swapnumbers

\usepackage{hyperref}
\hypersetup{colorlinks,linkcolor=red}

\usepackage{zref-clever}
\zcsetup{
  cap,
  noabbrev,
  countertype={namedtheorem=theorem},
}
\usepackage{zref-titleref,zref-counter}

\makeatletter
\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  headpunct={\bfseries\sffamily.},
  postheadspace=0.5em,
  notefont=\sffamily\mdseries,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{thmstyle}

\declaretheoremstyle[
  headfont=\bfseries\sffamily,
  postheadspace=0.5em,
  notefont=\bfseries\sffamily,
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\slshape,
]{namedthmstyle}
\makeatother

\declaretheorem[name=Theorem, style=thmstyle, numberwithin=chapter]{theorem}
\declaretheorem[name=Theorem, style=namedthmstyle, title={}, numberlike=theorem]{namedtheorem}

% Note that this implementation requires that a single label be received as
% the mandatory argument of \zcrefthm.  But it is the same as with yours.
\ExplSyntaxOn
\makeatletter
\NewDocumentCommand{\zcrefthm}{sO{}m}{
  \tl_if_empty:eF { \zref@extractdefault {#3} { title } { } }
    {
      \IfBooleanTF{#1}
        { \zcref*[noname,ref=title]{#3} }
        { \zcref[noname,ref=title]{#3}  }
      \nobreakspace
    }
  \tl_if_eq:enTF
    { \zref@extractdefault {#3} { counter } { } } { namedtheorem }
    { (\zcref[noname,#2]{#3}) }
    { (\zcref[#2]{#3}) }
}
\makeatother
\ExplSyntaxOff

\begin{document}

\mainmatter
\chapter{Math}

\begin{theorem}\label{thm:plain}
    $a + b = b + a$.
\end{theorem}

\begin{theorem}[basic arithmetic]\label{thm:simple}
    $1+1=2$.
\end{theorem}

\begin{namedtheorem}[Pythagorean theorem]\label{thm:pythag}
    The square upon the hypotenuse of a right triangle equals
    the sum of the squares upon the other two sises.
\end{namedtheorem}

While \zcrefthm*{thm:simple} may seem simple, the \zcrefthm{thm:pythag} is
not.

Straightforward \verb!\zcref! reference \zcref{thm:plain} is OK, whereas
\verb!\zcrefthm! gives: \zcrefthm{thm:plain}.

\end{document}

在此处输入图片描述

相关内容