3

Suppose somewhere in my long Ph.D. thesis I use a theorem-like environment (maybe it's a theorem, maybe it's a lemma, etc.), and label it. At another place I want to have an environment which is the same as that earlier one (not with the same number though). I can get the environment's name with cleveref's \namecref - but I can't just use it:

\documentclass{article}
\usepackage{ntheorem}
\usepackage{cleveref}
\newtheorem{theorem}{Theorem}
\begin{document}
\begin{theorem}
\label{myfirst}
This is the first theorem.
\end{theorem}
\begin{\namecref{myfirst}}
This is another environment of the same kind as \ref{myfirst}!.
\end{\namecref{myfirst}}
\end{document}

trying to \def or \edef something to the \namecref doesn't work either. What can I do? Of course, the environment cannot be known on the first run, so I would obviously need a macro which would expand to some 'dummy environment' on the first run and the real environment on the second (\namecref should give ?? on the first run which is not useful.)

Note: This questions is a lead-up to the question Need a 'thin', flexible, theorem restatement environment.

4
  • You have to extract the environment name from the label for yourself. Would you like to have a solution based on hyperref or a solution based on cleverref? (Both do store the environment name in the aux file, but in a different way.)
    – user2574
    Dec 25, 2011 at 12:00
  • @AxelSommerfeldt: The best option would be a solution not based on any of them... otherwise, and if the solutions are short, then I'd like one for each of them; otherwise just for the one allowing the easiest solution.
    – einpoklum
    Dec 25, 2011 at 12:11
  • "Not based on any of them" is IMHO the most difficult approach since one need to redefine \label for oneself, keeping this working with packages which redefine \label, too, especially hyperref. So I just posted a solution based on cleveref and one based on hyperref.
    – user2574
    Dec 25, 2011 at 12:38
  • BTW: Why do you think "the best option would be a solution not based on any of them"? This just means writing extra code which already has been written by other persons and offered by other packages. IMHO this would be rather silly.
    – user2574
    Dec 25, 2011 at 18:12

2 Answers 2

4

The following is a hack, which is based on the existing cleveref implementation, which I'm not familiar with. It seems to work, but you may have to add a bit more robustness. (The solution is similar to one of Axel's solutions.)

\documentclass{article}

\newtheorem{theorem}{Theorem}
\newtheorem{lemma}{Lemma}

\usepackage{cleveref}
\makeatletter

\newenvironment{reformulation}[1]
    {\expandafter\ifx\csname r@cref@#1\endcsname\relax% label undefined
         \def\my@env{theorem}% if label is undefined, assume it's a theorem
     \else%
         \cref@gettype{#1}{\my@env}%
     \fi%
     \begin{\my@env}}%
    {\end{\my@env}}

\makeatother

\begin{document}
   \begin{lemma}\label{hi}
      Lemma.
   \end{lemma}
   \begin{reformulation}{hi}
      Theorem or lemma.
   \end{reformulation}
\end{document}
2
  • It's not clear to me why you are using \edef\my@env{\csname cref@\@tempa @name\endcsname}. IMHO \cref@gettype{#1}{\my@env} should be sufficient.
    – user2574
    Dec 25, 2011 at 13:17
  • Hi Marc, I removed the salutation. This is just the style here, in order to keep things concise. See the welcome message for more information.
    – qubyte
    Dec 26, 2011 at 2:46
5

One can use either cleveref or hyperref to get the "pure" name of the environment from the aux file. Unfortunately there are no documented ways on how to do it, so one has to use internal macros (which can change in future versions) in both cases.

First a solution for cleveref. It uses two internals from the cleveref package:

  1. cleveref stores an additional label preceding with "cref@" to hold the environment name
  2. cleveref offers an internal macro called \cref@gettype to get the "pure" environment name
\documentclass{article}
\usepackage{ntheorem}
\usepackage{cleveref}
\newtheorem{theorem}{Theorem}

\makeatletter
\newenvironment{xxxref}[1]{%
  \@ifundefined{r@cref@#1}%
    {\def\@xxx@env{quote}}% use default environment
    {\cref@gettype{#1}{\@xxx@env}}%
  \begin{\@xxx@env}}%
{\end{\@xxx@env}}%
\makeatother

\begin{document}
\begin{theorem}
\label{myfirst}
This is the first theorem.
\end{theorem}
\begin{xxxref}{myfirst}
\label{xxxfirst}
This is another environment of the same kind as \ref{myfirst}!.
\end{xxxref}
\begin{xxxref}{myfirst}
This is another environment of the same kind as \ref{xxxfirst}!.
\end{xxxref}
\end{document}

Second, a solution for hyperref. It uses two internals from the hyperref package:

  1. hyperref stores the environment name inside the 4th argument of the label
  2. The environment name is limited by a period inside that argument.

See also my answer here: Get label target type

\documentclass{article}
\usepackage{ntheorem}
\usepackage{hyperref}
\newtheorem{theorem}{Theorem}

\makeatletter
\newcommand*\@myautoref[2]{% \HyPsd@@@autoref from hyperref, modified
  \expandafter\expandafter\expandafter\@@myautoref
      \csname r@#2\endcsname{}{}{}{}\@nil#1\@nil
}
\def\@@myautoref#1#2#3#4#5\@nil#6\@nil{% \HyPsd@autorefname, modified
  #6#4.\@nil}% Argument #4 = type and number, e.g. "section.1" or "subsection.1.2"
\def\@myreftype#1.#2\@nil{#1}

\newcommand*\beginref{\xxx@ref{\begin}}
\def\endref{\xxx@ref{\end}}
\newcommand*\xxx@ref[2]{%
  \@ifundefined{r@#2}%
    {\def\@tempa{quote}}% use default environment
    {\def\@tempa{\@myautoref\@myreftype{#2}}}%
  \edef\@tempa{\noexpand#1{\@tempa}}%
  \@tempa}
\makeatother

\begin{document}
\begin{theorem}
\label{myfirst}
This is the first theorem.
\end{theorem}
\beginref{myfirst}
This is another environment of the same kind as \ref{myfirst}!.
\endref{myfirst}
\beginref{xxxfirst}
This is another environment of the same kind as \ref{xxxfirst}!.
\endref{xxxfirst}
\makeatother
\end{document}
10
  • 1
    Why is the \beginref a \newcommand* while the \endref is a \def? Also, is there a reason not to define an environment, but rather just being and end macros?
    – einpoklum
    Dec 25, 2011 at 13:17
  • Another question: You're using \cref@gettype as the pure name, while @MarcvanDongen's code uses \csname cref@\@tempa @name\endcsname. Is there a (potential) difference?
    – einpoklum
    Dec 25, 2011 at 13:31
  • 1
    \endref is a \def since one can't define a new command starting with "end" using \newcommand. No, there is no reason not to define an environment. There was no wish given, so I implemented it as it first came into my mind. (In fact I even like an environment based solution.) And regarding the "@name" stuff: AFAIK this is for translation issues, so using \csname cref@\@tempa @name\endcsname is wrong. See also cleveref documentation, section "Language and babel support".
    – user2574
    Dec 25, 2011 at 14:14
  • Addendum to last comment: \cref@<type>@name is the same as \<type>autorefname in hyperref, e.g. \sectionautorefname is "section" in English but "Abschnitt" in German, so \autoref{..} will give you an localized name, just like \namecref{..}.
    – user2574
    Dec 25, 2011 at 14:27
  • Well, I suppose the non-hyperref and non-cleveref way is too long/complicated/brittle to use. Now, if I could only get the counter rather than the name, I could resolve my followup question.
    – einpoklum
    Dec 25, 2011 at 15:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .