% \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) %<*patch> %\fi % % This package is maybe not very suitable for the end user. It redefines % |\newtheorem| in a way that lets other packages (or the user) add code % to the newly-defined theorems, in a reasonably cross-compatible (with % the kernel, \pkg{theorem} and \pkg{amsthm}) way. % % \textbf{Warning:} the new |\newtheorem| is a superset of the allowed % syntax. For example, you can give a star and both optional arguments, % even though you cannot have an unnumbered theorem that shares a counter % and yet has a different reset-regimen. At some point, your command is % re-assembled and passed on to the original |\newtheorem|. This might % complain, or give you the usual ``Missing |\begin{document}|'' that % marks too many arguments in the preamble. % % \DescribeMacro{\addtotheorem(pre/post)(head/foot)hook} % A call to |\addtotheorempreheadhook|\oarg{kind}\marg{code} will % insert the code to be executed whenever a kind theorem is opened, before % the actual call takes place. (I.e., before the header ``Kind 1.3 (Foo)'' % is typeset.) There are also posthooks that are executed after this header, % and the same for the end of the environment, even though nothing % interesting ever happens there. These are useful to put % |\begin{shaded}|\dots |\end{shaded}| around your theorems. % Note that foothooks are executed LIFO (last addition first) and headhooks % are executed FIFO (first addition first). There is a special kind called % generic that is called for all theorems. This is the default if no kind % is given. % % The added code may examine |\thmt@thmname| to get the title, % |\thmt@envname| to get the environment's name, and |\thmt@optarg| to get % the extra optional title, if any. % %\StopEventually{} % \begin{macrocode} \RequirePackage{parseargs} \newif\ifthmt@isstarred \newif\ifthmt@hassibling \newif\ifthmt@hasparent \def\thmt@parsetheoremargs#1{% \parse{% {\parseOpt[]{\def\thmt@optarg{##1}}{% \let\thmt@shortoptarg\@empty \let\thmt@optarg\@empty}}% {% \def\thmt@local@preheadhook{}% \def\thmt@local@postheadhook{}% \def\thmt@local@prefoothook{}% \def\thmt@local@postfoothook{}% \thmt@local@preheadhook \csname thmt@#1@preheadhook\endcsname \thmt@generic@preheadhook % change following to \@xa-orgy at some point? % forex, might have keyvals involving commands. %\protected@edef\tmp@args{% % \ifx\@empty\thmt@optarg\else [{\thmt@optarg}]\fi %}% \ifx\@empty\thmt@optarg \def\tmp@args{}% \else \@xa\def\@xa\tmp@args\@xa{\@xa[\@xa{\thmt@optarg}]}% \fi \csname thmt@original@#1\@xa\endcsname\tmp@args %%moved down: \thmt@local@postheadhook %% (give postheadhooks a chance to re-set nameref data) \csname thmt@#1@postheadhook\endcsname \thmt@generic@postheadhook \thmt@local@postheadhook %FMi 2019-07-31 % \let\@parsecmd\@empty \let\@parsecmd\ignorespaces %FMi --- }% }% }% \let\thmt@original@newtheorem\newtheorem \let\thmt@theoremdefiner\thmt@original@newtheorem \def\newtheorem{% \thmt@isstarredfalse \thmt@hassiblingfalse \thmt@hasparentfalse \parse{% {\parseFlag*{\thmt@isstarredtrue}{}}% {\parseMand{\def\thmt@envname{##1}}}% {\parseOpt[]{\thmt@hassiblingtrue\def\thmt@sibling{##1}}{}}% {\parseMand{\def\thmt@thmname{##1}}}% {\parseOpt[]{\thmt@hasparenttrue\def\thmt@parent{##1}}{}}% {\let\@parsecmd\thmt@newtheoremiv}% }% } \newcommand\thmt@newtheoremiv{% \thmt@newtheorem@predefinition % whee, now reassemble the whole shebang. \protected@edef\thmt@args{% \@nx\thmt@theoremdefiner% \ifthmt@isstarred *\fi {\thmt@envname}% \ifthmt@hassibling [\thmt@sibling]\fi {\thmt@thmname}% \ifthmt@hasparent [\thmt@parent]\fi } \thmt@args \thmt@newtheorem@postdefinition } \newcommand\thmt@newtheorem@predefinition{} \newcommand\thmt@newtheorem@postdefinition{% \let\thmt@theoremdefiner\thmt@original@newtheorem } \g@addto@macro\thmt@newtheorem@predefinition{% \@xa\thmt@providetheoremhooks\@xa{\thmt@envname}% } \g@addto@macro\thmt@newtheorem@postdefinition{% \@xa\thmt@addtheoremhook\@xa{\thmt@envname}% \ifthmt@isstarred\@namedef{the\thmt@envname}{}\fi \protected@edef\thmt@tmp{% \def\@nx\thmt@envname{\thmt@envname}% \def\@nx\thmt@thmname{\thmt@thmname}% }% \@xa\addtotheorempreheadhook\@xa[\@xa\thmt@envname\@xa]\@xa{% \thmt@tmp }% } \newcommand\thmt@providetheoremhooks[1]{% \@namedef{thmt@#1@preheadhook}{}% \@namedef{thmt@#1@postheadhook}{}% \@namedef{thmt@#1@prefoothook}{}% \@namedef{thmt@#1@postfoothook}{}% \def\thmt@local@preheadhook{}% \def\thmt@local@postheadhook{}% \def\thmt@local@prefoothook{}% \def\thmt@local@postfoothook{}% } \newcommand\thmt@addtheoremhook[1]{% % this adds two command calls to the newly-defined theorem. \@xa\let\csname thmt@original@#1\@xa\endcsname \csname#1\endcsname \@xa\renewcommand\csname #1\endcsname{% \thmt@parsetheoremargs{#1}% }% \@xa\let\csname thmt@original@end#1\@xa\endcsname\csname end#1\endcsname \@xa\def\csname end#1\endcsname{% % these need to be in opposite order of headhooks. \csname thmt@generic@prefoothook\endcsname \csname thmt@#1@prefoothook\endcsname \csname thmt@local@prefoothook\endcsname \csname thmt@original@end#1\endcsname \csname thmt@generic@postfoothook\endcsname \csname thmt@#1@postfoothook\endcsname \csname thmt@local@postfoothook\endcsname }% } \newcommand\thmt@generic@preheadhook{\refstepcounter{thmt@dummyctr}} \newcommand\thmt@generic@postheadhook{} \newcommand\thmt@generic@prefoothook{} \newcommand\thmt@generic@postfoothook{} \def\thmt@local@preheadhook{} \def\thmt@local@postheadhook{} \def\thmt@local@prefoothook{} \def\thmt@local@postfoothook{} \providecommand\g@prependto@macro[2]{% \begingroup \toks@\@xa{\@xa{#1}{#2}}% \def\tmp@a##1##2{##2##1}% \@xa\@xa\@xa\gdef\@xa\@xa\@xa#1\@xa\@xa\@xa{\@xa\tmp@a\the\toks@}% \endgroup } \newcommand\addtotheorempreheadhook[1][generic]{% \expandafter\g@addto@macro\csname thmt@#1@preheadhook\endcsname% } \newcommand\addtotheorempostheadhook[1][generic]{% \expandafter\g@addto@macro\csname thmt@#1@postheadhook\endcsname% } \newcommand\addtotheoremprefoothook[1][generic]{% \expandafter\g@prependto@macro\csname thmt@#1@prefoothook\endcsname% } \newcommand\addtotheorempostfoothook[1][generic]{% \expandafter\g@prependto@macro\csname thmt@#1@postfoothook\endcsname% } % \end{macrocode} % Since rev1.16, we add hooks to the proof environment as well, if it exists. % If it doesn't exist at this point, we're probably using ntheorem as % backend, where it goes through the regular theorem mechanism anyway. % \begin{macrocode} \ifx\proof\endproof\else% yup, that's a quaint way of doing it :) % FIXME: this assumes proof has the syntax of theorems, which % usually happens to be true (optarg overrides "Proof" string). % FIXME: refactor into thmt@addtheoremhook, but we really don't want to % call the generic-hook... \let\thmt@original@proof=\proof \renewcommand\proof{% \thmt@parseproofargs% }% \def\thmt@parseproofargs{% \parse{% {\parseOpt[]{\def\thmt@optarg{##1}}{\let\thmt@optarg\@empty}}% {% \thmt@proof@preheadhook %\thmt@generic@preheadhook \protected@edef\tmp@args{% \ifx\@empty\thmt@optarg\else [\thmt@optarg]\fi }% \csname thmt@original@proof\@xa\endcsname\tmp@args \thmt@proof@postheadhook %\thmt@generic@postheadhook \let\@parsecmd\@empty }% }% }% \let\thmt@original@endproof=\endproof \def\endproof{% % these need to be in opposite order of headhooks. %\csname thmtgeneric@prefoothook\endcsname \thmt@proof@prefoothook \thmt@original@endproof %\csname thmt@generic@postfoothook\endcsname \thmt@proof@postfoothook }% \@namedef{thmt@proof@preheadhook}{}% \@namedef{thmt@proof@postheadhook}{}% \@namedef{thmt@proof@prefoothook}{}% \@namedef{thmt@proof@postfoothook}{}% \fi % \end{macrocode} %\iffalse % %\fi