[Tex/LaTex] Easy-to-use reference-able environment for restating theorem-like environments

counterscross-referencingenvironmentsnamingtheorems

This question is a development of the same issue as this one; following my own answer and later comment there, I decided it deserves a spin-off.

I would like to define an environment for restating theorems(/lemmata/propositions/etc), which makes the following code work:

\documentclass{article}
\usepackage{ntheorem}

% Magic goes here

\newtheorem{theorem}{Theorem}[section]
\newtheorem{prop}[theorem]{Proposition}

\begin{document}
\begin{theorem}\label{myfirst}
This is the first environment.
\end{theorem}
\begin{prop}\label{mysecond}
This is the second environment.
\end{prop}
\begin{theorem}\label{mythird}
This is the third environment.
\end{theorem}
\clearpage
\begin{restatement}[restated]{mysecond}
\label{mysecond-restated}
This is a restatement of the second environment.
\end{restatement}
\begin{theorem}\label{myfourth}
This is the fourth environment.
\end{theorem}
a \verb|ref| to the second environment: \ref{mysecond} \
a \verb|ref| to its restatement: \ref{mysecond-restated} \
a \verb|pageref| to the second environment: \pageref{mysecond} \
a \verb|pageref| to its restatement: \pageref{mysecond-restated}
\end{document}

Requirements:

  1. The environment only requires the label of the theorem you're referencing, nothing else.
  2. You should be able to reference the restatement rather than the original statement.
  3. You can't assume the environment's counter has the same name as the environment (e.g. the user may have \newtheorem{proposition}[theorem]{Proposition}, so propositions use the theorem counter).

Optional, Nice-to-Have features:

  1. No reliance on hyperref, cleveref or thmtools. (This was "Requirement 5" which the bounty mentions)
  2. Code which works with amsthm as well.
  3. \autorefing or \namecrefing the restatement work when hyperref or cleveref are used.
  4. Code doesn't break when writing right-to-left documents (Hebrew, Arabic)
  5. Possibility of restating unnumbered theorems.

An initial solution

My initial work has evolved into a basically-satisfactory solution, see below, with the help I got asking lead-up questions. But that solution suffers from several problems:

The problems with this are:

  • I have no idea what \cref@constructprefix in ntheorem does, and what's the intended use of p@somecounter, so I basically copy-pasted that part blindly and maybe I'm doing something wrong.
  • The code is already not so short.
  • Code likely to break if cleveref or ntheorem change slightly.

And it does not meet most of the useful want-to-have's above. So improvements are quite welcome for your bounty!

Best Answer

Well, with a little help from friends in other questions (this one and this one, it looks like I have a solution satisfying the basics:

Edit: Now supporting hyperref, but for that we need counter aliasing, see this question for the reason we need that.

\documentclass{article}
\usepackage{etoolbox}
\usepackage{ntheorem}
\usepackage{hyperref}
% cleveref after hyperref!
\usepackage{cleveref}
\usepackage{aliascnt}

\makeatletter

% usage:
% same as you would use \newtheorem using an existing counter
\def\newaliasedtheorem#1[#2]#3{%
  \newaliascnt{#1@alt}{#2}
  \newtheorem{#1}[#1@alt]{#3}
  \expandafter\newcommand\csname #1@altname\endcsname{#3}
}

% usage:
% \begin{restatement}[comment]{label-of-original-statement}
%
\newenvironment{restatement}[2][]{%
  \begingroup%
  \@ifundefined{r@cref@#2}{%
    \GenericWarning{}{Reference `#2' undefined, using %
      environment `\restatement@defaultenv' for restatement.}
    \def\restatement@envname{\restatement@defaultenv}
  }{%
    \cref@gettype{#2}{\restatement@envname}%
    \typeout{restatement: env name is \restatement@envname}%
    \cref@getlabel{#2}{\restatement@label}%
    \typeout{restatement: label is \restatement@label}%
    \edef\restatement@countername{\getenvcountername{\restatement@envname}}
    \typeout{restatement: counter name is \restatement@countername}%
    \patchcmd{\@thm}%
      {\@ifnextchar}%
      {%
       \@namedef{the\restatement@countername}{\restatement@label}%
       % This next macro invocation is lifted from latex.ltx; it
       % controls the contents of the line which will be written to the aux
       % file for a possible \label{..} command within the environment;
       % Note that \csname p@\restatement@countername\endcsname seems to
       % expand to nothing eventually, for just about any environment you're
       % restating
       \protected@edef\@currentlabel%
         {\csname p@\restatement@countername\endcsname \restatement@label}%
       %
       \cref@getcounter{#2}{\restatement@counterval}%
       \typeout{restatement: counter value is \restatement@counterval}%
       % These next two macro invocations are lifted from cleveref.sty,
       % which adds its own .aux line for each \label.
       % Note the environment-vs-counter-name trickery, and that
       % \csname p@#2\endcsname seems to expand to nothing;
       % also, I'm not sure what this next line does, if anything
       \cref@constructprefix{\restatement@envname}{\cref@result}%
       \typeout{restatement: cref@result is \cref@result}%
       \typeout{restatement: p@... is \csname p@\restatement@countername\endcsname}%
       \protected@xdef\cref@currentlabel{%
         [\restatement@envname][\restatement@counterval][\cref@result]%
         \csname p@\restatement@countername\endcsname \restatement@label}%
       \@ifnextchar}%
     {}{}%
  }%
  \def\restatement@comment{#1}%
  \ifx\restatement@comment\@empty%
    \begin{\restatement@envname}%
  \else%
    \begin{\restatement@envname}[#1]%
  \fi%
  \@ifundefined{r@cref@#2}{%
  }{%
    \addtocounter{\restatement@countername}{-1}
  }%
}%
{%
  \end{\restatement@envname}%
  \endgroup%
}

% Suggestion at:
% http://tex.stackexchange.com/a/39328/5640
% this works with all of amsthm, ntheorem and thmtools (!)
\def\getenvcountername#1{%
  \@ifundefined{mkheader@#1}
    {\expandafter\expandafter\expandafter\@getenvcountername@kernel
     \csname\ifcsname thmt@original@#1\endcsname thmt@original@\fi#1\endcsname}
    {\expandafter\expandafter\expandafter\@getenvcountername@ntheorem\csname mkheader@#1\endcsname}}
\def\@getenvcountername@kernel#1#2#3{#2}
\def\@getenvcountername@ntheorem\csname#1\endcsname#2#3#4#5{#4}

\newcommand{\restatement@defaultenv}{quote}
\makeatother


\newtheorem{theorem}{Theorem}[section]
\newaliasedtheorem{prop}[theorem]{Proposition}
\begin{document}
\begin{theorem}\label{myfirst}
This is the first environment.
\end{theorem}
\begin{prop}\label{mysecond}
This is the second environment.
\end{prop}
\begin{theorem}\label{mythird}
This is the third environment.
\end{theorem}
\clearpage
\begin{restatement}[restated]{mysecond}
\label{mysecond-restated}
This is a restatement of the second environment.
\end{restatement}
\begin{theorem}\label{myfourth}
This is the fourth environment.
\end{theorem}
a \verb|ref| to the second environment: \ref{mysecond} \\
a \verb|ref| to its restatement: \ref{mysecond-restated} \\
a \verb|pageref| to the second environment: \pageref{mysecond} \\
a \verb|pageref| to its restatement: \pageref{mysecond-restated} \\
a \verb|autoref| to the second environment: \autoref{mysecond} \\
a \verb|autoref| to its restatement: \autoref{mysecond-restated}
\end{document}
Related Question