# How to use an environment whose name comes from a reference?

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.

-
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.) – Axel Sommerfeldt Dec 25 '11 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 '11 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. – Axel Sommerfeldt Dec 25 '11 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. – Axel Sommerfeldt Dec 25 '11 at 18:12

## 2 Answers

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}

-
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. – Axel Sommerfeldt Dec 25 '11 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 '11 at 2:46

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}

-
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 '11 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 '11 at 13:31
\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". – Axel Sommerfeldt Dec 25 '11 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{..}. – Axel Sommerfeldt Dec 25 '11 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 '11 at 15:28