diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/exptl/thmtools |
Initial commit
Diffstat (limited to 'macros/latex/exptl/thmtools')
23 files changed, 4128 insertions, 0 deletions
diff --git a/macros/latex/exptl/thmtools/COPYING b/macros/latex/exptl/thmtools/COPYING new file mode 100644 index 0000000000..2244313901 --- /dev/null +++ b/macros/latex/exptl/thmtools/COPYING @@ -0,0 +1,416 @@ +The LaTeX Project Public License +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +LPPL Version 1.3c 2008-05-04 + +Copyright 1999 2002-2008 LaTeX3 Project + Everyone is allowed to distribute verbatim copies of this + license document, but modification of it is not allowed. + + +PREAMBLE +======== + +The LaTeX Project Public License (LPPL) is the primary license under +which the LaTeX kernel and the base LaTeX packages are distributed. + +You may use this license for any work of which you hold the copyright +and which you wish to distribute. This license may be particularly +suitable if your work is TeX-related (such as a LaTeX package), but +it is written in such a way that you can use it even if your work is +unrelated to TeX. + +The section `WHETHER AND HOW TO DISTRIBUTE WORKS UNDER THIS LICENSE', +below, gives instructions, examples, and recommendations for authors +who are considering distributing their works under this license. + +This license gives conditions under which a work may be distributed +and modified, as well as conditions under which modified versions of +that work may be distributed. + +We, the LaTeX3 Project, believe that the conditions below give you +the freedom to make and distribute modified versions of your work +that conform with whatever technical specifications you wish while +maintaining the availability, integrity, and reliability of +that work. If you do not see how to achieve your goal while +meeting these conditions, then read the document `cfgguide.tex' +and `modguide.tex' in the base LaTeX distribution for suggestions. + + +DEFINITIONS +=========== + +In this license document the following terms are used: + + `Work' + Any work being distributed under this License. + + `Derived Work' + Any work that under any applicable law is derived from the Work. + + `Modification' + Any procedure that produces a Derived Work under any applicable + law -- for example, the production of a file containing an + original file associated with the Work or a significant portion of + such a file, either verbatim or with modifications and/or + translated into another language. + + `Modify' + To apply any procedure that produces a Derived Work under any + applicable law. + + `Distribution' + Making copies of the Work available from one person to another, in + whole or in part. Distribution includes (but is not limited to) + making any electronic components of the Work accessible by + file transfer protocols such as FTP or HTTP or by shared file + systems such as Sun's Network File System (NFS). + + `Compiled Work' + A version of the Work that has been processed into a form where it + is directly usable on a computer system. This processing may + include using installation facilities provided by the Work, + transformations of the Work, copying of components of the Work, or + other activities. Note that modification of any installation + facilities provided by the Work constitutes modification of the Work. + + `Current Maintainer' + A person or persons nominated as such within the Work. If there is + no such explicit nomination then it is the `Copyright Holder' under + any applicable law. + + `Base Interpreter' + A program or process that is normally needed for running or + interpreting a part or the whole of the Work. + + A Base Interpreter may depend on external components but these + are not considered part of the Base Interpreter provided that each + external component clearly identifies itself whenever it is used + interactively. Unless explicitly specified when applying the + license to the Work, the only applicable Base Interpreter is a + `LaTeX-Format' or in the case of files belonging to the + `LaTeX-format' a program implementing the `TeX language'. + + + +CONDITIONS ON DISTRIBUTION AND MODIFICATION +=========================================== + +1. Activities other than distribution and/or modification of the Work +are not covered by this license; they are outside its scope. In +particular, the act of running the Work is not restricted and no +requirements are made concerning any offers of support for the Work. + +2. You may distribute a complete, unmodified copy of the Work as you +received it. Distribution of only part of the Work is considered +modification of the Work, and no right to distribute such a Derived +Work may be assumed under the terms of this clause. + +3. You may distribute a Compiled Work that has been generated from a +complete, unmodified copy of the Work as distributed under Clause 2 +above, as long as that Compiled Work is distributed in such a way that +the recipients may install the Compiled Work on their system exactly +as it would have been installed if they generated a Compiled Work +directly from the Work. + +4. If you are the Current Maintainer of the Work, you may, without +restriction, modify the Work, thus creating a Derived Work. You may +also distribute the Derived Work without restriction, including +Compiled Works generated from the Derived Work. Derived Works +distributed in this manner by the Current Maintainer are considered to +be updated versions of the Work. + +5. If you are not the Current Maintainer of the Work, you may modify +your copy of the Work, thus creating a Derived Work based on the Work, +and compile this Derived Work, thus creating a Compiled Work based on +the Derived Work. + +6. If you are not the Current Maintainer of the Work, you may +distribute a Derived Work provided the following conditions are met +for every component of the Work unless that component clearly states +in the copyright notice that it is exempt from that condition. Only +the Current Maintainer is allowed to add such statements of exemption +to a component of the Work. + + a. If a component of this Derived Work can be a direct replacement + for a component of the Work when that component is used with the + Base Interpreter, then, wherever this component of the Work + identifies itself to the user when used interactively with that + Base Interpreter, the replacement component of this Derived Work + clearly and unambiguously identifies itself as a modified version + of this component to the user when used interactively with that + Base Interpreter. + + b. Every component of the Derived Work contains prominent notices + detailing the nature of the changes to that component, or a + prominent reference to another file that is distributed as part + of the Derived Work and that contains a complete and accurate log + of the changes. + + c. No information in the Derived Work implies that any persons, + including (but not limited to) the authors of the original version + of the Work, provide any support, including (but not limited to) + the reporting and handling of errors, to recipients of the + Derived Work unless those persons have stated explicitly that + they do provide such support for the Derived Work. + + d. You distribute at least one of the following with the Derived Work: + + 1. A complete, unmodified copy of the Work; + if your distribution of a modified component is made by + offering access to copy the modified component from a + designated place, then offering equivalent access to copy + the Work from the same or some similar place meets this + condition, even though third parties are not compelled to + copy the Work along with the modified component; + + 2. Information that is sufficient to obtain a complete, + unmodified copy of the Work. + +7. If you are not the Current Maintainer of the Work, you may +distribute a Compiled Work generated from a Derived Work, as long as +the Derived Work is distributed to all recipients of the Compiled +Work, and as long as the conditions of Clause 6, above, are met with +regard to the Derived Work. + +8. The conditions above are not intended to prohibit, and hence do not +apply to, the modification, by any method, of any component so that it +becomes identical to an updated version of that component of the Work as +it is distributed by the Current Maintainer under Clause 4, above. + +9. Distribution of the Work or any Derived Work in an alternative +format, where the Work or that Derived Work (in whole or in part) is +then produced by applying some process to that format, does not relax or +nullify any sections of this license as they pertain to the results of +applying that process. + +10. a. A Derived Work may be distributed under a different license + provided that license itself honors the conditions listed in + Clause 6 above, in regard to the Work, though it does not have + to honor the rest of the conditions in this license. + + b. If a Derived Work is distributed under a different license, that + Derived Work must provide sufficient documentation as part of + itself to allow each recipient of that Derived Work to honor the + restrictions in Clause 6 above, concerning changes from the Work. + +11. This license places no restrictions on works that are unrelated to +the Work, nor does this license place any restrictions on aggregating +such works with the Work by any means. + +12. Nothing in this license is intended to, or may be used to, prevent +complete compliance by all parties with all applicable laws. + + +NO WARRANTY +=========== + +There is no warranty for the Work. Except when otherwise stated in +writing, the Copyright Holder provides the Work `as is', without +warranty of any kind, either expressed or implied, including, but not +limited to, the implied warranties of merchantability and fitness for a +particular purpose. The entire risk as to the quality and performance +of the Work is with you. Should the Work prove defective, you assume +the cost of all necessary servicing, repair, or correction. + +In no event unless required by applicable law or agreed to in writing +will The Copyright Holder, or any author named in the components of the +Work, or any other party who may distribute and/or modify the Work as +permitted above, be liable to you for damages, including any general, +special, incidental or consequential damages arising out of any use of +the Work or out of inability to use the Work (including, but not limited +to, loss of data, data being rendered inaccurate, or losses sustained by +anyone as a result of any failure of the Work to operate with any other +programs), even if the Copyright Holder or said author or said other +party has been advised of the possibility of such damages. + + +MAINTENANCE OF THE WORK +======================= + +The Work has the status `author-maintained' if the Copyright Holder +explicitly and prominently states near the primary copyright notice in +the Work that the Work can only be maintained by the Copyright Holder +or simply that it is `author-maintained'. + +The Work has the status `maintained' if there is a Current Maintainer +who has indicated in the Work that they are willing to receive error +reports for the Work (for example, by supplying a valid e-mail +address). It is not required for the Current Maintainer to acknowledge +or act upon these error reports. + +The Work changes from status `maintained' to `unmaintained' if there +is no Current Maintainer, or the person stated to be Current +Maintainer of the work cannot be reached through the indicated means +of communication for a period of six months, and there are no other +significant signs of active maintenance. + +You can become the Current Maintainer of the Work by agreement with +any existing Current Maintainer to take over this role. + +If the Work is unmaintained, you can become the Current Maintainer of +the Work through the following steps: + + 1. Make a reasonable attempt to trace the Current Maintainer (and + the Copyright Holder, if the two differ) through the means of + an Internet or similar search. + + 2. If this search is successful, then enquire whether the Work + is still maintained. + + a. If it is being maintained, then ask the Current Maintainer + to update their communication data within one month. + + b. If the search is unsuccessful or no action to resume active + maintenance is taken by the Current Maintainer, then announce + within the pertinent community your intention to take over + maintenance. (If the Work is a LaTeX work, this could be + done, for example, by posting to comp.text.tex.) + + 3a. If the Current Maintainer is reachable and agrees to pass + maintenance of the Work to you, then this takes effect + immediately upon announcement. + + b. If the Current Maintainer is not reachable and the Copyright + Holder agrees that maintenance of the Work be passed to you, + then this takes effect immediately upon announcement. + + 4. If you make an `intention announcement' as described in 2b. above + and after three months your intention is challenged neither by + the Current Maintainer nor by the Copyright Holder nor by other + people, then you may arrange for the Work to be changed so as + to name you as the (new) Current Maintainer. + + 5. If the previously unreachable Current Maintainer becomes + reachable once more within three months of a change completed + under the terms of 3b) or 4), then that Current Maintainer must + become or remain the Current Maintainer upon request provided + they then update their communication data within one month. + +A change in the Current Maintainer does not, of itself, alter the fact +that the Work is distributed under the LPPL license. + +If you become the Current Maintainer of the Work, you should +immediately provide, within the Work, a prominent and unambiguous +statement of your status as Current Maintainer. You should also +announce your new status to the same pertinent community as +in 2b) above. + + +WHETHER AND HOW TO DISTRIBUTE WORKS UNDER THIS LICENSE +====================================================== + +This section contains important instructions, examples, and +recommendations for authors who are considering distributing their +works under this license. These authors are addressed as `you' in +this section. + +Choosing This License or Another License +---------------------------------------- + +If for any part of your work you want or need to use *distribution* +conditions that differ significantly from those in this license, then +do not refer to this license anywhere in your work but, instead, +distribute your work under a different license. You may use the text +of this license as a model for your own license, but your license +should not refer to the LPPL or otherwise give the impression that +your work is distributed under the LPPL. + +The document `modguide.tex' in the base LaTeX distribution explains +the motivation behind the conditions of this license. It explains, +for example, why distributing LaTeX under the GNU General Public +License (GPL) was considered inappropriate. Even if your work is +unrelated to LaTeX, the discussion in `modguide.tex' may still be +relevant, and authors intending to distribute their works under any +license are encouraged to read it. + +A Recommendation on Modification Without Distribution +----------------------------------------------------- + +It is wise never to modify a component of the Work, even for your own +personal use, without also meeting the above conditions for +distributing the modified component. While you might intend that such +modifications will never be distributed, often this will happen by +accident -- you may forget that you have modified that component; or +it may not occur to you when allowing others to access the modified +version that you are thus distributing it and violating the conditions +of this license in ways that could have legal implications and, worse, +cause problems for the community. It is therefore usually in your +best interest to keep your copy of the Work identical with the public +one. Many works provide ways to control the behavior of that work +without altering any of its licensed components. + +How to Use This License +----------------------- + +To use this license, place in each of the components of your work both +an explicit copyright notice including your name and the year the work +was authored and/or last substantially modified. Include also a +statement that the distribution and/or modification of that +component is constrained by the conditions in this license. + +Here is an example of such a notice and statement: + + %% pig.dtx + %% Copyright 2005 M. Y. Name + % + % This work may be distributed and/or modified under the + % conditions of the LaTeX Project Public License, either version 1.3 + % of this license or (at your option) any later version. + % The latest version of this license is in + % http://www.latex-project.org/lppl.txt + % and version 1.3 or later is part of all distributions of LaTeX + % version 2005/12/01 or later. + % + % This work has the LPPL maintenance status `maintained'. + % + % The Current Maintainer of this work is M. Y. Name. + % + % This work consists of the files pig.dtx and pig.ins + % and the derived file pig.sty. + +Given such a notice and statement in a file, the conditions +given in this license document would apply, with the `Work' referring +to the three files `pig.dtx', `pig.ins', and `pig.sty' (the last being +generated from `pig.dtx' using `pig.ins'), the `Base Interpreter' +referring to any `LaTeX-Format', and both `Copyright Holder' and +`Current Maintainer' referring to the person `M. Y. Name'. + +If you do not want the Maintenance section of LPPL to apply to your +Work, change `maintained' above into `author-maintained'. +However, we recommend that you use `maintained', as the Maintenance +section was added in order to ensure that your Work remains useful to +the community even when you can no longer maintain and support it +yourself. + +Derived Works That Are Not Replacements +--------------------------------------- + +Several clauses of the LPPL specify means to provide reliability and +stability for the user community. They therefore concern themselves +with the case that a Derived Work is intended to be used as a +(compatible or incompatible) replacement of the original Work. If +this is not the case (e.g., if a few lines of code are reused for a +completely different task), then clauses 6b and 6d shall not apply. + + +Important Recommendations +------------------------- + + Defining What Constitutes the Work + + The LPPL requires that distributions of the Work contain all the + files of the Work. It is therefore important that you provide a + way for the licensee to determine which files constitute the Work. + This could, for example, be achieved by explicitly listing all the + files of the Work near the copyright notice of each file or by + using a line such as: + + % This work consists of all files listed in manifest.txt. + + in that place. In the absence of an unequivocal list it might be + impossible for the licensee to determine what is considered by you + to comprise the Work and, in such a case, the licensee would be + entitled to make reasonable conjectures as to which files comprise + the Work. + diff --git a/macros/latex/exptl/thmtools/README b/macros/latex/exptl/thmtools/README new file mode 100644 index 0000000000..34aa5feb9f --- /dev/null +++ b/macros/latex/exptl/thmtools/README @@ -0,0 +1,21 @@ + The \thmtools\ bundle provides several packages for commonly-needed + features for theorems. As designed, the bundle should work with kernel + theorems, the theorem package and the amsthm package. + + WARNING: Currently, things might still be a bit rough. You + might want to consider not relying on \thmtools\ for your Ph.D. thesis + masterpiece. + +Provided features: +a keyval interface to \newtheorem +a \listoftheorem command +hyperref/autoref compatibility +a way of restating entire theorems with a single macro call + +License: LPPL 1.3c + +Currently the package has no maintainer. +Previous Maintainer was Ulrich M. Schwarz, ulmi@absatzen.de + + +$Id: README,v 1.1 2008/02/17 21:13:58 ulmi Exp ulmi $ diff --git a/macros/latex/exptl/thmtools/TODO b/macros/latex/exptl/thmtools/TODO new file mode 100644 index 0000000000..e35b77530a --- /dev/null +++ b/macros/latex/exptl/thmtools/TODO @@ -0,0 +1,3 @@ +- ref close-by/far-away +- complex refs + (these two are very similar) diff --git a/macros/latex/exptl/thmtools/VERSION.tex b/macros/latex/exptl/thmtools/VERSION.tex new file mode 100644 index 0000000000..8e8f442d1e --- /dev/null +++ b/macros/latex/exptl/thmtools/VERSION.tex @@ -0,0 +1 @@ +\def\x #1-#2-#3 #4 v#5\@{\def\VERSION{#1/#2/#3 v#5}}\x 2019-07-31 00:00:00 +0200 v67\@ diff --git a/macros/latex/exptl/thmtools/aliasctr.dtx b/macros/latex/exptl/thmtools/aliasctr.dtx new file mode 100644 index 0000000000..b492f95f56 --- /dev/null +++ b/macros/latex/exptl/thmtools/aliasctr.dtx @@ -0,0 +1,114 @@ +% \iffalse meta-comment +% +% Copyright (C) 2005-7 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. The full license text +% is available from http://www.latex-project.org/ +% +%<*code> +% \fi +% |\@counteralias{#1}{#2}| makes |#1| a counter that uses |#2|'s count register. +% This is useful for things like \pkg{hyperref}'s |\autoref|, which otherwise +% can't distinguish theorems and definitions if they share a counter. +% +% For detailed information, see Die TeXnische Kom\"odie 3/2006. +% \StopEventually{} +% \begin{macro}{\@addtoreset} +% add |\@elt{#1}| to |\cl@#2|. +% This differs from the kernel implementation insofar as we trail the +% cl lists until we find one that is empty or starts with |\@elt|. +% \begin{macrocode} +\def\aliasctr@f@llow#1#2\@nil#3{% + \ifx#1\@elt + \noexpand #3% + \else + \expandafter\aliasctr@f@llow#1\@elt\@nil{#1}% + \fi +} +% \end{macrocode} +% +% \begin{macrocode} +\newcommand\aliasctr@follow[1]{% + \expandafter\aliasctr@f@llow +% \end{macrocode} +% Don't be confused: the third parameter is ignored here, we always +% have recursion here since the \emph{token} |\cl@#1| is (hopefully) not |\@elt|. +% \begin{macrocode} + \csname cl@#1\endcsname\@elt\@nil{\csname cl@#1\endcsname}% +} +% \end{macrocode} +% +% \begin{macrocode} +\renewcommand*\@addtoreset[2]{\bgroup + \edef\aliasctr@@truelist{\aliasctr@follow{#2}}% + \let\@elt\relax + \expandafter\@cons\aliasctr@@truelist{{#1}}% +\egroup} +% \end{macrocode} +% +% This code has been adapted from David Carlisle's \pkg{remreset}. We +% load that here only to prevent it from being loaded again. +% \begin{macrocode} +% FMi 2019-07-31 \@removereset is in the kernel these days +\@ifundefined{@removefromreset}{\RequirePackage{remreset}}{} +\renewcommand*\@removefromreset[2]{\bgroup + \edef\aliasctr@@truelist{\aliasctr@follow{#2}}% + \expandafter\let\csname c@#1\endcsname\@removefromreset + \def\@elt##1{% + \expandafter\ifx\csname c@##1\endcsname\@removefromreset + \else + \noexpand\@elt{##1}% + \fi}% + \expandafter\xdef\aliasctr@@truelist{% + \aliasctr@@truelist} +\egroup} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@counteralias} +% make |#1| a counter that uses counter |#2|'s count register. +% \begin{macrocode} +\newcommand\@counteralias[2]{{% + \def\@@gletover##1##2{% + \expandafter\global + \expandafter\let\csname ##1\expandafter\endcsname + \csname ##2\endcsname + }% + \@ifundefined{c@#2}{\@nocounterr{#2}}{% + \@ifdefinable{c@#1}{% +% \end{macrocode} +% Four values make a counter foo: +% \begin{itemize} +% \item the count register accessed through |\c@foo|, +% \item the output macro |\thefoo|, +% \item the prefix macro |\p@foo|, +% \item the reset list |\cl@foo|. +% \end{itemize} +% \pkg{hyperref} adds |\theHfoo| in particular. +% \begin{macrocode} + \@@gletover{c@#1}{c@#2}% + \@@gletover{the#1}{the#2}% +% \end{macrocode} +% I don't see \@counteralias being called hundreds of times, +% let's just unconditionally create |\theHctr|-macros for hyperref. +% \begin{macrocode} + \@@gletover{theH#1}{theH#2}% + \@@gletover{p@#1}{p@#2}% + \expandafter\global + \expandafter\def\csname cl@#1\expandafter\endcsname + \expandafter{\csname cl@#2\endcsname}% +% \end{macrocode} +% It is not necessary to save the value again: since we share a +% count register, we will pick up the restored value of the +% original counter. +% \begin{macrocode} + %\@addtoreset{#1}{@ckpt}% + }% + }% +}} +% \end{macrocode} +% \end{macro} +%\iffalse +%</code> +%\fi diff --git a/macros/latex/exptl/thmtools/parseargs.dtx b/macros/latex/exptl/thmtools/parseargs.dtx new file mode 100644 index 0000000000..8f4aa42171 --- /dev/null +++ b/macros/latex/exptl/thmtools/parseargs.dtx @@ -0,0 +1,80 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.txt +% +% \fi +% +%\iffalse (hide this from DocInput) +%<*parseargs> +%\fi +% +% The main command provided by the package is |\parse|\marg{spec}. +% \emph{spec} consists of groups of commands. Each group should set up the +% command |\@parsecmd| which is then run. The important point is that +% |\@parsecmd| will pick up its arguments from the running text, not from +% the rest of \emph{spec}. When it's done storing the arguments, +% |\@parsecmd| must call |\@parse| to continue with the next element of +% \emph{spec}. The process terminates when we run out of spec. +% +% Helper macros are provided for the three usual argument types: mandatory, +% optional, and flag. +% +%\StopEventually{} +% \begin{macrocode} + +\newtoks\@parsespec +\def\parse@endquark{\parse@endquark} +\newcommand\parse[1]{% + \@parsespec{#1\parse@endquark}\@parse} + +\newcommand\@parse{% + \edef\p@tmp{\the\@parsespec}% + \ifx\p@tmp\parse@endquark + \expandafter\@gobble + \else +% \typeout{parsespec remaining: \the\@parsespec}% + \expandafter\@firstofone + \fi{% + \@parsepop + }% +} +\def\@parsepop{% + \expandafter\p@rsepop\the\@parsespec\@nil + \@parsecmd +} +\def\p@rsepop#1#2\@nil{% + #1% + \@parsespec{#2}% +} + +\newcommand\parseOpt[4]{% + %\parseOpt{openchar}{closechar}{yes}{no} +% \typeout{attemping #1#2...}% + \def\@parsecmd{% + \@ifnextchar#1{\@@reallyparse}{#4\@parse}% + }% + \def\@@reallyparse#1##1#2{% + #3\@parse + }% +} + +\newcommand\parseMand[1]{% + %\parseMand{code} + \def\@parsecmd##1{#1\@parse}% +} + +\newcommand\parseFlag[3]{% + %\parseFlag{flagchar}{yes}{no} + \def\@parsecmd{% + \@ifnextchar#1{#2\expandafter\@parse\@gobble}{#3\@parse}% + }% +} +% \end{macrocode} +%\iffalse +%</parseargs> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-amsthm.dtx b/macros/latex/exptl/thmtools/thm-amsthm.dtx new file mode 100644 index 0000000000..31a2397f47 --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-amsthm.dtx @@ -0,0 +1,162 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*amsthm> +%\fi +% \begin{macrocode} +\providecommand\thmt@space{ } + +\define@key{thmstyle}{spaceabove}{% + \def\thmt@style@spaceabove{#1}% +} +\define@key{thmstyle}{spacebelow}{% + \def\thmt@style@spacebelow{#1}% +} +\define@key{thmstyle}{headfont}{% + \def\thmt@style@headfont{#1}% +} +\define@key{thmstyle}{bodyfont}{% + \def\thmt@style@bodyfont{#1}% +} +\define@key{thmstyle}{notefont}{% + \def\thmt@style@notefont{#1}% +} +\define@key{thmstyle}{headpunct}{% + \def\thmt@style@headpunct{#1}% +} +\define@key{thmstyle}{notebraces}{% + \def\thmt@style@notebraces{\thmt@embrace#1}% +} +\define@key{thmstyle}{break}[]{% + \def\thmt@style@postheadspace{\newline}% +} +\define@key{thmstyle}{postheadspace}{% + \def\thmt@style@postheadspace{#1}% +} +\define@key{thmstyle}{headindent}{% + \def\thmt@style@headindent{#1}% +} + +\newtoks\thmt@style@headstyle +\define@key{thmstyle}{headformat}[]{% + \thmt@setheadstyle{#1}% +} +\define@key{thmstyle}{headstyle}[]{% + \thmt@setheadstyle{#1}% +} +\def\thmt@setheadstyle#1{% + \thmt@style@headstyle{% + \def\NAME{\the\thm@headfont ##1}% + \def\NUMBER{\bgroup\@upn{##2}\egroup}% + \def\NOTE{\if=##3=\else\bgroup\thmt@space\the\thm@notefont(##3)\egroup\fi}% + }% + \def\thmt@tmp{#1}% + \@onelevel@sanitize\thmt@tmp + %\tracingall + \ifcsname thmt@headstyle@\thmt@tmp\endcsname + \thmt@style@headstyle\@xa{% + \the\thmt@style@headstyle + \csname thmt@headstyle@#1\endcsname + }% + \else + \thmt@style@headstyle\@xa{% + \the\thmt@style@headstyle + #1% + }% + \fi + %\showthe\thmt@style@headstyle +} +% examples: +\def\thmt@headstyle@margin{% + \makebox[0pt][r]{\NUMBER\ }\NAME\NOTE +} +\def\thmt@headstyle@swapnumber{% + \NUMBER\ \NAME\NOTE +} + + + +\def\thmt@embrace#1#2(#3){#1#3#2} + +\def\thmt@declaretheoremstyle@setup{% + \let\thmt@style@notebraces\@empty% + \thmt@style@headstyle{}% + \kvsetkeys{thmstyle}{% + spaceabove=3pt, + spacebelow=3pt, + headfont=\bfseries, + bodyfont=\normalfont, + headpunct={.}, + postheadspace={ }, + headindent={}, + notefont={\fontseries\mddefault\upshape} + }% +} +\def\thmt@declaretheoremstyle#1{% + %\show\thmt@style@spaceabove + \thmt@toks{\newtheoremstyle{#1}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@spaceabove}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@spacebelow}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@bodyfont}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@headindent}}% indent1 FIXME + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@headfont}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@headpunct}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\thmt@style@postheadspace}}% + \thmt@toks\@xa\@xa\@xa{\@xa\the\@xa\thmt@toks\@xa{\the\thmt@style@headstyle}}% headspec FIXME + \the\thmt@toks + %1 Indent amount: empty = no indent, \parindent = normal paragraph indent + %2 Space after theorem head: { } = normal interword space; \newline = linebreak + %% BUGFIX: amsthm ignores notefont setting altogether: + \thmt@toks\@xa\@xa\@xa{\csname th@#1\endcsname}% + \thmt@toks + \@xa\@xa\@xa\@xa\@xa\@xa\@xa{% + \@xa\@xa\@xa\@xa\@xa\@xa\@xa\thm@notefont + \@xa\@xa\@xa\@xa\@xa\@xa\@xa{% + \@xa\@xa\@xa\thmt@style@notefont + \@xa\thmt@style@notebraces + \@xa}\the\thmt@toks}% + \@xa\def\csname th@#1\@xa\endcsname\@xa{\the\thmt@toks}% +% \@xa\def\csname th@#1\@xa\@xa\@xa\@xa\@xa\@xa\@xa\endcsname +% \@xa\@xa\@xa\@xa\@xa\@xa\@xa{% +% \@xa\@xa\@xa\@xa\@xa\@xa\@xa\thm@notefont +% \@xa\@xa\@xa\@xa\@xa\@xa\@xa{% +% \@xa\@xa\@xa\thmt@style@notefont +% \@xa\@xa\@xa\thmt@style@notebraces +% \@xa\@xa\@xa}\csname th@#1\endcsname +% } +} + +\define@key{thmdef}{qed}[\qedsymbol]{% + \thmt@trytwice{}{% + \addtotheorempostheadhook[\thmt@envname]{% + \protected@edef\qedsymbol{#1}% + \pushQED{\qed}% + }% + \addtotheoremprefoothook[\thmt@envname]{% + \protected@edef\qedsymbol{#1}% + \popQED + }% + }% +} + +\def\thmt@amsthmlistbreakhack{% + \leavevmode + \vspace{-\baselineskip}% + \par + \everypar{\setbox\z@\lastbox\everypar{}}% +} + +\define@key{thmuse}{listhack}[\relax]{% + \addtotheorempostheadhook[local]{% + \thmt@amsthmlistbreakhack + }% +} + +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</amsthm> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-autoref.dtx b/macros/latex/exptl/thmtools/thm-autoref.dtx new file mode 100644 index 0000000000..90a164f1af --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-autoref.dtx @@ -0,0 +1,119 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.txt +% +% \fi +% +%\iffalse (hide this from DocInput) +%<*autoref> +%\fi +% +% \pkg{hyperref}'s |\autoref| command does not work well with theorems that +% share a counter: it'll always think it's a Lemma even if it's a Remark +% that shares the Lemma counter. Load this package to fix it. No further +% intervention needed. +% +%\StopEventually{} +% \begin{macrocode} + +\RequirePackage{thm-patch, aliasctr, parseargs, keyval} + +\let\@xa=\expandafter +\let\@nx=\noexpand + +\newcommand\thmt@autorefsetup{% + \@xa\def\csname\thmt@envname autorefname\@xa\endcsname\@xa{\thmt@thmname}% + \ifthmt@hassibling + \@counteralias{\thmt@envname}{\thmt@sibling}% + \@xa\def\@xa\thmt@autoreffix\@xa{% + \@xa\let\csname the\thmt@envname\@xa\endcsname + \csname the\thmt@sibling\endcsname + \def\thmt@autoreffix{}% + }% + \protected@edef\thmt@sibling{\thmt@envname}% + \fi +} +\g@addto@macro\thmt@newtheorem@predefinition{\thmt@autorefsetup}% +\g@addto@macro\thmt@newtheorem@postdefinition{\csname thmt@autoreffix\endcsname}% + +\def\thmt@refnamewithcomma #1#2#3,#4,#5\@nil{% + \@xa\def\csname\thmt@envname #1utorefname\endcsname{#3}% + \ifcsname #2refname\endcsname + \csname #2refname\@xa\endcsname\@xa{\thmt@envname}{#3}{#4}% + \fi +} +\define@key{thmdef}{refname}{\thmt@trytwice{}{% + \thmt@refnamewithcomma{a}{c}#1,\textbf{?? (pl. #1)},\@nil +}} +\define@key{thmdef}{Refname}{\thmt@trytwice{}{% + \thmt@refnamewithcomma{A}{C}#1,\textbf{?? (pl. #1)},\@nil +}} + + +\ifcsname Autoref\endcsname\else +\let\thmt@HyRef@testreftype\HyRef@testreftype +\def\HyRef@Testreftype#1.#2\\{% + \ltx@IfUndefined{#1Autorefname}{% + \thmt@HyRef@testreftype#1.#2\\% + }{% + \edef\HyRef@currentHtag{% + \expandafter\noexpand\csname#1Autorefname\endcsname + \noexpand~% + }% + }% +} + + +\let\thmt@HyPsd@@autorefname\HyPsd@@autorefname +\def\HyPsd@@Autorefname#1.#2\@nil{% + \tracingall + \ltx@IfUndefined{#1Autorefname}{% + \thmt@HyPsd@@autorefname#1.#2\@nil + }{% + \csname#1Autorefname\endcsname\space + }% +}% +\def\Autoref{% + \parse{% + {\parseFlag*{\def\thmt@autorefstar{*}}{\let\thmt@autorefstar\@empty}}% + {\parseMand{% + \bgroup + \let\HyRef@testreftype\HyRef@Testreftype + \let\HyPsd@@autorefname\HyPsd@@Autorefname + \@xa\autoref\thmt@autorefstar{##1}% + \egroup + \let\@parsecmd\@empty + }}% + }% +} +\fi % ifcsname Autoref + +% not entirely appropriate here, but close enough: +\AtBeginDocument{% + \@ifpackageloaded{nameref}{% + \addtotheorempostheadhook{% + \expandafter\NR@gettitle\expandafter{\thmt@shortoptarg}% + }}{} +} + +\AtBeginDocument{% + \@ifpackageloaded{cleveref}{% + \@ifpackagelater{cleveref}{2010/04/30}{% + % OK, new enough + }{% + \PackageWarningNoLine{thmtools}{% + Your version of cleveref is too old!\MessageBreak + Update to version 0.16.1 or later% + } + } + }{} +} +% \end{macrocode} +%\iffalse +%</autoref> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-beamer.dtx b/macros/latex/exptl/thmtools/thm-beamer.dtx new file mode 100644 index 0000000000..7c56099ce6 --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-beamer.dtx @@ -0,0 +1,44 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*beamer> +%\fi +% \begin{macrocode} +\newif\ifthmt@hasoverlay +\def\thmt@parsetheoremargs#1{% + \parse{% + {\parseOpt<>{\thmt@hasoverlaytrue\def\thmt@overlay{##1}}{}}% + {\parseOpt[]{\def\thmt@optarg{##1}}{% + \let\thmt@shortoptarg\@empty + \let\thmt@optarg\@empty}}% + {\ifthmt@hasoverlay\expandafter\@gobble\else\expandafter\@firstofone\fi + {\parseOpt<>{\thmt@hasoverlaytrue\def\thmt@overlay{##1}}{}}% + }% + {% + \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 + \protected@edef\tmp@args{% + \ifthmt@hasoverlay <\thmt@overlay>\fi + \ifx\@empty\thmt@optarg\else [{\thmt@optarg}]\fi + }% + \csname thmt@original@#1\@xa\endcsname\tmp@args + \thmt@local@postheadhook + \csname thmt@#1@postheadhook\endcsname + \thmt@generic@postheadhook + \let\@parsecmd\@empty + }% + } +}% +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</beamer> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-kv.dtx b/macros/latex/exptl/thmtools/thm-kv.dtx new file mode 100644 index 0000000000..1e7e358082 --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-kv.dtx @@ -0,0 +1,486 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.txt +% +% \fi +% +%\iffalse (hide this from DocInput) +%<*kv> +%\fi +% +%\StopEventually{} +% \begin{macrocode} + +\let\@xa\expandafter +\let\@nx\noexpand + +\DeclareOption{lowercase}{% + \PackageInfo{thm-kv}{Theorem names will be lowercased}% + \global\let\thmt@modifycase\MakeLowercase} + +\DeclareOption{uppercase}{% + \PackageInfo{thm-kv}{Theorem names will be uppercased}% + \global\let\thmt@modifycase\MakeUppercase} + +\DeclareOption{anycase}{% + \PackageInfo{thm-kv}{Theorem names will be unchanged}% + \global\let\thmt@modifycase\@empty} + +\ExecuteOptions{uppercase} +\ProcessOptions\relax + +\RequirePackage{keyval,kvsetkeys,thm-patch} + +\long\def\thmt@kv@processor@default#1#2#3{% + \def\kvsu@fam{#1}% new + \@onelevel@sanitize\kvsu@fam% new + \def\kvsu@key{#2}% new + \@onelevel@sanitize\kvsu@key% new + \unless\ifcsname KV@#1@\kvsu@key\endcsname + \unless\ifcsname KVS@#1@handler\endcsname + \kv@error@unknownkey{#1}{\kvsu@key}% + \else + \csname KVS@#1@handler\endcsname{#2}{#3}% + % still using #2 #3 here is intentional: handler might + % be used for strange stuff like implementing key names + % that contain strange characters or other strange things. + \relax + \fi + \else + \ifx\kv@value\relax + \unless\ifcsname KV@#1@\kvsu@key @default\endcsname + \kv@error@novalue{#1}{\kvsu@key}% + \else + \csname KV@#1@\kvsu@key @default\endcsname + \relax + \fi + \else + \csname KV@#1@\kvsu@key\endcsname{#3}% + \fi + \fi +} + +\@ifpackagelater{kvsetkeys}{2012/04/23}{% + \PackageInfo{thm-kv}{kvsetkeys patch (v1.16 or later)}% + \long\def\tmp@KVS@PD#1#2#3{% + \def \kv@fam {#1}% + \unless \ifcsname KV@#1@#2\endcsname + \unless \ifcsname KVS@#1@handler\endcsname + \kv@error@unknownkey {#1}{#2}% + \else + \kv@handled@true + \csname KVS@#1@handler\endcsname {#2}{#3}\relax + \ifkv@handled@ \else + \kv@error@unknownkey {#1}{#2}% + \fi + \fi + \else + \ifx \kv@value \relax + \unless \ifcsname KV@#1@#2@default\endcsname + \kv@error@novalue {#1}{#2}% + \else + \csname KV@#1@#2@default\endcsname \relax + \fi + \else + \csname KV@#1@#2\endcsname {#3}% + \fi + \fi + }% + \ifx\tmp@KVS@PD\KVS@ProcessorDefault + \let\KVS@ProcessorDefault\thmt@kv@processor@default + \def\kv@processor@default#1#2{% + \begingroup + \csname @safe@activestrue\endcsname + \@xa\let\csname ifincsname\@xa\endcsname\csname iftrue\endcsname + \edef\KVS@temp{\endgroup + \noexpand\KVS@ProcessorDefault{#1}{\etex@unexpanded{#2}}% + }% + \KVS@temp + }% + \else + \PackageError{thm-kv}{kvsetkeys patch failed}{Try kvsetkeys v1.16 or earlier} + \fi +}{\@ifpackagelater{kvsetkeys}{2011/04/06}{% + % Patch has disappeared somewhere... thanksalot. + \PackageInfo{thm-kv}{kvsetkeys patch (v1.13 or later)} + \long\def\tmp@KVS@PD#1#2#3{% no non-etex-support here... + \unless\ifcsname KV@#1@#2\endcsname + \unless\ifcsname KVS@#1@handler\endcsname + \kv@error@unknownkey{#1}{#2}% + \else + \csname KVS@#1@handler\endcsname{#2}{#3}% + \relax + \fi + \else + \ifx\kv@value\relax + \unless\ifcsname KV@#1@#2@default\endcsname + \kv@error@novalue{#1}{#2}% + \else + \csname KV@#1@#2@default\endcsname + \relax + \fi + \else + \csname KV@#1@#2\endcsname{#3}% + \fi + \fi + }% + \ifx\tmp@KVS@PD\KVS@ProcessorDefault + \let\KVS@ProcessorDefault\thmt@kv@processor@default + \def\kv@processor@default#1#2{% + \begingroup + \csname @safe@activestrue\endcsname + \let\ifincsname\iftrue + \edef\KVS@temp{\endgroup + \noexpand\KVS@ProcessorDefault{#1}{\unexpanded{#2}}% + }% + \KVS@temp + } + \else + \PackageError{thm-kv}{kvsetkeys patch failed, try kvsetkeys v1.13 or earlier} + \fi +}{% + \RequirePackage{etex} + \PackageInfo{thm-kv}{kvsetkeys patch applied (pre-1.13)}% + \let\kv@processor@default\thmt@kv@processor@default +}} + +% useful key handler defaults. +\newcommand\thmt@mkignoringkeyhandler[1]{% + \kv@set@family@handler{#1}{% + \thmt@debug{Key `##1' with value `##2' ignored by #1.}% + }% +} +\newcommand\thmt@mkextendingkeyhandler[3]{% +% #1: family +% #2: prefix for file +% #3: key hint for error + \kv@set@family@handler{#1}{% + \thmt@selfextendingkeyhandler{#1}{#2}{#3}% + {##1}{##2}% + }% +} + +\newcommand\thmt@selfextendingkeyhandler[5]{% + % #1: family + % #2: prefix for file + % #3: key hint for error + % #4: actual key + % #5: actual value + \IfFileExists{#2-#4.sty}{% + \PackageInfo{thmtools}% + {Automatically pulling in `#2-#4'}% + \RequirePackage{#2-#4}% + \ifcsname KV@#1@#4\endcsname + \csname KV@#1@#4\endcsname{#5}% + \else + \PackageError{thmtools}% + {#3 `#4' not known} + {I don't know what that key does.\MessageBreak + I've even loaded the file `#2-#4.sty', but that didn't help. + }% + \fi + }{% + \PackageError{thmtools}% + {#3 `#4' not known} + {I don't know what that key does by myself,\MessageBreak + and no file `#2-#4.sty' to tell me seems to exist. + }% + }% +} + + +\newif\if@thmt@firstkeyset + +% many keys are evaluated twice, because we don't know +% if they make sense before or after, or both. +\def\thmt@trytwice{% + \if@thmt@firstkeyset + \@xa\@firstoftwo + \else + \@xa\@secondoftwo + \fi +} + +\@for\tmp@keyname:=parent,numberwithin,within\do{% +\define@key{thmdef}{\tmp@keyname}{\thmt@trytwice{\thmt@setparent{#1}}{}}% +} + +\@for\tmp@keyname:=sibling,numberlike,sharenumber\do{% +\define@key{thmdef}{\tmp@keyname}{\thmt@trytwice{\thmt@setsibling{#1}}{}}% +} + +\@for\tmp@keyname:=title,name,heading\do{% +\define@key{thmdef}{\tmp@keyname}{\thmt@trytwice{\thmt@setthmname{#1}}{}}% +} + +\@for\tmp@keyname:=unnumbered,starred\do{% +\define@key{thmdef}{\tmp@keyname}[]{\thmt@trytwice{\thmt@isnumberedfalse}{}}% +} + +\def\thmt@YES{yes} +\def\thmt@NO{no} +\def\thmt@UNIQUE{unless unique} +\define@key{thmdef}{numbered}[\thmt@YES]{ + \def\thmt@tmp{#1}% + \thmt@trytwice{% + \ifx\thmt@tmp\thmt@YES + \thmt@isnumberedtrue + \else\ifx\thmt@tmp\thmt@NO + \thmt@isnumberedfalse + \else\ifx\thmt@tmp\thmt@UNIQUE + \RequirePackage[unq]{unique} + \ifuniq{\thmt@envname}{% + \thmt@isnumberedfalse + }{% + \thmt@isnumberedtrue + }% + \else + \PackageError{thmtools}{Unknown value `#1' to key numbered}{}% + \fi\fi\fi + }{% trytwice: after definition + \ifx\thmt@tmp\thmt@UNIQUE + \addtotheorempreheadhook[\thmt@envname]{\setuniqmark{\thmt@envname}}% + \addtotheorempreheadhook[\thmt@envname]{\def\thmt@dummyctrautorefname{\thmt@thmname\@gobble}} + \fi + }% +} + + +\define@key{thmdef}{preheadhook}{\thmt@trytwice{}{\addtotheorempreheadhook[\thmt@envname]{#1}}} +\define@key{thmdef}{postheadhook}{\thmt@trytwice{}{\addtotheorempostheadhook[\thmt@envname]{#1}}} +\define@key{thmdef}{prefoothook}{\thmt@trytwice{}{\addtotheoremprefoothook[\thmt@envname]{#1}}} +\define@key{thmdef}{postfoothook}{\thmt@trytwice{}{\addtotheorempostfoothook[\thmt@envname]{#1}}} + +\define@key{thmdef}{style}{\thmt@trytwice{\thmt@setstyle{#1}}{}} + +% ugly hack: style needs to be evaluated first so its keys +% are not overridden by explicit other settings +\define@key{thmdef0}{style}{% + \ifcsname thmt@style #1@defaultkeys\endcsname + \thmt@toks{\kvsetkeys{thmdef}}% + \@xa\@xa\@xa\the\@xa\@xa\@xa\thmt@toks\@xa\@xa\@xa{% + \csname thmt@style #1@defaultkeys\endcsname}% + \fi +} +\thmt@mkignoringkeyhandler{thmdef0} + +% fallback definition. +% actually, only the kernel does not provide \theoremstyle. +% is this one worth having glue code for the theorem package? +\def\thmt@setstyle#1{% + \PackageWarning{thm-kv}{% + Your backend doesn't have a `\string\theoremstyle' command. + }% +} + +\ifcsname theoremstyle\endcsname + \let\thmt@originalthmstyle\theoremstyle + \def\thmt@outerstyle{plain} + \renewcommand\theoremstyle[1]{% + \def\thmt@outerstyle{#1}% + \thmt@originalthmstyle{#1}% + } + \def\thmt@setstyle#1{% + \thmt@originalthmstyle{#1}% + } + \g@addto@macro\thmt@newtheorem@postdefinition{% + \thmt@originalthmstyle{\thmt@outerstyle}% + } +\fi + +\newif\ifthmt@isnumbered +\newcommand\thmt@setparent[1]{% + \def\thmt@parent{#1}% +} +\newcommand\thmt@setsibling{% + \def\thmt@sibling +} +\newcommand\thmt@setthmname{% + \def\thmt@thmname +} + +\thmt@mkextendingkeyhandler{thmdef}{thmdef}{\string\declaretheorem\space key} + +\let\thmt@newtheorem\newtheorem + +\newcommand\declaretheorem[2][]{% + % why was that here? + %\let\thmt@theoremdefiner\thmt@original@newtheorem + \def\thmt@envname{#2}% + \thmt@setthmname{\thmt@modifycase #2}% + \thmt@setparent{}% + \thmt@setsibling{}% + \thmt@isnumberedtrue% + \@thmt@firstkeysettrue% + \kvsetkeys{thmdef0}{#1}% + \kvsetkeys{thmdef}{#1}% + \protected@edef\thmt@tmp{% + \@nx\thmt@newtheorem + \ifthmt@isnumbered\else *\fi + {#2}% + \ifx\thmt@sibling\@empty\else [\thmt@sibling]\fi + {\thmt@thmname}% + \ifx\thmt@parent\@empty\else [\thmt@parent]\fi + \relax% added so we can delimited-read everything later + % (recall newtheorem is patched) + }%\show\thmt@tmp + \thmt@tmp + % uniquely ugly kludge: some keys make only sense + % afterwards. + % and it gets kludgier: again, the default-inherited + % keys need to have a go at it. + \@thmt@firstkeysetfalse% + \kvsetkeys{thmdef0}{#1}% + \kvsetkeys{thmdef}{#1}% +} +\@onlypreamble\declaretheorem + +\providecommand\thmt@quark{\thmt@quark} + +% in-document keyval, i.e. \begin{theorem}[key=val,key=val] + +\thmt@mkextendingkeyhandler{thmuse}{thmuse}{\thmt@envname\space optarg key} + +\addtotheorempreheadhook{% + \ifx\thmt@optarg\@empty\else + \@xa\thmt@garbleoptarg\@xa{\thmt@optarg}\fi +}% + +\newif\ifthmt@thmuse@iskv + +\providecommand\thmt@garbleoptarg[1]{% + \thmt@thmuse@iskvfalse + \def\thmt@newoptarg{\@gobble}% + \def\thmt@newoptargextra{}% + \let\thmt@shortoptarg\@empty + \def\thmt@warn@unusedkeys{}% + \@for\thmt@fam:=\thmt@thmuse@families\do{% + \kvsetkeys{\thmt@fam}{#1}% + }% + \ifthmt@thmuse@iskv + \protected@edef\thmt@optarg{% + \@xa\thmt@newoptarg + \thmt@newoptargextra\@empty + }% + \ifx\thmt@shortoptarg\@empty + \protected@edef\thmt@shortoptarg{\thmt@newoptarg\@empty}% + \fi + \thmt@warn@unusedkeys + \else + \def\thmt@optarg{#1}% + \def\thmt@shortoptarg{#1}% + \fi +} +\def\thmt@splitopt#1=#2\thmt@quark{% + \def\thmt@tmpkey{#1}% + \ifx\thmt@tmpkey\@empty + \def\thmt@tmpkey{\thmt@quark}% + \fi + \@onelevel@sanitize\thmt@tmpkey +} + +\def\thmt@thmuse@families{thm@track@keys} + +\kv@set@family@handler{thm@track@keys}{% + \@onelevel@sanitize\kv@key + \@namedef{thmt@unusedkey@\kv@key}{% + \PackageWarning{thmtools}{Unused key `#1'}% + }% + \@xa\g@addto@macro\@xa\thmt@warn@unusedkeys\@xa{% + \csname thmt@unusedkey@\kv@key\endcsname + } +} + +% key, code. +\def\thmt@define@thmuse@key#1#2{% + \g@addto@macro\thmt@thmuse@families{,#1}% + \define@key{#1}{#1}{\thmt@thmuse@iskvtrue + \@namedef{thmt@unusedkey@#1}{}% + #2}% + \thmt@mkignoringkeyhandler{#1}% +} + +\thmt@define@thmuse@key{label}{% + \addtotheorempostheadhook[local]{\label{#1}}% +} +\thmt@define@thmuse@key{name}{% + \thmt@setnewoptarg #1\@iden% +} +\newcommand\thmt@setnewoptarg[1][]{% + \def\thmt@shortoptarg{#1}\thmt@setnewlongoptarg +} +\def\thmt@setnewlongoptarg #1\@iden{% + \def\thmt@newoptarg{#1\@iden}} + +\providecommand\thmt@suspendcounter[2]{% + \@xa\protected@edef\csname the#1\endcsname{#2}% + \@xa\let\csname c@#1\endcsname\c@thmt@dummyctr +} + +\providecommand\thmcontinues[1]{% + \ifcsname hyperref\endcsname + \hyperref[#1]{continuing} + \else + continuing + \fi + from p.\,\pageref{#1}% +} + +\thmt@define@thmuse@key{continues}{% + \thmt@suspendcounter{\thmt@envname}{\thmt@trivialref{#1}{??}}% + \g@addto@macro\thmt@newoptarg{{, }% + \thmcontinues{#1}% + \@iden}% +} + + +% \end{macrocode} +% +% Defining new theorem styles; keys are in opt-arg +% even though not having any doesn't make much sense. +% It doesn't do anything exciting here, it's up to +% the glue layer to provide keys. +% +% \begin{macrocode} +\def\thmt@declaretheoremstyle@setup{} +\def\thmt@declaretheoremstyle#1{% + \PackageWarning{thmtools}{Your backend doesn't allow styling theorems}{} +} +\newcommand\declaretheoremstyle[2][]{% + \def\thmt@style{#2}% + \@xa\def\csname thmt@style \thmt@style @defaultkeys\endcsname{}% + \thmt@declaretheoremstyle@setup + \kvsetkeys{thmstyle}{#1}% + \thmt@declaretheoremstyle{#2}% +} +\@onlypreamble\declaretheoremstyle + +\kv@set@family@handler{thmstyle}{% + \@onelevel@sanitize\kv@value + \@onelevel@sanitize\kv@key + \PackageInfo{thmtools}{% + Key `\kv@key' (with value `\kv@value')\MessageBreak + is not a known style key.\MessageBreak + Will pass this to every \string\declaretheorem\MessageBreak + that uses `style=\thmt@style'% + }% + \ifx\kv@value\relax% no value given, don't pass on {}! + \@xa\g@addto@macro\csname thmt@style \thmt@style @defaultkeys\endcsname{% + #1,% + }% + \else + \@xa\g@addto@macro\csname thmt@style \thmt@style @defaultkeys\endcsname{% + #1={#2},% + }% + \fi +} +% \end{macrocode} +% +%\iffalse +%</kv> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-listof.dtx b/macros/latex/exptl/thmtools/thm-listof.dtx new file mode 100644 index 0000000000..e91219eca1 --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-listof.dtx @@ -0,0 +1,222 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.txt +% +% \fi +% +%\iffalse (hide this from DocInput) +%<*listof> +%\fi +% +% This package provides two main commands: +% \DescribeMacro{\listoftheorems} +% |\listoftheorems| will generate, well, a list of all theorems, lemmas, +% etc. in your document. This list is hyperlinked if you use \pkg{hyperref}, +% and it will list the optional argument to the theorem. +% +% Currently, some options can be given as an optional argument keyval list: +% \begin{description} +% \item[numwidth] The width allocated for the numbers, default 2.3em. Since +% you are more likely to have by-section numbering than with figures, this +% needs to be accessible. +% \item[ignore=foo,bar] A last-second call to |\ignoretheorems|, see below. +% \item[onlynamed=foo,bar] Only list those foo and bar environments that +% had an optional title. This weeds out unimportant definitions, for +% example. If no argument is given, this applies to all environments +% defined by |\newtheorem| and |\declaretheorem|. +% \item[show=foo,bar] Undo a previous |\ignoretheorems| and restore default +% formatting for these environments. Useful in combination with +% ignoreall. +% \item[ignoreall] +% \item[showall] Like applying ignore or show with a list of all theorems +% you have defined. +% \item[title] +% Provide a title for this list overwriting the default in |\listtheoremname|. +% \end{description} +% +% \DescribeMacro{\listtheoremname} +% The heading name is stored in the macro |\listtheoremname| and is +% ``List of Theorems'' by default. All other formatting aspects are taken +% from |\listoffigures|. (As a matter of fact, |\listoffigures| is called +% internally.) +% +% \DescribeMacro{\ignoretheorems} +% |\ignoretheorems|\marg{remark,example,...} can be used to suppress some +% types of theorem from the LoTh. Be careful not to have spaces in the list, +% those are currently \emph{not} filtered out. +% +% There's currently no interface to change the look of the list. If you're +% daring, the code for the theorem type ``lemma'' is in |\l@lemma| and so on. +% +%\StopEventually{} +% \begin{macrocode} +\let\@xa=\expandafter +\let\@nx=\noexpand +\RequirePackage{thm-patch,keyval,kvsetkeys} + +\def\thmtlo@oldchapter{0}% +\newcommand\thmtlo@chaptervspacehack{} +\ifcsname c@chapter\endcsname + \ifx\c@chapter\relax\else + \def\thmtlo@chaptervspacehack{% + \ifnum \value{chapter}=\thmtlo@oldchapter\relax\else + % new chapter, add vspace to loe. + \addtocontents{loe}{\protect\addvspace{10\p@}}% + \xdef\thmtlo@oldchapter{\arabic{chapter}}% + \fi + }% + \fi +\fi + + +\providecommand\listtheoremname{List of Theorems} +\newcommand\listoftheorems[1][]{% + %% much hacking here to pick up the definition from the class + %% without oodles of conditionals. + \bgroup + \setlisttheoremstyle{#1}% + \let\listfigurename\listtheoremname + \def\contentsline##1{% + \csname thmt@contentsline@##1\endcsname{##1}% + }% + \@for\thmt@envname:=\thmt@allenvs\do{% + \@xa\protected@edef\csname l@\thmt@envname\endcsname{% CHECK: why p@edef? + \@nx\@dottedtocline{1}{1.5em}{\@nx\thmt@listnumwidth}% + }% + }% + \let\thref@starttoc\@starttoc + \def\@starttoc##1{\thref@starttoc{loe}}% + % new hack: to allow multiple calls, we defer the opening of the + % loe file to AtEndDocument time. This is before the aux file is + % read back again, that is early enough. + % TODO: is it? crosscheck include/includeonly! + \@fileswfalse + \AtEndDocument{% + \if@filesw + \@ifundefined{tf@loe}{% + \expandafter\newwrite\csname tf@loe\endcsname + \immediate\openout \csname tf@loe\endcsname \jobname.loe\relax + }{}% + \fi + }% + %\expandafter + \listoffigures + \egroup +} + +\newcommand\setlisttheoremstyle[1]{% + \kvsetkeys{thmt-listof}{#1}% +} +\define@key{thmt-listof}{numwidth}{\def\thmt@listnumwidth{#1}} +\define@key{thmt-listof}{ignore}[\thmt@allenvs]{\ignoretheorems{#1}} +\define@key{thmt-listof}{onlynamed}[\thmt@allenvs]{\onlynamedtheorems{#1}} +\define@key{thmt-listof}{show}[\thmt@allenvs]{\showtheorems{#1}} +\define@key{thmt-listof}{ignoreall}[true]{\ignoretheorems{\thmt@allenvs}} +\define@key{thmt-listof}{showall}[true]{\showtheorems{\thmt@allenvs}} +% FMi 2019-09-31 allow local title +\define@key{thmt-listof}{title}{\def\listtheoremname{#1}} +% -- FMi + +\providecommand\thmt@listnumwidth{2.3em} + +\providecommand\thmtformatoptarg[1]{ (#1)} + +\newcommand\thmt@mklistcmd{% + \@xa\protected@edef\csname l@\thmt@envname\endcsname{% CHECK: why p@edef? + \@nx\@dottedtocline{1}{1.5em}{\@nx\thmt@listnumwidth}% + }% + \ifthmt@isstarred + \@xa\def\csname ll@\thmt@envname\endcsname{% + \protect\numberline{\protect\let\protect\autodot\protect\@empty}% + \thmt@thmname + \ifx\@empty\thmt@shortoptarg\else\protect\thmtformatoptarg{\thmt@shortoptarg}\fi + }% + \else + \@xa\def\csname ll@\thmt@envname\endcsname{% + \protect\numberline{\csname the\thmt@envname\endcsname}% + \thmt@thmname + \ifx\@empty\thmt@shortoptarg\else\protect\thmtformatoptarg{\thmt@shortoptarg}\fi + }% + \fi + \@xa\gdef\csname thmt@contentsline@\thmt@envname\endcsname{% + \thmt@contentslineShow% default:show + }% +} +\def\thmt@allenvs{\@gobble} +\newcommand\thmt@recordenvname{% + \edef\thmt@allenvs{\thmt@allenvs,\thmt@envname}% +} +\g@addto@macro\thmt@newtheorem@predefinition{% + \thmt@mklistcmd + \thmt@recordenvname +} + +\addtotheorempostheadhook{% + \thmtlo@chaptervspacehack + \addcontentsline{loe}{\thmt@envname}{% + \csname ll@\thmt@envname\endcsname + }% +} + +\newcommand\showtheorems[1]{% + \@for\thmt@thm:=#1\do{% + \typeout{showing \thmt@thm}% + \@xa\let\csname thmt@contentsline@\thmt@thm\endcsname + =\thmt@contentslineShow + }% +} + +\newcommand\ignoretheorems[1]{% + \@for\thmt@thm:=#1\do{% + \@xa\let\csname thmt@contentsline@\thmt@thm\endcsname + =\thmt@contentslineIgnore + }% +} +\newcommand\onlynamedtheorems[1]{% + \@for\thmt@thm:=#1\do{% + \global\@xa\let\csname thmt@contentsline@\thmt@thm\endcsname + =\thmt@contentslineIfNamed + }% +} + +\AtBeginDocument{% +\@ifpackageloaded{hyperref}{% + \let\thmt@hygobble\@gobble +}{% + \let\thmt@hygobble\@empty +} +\let\thmt@contentsline\contentsline +} + +\def\thmt@contentslineIgnore#1#2#3{% + \thmt@hygobble +} +\def\thmt@contentslineShow{% + \thmt@contentsline +} + +\def\thmt@contentslineIfNamed#1#2#3{% + \thmt@ifhasoptname #2\thmtformatoptarg\@nil{% + \thmt@contentslineShow{#1}{#2}{#3}% + }{% + \thmt@contentslineIgnore{#1}{#2}{#3}% + %\thmt@contentsline{#1}{#2}{#3}% + } +} + +\def\thmt@ifhasoptname #1\thmtformatoptarg#2\@nil{% + \ifx\@nil#2\@nil + \@xa\@secondoftwo + \else + \@xa\@firstoftwo + \fi +} +% \end{macrocode} +%\iffalse +%</listof> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-llncs.dtx b/macros/latex/exptl/thmtools/thm-llncs.dtx new file mode 100644 index 0000000000..5a3b480c2e --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-llncs.dtx @@ -0,0 +1,90 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*llncs> +%\fi +% \begin{macrocode} +\@ifclasslater{llncs}{2010/04/15}{}{% + \PackageWarningNoLine{thmtools}{% + LLNCS.cls too old, not supported by thmtools + }% + \endinput} +% Thank you very much, Springer, for having yet another bloody +% system. Annoyingly, it makes \xdefs all over the place, so +% they break \MakeUppercase and hence name=. +\ifx\thmt@modifycase\@empty\else + \PackageWarningNoLine{thmtools}{% + LLNCS support disables automatic casing of theorem names + }% + \let\thmt@modifycase\@empty +\fi +%% +% Usage: +% +% \spnewtheorem{env_nam}{caption}[within]{cap_font}{body_font} +% or \spnewtheorem{env_nam}[numbered_like]{caption}{cap_font}{body_font} +% or \spnewtheorem*{env_nam}{caption}{cap_font}{body_font} +\providecommand\thmt@style@headfont{\normalfont\bfseries} +\providecommand\thmt@style@bodyfont{\normalfont\itshape} + +\let\thmt@original@spnewtheorem\spnewtheorem +\let\thmt@theoremdefiner\thmt@original@spnewtheorem + +% cf thm-patch.dtx +\def\spnewtheorem{% + \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}}{}}% + {\parseMand{\def\thmt@style@headfont{##1}}}% + {\parseMand{\def\thmt@style@bodyfont{##1}}}% + {\let\@parsecmd\thmt@spnewtheoremiv}% + }% +} + +\newcommand\thmt@spnewtheoremiv{% + \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@style@headfont}{\thmt@style@bodyfont}% + } + \thmt@args + \thmt@newtheorem@postdefinition +} + +% for the keyval interface: +\define@key{thmdef}{headfont}{% + \def\thmt@style@headfont{#1}% +} +\define@key{thmdef}{bodyfont}{% +\def\thmt@style@bodyfont{#1}% +} + +\def\thmt@almost@spnewtheorem#1\relax{% + \def\thm@tmpa{\spnewtheorem#1}% + \@xa\@xa\@xa\thm@tmpa + \@xa\@xa\@xa{\@xa\thmt@style@headfont\@xa}% + \@xa{\thmt@style@bodyfont}% +} +\let\thmt@newtheorem\thmt@almost@spnewtheorem +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</llncs> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-ntheorem.dtx b/macros/latex/exptl/thmtools/thm-ntheorem.dtx new file mode 100644 index 0000000000..ccd12dc30d --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-ntheorem.dtx @@ -0,0 +1,131 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*ntheorem> +%\fi +% \begin{macrocode} + +\providecommand\thmt@space{ } + +% actually, ntheorem's so-called style is nothing like a style at all... +\def\thmt@declaretheoremstyle@setup{} +\def\thmt@declaretheoremstyle#1{% + \ifcsname th@#1\endcsname\else + \@xa\let\csname th@#1\endcsname\th@plain + \fi +} + +\def\thmt@notsupported#1#2{% + \PackageWarning{thmtools}{Key `#2' not supported by #1}{}% +} + +\define@key{thmstyle}{spaceabove}{% + \setlength\theorempreskipamount{#1}% +} +\define@key{thmstyle}{spacebelow}{% + \setlength\theorempostskipamount{#1}% +} +\define@key{thmstyle}{headfont}{% + \theoremheaderfont{#1}% +} +\define@key{thmstyle}{bodyfont}{% + \theorembodyfont{#1}% +} +% not supported in ntheorem. +\define@key{thmstyle}{notefont}{% + \thmt@notsupported{ntheorem}{notefont}% +} +\define@key{thmstyle}{headpunct}{% + \theoremseparator{#1}% +} +% not supported in ntheorem. +\define@key{thmstyle}{notebraces}{% + \thmt@notsupported{ntheorem}{notebraces}% +} +\define@key{thmstyle}{break}{% + \theoremstyle{break}% +} +% not supported in ntheorem... +\define@key{thmstyle}{postheadspace}{% + %\def\thmt@style@postheadspace{#1}% + \@xa\g@addto@macro\csname thmt@style \thmt@style @defaultkeys\endcsname{% + postheadhook={\hspace{-\labelsep}\hspace*{#1}},% + }% +} + +% not supported in ntheorem +\define@key{thmstyle}{headindent}{% + \thmt@notsupported{ntheorem}{headindent}% +} +% sorry, only style, not def with ntheorem. +\define@key{thmstyle}{qed}[\qedsymbol]{% + \@ifpackagewith{ntheorem}{thmmarks}{% + \theoremsymbol{#1}% + }{% + \thmt@notsupported + {ntheorem without thmmarks option}% + {headindent}% + }% +} + +\let\@upn=\textup +\define@key{thmstyle}{headformat}[]{% + \def\thmt@tmp{#1}% + \@onelevel@sanitize\thmt@tmp + %\tracingall + \ifcsname thmt@headstyle@\thmt@tmp\endcsname + \newtheoremstyle{\thmt@style}{% + \item[\hskip\labelsep\theorem@headerfont% + \def\NAME{\theorem@headerfont ####1}% + \def\NUMBER{\bgroup\@upn{####2}\egroup}% + \def\NOTE{}% + \csname thmt@headstyle@#1\endcsname + \theorem@separator + ] + }{% + \item[\hskip\labelsep\theorem@headerfont% + \def\NAME{\theorem@headerfont ####1}% + \def\NUMBER{\bgroup\@upn{####2}\egroup}% + \def\NOTE{\if=####3=\else\bgroup\thmt@space(####3)\egroup\fi}% + \csname thmt@headstyle@#1\endcsname + \theorem@separator + ] + } + \else + \newtheoremstyle{\thmt@style}{% + \item[\hskip\labelsep\theorem@headerfont% + \def\NAME{\the\thm@headfont ####1}% + \def\NUMBER{\bgroup\@upn{####2}\egroup}% + \def\NOTE{}% + #1% + \theorem@separator + ] + }{% + \item[\hskip\labelsep\theorem@headerfont% + \def\NAME{\the\thm@headfont ####1}% + \def\NUMBER{\bgroup\@upn{####2}\egroup}% + \def\NOTE{\if=####3=\else\bgroup\thmt@space(####3)\egroup\fi}% + #1% + \theorem@separator + ] + } + \fi +} + +\def\thmt@headstyle@margin{% + \makebox[0pt][r]{\NUMBER\ }\NAME\NOTE +} +\def\thmt@headstyle@swapnumber{% + \NUMBER\ \NAME\NOTE +} + + + +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</ntheorem> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-patch.dtx b/macros/latex/exptl/thmtools/thm-patch.dtx new file mode 100644 index 0000000000..b1e28b6fe4 --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-patch.dtx @@ -0,0 +1,252 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.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 +%</patch> +%\fi diff --git a/macros/latex/exptl/thmtools/thm-restate.dtx b/macros/latex/exptl/thmtools/thm-restate.dtx new file mode 100644 index 0000000000..033a48254e --- /dev/null +++ b/macros/latex/exptl/thmtools/thm-restate.dtx @@ -0,0 +1,336 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.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=\@gobble + \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. +} + +\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 diff --git a/macros/latex/exptl/thmtools/thmdef-mdframed.dtx b/macros/latex/exptl/thmtools/thmdef-mdframed.dtx new file mode 100644 index 0000000000..a3fd3658cb --- /dev/null +++ b/macros/latex/exptl/thmtools/thmdef-mdframed.dtx @@ -0,0 +1,28 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*mdframed> +%\fi +% +% Mostly, this key wraps the theorem in a mdframed environment. +% The parameters are set by treating the value we are given as +% a new key-val list, see below. +% +% \begin{macrocode} +\define@key{thmdef}{mdframed}[{}]{% + \thmt@trytwice{}{% + \RequirePackage{mdframed}% + \RequirePackage{thm-patch}% + \addtotheorempreheadhook[\thmt@envname]{% + \begin{mdframed}[#1]}% + \addtotheorempostfoothook[\thmt@envname]{\end{mdframed}}% + }% +} +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</mdframed> +%\fi diff --git a/macros/latex/exptl/thmtools/thmdef-shaded.dtx b/macros/latex/exptl/thmtools/thmdef-shaded.dtx new file mode 100644 index 0000000000..6377182c3e --- /dev/null +++ b/macros/latex/exptl/thmtools/thmdef-shaded.dtx @@ -0,0 +1,109 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*shaded> +%\fi +% +% Mostly, this key wraps the theorem in a shadebox environment. +% The parameters are set by treating the value we are given as +% a new key-val list, see below. +% +% \begin{macrocode} + \define@key{thmdef}{shaded}[{}]{% + \thmt@trytwice{}{% + \RequirePackage{shadethm}% + \RequirePackage{thm-patch}% + \addtotheorempreheadhook[\thmt@envname]{% + \setlength\shadedtextwidth{\linewidth}% + \kvsetkeys{thmt@shade}{#1}\begin{shadebox}}% + \addtotheorempostfoothook[\thmt@envname]{\end{shadebox}}% + }% + } +% \end{macrocode} +% The docs for shadethm say: +% \begin{quote} +% There are some parameters you could set the default for (try them as is, +% first). +% \begin{itemize} +% \item shadethmcolor The shading color of the background. See the +% documentation for the color package, but with a `gray' model, I find .97 +% looks good out of my printer, while a darker shade like .92 is needed +% to make it copy well. (Black is 0, white is 1.) +% \item shaderulecolor The shading color of the border of the shaded box. +% See (i). If shadeboxrule is set to 0pt then this won't print anyway. +% \item shadeboxrule The width of the border around the shading. Set it to +% 0pt (not just 0) to make it disappear. +% \item shadeboxsep The length by which the shade box surrounds the text. +% \end{itemize} +% \end{quote} +% +% So, let's just define keys for all of these. +% +% \begin{macrocode} +\define@key{thmt@shade}{textwidth}{\setlength\shadedtextwidth{#1}} +\define@key{thmt@shade}{bgcolor}{\thmt@definecolor{shadethmcolor}{#1}} +\define@key{thmt@shade}{rulecolor}{\thmt@definecolor{shaderulecolor}{#1}} +\define@key{thmt@shade}{rulewidth}{\setlength\shadeboxrule{#1}} +\define@key{thmt@shade}{margin}{\setlength\shadeboxsep{#1}} +\define@key{thmt@shade}{padding}{\setlength\shadeboxsep{#1}} +\define@key{thmt@shade}{leftmargin}{\setlength\shadeleftshift{#1}} +\define@key{thmt@shade}{rightmargin}{\setlength\shaderightshift{#1}} +% \end{macrocode} +% +% What follows is wizardry you don't have to understand. In essence, +% we want to support two notions of color: one is ``everything that goes +% after \lstinline|\definecolor{shadethmcolor}|'', such as +% \lstinline|{rgb}{0.8,0.85,1}|. On the other hand, we'd also like +% to recognize an already defined color name such as \lstinline|blue|. +% +% To handle the latter case, we need to copy the definition of one color +% into another. The xcolor package offers \lstinline|\colorlet| for that, +% for the color package, we just cross our fingers. +% \begin{macrocode} +\def\thmt@colorlet#1#2{% + %\typeout{don't know how to let color `#1' be like color `#2'!}% + \@xa\let\csname\string\color@#1\@xa\endcsname + \csname\string\color@#2\endcsname + % this is dubious at best, we don't know what a backend does. +} +\AtBeginDocument{% + \ifcsname colorlet\endcsname + \let\thmt@colorlet\colorlet + \fi +} +% \end{macrocode} +% Now comes the interesting part: we assume that a simple color name +% must not be in braces, and a color definition starts with an opening +% curly brace. (So, if \lstinline|\definecolor| ever gets an optional arg, +% we are in a world of pain.) +% +% If the second argument to \lstinline|\thmt@definecolor| (the key) starts +% with a brace, +% then \lstinline|\thmt@def@color| will have an empty second argument, +% delimited by the brace of the key. Hopefully, the key will have exactly +% enough arguments to satisfy \lstinline|\definecolor|. Then, +% \lstinline|thmt@drop@relax| will be executed and gobble the fallback +% values and the \lstinline|\thmt@colorlet|. +% +% If the key does not contain an opening brace, \lstinline|\thmt@def@color| +% will drop everything up to \lstinline|{gray}{0.5}|. So, first the color +% gets defined to a medium gray, but then, it immediately gets overwritten +% with the definition corresponding to the color name. +% \begin{macrocode} +\def\thmt@drop@relax#1\relax{} +\def\thmt@definecolor#1#2{% + \thmt@def@color{#1}#2\thmt@drop@relax + {gray}{0.5}% + \thmt@colorlet{#1}{#2}% + \relax +} +\def\thmt@def@color#1#2#{% + \definecolor{#1}} +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</shaded> +%\fi diff --git a/macros/latex/exptl/thmtools/thmdef-thmbox.dtx b/macros/latex/exptl/thmtools/thmdef-thmbox.dtx new file mode 100644 index 0000000000..ea22cbae97 --- /dev/null +++ b/macros/latex/exptl/thmtools/thmdef-thmbox.dtx @@ -0,0 +1,36 @@ +% \iffalse meta-comment +% +% Copyright (C) 2010 by Ulrich M. Schwarz +% See file COPYING for more details. +%\fi +% +%\iffalse (hide this from DocInput) +%<*thmbox> +%\fi +% The thmbox package does something else: instead of having a separate +% environment, we have to use a command different from +% \lstinline|\newtheorem| to get the boxed style. Fortunately, +% \thmtools stores the command as \lstinline|\thmt@theoremdefiner|, so we +% can modify it. (One of the perks if extension writer and framework writer +% are the same person.) So, in contrast to the previous example, this time +% we need to do something before the actual \lstinline|\newtheorem| is +% called. +% \begin{macrocode} +\define@key{thmdef}{thmbox}[L]{% + \thmt@trytwice{% + \let\oldproof=\proof + \let\oldendproof=\endproof + \let\oldexample=\example + \let\oldendexample=\endexample + \RequirePackage[nothm]{thmbox} + \let\proof=\oldproof + \let\endproof=\oldendproof + \let\example=\oldexample + \let\endexample=\oldendexample + \def\thmt@theoremdefiner{\newboxtheorem[#1]}% + }{}% +}% +% \end{macrocode} +%\iffalse (hide this from DocInput) +%</thmbox> +%\fi diff --git a/macros/latex/exptl/thmtools/thmtools-manual.tex b/macros/latex/exptl/thmtools/thmtools-manual.tex new file mode 100644 index 0000000000..111acda6dc --- /dev/null +++ b/macros/latex/exptl/thmtools/thmtools-manual.tex @@ -0,0 +1,1154 @@ +%&pdflatex +\documentclass[paper=a4, pagesize, DIV=20, + english, + headings=small,11pt, + titlepage=false, + numbers=noendperiod +]{scrreprt} +\addtokomafont{sectioning}{\rmfamily} + +\usepackage[T1]{fontenc} +\usepackage[charter]{mathdesign} +\usepackage{luximono} +\usepackage[scaled]{helvet} + +\usepackage[dvipsnames]{xcolor} + +\usepackage{doc,shortvrb,xspace} +\makeatletter +% to be fixed at some point... +\let\PrintDescribeMacro\@gobble +\let \PrintDescribeEnv\@gobble +\let \PrintMacroName\@gobble +\let \PrintEnvName\@gobble +\makeatother +\CodelineNumbered + +\usepackage{listings} + +\usepackage{amsmath, amsthm} +\usepackage{tikz} + +\usepackage{nameref} +\usepackage{hyperref} +\usepackage{cleveref}[2010/05/01] + +\usepackage{thmtools, thm-restate} +\usepackage[unq]{unique} + +\providecommand\pkg[1]{\textsf{#1}} +\providecommand\Thmtools{\pkg{Thmtools}\xspace} +\providecommand\thmtools{\pkg{thmtools}\xspace} +\providecommand\oarg[1]{\texttt{[}\textit{#1}\texttt{]}} +\providecommand\marg[1]{\texttt{\{}\textit{#1}\texttt{\}}} + + +\providecommand\clap{\makebox[0pt][c]} + +\newcommand\key[2][\keydefaultcontext]{% + % todo: create an index from this... + \paragraph*{\texttt{#2}} +} + +\lstloadlanguages{[LaTeX]TeX} +\lstset{language=[LaTeX]TeX,basicstyle=\small\ttfamily,keywordstyle=\mdseries,aboveskip=0pt} + +\lstnewenvironment{preamble}[1][]{% + \lstset{backgroundcolor=\color{Purple!15},#1}% +}{% +} +\lstnewenvironment{body}[1][]{% + \lstset{backgroundcolor=\color{Yellow!30},#1}% +}{% +} + +\newenvironment{source}{% + \par\noindent\strut\minipage[t]{0.61\linewidth} +}{% + \endminipage +} +\newenvironment{result}{% + \hfill\minipage[t]{0.37\linewidth} +}{% + \endminipage\strut\par +} +%\MakeShortVerb{\|} +\lstMakeShortInline{|} + + +\declaretheorem{theorem} +\declaretheorem[numberwithin=section]{theoremS} +\declaretheorem[name=\"Ubung]{exercise} +\declaretheorem[sibling=theorem]{lemma} +\declaretheorem[numbered=no, + name=Euclid's Prime Theorem]{euclid} +\declaretheorem[numbered=unless unique]{singleton} +\declaretheorem[numbered=unless unique]{couple} +\declaretheorem[style=remark]{remark} +\declaretheorem{Theorem} + +\declaretheorem[shaded={bgcolor=Lavender, + textwidth=12em}]{BoxI} + +\declaretheorem[shaded={rulecolor=Lavender, + rulewidth=2pt, bgcolor={rgb}{1,1,1}}]{BoxII} + + \declaretheorem[thmbox=L]{boxtheorem L} + \declaretheorem[thmbox=M]{boxtheorem M} + \declaretheorem[thmbox=S]{boxtheorem S} + +\declaretheoremstyle[ + spaceabove=6pt, spacebelow=6pt, + headfont=\normalfont\bfseries, + notefont=\mdseries, notebraces={(}{)}, + bodyfont=\normalfont, + postheadspace=1em, + qed=\qedsymbol + ]{mystyle} +\declaretheorem[style=mystyle + ]{styledtheorem} + +\declaretheorem[name=Theorem, refname={theorem,theorems}, + Refname={Theorem,Theorems}]{callmeal} + + +\input{VERSION.tex} + +\title{\Thmtools Users' Guide} +\author{Dr. Ulrich M. Schwarz -- ulmi@absatzen.de\thanks{ + who would like to thank the users for testing, encouragement, feature requests, and + bug reports. In particular, Denis Bitouz\'e prompted further improvement + when \thmtools got stuck in a ``good enough for me'' slump. +}} +\date{\VERSION} + +\begin{document} + \maketitle + \section*{\abstractname} + + The \thmtools bundle is a collection of packages that is designed to + provide an easier interface to theorems, and to facilitate some more + advanced tasks. + + If you are a first-time user and you don't think your requirements are out + of the ordinary, browse the examples in \autoref{cha:impatient}. If you're + here because the other packages you've tried so far just can't do what you + want, take inspiration from \autoref{cha:extravagant}. If you're a repeat + customer, you're most likely to be interested in the refence section in + \autoref{cha:reference}. + + \begin{multicols}{2}[\section*{\contentsname}] + \makeatletter\let\chapter\@gobbletwo + \tableofcontents + \end{multicols} + \clearpage + + \chapter{\Thmtools for the impatient}\label{cha:impatient} + + \section*{How to use this document} + + This guide consists mostly of examples and their output, sometimes with a + few additional remarks. Since theorems are defined in the preamble and + used in the document, the snippets are two-fold: + \begin{source} + \begin{preamble}[gobble=4] + % Preamble code looks like this. + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem{theorem} + \end{preamble} + \begin{body}[gobble=4] + % Document code looks like this. + \begin{theorem}[Euclid] + \label{thm:euclid}% + For every prime $p$, there is a prime $p'>p$. + In particular, the list of primes, + \begin{equation}\label{eq:1} + 2,3,5,7,\dots + \end{equation} + is infinite. + \end{theorem} + \end{body} + \end{source} + \begin{result} + The result looks like this: +% \begin{theorem}[Euclid] +% For every prime $p$, there is a prime $p'>p$. +% In particular, there are infinitely many primes. +% \end{theorem} + \begin{restatable}[Euclid]{theorem}{firsteuclid} + \label{thm:euclid}% + For every prime $p$, there is a prime $p'>p$. + In particular, the list of primes, + \begin{equation}\label{eq:1} + 2,3,5,7,\dots + \end{equation} + is infinite. + \end{restatable} + \end{result} + + Note that in all cases, you will need a \emph{backend} to provide the + command |\newtheorem| with the usual behaviour. The \LaTeX\ + kernel has a built-in backend which cannot do very much; the most common + backends these days are the \pkg{amsthm} and \pkg{ntheorem} packages. + Throughout this document, we'll use \pkg{amsthm}, and some of the features + won't work with \pkg{ntheorem}. + + \section{Elementary definitions} + + As you have seen above, the new command to define theorems is + |\declaretheorem|, which in its most basic form just takes the + name of the environment. All other options can be set through a key-val + interface: + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem[numberwithin=section]{theoremS} + \end{preamble} + \begin{body}[gobble=4] + \begin{theoremS}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{theoremS} + \end{body} + \end{source} + \begin{result} + \begin{restatable}[Euclid]{theoremS}{euclidii} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{restatable} + \end{result} + + Instead of ``numberwithin='', you can also use ``parent='' and + ``within=''. They're all the same, use the one you find easiest to + remember. + + Note the example above looks somewhat bad: sometimes, the name of the environment, + with the first + letter uppercased, is not a good choice for the theorem's title. + + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem[name=\"Ubung]{exercise} + \end{preamble} + \begin{body}[gobble=4] + \begin{exercise} + Prove Euclid's Theorem. + \end{exercise} + \end{body} + \end{source} + \begin{result} + \begin{exercise} + Prove Euclid's Theorem. + \end{exercise} + \end{result} + + To save you from having to look up the name of the key every time, you can + also use ``title='' and ``heading='' instead of ``name=''; they do exactly + the same and hopefully one of these will be easy to remember for you. + + Of course, you do not have to follow the abominal practice of numbering + theorems, lemmas, etc., separately: + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem[sibling=theorem]{lemma} + \end{preamble} + \begin{body}[gobble=4] + \begin{lemma} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{lemma} + \end{body} + \end{source} + \begin{result} + \begin{lemma} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{lemma} + \end{result} + + Again, instead of ``sibling='', you can also use ``numberlike='' and + ``sharecounter=''. + + Some theorems have a fixed name and are not supposed to get a number. + To this end, \pkg{amsthm} provides |\newtheorem*|, which is + accessible through \thmtools: + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem[numbered=no, + name=Euclid's Prime Theorem]{euclid} + \end{preamble} + \begin{body}[gobble=4] + \begin{euclid} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{euclid} + \end{body} + \end{source} + \begin{result} + \begin{euclid} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{euclid} + \end{result} + + As a somewhat odd frill, you can turn off the number if there's only one + instance of the kind in the document. This might happen when you split and + join your papers into short conference versions and longer journal papers + and tech reports. Note that this doesn't combine well with the sibling + key: how do you count like somebody who suddenly doesn't count anymore? + Also, it takes an extra \LaTeX\ run to settle. + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \usepackage[unq]{unique} + \declaretheorem[numbered=unless unique]{singleton} + \declaretheorem[numbered=unless unique]{couple} + \end{preamble} + \begin{body}[gobble=4] + \begin{couple} + Marc \& Anne + \end{couple} + \begin{singleton} + Me. + \end{singleton} + \begin{couple} + Buck \& Britta + \end{couple} + \end{body} + \end{source} + \begin{result} + \begin{couple} + Marc \& Anne + \end{couple} + \begin{singleton} + Me. + \end{singleton} + \begin{couple} + Buck \& Britta + \end{couple} + \end{result} + + \section{Frilly references} + + In case you didn't know, you should: \pkg{hyperref}, \pkg{nameref} and + \pkg{cleveref} offer ways of ``automagically'' knowing that + |\label{foo}| was inside a theorem, so that a reference adds the + string ``Theorem''. This is all done for you, but there's one catch: you + have to tell \thmtools\ what the name to add is. By default, it will use + the title of the theorem, in particular, it will be uppercased. + (This happens to match the guidelines of all + publishers I have encountered.) But there is an alternate spelling + available, denoted by a capital letter, and in any case, if you use + \pkg{cleveref}, you should give two values separated by a comma, because + it will generate plural forms if you reference many theorems in one + |\cite|. + \begin{source} + \begin{preamble}[gobble=6] + \usepackage{amsthm, thmtools} + \usepackage{ + nameref,%\nameref + hyperref,%\autoref + % n.b. \Autoref is defined by thmtools + cleveref,% \cref + % n.b. cleveref after! hyperref + } + \declaretheorem[name=Theorem, + refname={theorem,theorems}, + Refname={Theorem,Theorems}]{callmeal} + \end{preamble} + \begin{body}[gobble=6] + \begin{callmeal}[Simon]\label{simon} + One + \end{callmeal} + \begin{callmeal}\label{garfunkel} + and another, and together, + \autoref{simon}, ``\nameref{simon}'', + and \cref{garfunkel} are referred + to as \cref{simon,garfunkel}. + \Cref{simon,garfunkel}, if you are at + the beginning of a sentence. + \end{callmeal} + \end{body} + \end{source} + \begin{result} + \begin{callmeal}[Simon]\label{simon} + One + \end{callmeal} + \begin{callmeal}\label{garfunkel} + and another, and together, \autoref{simon}, ``\nameref{simon}'', + and \cref{garfunkel} are referred to as \cref{simon,garfunkel}. + \Cref{simon,garfunkel}, if you are at the beginning of a sentence. + \end{callmeal} + \end{result} + + \section{Styling theorems} + + The major backends provide a command |\theoremstyle| to switch + between looks of theorems. This is handled as follows: + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem[style=remark]{remark} + \declaretheorem{Theorem} + \end{preamble} + \begin{body}[gobble=4] + \begin{Theorem} + This is a theorem. + \end{Theorem} + \begin{remark} + Note how it still retains the default style, `plain'. + \end{remark} + \end{body} + \end{source} + \begin{result} + \begin{Theorem} + This is a theorem. + \end{Theorem} + \begin{remark} + Note how it still retains the default style, `plain'. + \end{remark} + \end{result} + + Thmtools also supports the shadethm and thmbox packages: + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \usepackage[dvipsnames]{xcolor} + \declaretheorem[shaded={bgcolor=Lavender, + textwidth=12em}]{BoxI} + \declaretheorem[shaded={rulecolor=Lavender, + rulewidth=2pt, bgcolor={rgb}{1,1,1}}]{BoxII} + \end{preamble} + \begin{body}[gobble=4] + \begin{BoxI}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{BoxI} + \begin{BoxII}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{BoxII} + \end{body} + \end{source} + \begin{result} + \begin{BoxI} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{BoxI} + \begin{BoxII} + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{BoxII} + \end{result} + + As you can see, the color parameters can take two forms: it's either the + name of a color that is already defined, without curly braces, or it can + start with a curly brace, in which case it is assumed that + |\definecolor{colorname}|$\langle$\textsl{what you said}$\rangle$ will be + valid \LaTeX\ code. In our case, we use the rbg model to manually specify + white. (Shadethm's default value is some sort of gray.) + + For the thmbox package, use the thmbox key: + \begin{source} + \begin{preamble}[gobble=4] + \usepackage{amsthm} + \usepackage{thmtools} + \declaretheorem[thmbox=L]{boxtheorem L} + \declaretheorem[thmbox=M]{boxtheorem M} + \declaretheorem[thmbox=S]{boxtheorem S} + \end{preamble} + \begin{body}[gobble=4] + \begin{boxtheorem L}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{boxtheorem L} + \begin{boxtheorem M}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{boxtheorem M} + \begin{boxtheorem S}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{boxtheorem S} + \end{body} + \end{source} + \begin{result} + \begin{boxtheorem L}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{boxtheorem L} + \begin{boxtheorem M}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{boxtheorem M} + \begin{boxtheorem S}[Euclid] + For every prime $p$, there is a prime $p'>p$. + In particular, there are infinitely many primes. + \end{boxtheorem S} + \end{result} + + Note that for both thmbox and shaded keys, it's quite possible they will not + cooperate with a style key you give at the same time. + + \subsection{Declaring new theoremstyles} + + \Thmtools\ also offers a new command to define new theoremstyles. It is + partly a frontend to the |\newtheoremstyle| command of \pkg{amsthm} or + \pkg{ntheorem}, but it offers (more or less successfully) the settings of both to + either. So we are talking about the same things, consider the sketch in + \autoref{fig:params}. To get a result like that, you would use something + like + \begin{source} + \begin{preamble}[gobble=4] + \declaretheoremstyle[ + spaceabove=6pt, spacebelow=6pt, + headfont=\normalfont\bfseries, + notefont=\mdseries, notebraces={(}{)}, + bodyfont=\normalfont, + postheadspace=1em, + qed=\qedsymbol + ]{mystyle} + \declaretheorem[style=mystyle]{styledtheorem} + \end{preamble} + \begin{body}[gobble=4] + \begin{styledtheorem}[Euclid] + For every prime $p$\dots + \end{styledtheorem} + \end{body} + \end{source} + \begin{result} + \begin{styledtheorem}[Euclid] + For every prime $p$\dots + \end{styledtheorem} + \end{result} + Again, the defaults are reasonable and you don't + have to give values for everything. + + There is one important thing you cannot see in this example: there are + more keys you can pass to |\declaretheoremstyle|: if \thmtools\ cannot + figure out at all what to do with it, it will pass it on to the + |\declaretheorem| commands that use that style. For example, you may use + the boxed and shaded keys here. + + To change the order in which title, number and note appear, there is a key + headformat. Currently, the values ``margin'' and ``swapnumber'' are + supported. The daring may also try to give a macro here that uses the + commands |\NUMBER|, |\NAME| and |\NOTE|. + You cannot circumvent the fact + that headpunct comes at the end, though, nor the fonts and braces you + select with the other keys. + + \begin{figure}\centering + % please don't make me touch this picture ever again. + \fbox{ + \begin{minipage}{0.618\textwidth}\Large + \tikzset{font=\normalfont\small\sffamily\itshape,y=12pt,>=latex} + \noindent which resulted in the following insight: + \par + \tikz{\draw[|<->|] (0,-1)--(0,1); + \draw[anchor=west] (0,0) node {spaceabove};} + \par + \tikz{\draw[|<->|] (-1,0)--(1,0); + \draw[anchor=south] (0,0) node {headindent};} + \textbf{Theo% + \smash{\clap{\tikz{\draw (0,0)--(0,1.2) node [anchor=south]{headfont};}}}% + rem 1.2 + (\smash{\rlap{\tikz{\draw (0,0)--(0,2.5) node [anchor=base west]{notebraces};}}}% + Euc% +\smash{\clap{\tikz{\draw (0,0)--(0,1.2) node [anchor=south]{notefont};}}}% + lid)% + .\smash{\rlap{\tikz{\draw (0,0)--(0,1.2) node [anchor=south west]{headpunct};}}}}% + \tikz{\draw[|<->|] (-1,0)--(1,0); + \draw[anchor=south] (0,0) node {postheadspace};} + For every prime $p$, there is a prime $p'>p$. + In particular, the list of primes, + $2,3,5,7,\dots$, + is infinite. + \hfill{\tikz{\draw[anchor=north east] (0,0) node{qed}; }}$\Box$ + \par + \tikz{\draw[|<->|] (0,-1)--(0,1); + \draw[anchor=west] (0,0) node {spacebelow};} + \par + + As a consequence, lorem ipsum dolor sit amet frob-%nicate foo +% paret. + \end{minipage} + } + \caption{Settable parameters of a theorem style.} + \label{fig:params} + \end{figure} + + \section{Repeating theorems} + + Sometimes, you want to repeat a theorem you have given in full earlier, + for example you either want to state your strong result in the + introduction and then again in the full text, or you want to re-state a + lemma in the appendix where you prove it. For example, I lied about + \autoref{thm:euclid} on p.\,\pageref{thm:euclid}: the true code used was + \begin{source} + \begin{preamble}[gobble=6] + \usepackage{thmtools, thm-restate} + \declaretheorem{theorem} + \end{preamble} + \begin{body}[gobble=6] + \begin{restatable}[Euclid]{theorem}{firsteuclid} + \label{thm:euclid}% + For every prime $p$, there is a prime $p'>p$. + In particular, the list of primes, + \begin{equation}\label{eq:1} + 2,3,45,7,\dots + \end{equation} + is infinite. + \end{restatable} + \end{body} + and to the right, I just use + \begin{body}[gobble=6] + \firsteuclid* + \vdots + \firsteuclid* + \end{body} + \end{source} + \begin{result} + \firsteuclid* + \vdots + \firsteuclid* + \end{result} + + Note that in spite of being a theorem-environment, it gets number one all + over again. Also, we get equation number~\eqref{eq:1} again. The star in + |\firsteuclid*| tells thmtools that it should redirect the label + mechanism, so that this reference: \autoref{thm:euclid} points to + p.\,\pageref{thm:euclid}, where the unstarred environment is used. (You can + also use a starred environment and an unstarred command, in which case the + behaviour is reversed.) Also, if you use \pkg{hyperref}, the links will lead you + to the unstarred occurence. + + Just to demonstrate that we also handle more involved cases, I repeat + another theorem here, but this one was numbered within its section: note + we retain the section number which does not fit the current section: + \begin{source} + \begin{body} + \euclidii* + \end{body} + \end{source} + \begin{result} + \euclidii* + \end{result} + + + \section{Lists of theorems} + + To get a list of theorems with default formatting, just use + |\listoftheorems|: + \begin{source} + \begin{body}[gobble=6] + \listoftheorems + \end{body} + \end{source} + \begin{result} + \let\chapter\section + \let\clearpage\relax + \listoftheorems + \end{result} + + Not everything might be of the same importance, so you can filter out + things by environment name: + \begin{source} + \begin{body}[gobble=6] + \listoftheorems[ignoreall, + show={theorem,Theorem,euclid}] + \end{body} + \end{source} + \begin{result} + \let\chapter\section + \let\clearpage\relax + \listoftheorems[ignoreall, show={theorem,Theorem,euclid}] + \end{result} + + And you can also restrict to those environments that have an optional + argument given. Note that two theorems disappear compared to the previous + example. You could also say just ``onlynamed'', in which case it will + apply to \emph{all} theorem environments you have defined. + \begin{source} + \begin{body}[gobble=6] + \listoftheorems[ignoreall, + onlynamed={theorem,Theorem,euclid}] + \end{body} + \end{source} + \begin{result} + \let\chapter\section + \let\clearpage\relax + \listoftheorems[ignoreall, onlynamed={theorem,Theorem,euclid}] + \end{result} + + As might be expected, the heading given is defined in |\listtheoremname|. + + \section{Extended arguments to theorem environments} + + Usually, the optional argument of a theorem serves just to give a note + that is shown in the theorem's head. \Thmtools\ allows you to have a + key-value list here as well. The following keys are known right now: + \begin{description} + \item[name] This is what used to be the old argument. It usually holds + the name of the theorem, or a source. This key also accepts an + \emph{optional} argument, which will go into the list of theorems. Be + aware that since we already are within an optional argument, you have to + use an extra level of curly braces: + |\begin{theorem}[{name=[Short name]A long name,...}]| + \item[label] This will issue a |\label| command after the head. Not very + useful, more of a demo. + \item[continues] Saying |continues=foo| will cause the number that is + given to be changed to |\ref{foo}|, and a text is added to the note. + (The exact text is given by the macro |\thmcontinues|, which takes the + label as its argument.) + \item[restate] Saying |restate=foo| will hopefully work like + wrapping this theorem in a restatable environment. (It probably still fails + in cases that I didn't think of.) This key also accepts an optional + argument: when restating, the restate key is replaced by this argument, + for example, |restate=[name=Boring rehash]foo| will result in a + different name. (Be aware that it is possible to give the same key + several times, but I don't promise the results. In case of the name key, + the names happen to override one another.) + \end{description} + \begin{source} + \begin{body}[gobble=6] + \begin{theorem}[name=Keyed theorem, + label=thm:key] + This is a + key-val theorem. + \end{theorem} + \begin{theorem}[continues=thm:key] + And it's spread out. + \end{theorem} + \end{body} + \end{source} + \begin{result} + \begin{theorem}[name=Keyed theorem, + label=thm:key] + This is a key-val theorem. + \end{theorem} + \begin{theorem}[continues=thm:key] + And it's spread out. + \end{theorem} + \end{result} + + + + \chapter{\Thmtools for the extravagant}\label{cha:extravagant} + + This chapter will go into detail on the slightly more technical offerings + of this bundle. In particular, it will demonstrate how to use the general + hooks provided to extend theorems in the way you want them to behave. + Again, this is done mostly by some examples. + + \section{Understanding \thmtools' extension mechanism} + + \Thmtools\ draws most of its power really only from one feature: + the |\newtheorem| of the backend will, for example, create + a theorem environment, i.e. the commands |\theorem| and + |\endtheorem|. To add functionality, four places immediately + suggest themselves: ``immediately before'' and ``immediately after'' those + two. + + There are two equivalent ways of adding code there: one is to call + |\addtotheorempreheadhook| and its brothers and sisters + |...postheadhook|, |...prefoothook| + and |...postfoothook|. + All of these take an \emph{optional} argument, the name of the + environment, and the new code as a mandatory argument. The environment is + optional because there is also a set of ``generic'' hooks added to every + theorem that you define. + + The other way is to use the keys |preheadhook| et al. in your + |\declaretheorem|. (There is no way of accessing the generic + hook in this way.) + + The hooks are arranged in the following way: first the specific prehead, + then the generic one. Then, the original |\theorem| (or + whatever) will be called. Afterwards, first the specific posthead again, + then the generic one. (This means that you cannot wrap the head alone in + an environment this way.) At the end of the theorem, it is the other way + around: first the generic, then the specific, both before and after that + |\endtheorem|. This means you can wrap the entire theorem + easily by adding to the prehead and the postfoot hooks. Note that + \thmtools\ does not look inside |\theorem|, so you cannot get + inside the head formatting, spacing, punctuation in this way. + + In many situations, adding static code will not be enough. Your code can + look at |\thmt@envname|, |\thmt@thmname| and + |\thmt@optarg|, which will contain the name of the environment, + its title, and, if present, the optional argument (otherwise, it is + |\@empty|). + \emph{However}, you should not make assumptions about the optional + argument in the preheadhook: it might still be key-value, or it might + already be what will be placed as a note. (This is because the key-val + handling itself is added as part of the headkeys.) + + + \section{Case in point: the shaded key} + + Let us look at a reasonably simple example: the shaded key, which we've + already seen in the first section. You'll observe that we run into a + problem similar to the four-hook mess: your code may either want to modify + parameters that need to be set beforehand, or it wants to modify the + environment after it has been created. To hide this from the user, the + code you define for the key is actually executed twice, and + |\thmt@trytwice{A}{B}| will execute A on the first pass, and B + on the second. Here, we want to add to the hooks, and the hooks are only + there in the second pass. + + \DocInput{thmdef-shaded.dtx} + + \section{Case in point: the thmbox key} + + \DocInput{thmdef-thmbox.dtx} + + \section{Case in point: the mdframed key} + \DocInput{thmdef-mdframed.dtx} + + \section{How \thmtools\ finds your extensions} + + Up to now, we have discussed how to write the code that adds functionality + to your theorems, but you don't know how to activate it yet. + Of course, you can put it in your preamble, likely embraced by + |\makeatletter| and |\makeatother|, because you are + using internal macros with @ in their name (viz., + |\thmt@envname| and friends). You can also put them into a + package (then, without the |\makeat...|), + which is simply a file ending in .sty put somewhere that \LaTeX\ can find + it, which can then be laoded with |\usepackage|. + To find out where exactly that is, and if you'd need to update + administrative helper files such as a filename database FNDB, + please consult the documentation of your \TeX\ distribution. + + Since you most likely want to add keys as well, there is a shortcut that + \thmtools\ offers you: whenever you use a key |key| in a + |\declaretheorem| command, and \thmtools\ doesn't already know + what to do with it, it will try to |\usepackage{thmdef-key}| and + evaluate the key again. (If that doesn't work, \thmtools\ will cry + bitterly.) + + For example, there is no provision in \thmtools\ itself that make the + |shaded| and |thmbox| keys described above special: + in fact, if you want to use a different package to create frames, you just + put a different |thmdef-shaded.sty| into a preferred texmf tree. + Of course, if your new package doesn't offer the old keys, your old + documents might break! + + The behaviour for the keys in the style definition is slightly different: + if a key is not known there, it will be used as a ``default key'' to every + theorem that is defined using this style. For example, you can give the + |shaded| key in a style definition. + + Lastly, the key-val arguments to the theorem environments themselves need + to be loaded manually, not least because inside the document it's too late + to call |\usepackage|. + + \chapter{\Thmtools for the completionist}\label{cha:reference} + + This will eventually contain a reference to all known keys, commands, etc. + + + \section{Known keys to \texttt{\textbackslash declaretheoremstyle}} + \def\keydefaultcontext{declaretheoremstyle} + + N.b. implementation for \pkg{amsthm} and \pkg{ntheorem} is separate for + these, so if it doesn't work for \pkg{ntheorem}, try if it works with + \pkg{amsthm}, which in general supports more things. + + Also, all keys listed as known to |\declaretheorem| are valid. + + \key{spaceabove} Value: a length. Vertical space above the theorem, + possibly discarded if the theorem is at the top of the page. + + \key{spacebelow} Value: a length. Vertical space after the theorem, + possibly discarded if the theorem is at the top of the page. + + \key{headfont} Value: \TeX\ code. Executed just before the head of the + theorem is typeset, inside a group. Intended use it to put font switches here. + + \key{notefont} + Value: \TeX\ code. Executed just before the note in the head is typeset, inside a group. + Intended use it to put font switches here. Formatting also applies to + the braces around the note. + Not supported by \pkg{ntheorem}. + + \key{bodyfont} + Value: \TeX\ code. Executed before the begin part of the theorem ends, + but before all afterheadhooks. Intended use it to put font switches here. + + \key{headpunct} + Value: \TeX\ code, usually a single character. Put at the end of the + theorem's head, prior to linebreaks or indents. + + \key{notebraces} + Value: Two characters, the opening and closing symbol to use around a + theorem's note. + (Not supported by \pkg{ntheorem}.) + + \key{postheadspace} + Value: a length. Horizontal space inserted after the entire head of the + theorem, before the body. Does probably not apply (or make sense) for + styles that have a linebreak after the head. + + \key{headformat} + Value: \LaTeX\ code using the special placeholders |\NUMBER|, |\NAME| + and |\NOTE|, which correspond to the (formatted, including the braces + for |\NOTE| etc.) three parts of a theorem's head. This can be used to + override the usual style ``1.1 Theorem (Foo)'', for example to let the + numbers protude in the margin or put them after the name. + + Additionally, a number of keywords are allowed here instead of \LaTeX\ + code: + \begin{description} + \item[margin] Lets the number protude in the (left) margin. + \item[swapnumber] Puts the number before the name. Currently + not working so well for unnumbered theorems. + \item[] \emph{This list is likely to grow} + \end{description} + + \key{headindent} + Value: a length. Horizontal space inserted before the head. Some + publishers like |\parindent| here for remarks, for example. + + + \section{Known keys to \texttt{\textbackslash declaretheorem}} + \def\keydefaultcontext{declaretheorem} + + \key{parent} + Value: a counter name. The theorem will be reset whenever that counter + is incremented. Usually, this will be a sectioning level, |chapter| or + |section|. + + \key{numberwithin} + Value: a counter name. The theorem will be reset whenever that counter + is incremented. Usually, this will be a sectioning level, |chapter| or + |section|. + (Same as parent.) + + \key{within} + Value: a counter name. The theorem will be reset whenever that counter + is incremented. Usually, this will be a sectioning level, |chapter| or + |section|. + (Same as parent.) + + + \key{sibling} + Value: a counter name. The theorem will use this counter for numbering. + Usually, this is the name of another theorem environment. + + \key{numberlike} + Value: a counter name. The theorem will use this counter for numbering. + Usually, this is the name of another theorem environment. + (Same as sibling.) + + \key{sharenumber} + Value: a counter name. The theorem will use this counter for numbering. + Usually, this is the name of another theorem environment. + (Same as sibling.) + + + \key{title} + Value: \TeX\ code. The title of the theorem. Default is the name of the + environment, with |\MakeUppercase| prepended. You'll have to give + this if your title starts with a accented character, for example. + + \key{name} + Value: \TeX\ code. The title of the theorem. Default is the name of the + environment, with |\MakeUppercase| prepended. You'll have to give + this if your title starts with a accented character, for example. + (Same as title.) + + \key{heading} + Value: \TeX\ code. The title of the theorem. Default is the name of the + environment, with |\MakeUppercase| prepended. You'll have to give + this if your title starts with a accented character, for example. + (Same as title.) + + \key{numbered} + Value: one of the keywords |yes|, |no| or |unless unique|. The theorem + will be numbered, not numbered, or only numbered if it occurs more than + once in the document. (The latter requires another \LaTeX\ run and will + not work well combined with |sibling|.) + + \key{style} + Value: the name of a style defined with |\declaretheoremstyle| or + |\newtheoremstyle|. The theorem will use the settings of this style. + + \key{preheadhook} + Value: \LaTeX\ code. This code will be executed at the beginning of the + environment, even before vertical spacing is added and the head is + typeset. However, it is already within the group defined by the + environment. + + \key{postheadhook} + Value: \LaTeX\ code. This code will be executed after the call to the + original begin-theorem code. Note that all backends seem to delay + typesetting the actual head, so code here should probably enter + horizontal mode to be sure it is after the head, but this will change + the spacing/wrapping behaviour if your body starts with another list. + + \key{prefoothook} + Value: \LaTeX\ code. This code will be executed at the end of the body + of the environment. + + \key{postfoothook} + Value: \LaTeX\ code. This code will be executed at the end of the + environment, even after eventual vertical spacing, but still within the + group defined by the environment. + + \key{refname} + Value: one string, or two string separated by a comma (no spaces). This + is the name of the theorem as used by |\autoref|, |\cref| and friends. If it is + two strings, the second is the plural form used by |\cref|. Default + value is the value of |name|, i.e. usually the environment name, with + \MakeUppercase. + + \key{Refname} + Value: one string, or two string separated by a comma (no spaces). This + is the name of the theorem as used by |\Autoref|, |\Cref| and friends. If it is + two strings, the second is the plural form used by |\Cref|. This can be + used for alternate spellings, for example if your style requests no + abbreviations at the beginning of a sentence. No default. + + + \key{shaded} + Value: a key-value list, where the following keys are possible: + \begin{description} + \item[textwidth] + The linewidth within the theorem. + \item[bgcolor] + The color of the background of the theorem. Either a color name or a + color spec as accepted by |\definecolor|, such as |{gray}{0.5}|. + \item[rulecolor] + The color of the box surrounding the theorem. Either a color name or + a color spec. + \item[rulewidth] + The width of the box surrounding the theorem. + \item[margin] + The length by which the shade box surrounds the text. + \end{description} + + \key{thmbox} + Value: one of the characters L, M and S; see examples above. + + + \section{Known keys to in-document theorems} + \def\keydefaultcontext{theorem} + + \key{label} Value: a legal |\label| name. + Issues a |\label| command after the theorem's head. + + \key{name} Value: \TeX\ code that will be typeset. + What you would have put in the optional argument in the + non-keyval style, i.e. the note to the head. This is \emph{not} the same + as the name key to |\declaretheorem|, you cannot override that from within + the document. + + \key{listhack} Value: doesn't matter. (But put something to trigger + key-val behaviour, maybe listhack=true.) Linebreak styles in \pkg{amsthm} + don't linebreak if they start with another list, like an |enumerate| + environment. Giving the |listhack| key fixes that. \emph{Don't} give this + key for non-break styles, you'll get too little vertical space! (Just use + |\leavevmode| manually there.) + An all-around listhack that handles both situations might come in a + cleaner rewrite of the style system. + + \section{Restatable -- hints and caveats} + + TBD. + \begin{itemize} + \item Some counters are saved so that the same values appear when you + re-use them. The list of these counters is stored in the macro + |\thmt@innercounters| as a comma-separated list without spaces; default: equation. + + \item To preserve the influence of other counters (think: equation + numbered per section and recall the theorem in another section), we need + to know all macros that are used to turn a counter into printed output. + Again, comma-separated list without spaces, without leading backslash, stored as + |\thmt@counterformatters|. Default: + |@alph,@Alph,@arabic,@roman,@Roman,@fnsymbol| + All these only take + the \LaTeX\ counter |\c@foo| as arguments. If you bypass this and use + |\romannumeral|, your numbers go wrong and you get what you deserve. + Important if you have very strange numbering, maybe using greek letters + or somesuch. + + \item I think you cannot have one stored counter within another one's + typeset representation. I don't think that ever occurs in reasonable + circumstances, either. Only one I could think of: multiple subequation + blocks that partially overlap the theorem. Dude, that doesn't even nest. + You get what you deserve. + + \item |\label| and \pkg{amsmath}'s |\ltx@label| are disabled inside the + starred execution. Possibly, |\phantomsection| should be disabled as + well? + \end{itemize} + + \appendix + + + \chapter{\Thmtools for the morbidly curious}\label{cha:sourcecode} + + This chapter consists of the implementation of Thmtools, in case you + wonder how this or that feature was implemented. Read on if you want a + look under the bonnet, but you enter at your own risk, and bring an oily + rag with you. + + \section{Core functionality} + + \subsection{The main package} + \DocInput{thmtools.dtx} + + \subsection{Adding hooks to the relevant commands} + \DocInput{thm-patch.dtx} + + \subsection{The key-value interfaces} + \DocInput{thm-kv.dtx} + + \subsection{Lists of theorems} + \DocInput{thm-listof.dtx} + + \subsection{Re-using environments} + \DocInput{thm-restate.dtx} + + \subsection{Fixing autoref and friends} + \DocInput{thm-autoref.dtx} + + \section{Glue code for different backends} + + \subsection{amsthm} + \DocInput{thm-amsthm.dtx} + + \subsection{beamer} + \DocInput{thm-beamer.dtx} + + \subsection{ntheorem} + \DocInput{thm-ntheorem.dtx} + + \section{Generic tools} + + \subsection{A generalized argument parser} + \DocInput{parseargs.dtx} + + \subsection{Different counters sharing the same register} + \DocInput{aliasctr.dtx} + + \subsection{Tracking occurences: none, one or many} + \DocInput{unique.dtx} + + + + +\end{document} diff --git a/macros/latex/exptl/thmtools/thmtools.dtx b/macros/latex/exptl/thmtools/thmtools.dtx new file mode 100644 index 0000000000..d5139e30c6 --- /dev/null +++ b/macros/latex/exptl/thmtools/thmtools.dtx @@ -0,0 +1,90 @@ +% \iffalse meta-comment +% +% Copyright (C) 2008 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.txt +% +% \fi +% +%\iffalse (hide this from DocInput) +%<*driver> +\makeatletter +\ifx\documentclass\@twoclasserror\else + \expandafter\@firstofone +\fi{% + \makeatother + %% we are either \RequirePackage'd + %% (which we won't support) or compiled directly. + %% If we are compiled directly, yield the manual. + %% Otherwise, this looks like a debugging session + %% that directly uses the dtx file instead of the sty. + \input{thmtools-manual.tex} + \endinput +} +%</driver> +%<*thmtools> +%\fi +% \begin{macrocode} +\DeclareOption{debug}{% + \def\thmt@debug{\typeout}% +} +% common abbreviations and marker macros. +\let\@xa\expandafter +\let\@nx\noexpand +\def\thmt@debug{\@gobble} +\def\thmt@quark{\thmt@quark} +\newtoks\thmt@toks + +\@for\thmt@opt:=lowercase,uppercase,anycase\do{% + \@xa\DeclareOption\@xa{\thmt@opt}{% + \@xa\PassOptionsToPackage\@xa{\CurrentOption}{thm-kv}% + }% +} + +\ProcessOptions\relax + +% a scratch counter, mostly for fake hyperlinks +\newcounter{thmt@dummyctr}% +\def\theHthmt@dummyctr{dummy.\arabic{thmt@dummyctr}}% +\def\thethmt@dummyctr{}% + + +\RequirePackage{thm-patch, thm-kv, + thm-autoref, thm-listof, + thm-restate} + +% Glue code for the big players. +\@ifpackageloaded{amsthm}{% + \RequirePackage{thm-amsthm} +}{% + \AtBeginDocument{% + \@ifpackageloaded{amsthm}{% + \PackageWarningNoLine{thmtools}{% + amsthm loaded after thmtools + }{}% + }{}}% +} +\@ifpackageloaded{ntheorem}{% + \RequirePackage{thm-ntheorem} +}{% + \AtBeginDocument{% + \@ifpackageloaded{ntheorem}{% + \PackageWarningNoLine{thmtools}{% + ntheorem loaded after thmtools + }{}% + }{}}% +} +\@ifclassloaded{beamer}{% + \RequirePackage{thm-beamer} +}{} +\@ifclassloaded{llncs}{% + \RequirePackage{thm-llncs} +}{} +% \end{macrocode} + +%\iffalse +%</thmtools> +%\fi diff --git a/macros/latex/exptl/thmtools/thmtools.ins b/macros/latex/exptl/thmtools/thmtools.ins new file mode 100644 index 0000000000..4b97aae226 --- /dev/null +++ b/macros/latex/exptl/thmtools/thmtools.ins @@ -0,0 +1,61 @@ +%% +%% This is a bog-standard .ins file: thmtools.ins +%% +\input VERSION.tex +%\show\VERSION +\def\dropext #1.#2\relax{#1} +\input docstrip.tex +%\keepsilent +\askonceonly +\preamble +This is a generated file. + +This file is part of the `thmtools' package. +The `thmtools' package has the LPPL maintenance status: unmaintained. + +Copyright (C) 2008-2014 by Ulrich M. Schwarz. + +This file may be distributed and/or modified under the +conditions of the LaTeX Project Public License, version 1.3a. +This version is obtainable at +http://www.latex-project.org/lppl/lppl-1-3a.txt + +^^J\noexpand\noexpand\noexpand\NeedsTeXFormat{LaTeX2e}^^J\noexpand\noexpand\noexpand\ProvidesPackage{\noexpand\expandafter\noexpand\dropext\outFileName\relax}[\VERSION] +\endpreamble + +\generate{% + \file{thmtools.sty}{\from{thmtools.dtx}{thmtools}} + \file{thm-restate.sty}{\from{thm-restate.dtx}{restate}} + \file{thm-patch.sty}{\from{thm-patch.dtx}{patch}} + \file{thm-autoref.sty}{\from{thm-autoref.dtx}{autoref}} + \file{thm-listof.sty}{\from{thm-listof.dtx}{listof}} + \file{thm-kv.sty}{\from{thm-kv.dtx}{kv}} + \file{parseargs.sty}{\from{parseargs.dtx}{parseargs}} + \file{aliasctr.sty}{\from{aliasctr.dtx}{code}} + \file{unique.sty}{\from{unique.dtx}{code}} + \file{thm-amsthm.sty}{\from{thm-amsthm.dtx}{amsthm}} + \file{thm-ntheorem.sty}{\from{thm-ntheorem.dtx}{ntheorem}} + \file{thm-beamer.sty}{\from{thm-beamer.dtx}{beamer}} + \file{thm-llncs.sty}{\from{thm-llncs.dtx}{llncs}} + \file{thmdef-shaded.sty}{\from{thmdef-shaded.dtx}{shaded}} + \file{thmdef-thmbox.sty}{\from{thmdef-thmbox.dtx}{thmbox}} + \file{thmdef-mdframed.sty}{\from{thmdef-mdframed.dtx}{mdframed}} + } +\Msg{*********************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the} +\Msg{* following files into a directory searched by TeX:} +\Msg{*} +\Msg{* \space\space thmtools.sty} +\Msg{* \space\space thm-restate.sty} +\Msg{* \space\space thm-patch.sty} +\Msg{* \space\space thm-autoref.sty} +\Msg{* \space\space thm-listof.sty} +\Msg{* \space\space thm-kv.sty} +\Msg{* \space\space aliasctr.sty} +\Msg{* \space\space unique.sty} +\Msg{* \space\space parseargs.sty} +\Msg{*} +\Msg{* Happy TeXing!} +\Msg{*********************************************************} +\endbatchfile diff --git a/macros/latex/exptl/thmtools/thmtools.pdf b/macros/latex/exptl/thmtools/thmtools.pdf Binary files differnew file mode 100644 index 0000000000..5ab3fd1d69 --- /dev/null +++ b/macros/latex/exptl/thmtools/thmtools.pdf diff --git a/macros/latex/exptl/thmtools/unique.dtx b/macros/latex/exptl/thmtools/unique.dtx new file mode 100644 index 0000000000..9afbd2cffa --- /dev/null +++ b/macros/latex/exptl/thmtools/unique.dtx @@ -0,0 +1,173 @@ +% \iffalse meta-comment +% +% Copyright (C) 2005-8 by Ulrich M. Schwarz +% +% This file may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3a. +% The license can be obtained from +% http://www.latex-project.org/lppl/lppl-1-3a.txt +% +% \fi +% +%\iffalse +%<*code> +%\fi +% Two macros are provided: |\setuniqmark| takes a single parameter, +% the name, which should be a string of letters. |\ifuniqmark| takes +% three parameters: a name, a true-part and a false-part. The true +% part is executed if and only if there was exactly one call to +% |\setuniqmark| with the given name during the previous \LaTeX\ run. +% +% Example application: legal documents are often very strongly numbered. +% However, if a section has only a single paragraph, this paragraph is +% not numbered separately, this only occurs from two paragraphs onwards. +% +% It's also possible to not-number the single theorem in your paper, but +% fall back to numbering when you add another one. +% +% \StopEventually{} +% +% \begin{macrocode} + +\DeclareOption{unq}{% + \newwrite\uniq@channel + \InputIfFileExists{\jobname.unq}{}{}% + \immediate\openout\uniq@channel=\jobname.unq + \AtEndDocument{% + \immediate\closeout\uniq@channel% + } +} +\DeclareOption{aux}{% + \let\uniq@channel\@auxout +} + +% \end{macrocode} +% +% +% \iffalse $Id: unique.dtx,v 1.4 2010/04/25 19:37:46 ulmi Exp $\fi +% \begin{macro}{\setuniqmark} +% Call this with a name to set the corresponding uniqmark. The name must +% be suitable for |\csname|-constructs, i.e. fully expansible to a +% string of characters. If you use some counter values to generate this, +% it might be a good idea to try and use hyperref's |\theH...| macros, +% which have similar restrictions. You can check whether a particular +% |\setuniqmark| was called more than once during \emph{the last run} +% with |\ifuniq|. +% \begin{macrocode} +\newcommand\setuniqmark[1]{% + \expandafter\ifx\csname uniq@now@#1\endcsname\relax + \global\@namedef{uniq@now@#1}{\uniq@ONE}% + \else + \expandafter\ifx\csname uniq@now@#1\endcsname\uniq@MANY\else + \immediate\write\uniq@channel{% + \string\uniq@setmany{#1}% + }% + \ifuniq{#1}{% + \uniq@warnnotunique{#1}% + }{}% + \fi + \global\@namedef{uniq@now@#1}{\uniq@MANY}% + \fi +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifuniq} +% Companion to |\setuniqmark|: if the uniqmark given in the first +% argument was called more than once, execute the second argument, +% otherwise execute the first argument. Note than no call to +% |\setuniqmark| for a particular uniqmark at all means that this +% uniqmark is unique. +% +% This is a lazy version: we could always say false if we already had two calls +% to setuniqmark this run, but we have to rerun for any ifuniq prior +% to the first setuniqmark anyway, so why bother? +% \begin{macrocode} +\newcommand\ifuniq[1]{% + \expandafter\ifx\csname uniq@last@#1\endcsname\uniq@MANY + \expandafter \@secondoftwo + \else + \expandafter\@firstoftwo + \fi +} +% \end{macrocode} +% \end{macro} +% +% Two quarks to signal if we have seen an uniqmark more than once. +% \begin{macrocode} +\def\uniq@ONE{\uniq@ONE} +\def\uniq@MANY{\uniq@MANY} +% \end{macrocode} +% Flag: suggest a rerun? +% \begin{macrocode} +\newif\if@uniq@rerun +% \end{macrocode} +% +% Helper macro: a call to this is written to the .aux file when we see +% an uniqmark for the second time. This sets the right information for +% the next run. It also checks on subsequent runs if the number of +% uniqmarks drops to less than two, so that we'll need a rerun. +% \begin{macrocode} +\def\uniq@setmany#1{% + \global\@namedef{uniq@last@#1}{\uniq@MANY}% + \AtEndDocument{% + \uniq@warnifunique{#1}% + }% +} +% \end{macrocode} +% +% Warning if something is unique now. This always warns if the +% setting for this run is not ``many'', because it was generated +% by a setmany from the last run. +% \begin{macrocode} +\def\uniq@warnifunique#1{% + \expandafter\ifx\csname uniq@now@#1\endcsname\uniq@MANY\else + \PackageWarningNoLine{uniq}{% + `#1' is unique now.\MessageBreak + Rerun LaTeX to pick up the change% + }% + \@uniq@reruntrue + \fi +} +% \end{macrocode} +% +% Warning if we have a second uniqmark this run around. Since this is +% checked immediately, we could give the line of the second +% occurence, but we do not do so for symmetry. +% \begin{macrocode} +\def\uniq@warnnotunique#1{% + \PackageWarningNoLine{uniq}{% + `#1' is not unique anymore.\MessageBreak + Rerun LaTeX to pick up the change% + }% + \@uniq@reruntrue +} +% \end{macrocode} +% +% Maybe advise a rerun (duh!). This is executed at the end of the +% second reading of the aux-file. If you manage to set uniqmarks +% after that (though I cannot imagine why), you might need reruns +% without being warned, so don't to that. +% \begin{macrocode} +\def\uniq@maybesuggestrerun{% + \if@uniq@rerun + \PackageWarningNoLine{uniq}{% + Uniquenesses have changed. \MessageBreak + Rerun LaTeX to pick up the change% + }% + \fi +} +% \end{macrocode} +% +% Make sure the check for rerun is pretty late in processing, so it +% can catch all of the uniqmarks (hopefully). +% \begin{macrocode} +\AtEndDocument{% + \immediate\write\@auxout{\string\uniq@maybesuggestrerun}% +} +\ExecuteOptions{aux} +\ProcessOptions\relax +% \end{macrocode} +%\iffalse +%</code> +%\fi |