0

Using crossreftools along with hyperref and cleveref, I can obtain cross-references, as shown in the output below, that include the names of "named theorems" or the note fields of ordinary theorems:

Using crossreftools Here is the source:

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

Question: How might one accomplish the same thing without using crossreftools (or recreating the relevant code from it) ?

Might the new LaTeX release 2023-11-01 \NewProperty / RecordProperties / RefProperty mechanism help here? (See LaTeX News, Issue 38, November 2023)

Notes:

  1. In contrast to that MWE, in my actual document there are also "named propositions", "named lemmas", etc., and so the definitions of \crefthm and \crefthm* have additional alternatives included in the \IfStrEqCase* bodies.
  2. The reason for asking the question is concern that crossreftools does not seem to be actively maintained, its current version dating from 2020.
mbert
  • 4,171
murray
  • 7,944
  • See, for example https://tex.stackexchange.com/a/692754/105447, on how to get the type directly from cleveref (which I think is the equivalent of \crtcrefcounter). For the anchor and name, you could probably rely on refcount. Off-topic: alas, your reasons for not wanting to use crossreftools seem a bit unfair. Just because a package has no recent update, it doesn't mean it is not working or not maintained. The latest version of cleveref itself is from 2018... – gusbrs Dec 05 '23 at 22:10
  • @gusbrs: I don't see how refcount can provide the names; I am trying to get the contents of the theorem note field, after all. (But your comment about package status is well-taken!) – murray Dec 05 '23 at 22:32
  • Where do you think the name is stored? It is in the standard label, just like section names, captions, etc. Try \getrefbykeydefault{thm:pythag}{name}{}. – gusbrs Dec 05 '23 at 22:52
  • @gusbrs: Aha! I didn't know about that. Where does \getrefbykeydefault come from? I don't find it in the docs for hyperref or cleveref. – murray Dec 05 '23 at 23:24
  • From refcount! ;-) I think hyperref (or nameref) loads it for you. Btw, I think you have everything you need to answer, but if you are interested in a zref-clever answer, I can provide one. – gusbrs Dec 05 '23 at 23:32
  • @gusbrs: OK, I found the documentation for \getrefbykeydefault in refcount. But I'd like to see, also, a zref-clever answer. Then I'll have 3 ways to approach this and can see which is the most appropriate for my needs. – murray Dec 06 '23 at 01:45
  • Ok, I'll do so. It would be appreciated though if you provided a self answer using \cref@gettype and refcount (and accept it, because it is the answer to the actual question). – gusbrs Dec 06 '23 at 01:59
  • Ah, just saw your edit. And, yes, the new ltproperties is also an alternative for this. – gusbrs Dec 06 '23 at 17:24
  • I'm not seeing how \getrefbykeydefault can grab the "note" field (the optional argument from something like \begin{theorem}[some description]. I don't see in the \refcount any key for that. – murray Dec 07 '23 at 01:53
  • murray, it's the same, it's in the name field (for refcount). The standard label has only 4 fields (actually five, but...): the ref, the page, the anchor, and the name/title. So it can only be in the name, and indeed that's where it is stored. – gusbrs Dec 07 '23 at 03:10

1 Answers1

2

Ok, I'll add a full answer then.

Method 1: Get the type/counter with cleveref's \cref@gettype (see https://tex.stackexchange.com/a/692754/105447) and the rest with refcount's \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}

enter image description here

Method 2: Using the new ltproperties module:

(Proof of concept. I'd use method 1 myself, since there's no need to set any additional labels. The data is already there.)

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

enter image description here

Alternative: Using zref-clever.

Since discussion in the comments suggested it might be of interest.

It turns out things are slightly simpler to set up, since zref makes it more straightforward to extract the references to different properties, and zref-clever allows for more flexibility with optional arguments, so we don't have to handle the hyperlink anchor manually. I also leveraged ltcmd (formerly xparse) and expl3 to also drop the dependencies on xstring and suffix.

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

enter image description here

gusbrs
  • 13,740
  • Your \zcrefthm*{thm:simple} may seem simple is giving "While (Theorem 1.2) may seem simple". But in my original version using crossreftools, I had, and want to have, "While basic arithmetic (Theorem 1.2) may seem simple", which includes the contents of the note field of that theorem. – murray Dec 06 '23 at 15:03
  • @murray Ah, I had missed that! I'm not really acquainted with thmtools... (In my defense, I was trying to fix the spurious space you get with \crefthm{thm:plain}). Anyway, hopefully fixed now. – gusbrs Dec 06 '23 at 15:44