diff options
Diffstat (limited to 'macros/latex/exptl/thmtools/thm-kv.dtx')
-rw-r--r-- | macros/latex/exptl/thmtools/thm-kv.dtx | 486 |
1 files changed, 486 insertions, 0 deletions
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 |