diff options
Diffstat (limited to 'macros/latex/contrib/thmtools/source/thm-restate.dtx')
-rw-r--r-- | macros/latex/contrib/thmtools/source/thm-restate.dtx | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/macros/latex/contrib/thmtools/source/thm-restate.dtx b/macros/latex/contrib/thmtools/source/thm-restate.dtx new file mode 100644 index 0000000000..d02b3630ab --- /dev/null +++ b/macros/latex/contrib/thmtools/source/thm-restate.dtx @@ -0,0 +1,346 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008-2014 by Ulrich M. Schwarz +% Copyright (C) 2019 by Frank Mittelbach +% Copyright (C) 2020- by Yukai Chou +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3c. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1.3c.txt +% +% \fi +% +%\iffalse (hide this from DocInput) +%<*restate> +%\fi +% +%\DescribeEnv{restatable} +%Only one environment is provided: \verb|restatable|, which takes one +%optional and two mandatory arguments. The first mandatory argument is the +%type of the theorem, i.e. if you want |\begin{lemma}| to be called on +%the inside, give |lemma|. The second argument is the name of the macro +%that the text should be stored in, for example \verb|mylemma|. Be careful +%not to specify existing command names! The optional argument will become the +%optional argument to your theorem command. Consider the following example: +%\begin{verbatim} +% \documentclass{article} +% \usepackage{amsmath, amsthm, thm-restate} +% \newtheorem{lemma}{Lemma} +% \begin{document} +% \begin{restatable}[Zorn]{lemma}{zornlemma}\label{thm:zorn} +% If every chain in $X$ is upper-bounded, +% $X$ has a maximal element. +% +% It's true, you know! +% \end{restatable} +% \begin{lemma} +% This is some other lemma of no import. +% \end{lemma} +% And now, here's Mr. Zorn again: \zornlemma* +% \end{document} +%\end{verbatim} +%which yields +% \begin{restatable}[Zorn]{lemma}{zornlemma}\label{thm:zorn} +% If every chain in $X$ is upper-bounded, $X$ has a maximal element. +% +% It's true, you know! +% \end{restatable} +% \begin{lemma} +% This is some other lemma of no import. +% \end{lemma} +% Actually, we have set a label in the environment, so we know that +% it's Lemma~\ref{thm:zorn} on page~\ref{thm:zorn}. +% And now, here's Mr. Zorn again: \zornlemma* +% Since we prevent the label from being set again, we find that +% it's still Lemma~\ref{thm:zorn} on page~\ref{thm:zorn}, even though +% it occurs later also. +% +% \DescribeEnv{restatable*} +% As you can see, we use the starred form |\mylemma*|. As in many cases in +% \LaTeX, the star means ``don't give a number'', since we want to retain +% the original number. There is also a starred variant of the |restatable| +% environment, where the first call doesn't determine the number, but a +% later call to |\mylemma| without star would. Since the number is carried +% around using \LaTeX' |\label| machanism, you'll need a rerun for things to +% settle. +% +% \subsection{Restrictions} +% The only counter that is saved is the one for the theorem number. So, +% putting floats inside a restatable is not advised: they will appear in the +% LoF several times with new numbers. +% Equations should work, but the code handling them might turn out to be +% brittle, in particular when you add/remove hyperref. +% %In the same vein, numbered equations +% %within the statement appear again and are numbered again, with new +% %numbers. (This is vaguely non-trivial to do correctly if equations are not +% %numbered consecutively, but per-chapter, or there are multiple numbered +% %equations.) +% Note that you cannot successfully reference the equations +% since all labels are disabled in the starred appearance. (The reference +% will point at the unstarred occurence.) +% +% You cannot nest +% restatables either. You \emph{can} use the |\restatable|\dots|\endrestatable| +% version, but everything up to the next matching |\end{...}| is scooped up. +% I've also probably missed many border cases. +% +% +%\StopEventually{} +% \begin{macrocode} +\RequirePackage{thmtools} +\let\@xa\expandafter +\let\@nx\noexpand +\@ifundefined{c@thmt@dummyctr}{% + \newcounter{thmt@dummyctr}% + }{} +\gdef\theHthmt@dummyctr{dummy.\arabic{thmt@dummyctr}}% +\gdef\thethmt@dummyctr{}% +\long\def\thmt@collect@body#1#2\end#3{% + \@xa\thmt@toks\@xa{\the\thmt@toks #2}% + \def\thmttmpa{#3}%\def\thmttmpb{restatable}% + \ifx\thmttmpa\@currenvir%thmttmpb + \@xa\@firstoftwo% this is the end of the environment. + \else + \@xa\@secondoftwo% go on collecting + \fi{% this is the end, my friend, drop the \end. + % and call #1 with the collected body. + \@xa#1\@xa{\the\thmt@toks}% + }{% go on collecting + \@xa\thmt@toks\@xa{\the\thmt@toks\end{#3}}% + \thmt@collect@body{#1}% + }% +} +% \end{macrocode} +% A totally ignorant version of |\ref|, defaulting to \#2 if label not +% known yet. Otherwise, return the formatted number. +% \begin{macrocode} +\def\thmt@trivialref#1#2{% + \ifcsname r@#1\endcsname + \@xa\@xa\@xa\thmt@trivi@lr@f\csname r@#1\endcsname\relax\@nil + \else #2\fi +} +\def\thmt@trivi@lr@f#1#2\@nil{#1} +% \end{macrocode} +% +% Counter safeties: some counters' values should be stored, such as +% equation, so we don't get a new number. (We cannot reference it anyway.) +% We cannot store everything, though, think page counter or section number! +% There is one problem here: we have to remove all references to other +% counters from |\theequation|, otherwise your equation could get a number +% like (3.1) in one place and (4.1) in another section. +% +% The best solution I can come up with is to override the usual macros +% that counter display goes through, to check if their argument is one +% that should be fully-expanded away or retained. +% +% The following should only be called from within a group, and the sanitized +% |\thectr| must not be called from within that group, since it needs the +% original |\@arabic| et al. +% +% \begin{macrocode} +\def\thmt@innercounters{% + equation} +\def\thmt@counterformatters{% + @alph,@Alph,@arabic,@roman,@Roman,@fnsymbol} + +\@for\thmt@displ:=\thmt@counterformatters\do{% + \@xa\let\csname thmt@\thmt@displ\@xa\endcsname\csname \thmt@displ\endcsname +}% +\def\thmt@sanitizethe#1{% + \@for\thmt@displ:=\thmt@counterformatters\do{% + \@xa\protected@edef\csname\thmt@displ\endcsname##1{% + \@nx\ifx\@xa\@nx\csname c@#1\endcsname ##1% + \@xa\protect\csname \thmt@displ\endcsname{##1}% + \@nx\else + \@nx\csname thmt@\thmt@displ\endcsname{##1}% + \@nx\fi + }% + }% + \expandafter\protected@edef\csname the#1\endcsname{\csname the#1\endcsname}% + \ifcsname theH#1\endcsname + \expandafter\protected@edef\csname theH#1\endcsname{\csname theH#1\endcsname}% + \fi +} + +\def\thmt@rst@storecounters#1{% + \bgroup + % ugly hack: save chapter,..subsection numbers + % for equation numbers. + %\refstepcounter{thmt@dummyctr}% why is this here? + %% temporarily disabled, broke autorefname. + \def\@currentlabel{}% + \@for\thmt@ctr:=\thmt@innercounters\do{% + \thmt@sanitizethe{\thmt@ctr}% + \protected@edef\@currentlabel{% + \@currentlabel + \protect\def\@xa\protect\csname the\thmt@ctr\endcsname{% + \csname the\thmt@ctr\endcsname}% + \ifcsname theH\thmt@ctr\endcsname + \protect\def\@xa\protect\csname theH\thmt@ctr\endcsname{% + (restate \protect\theHthmt@dummyctr)\csname theH\thmt@ctr\endcsname}% + \fi + \protect\setcounter{\thmt@ctr}{\number\csname c@\thmt@ctr\endcsname}% + }% + }% + \label{thmt@@#1@data}% + \egroup +}% +% \end{macrocode} +% +% Now, the main business. +% +% \begin{macrocode} +\newif\ifthmt@thisistheone +\newenvironment{thmt@restatable}[3][]{% + \thmt@toks{}% will hold body +% + \stepcounter{thmt@dummyctr}% used for data storage label. +% + \long\def\thmrst@store##1{% + \@xa\gdef\csname #3\endcsname{% + \@ifstar{% + \thmt@thisistheonefalse\csname thmt@stored@#3\endcsname + }{% + \thmt@thisistheonetrue\csname thmt@stored@#3\endcsname + }% + }% + \@xa\long\@xa\gdef\csname thmt@stored@#3\@xa\endcsname\@xa{% + \begingroup + \ifthmt@thisistheone + % these are the valid numbers, store them for the other + % occasions. + \thmt@rst@storecounters{#3}% + \else + % this one should use other numbers... + % first, fake the theorem number. + \@xa\protected@edef\csname the#2\endcsname{% + \thmt@trivialref{thmt@@#3}{??}}% + % if the number wasn't there, have a "re-run to get labels right" + % warning. + \ifcsname r@thmt@@#3\endcsname\else + \G@refundefinedtrue + \fi + % prevent stepcountering the theorem number, + % but still, have some number for hyperref, just in case. + \@xa\let\csname c@#2\endcsname=\c@thmt@dummyctr + \@xa\let\csname theH#2\endcsname=\theHthmt@dummyctr + % disable labeling. + \let\label=\thmt@gobble@label + \let\ltx@label=\@gobble% amsmath needs this + % We shall need to restore the counters at the end + % of the environment, so we get + % (4.2) [(3.1 from restate)] (4.3) + \def\thmt@restorecounters{}% + \@for\thmt@ctr:=\thmt@innercounters\do{% + \protected@edef\thmt@restorecounters{% + \thmt@restorecounters + \protect\setcounter{\thmt@ctr}{\arabic{\thmt@ctr}}% + }% + }% + % pull the new semi-static definition of \theequation et al. + % from the aux file. + \thmt@trivialref{thmt@@#3@data}{}% + \fi + % call the proper begin-env code, possibly with optional argument + % (omit if stored via key-val) + \ifthmt@restatethis + \thmt@restatethisfalse + \else + \csname #2\@xa\endcsname\ifx\@nx#1\@nx\else[{#1}]\fi + \fi + \ifthmt@thisistheone + % store a label so we can pick up the number later. + \label{thmt@@#3}% + \fi + % this will be the collected body. + ##1% + \csname end#2\endcsname + % if we faked the counter values, restore originals now. + \ifthmt@thisistheone\else\thmt@restorecounters\fi + \endgroup + }% thmt@stored@#3 + % in either case, now call the just-created macro, + \csname #3\@xa\endcsname\ifthmt@thisistheone\else*\fi + % and artificially close the current environment. + \@xa\end\@xa{\@currenvir} + }% thm@rst@store + \thmt@collect@body\thmrst@store +}{% + %% now empty, just used as a marker. +} + +\let\thmt@gobble@label\@gobble +% cleveref extends syntax of \label to \label[...]{...} +\AtBeginDocument{ + \@ifpackageloaded{cleveref}{ + \renewcommand*\thmt@gobble@label[2][]{} + }{} +} + +\newenvironment{restatable}{% + \thmt@thisistheonetrue\thmt@restatable +}{% + \endthmt@restatable +} +\newenvironment{restatable*}{% + \thmt@thisistheonefalse\thmt@restatable +}{% + \endthmt@restatable +} + +%%% support for keyval-style: restate=foobar +\protected@edef\thmt@thmuse@families{% + \thmt@thmuse@families% + ,restate phase 1% + ,restate phase 2% +} +\newcommand\thmt@splitrestateargs[1][]{% + \g@addto@macro\thmt@storedoptargs{,#1}% + \def\tmp@a##1\@{\def\thmt@storename{##1}}% + \tmp@a +} + +\newif\ifthmt@restatethis +\define@key{restate phase 1}{restate}{% + \thmt@thmuse@iskvtrue + \def\thmt@storedoptargs{}% discard the first time around + \thmt@splitrestateargs #1\@ + \def\thmt@storedoptargs{}% discard the first time around + %\def\thmt@storename{#1}% + \thmt@debug{we will restate as `\thmt@storename' with more args + `\thmt@storedoptargs'}% + \@namedef{thmt@unusedkey@restate}{}% + % spurious "unused key" fixes itself once we are after tracknames... + \thmt@restatethistrue + \protected@edef\tmp@a{% + \@nx\thmt@thisistheonetrue + \@nx\def\@nx\@currenvir{\thmt@envname}% + \@nx\@xa\@nx\thmt@restatable\@nx\@xa[\@nx\thmt@storedoptargs]% + {\thmt@envname}{\thmt@storename}% + }% + \@xa\g@addto@macro\@xa\thmt@local@postheadhook\@xa{% + \tmp@a + }% +} +\thmt@mkignoringkeyhandler{restate phase 1} + +\define@key{restate phase 2}{restate}{% + % do not store restate as a key for repetition: + % infinite loop. + % instead, retain the added keyvals + % overwriting thmt@storename should be safe here, it's been + % xdefd into the postheadhook + \thmt@splitrestateargs #1\@ +} +\kv@set@family@handler{restate phase 2}{% + \ifthmt@restatethis + \@xa\@xa\@xa\g@addto@macro\@xa\@xa\@xa\thmt@storedoptargs\@xa\@xa\@xa{\@xa\@xa\@xa,% + \@xa\kv@key\@xa=\kv@value}% + \fi +} + +% \end{macrocode} +%\iffalse +%</restate> +%\fi |