diff options
author | Karl Berry <karl@freefriends.org> | 2012-10-18 22:48:27 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-10-18 22:48:27 +0000 |
commit | b0e15470dc26b571d82f3998008a0936f8e3a597 (patch) | |
tree | 65059d813205a97e4af7602ed6c3826db063e4c5 /Master/texmf-dist/tex/latex/keyreader/keyreader.sty | |
parent | e828c375ba40d5ea05fd4cf79482c15d56c28789 (diff) |
keyreader (12oct12)
git-svn-id: svn://tug.org/texlive/trunk@28020 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/keyreader/keyreader.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/keyreader/keyreader.sty | 669 |
1 files changed, 473 insertions, 196 deletions
diff --git a/Master/texmf-dist/tex/latex/keyreader/keyreader.sty b/Master/texmf-dist/tex/latex/keyreader/keyreader.sty index 782d3db2354..e30f0dcaf02 100644 --- a/Master/texmf-dist/tex/latex/keyreader/keyreader.sty +++ b/Master/texmf-dist/tex/latex/keyreader/keyreader.sty @@ -1,6 +1,5 @@ %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% -% % -% This is file 'keyreader.sty', version 0.4b, January 2012. % +% This is file 'keyreader.sty', version 0.5, October 2012. % % % % This package and accompanying files may be distributed and/or % % modified under the conditions of the LaTeX Project Public License, % @@ -17,14 +16,14 @@ % purpose. % % % % Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). % -% % %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \ProvidesPackage{keyreader} - [2012/01/14 v0.4b Robust interfaces to xkeyval package (AM)] + [2012/10/10 v0.5 Robust interfaces to xkeyval package (AM)] +\newdimen\krdz@ \ifcase - \ifx\eTeXversion\@undefined\z@\else - \ifnum\eTeXversion<\tw@\z@\else\@ne\fi\fi + \ifx\eTeXversion\@undefined\krdz@\else + \ifnum\eTeXversion<\tw@\krdz@\else\@ne\fi\fi \PackageError{keyreader} {eTeX not loaded or old version} {This package requires eTeX version 2 or higher.}% @@ -38,7 +37,7 @@ \catcode044 12% , \def\reserved@a{\endgroup \def\do##1,{% - \ifx##1\end\else + \ifx\end##1\else \catcode##1\string=\the\catcode##1 % \expandafter\do \fi @@ -53,7 +52,7 @@ \catcode061 12% = \catcode044 12% , \def\do#1=#2,{% - \ifx#1\end\else + \ifx\end#1\else \edef\krd@restorecodes{% \krd@restorecodes \catcode#1=\the\catcode#1 % @@ -64,34 +63,67 @@ } \do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,% 059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\end=,% + \AtEndOfPackage{% \krdAfterEndPackage{% \krd@restorecodes - \let\krd@restorecodes\@undefined + \let\krd@restorecodes\relax }% } -\RequirePackage{xkeyval}[2008/08/13] + +\ifx\XKeyValLoaded\endinput\else + \input xkeyval +\fi +\let\XKV@doxs\relax + +\let\krd@err\@latex@error +\def\krd@ehd{% + There is a problem here. Investigate it before + \MessageBreak proceeding. Try typing <return> + to proceed.\MessageBreak If that doesn't work, + type X <return> to quit. +} \def\@space{ } -\protected\def\krdnewlet#1{\@ifdefinable#1\relax\let#1} +\protected\def\krdnewlet#1{\@ifdefinable{#1}\relax\let#1= } \krdnewlet\krd@nil\relax \def\krd@nnil{\krd@nil} \def\krdswap#1#2{#2#1} \def\krd@quark{\@gobble\krd@quark} \newcount\krd@csvdepth -\newif\ifkrdloopbreak +\newif\ifkrd@foreach@break \newif\ifkrd@st -\newif\ifkrddef -\krdnewlet\krdloopbreak\krdloopbreaktrue +\newif\ifkrdindef +\long\def\krdifblank#1{% + \ifcat$\detokenize\expandafter{\@gobble#1.}$% + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} + \begingroup -\catcode`\&=7 +\catcode`\&=8 +\gdef\krdifledbyspace#1{\krd@ifledbyspace&& \trim@nil} +\gdef\krd@ifledbyspace& #2\trim@nil{% + \krdifblank{#2}\@secondoftwo\@firstoftwo +} \gdef\krdtrimspace#1{\krd@trimspace@a.#1& &} \gdef\krd@trimspace@a#1 &{\krd@trimspace@b#1&} \gdef\krd@trimspace@b#1{% - \krdexpandonce{\romannumeral-`\q\expandafter\noexpand\@gobble#1}% + \krdexpandonce{% + \romannumeral-`\q + \expandafter\krdifledbyspace\expandafter{\@gobble#1}% + {\expandafter\noexpand\@gobble#1}{\expandafter\@space\@gobble#1}% + }% } \endgroup + +\def\krdzapspace#1{\krd@zapspace#1 \zap@nil} +\def\krd@zapspace#1 #2\zap@nil{% + \krdifblank{#2}{#1}{% + \krd@zapspace#1#2\zap@nil + }% +} + \protected\def\krdAfterEndPackage{% - \krdifcsndef{\@currname.\@currext-krd@endpkghook}{}{% + \krdifcsdef{\@currname.\@currext-krd@endpkghook}{}{% \@namedef{\@currname.\@currext-krd@endpkghook}{}% }% \expandafter\g@addto@macro @@ -119,7 +151,7 @@ \fi }% } -\newcommand*\krdifcsndef[1]{% +\newcommand*\krdifcsdef[1]{% \krdifblank{#1}{% \expandafter\@secondoftwo\@gobble }{% @@ -138,19 +170,15 @@ \ifx#1#2\krd@ifx@quark \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } -\long\def\krdifblank#1{% - \ifcat$\detokenize\expandafter{\@gobble#1.}$% - \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi -} \def\krdifbool#1{% \krdifblank{#1}{% - \@secondoftwo + \krd@err{No boolean}\krd@ehd }{% - \krdifcsndef{if#1}{% + \krdifcsdef{if#1}{% \csname @\csname if#1\endcsname first\else second\fi oftwo\endcsname }{% - \@latex@error{Undefined boolean '#1'}\@ehc + \krd@err{Undefined boolean '#1'}\krd@ehd }% }% } @@ -164,14 +192,15 @@ \expandafter\krd@ifswitch@aux\romannumeral-`\q#1\krd@nil{% \if#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi }{% - \@latex@error{Invalid switch '#1'}\@ehc + \krd@err{Invalid switch '#1'}\krd@ehd }% }% } \krdifx\pdfstrcmp\@undefined{% \RequirePackage{pdftexcmds}% \krdifx\pdf@strcmp\@undefined{% - \cpt@err{Neither '\string\pdfstrcmp' nor '\string\pdf@strcmp' exists}\@ehc + \krd@err{Neither '\string\pdfstrcmp' nor + '\string\pdf@strcmp' exists}\krd@ehd }{% \let\krd@pdfstrcmp\pdf@strcmp }% @@ -201,8 +230,13 @@ \def\krd@ifbraced@d#1\krd@nil#2{% \krdifstrcmp{#1}{#2}\@secondoftwo\@firstoftwo } + +\def\krdoxdetok#1{\detokenize\expandafter{#1}} +\def\krdusearg#1#2{% + \expandafter\krdswap\expandafter{\expandafter{#2}}{#1}% +} \def\krdexpandonce#1{\unexpanded\expandafter{#1}} -\def\krdnoexpandcsn#1{\krdexpandonce{\csname#1\endcsname}} +\def\krdnoexpandcs#1{\krdexpandonce{\csname#1\endcsname}} \protected\def\krdexpanded#1{% \begingroup \protected@edef\reserved@a{\endgroup#1}\reserved@a @@ -215,6 +249,16 @@ \protected\def\krdexpandsecondonce#1#2{% \krdexpanded{\unexpanded{#1}\krdexpandonce{#2}}% } +\protected\def\krdifescaped#1{% + \begingroup + \escapechar92\relax + \edef\x{\expandafter\@car\string#1x\@nil}% + \expandafter\endgroup + \csname @\ifx\x\@backslashchar first\else second\fi oftwo\endcsname +} +\def\krdifcond#1\fi{% + \csname @#1first\else second\fi oftwo\endcsname +} % Eg, % \newcount\nr\nr=\tw@ % \def\do#1{% @@ -224,6 +268,7 @@ % } % \edef\x{\krdfor{\cmda,\cmdb}} % \show\x -> \let\cmda\cmda@ii \let\cmdb\cmdb@ii +% \def\krdfor#1{\krd@for@a#1,\krd@nnil,\krd@nil} \def\krd@for@a#1,#2\krd@nil{% \krdifblank{#1}{% @@ -234,14 +279,16 @@ }% } % We redefine xkeyval's loops to increase robustness. -% We can't replace \@nil by \krd@nil here because xkeyval -% uses \@nil in calling these macros: +% We can't replace \@nil by \krd@nil here because xkeyval uses \@nil +% to terminate the loops. \protected\long\def\XKV@for@n#1#2#3{% \edef#2{\unexpanded{#1}}% \krdifx#2\@empty{}{% \XKV@f@r#2{#3}#1,\@nil,% }% } +\let\krdcommaloop\XKV@for@n +\let\krdecommaloop\XKV@for@o \protected\long\def\XKV@f@r#1#2#3,{% \edef#1{\unexpanded{#3}}% \krdifx#1\@nnil{}{#2\XKV@f@r#1{#2}}% @@ -277,64 +324,75 @@ \edef#1{\unexpanded{#2}}% \krdcsvnormalize#1% } -\def\krd@loopdo@stack{} -\protected\def\krd@pushloopdo{% - \global\advance\krd@csvdepth\@ne - \def\reserved@a##1{\expandafter\@gobble\string##1@% - \romannumeral\krd@csvdepth}% - \def\do##1{\let\noexpand##1\krdnoexpandcsn{\reserved@a{##1}}}% - \xdef\krd@loopdo@stack{% - \krdfor{\krd@loopdo,\ifkrdloopbreak,\krd@final@loopact,% - \krd@regular@loopact}% - {\krdexpandonce\krd@loopdo@stack}% - }% - \def\do##1{\let\krdnoexpandcsn{\reserved@a{##1}}\noexpand##1}% - \krdexpanded{% - \krdfor{\krd@loopdo,\ifkrdloopbreak,\krd@final@loopact,% - \krd@regular@loopact}% - }% + +\protected\def\krd@pushmacros#1#2#3{% + \begingroup + \global\advance#2\@ne + \krdifdef#1{}{\def#1{}}% + \def\reserved@a##1{\expandafter\@gobble\string##1@\romannumeral#2}% + \def\do##1{\let\noexpand##1\krdnoexpandcs{\reserved@a{##1}}}% + \xdef#1{#3{\krdexpandonce#1}}% + \def\do##1{\let\krdnoexpandcs{\reserved@a{##1}}\noexpand##1}% + \krdexpanded{\endgroup#3}% } -\protected\def\krd@poploopdo{% +\protected\def\krd@popmacros#1#2{% \begingroup - \def\reserved@a##1##{\endgroup##1\gdef\krd@loopdo@stack}% - \expandafter\reserved@a\krd@loopdo@stack - \global\advance\krd@csvdepth\m@ne + \def\reserved@a##1##{\endgroup##1\gdef#1}% + \expandafter\reserved@a#1% + \global\advance#2\m@ne } + \protected\def\krd@testst#1{\@ifstar{\krd@sttrue#1}{\krd@stfalse#1}} -% \krdlistloop[<parser>]{<list>}<\if...>\fi<ini-code><final-code><reg-code> -% When the conditional <\if...> isn't true, the regular code <reg-code> -% will be executed for every member of the list. -% <final-code> will be executed when the conditional <\if...> is true. -% <ini-code> may be used to first turn <\if...> off before commencing -% the loop. \ifkrdloopbreak may be used as the conditional in <\if...>. -% Both <ini-code> and <final-code> can be empty (ie, {}). -% Use '#1' in <final-code> and <reg-code> to access the current element -% of the list. -\protected\def\krdlistloop{\krd@testst{\@testopt\krd@listloop,}} -\protected\def\krd@listloop[#1]#2#3\fi#4#5#6{% - \krd@pushloopdo - \edef\krd@csvarg{\krdifbool{krd@st}\krdexpandonce\unexpanded{#2}}% - \krdcsvnormalize[#1]\krd@csvarg - \def\krd@final@loopact##1{#5}% - \def\krd@regular@loopact##1{#6}% +% \krdforeach[<parser>] +% {<list>}<\if...>\fi{<ini-code>}{<final-code>}{<reg-code>} +% \krdforeach*[<parser>] +% {<listcmd>}<\if...>\fi{<ini-code>}{<final-code>}{<reg-code>} +% +% 1. When the conditional <\if...> isn't true, the regular code <reg-code> +% will be executed for every member of the list. +% 2. <final-code> will be executed when the conditional <\if...> is true. +% <ini-code> may be used to first turn <\if...> off before commencing +% the loop. \ifkrd@foreach@break may be used as the conditional in +% <\if...>. +% 3. Both <ini-code> and <final-code> can be empty (ie, {}). +% 4. Use '#1' in <final-code> and <reg-code> to access the current element +% of the list. +% +\protected\def\krdforeach{\krd@testst{\@testopt\krd@foreach,}} +\protected\def\krd@foreach[#1]#2#3\fi#4#5#6{% + \krd@pushmacros\krd@foreach@stack\krd@csvdepth{% + \do\krd@foreach@do\do\krd@foreach@final\do\krd@foreach@regular + \do\stopforeach + }% + \edef\krd@foreach@item{\krdifbool{krd@st}\krdexpandonce\unexpanded{#2}}% + \krdcsvnormalize[#1]\krd@foreach@item + \def\krd@foreach@final##1{#5}% + \def\krd@foreach@regular##1{#6}% + \krd@foreach@breakfalse + \let\stopforeach\krd@foreach@breaktrue % Initial code: #4\relax - \def\krd@loopdo##1#1##2\krd@nnil{% - \edef\krd@csvarg{\krdexpandonce{\@gobble##1}}% - \krdifx\krd@csvarg\krd@nnil{}{% - #3\relax - \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi - {% - \expandafter\krd@final@loopact\expandafter{\krd@csvarg}\relax + \def\krd@foreach@do##1#1##2\krd@nnil{% + \edef\krd@foreach@item{\krdexpandonce{\@gobble##1}}% + \krdifx\krd@foreach@item\krd@nnil{% + \krd@foreach@breakfalse + }{% + \krdifcond#3\fi{% + \expandafter\krd@foreach@final\expandafter{\krd@foreach@item}\relax }{% - \expandafter\krd@regular@loopact\expandafter{\krd@csvarg}\relax - \krd@loopdo.##2\krd@nnil + \expandafter\krd@foreach@regular\expandafter{\krd@foreach@item}\relax + \krdifbool{krd@foreach@break}{% + \krd@foreach@breakfalse + }{% + \krd@foreach@do.##2\krd@nnil + }% }% }% }% - \expandafter\krd@loopdo\expandafter.\krd@csvarg#1\krd@nil#1\krd@nnil - \krd@poploopdo + \expandafter\krd@foreach@do\expandafter + .\krd@foreach@item#1\krd@nil#1\krd@nnil + \krd@popmacros\krd@foreach@stack\krd@csvdepth } \protected\def\krdaddtolist{\krd@testst{\@testopt{\krd@addtolist{e}},}} \protected\def\krdgaddtolist{\krd@testst{\@testopt{\krd@addtolist{x}},}} @@ -461,16 +519,85 @@ \def\krd@remleadparser#1##1\krd@nil{\noexpand##1}% \def\krd@parserequalerr##1#1=##2\krd@nil{% \krdifblank{##2}{}{% - \@latex@error{There is '#1=' in your key-value list}\@ehc + \krd@err{There is '#1=' in your key-value list}\krd@ehd }% }% } \endgroup \krd@setupnormalize{,} + +% Filter class options to remove '=' and option values. Do this +% retroactively if this package was loaded before \documentclass. +% The keyreader package can be loaded before \documentclass. +\protected\def\XKV@filterclassoptions{% + \XKV@sgfalse + \ifx\@classoptionslist\@undefined\else + \ifx\@classoptionslist\relax\else + \ifx\@classoptionslist\@empty\else + \XKV@sgtrue + \fi + \fi + \fi + \ifXKV@sg + \let\XKV@filterclassoptions\relax + \let\XKV@origclassoptionslist\@classoptionslist + \let\XKV@classoptionslist\@classoptionslist + \def\@classoptionslist{}% + \XKV@for@o\XKV@classoptionslist\XKV@tempa{% + \@expandtwoargs\in@{=}{\krdoxdetok\XKV@tempa}% + \ifin@\else + \edef\@classoptionslist{% + \@classoptionslist\ifx\@classoptionslist\@empty\else,\fi + \unexpanded\expandafter{\XKV@tempa}% + }% + \fi + }% + \fi +} +\def\XKV@getdocumentclass{% + \let\XKV@documentclass\@undefined + \XKV@sgfalse + \ifdefined\@filelist + \ifx\@filelist\@gobble\else + \ifx\@filelist\relax\else + \ifx\@filelist\@empty\else + \XKV@sgtrue + \fi + \fi + \fi + \fi + \ifXKV@sg + \def\XKV@tempb{00}% + \XKV@whilist\@filelist\XKV@tempa\if\XKV@tempb\fi{% + \filename@parse\XKV@tempa + \ifx\filename@ext\@clsextension + \edef\XKV@tempa{\filename@area\filename@base.\filename@ext}% + \XKV@ifundefined{opt@\XKV@tempa}{}{% + \let\XKV@documentclass\XKV@tempa + \def\XKV@tempb{01}% + }% + \fi + }% + \fi +} +\XKV@getdocumentclass +\ifdefined\XKV@documentclass + \XKV@filterclassoptions +\else + \let\XKV@documentclass\@empty + \let\XKV@classoptionslist\@empty + \xdef\@popfilename{% + \unexpanded\expandafter{\@popfilename}% + \noexpand\XKV@filterclassoptions + }% +\fi + % Redefine \XKV@define@key to heed a complaint about the grabbing % of the callback: \protected\def\XKV@define@key#1{% - \@ifnextchar[{\XKV@d@fine@k@y{#1}}{% + \@ifnextchar[{% + \XKV@d@fine@k@y{#1}% + }{% \begingroup \toks1{\endgroup\@namedef{\XKV@header#1}####1}% \def\reserved@a{\the\toks\expandafter1\expandafter{\the\toks0}}% @@ -489,7 +616,7 @@ \begingroup\expandafter\endgroup\expandafter\XKV@tempa\expandafter {\expandafter\edef\csname#1#2\endcsname{\unexpanded{##1}}#4}% } -% Allow macro prefix (mp@) for choice keys: +% Allow macro prefix (default: mp@) for choice keys: \protected\def\define@choicekey{% \XKV@testopta{\XKV@testoptb {\@testopt\XKV@define@choicekey{choice\XKV@header}}}% @@ -509,7 +636,7 @@ \XKV@d@fine@ch@ic@key{#1}% } \def\XKV@d@fine@ch@ic@key#1{% - \edef\reserved@a{\krdnoexpandcsn{\XKV@header#1}}% + \edef\reserved@a{\krdnoexpandcs{\XKV@header#1}}% \krdifbool{XKV@pl}{% \expandafter\XKV@d@f@ne@ch@ic@k@y\reserved@a }{% @@ -520,7 +647,7 @@ \def\XKV@d@f@ne@ch@ic@k@y#1#2#3{\XKV@d@f@n@@ch@ic@k@y#1{{#2}{#3}}} \def\XKV@d@f@n@@ch@ic@k@y#1#2{% \edef#1##1{% - \edef\krdnoexpandcsn{\XKV@macropf}{\noexpand\unexpanded{##1}}% + \edef\krdnoexpandcs{\XKV@macropf}{\noexpand\unexpanded{##1}}% \ifXKV@st\noexpand\XKV@sttrue\else\noexpand\XKV@stfalse\fi \ifXKV@pl\noexpand\XKV@pltrue\else\noexpand\XKV@plfalse\fi \noexpand\XKV@checkchoice[\the\XKV@tempa@toks]{##1}{\the\XKV@toks}% @@ -551,7 +678,7 @@ \expandafter\XKV@g@tkeyname\XKV@tempa=\@nil\XKV@tempa \XKV@addtolist@x\XKV@naa\XKV@tempa }% - \ifnum\XKV@depth=\z@\let\XKV@rm\@empty\fi + \ifnum\XKV@depth=\krdz@\let\XKV@rm\@empty\fi \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{preseth}% \krdexpandsecond\krd@s@tkeys {{\krdexpandonce\XKV@resb}{\krdexpandonce\krd@na}}% @@ -593,7 +720,8 @@ \krdexpandargonce{\KV@@sp@def\XKV@tkey}\XKV@tkey \krdifx\XKV@tkey\@empty{% \krdifblank{#2}{}{% - \XKV@err{No key specified for value '\the\XKV@toks'}% + \krd@err{No key specified for value + \MessageBreak '\the\XKV@toks'}\krd@ehd }% }{% \@expandtwoargs\in@{,\XKV@tkey,}{,\XKV@na,}% @@ -628,7 +756,8 @@ \krdifbool{XKV@st}{% \XKV@addtolist@o\XKV@rm\CurrentOption }{% - \XKV@err{Key '\XKV@tkey' undefined in families '\XKV@fams'}% + \krd@err{Key '\XKV@tkey' is undefined in + families \MessageBreak '\XKV@fams'}\krd@ehd }% }% }{% @@ -642,7 +771,7 @@ }% } % When the key default value has doubled hash characters, -% then xkeyval's definition of \XKV@default fails: +% xkeyval's definition of \XKV@default fails: \protected\def\XKV@default#1#2\@nil{% \edef\XKV@tempa{\expandafter\@gobble\string#1}% \edef\XKV@tempb{\XKV@header\XKV@tkey}% @@ -654,7 +783,7 @@ }% \csname\XKV@header\XKV@tkey @default\endcsname \expandafter\endgroup\the\toks@ - \krdifcsndef{XKV@\XKV@header save}{% + \krdifcsdef{XKV@\XKV@header save}{% \expandafter\XKV@testsavekey\csname XKV@\XKV@header save\endcsname\XKV@tkey }{}% @@ -673,6 +802,32 @@ \XKV@srstate{}{@\romannumeral\XKV@depth}% }% } +\protected\def\XKV@replacepointers#1{% + \let\XKV@tempa\@empty + \let\XKV@resa\@empty + \XKV@r@placepointers#1\usevalue\@nil +} +\def\XKV@r@placepointers#1\usevalue#2{% + \XKV@addtomacro@n\XKV@tempa{#1}% + \edef\XKV@tempb{\unexpanded{#2}}% + \ifx\XKV@tempb\@nnil\else\XKV@afterfi + \XKV@ifundefined{XKV@\XKV@header#2@value}{% + \krd@err{No value has been recorded for key + \MessageBreak '#2'; pointer not replaced}\krd@ehd + \XKV@r@placepointers + }{% + \@expandtwoargs\in@{,\detokenize{#2},}{,\krdoxdetok\XKV@resa,}% + \ifin@\XKV@afterelsefi + \krd@err{Possible back linking of pointers; + \MessageBreak pointer replacement terminated}\krd@ehd + \else\XKV@afterfi + \XKV@addtolist@x\XKV@resa{#2}% + \expandafter\expandafter\expandafter\XKV@r@placepointers + \csname XKV@\XKV@header#2@value\endcsname + \fi + }% + \fi +} \protected\def\krdsetrmkeys{\XKV@testopta{\XKV@testoptc\krd@setrmkeys}} \protected\def\krd@setrmkeys[#1]{% \krdexpandargonce{\krd@setkeys[#1]}\XKV@rm @@ -686,30 +841,39 @@ \protected\def\krdpostsetkeys{\@testopt\krd@postsetkeys{KV}} \protected\def\krd@postsetkeys[#1]#2#3{\presetkeys[#1]{#2}{}{#3}} \protected\def\krd@disabledkey@err#1{% - \@latex@error{Key '#1' has been disabled} + \krd@err{Key '#1' has been disabled} {You can't set or reset key '#1' at this\MessageBreak late stage. Perhaps you should have set it \MessageBreak earlier in \string\documentclass\@space or \string\usepackage}% } \protected\def\krddisablekeys{\XKV@testoptb\krd@disablekeys} \protected\def\krd@disablekeys#1{% - \def\krd@tempa{#1}% - \krdcsvnormalize\krd@tempa - \XKV@for@o\krd@tempa\krd@tempa{% - \krdifcsndef{\XKV@header\krd@tempa}{}{% - \@latex@warning@no@line{Key '\krd@tempa' is undefined: + \def\XKV@tempa{#1}% + \krdcsvnormalize\XKV@tempa + \XKV@for@o\XKV@tempa\XKV@tempa{% + \krdifcsdef{\XKV@header\XKV@tempa}{}{% + \@latex@warning@no@line{Key '\XKV@tempa' is undefined: couldn't be disabled}% }% - \krdifcsndef{\XKV@header\krd@tempa @default}{% - \edef\krd@tempb{\noexpand\XKV@define@key{\krd@tempa}[]}% + \krdifcsdef{\XKV@header\XKV@tempa @default}{% + \edef\XKV@tempb{\noexpand\XKV@define@key{\XKV@tempa}[]}% }{% - \edef\krd@tempb{\noexpand\XKV@define@key{\krd@tempa}}% + \edef\XKV@tempb{\noexpand\XKV@define@key{\XKV@tempa}}% }% - \krdexpandarg{\expandafter\krd@tempb\expandafter}% - {\krd@disabledkey@err{\krd@tempa}}% + \krdexpandarg{\expandafter\XKV@tempb\expandafter}% + {\krd@disabledkey@err{\XKV@tempa}}% }% } \edef\krd@hashchar{\string#} + +% \krddefinekeys[<pref>]{<fam>}[<mp>]{ +% ord/<key>/<dft>/<f1>; +% cmd/<key>/<dft>/<f1>; +% bool/<key>/<dft>/<f1>; +% bool+/<key>/<dft>/<f1>/<f2>; +% choice/<key>/<dft>/<alt>/<f1>; +% choice+/<key>/<dft>/<alt>/<f1>/<f2>; +% } \protected\def\krddefinekeys{% \begingroup \endlinechar\m@ne @@ -720,146 +884,186 @@ } \protected\def\krd@d@finekeys#1#2[#3]#4{% \expandafter\endgroup - \ifkrd@st - \def\krd@keyst{00}% - \else - \def\krd@keyst{01}% - \fi - \krddeftrue + \edef\krd@keyst{0\ifkrd@st0\else1\fi}% + \krdindeftrue \begingroup - \edef\key@prefix{\krdtrimspace{#1}}% - \edef\key@family{\krdtrimspace{#2}}% - \edef\macro@prefix{\krdtrimspace{#3}}% + \edef\krd@prefix{\krdtrimspace{#1}}% + \edef\krd@family{\krdtrimspace{#2}}% + \edef\krd@macpref{\krdtrimspace{#3}}% \toks@{}% \def\krd@rej{^?^}% - \def\key@vals{}% - \def\krd@altlista{}% - \def\krd@altlistb{}% + \def\krd@vals{}% + \def\krd@altlist@a{}% + \def\krd@altlist@b{}% \def\krd@splita##1/##2/{\krd@splitb##1/##2/.}% - \def\krd@splitb##1/##2/##3/##4/##5/##6\krd@nil{% - \edef\key@type{\krdtrimspace{##1}}% - \edef\key@name{\krdtrimspace{##2}}% + \def\krd@splitb##1/##2/##3/##4/##5/##6/##7/##8/##9\krd@nil{% + \edef\krd@type{\krdzapspace{##1}}% + \edef\krd@name{\krdtrimspace{##2}}% + \edef\krd@default{\krdusearg\krdtrimspace{\@gobble##3}}% + \edef\krd@itemfour{\krdtrimspace{##4}}% + \edef\krd@itemfive{\krdtrimspace{##5}}% + \edef\krd@itemsix{\krdtrimspace{##6}}% \@expandtwoargs\in@{\krd@hashchar}{\detokenize{##2}}% \ifin@ - \@latex@error{Bad key name '\detokenize{##2}'}\@ehc + \krd@err{Bad key name '\detokenize{##2}'}\krd@ehd \fi \if\krd@keyst - \krdifcsndef{\key@prefix @\key@family @##2}{% - \@latex@error{Key '##2' already exists in - family '\key@family'}\@ehc + \krdifcsdef{\krd@prefix @\krd@family @##2}{% + \krd@err{Key '##2' already exists in + family '\krd@family'}\krd@ehd }{}% \fi - \@expandtwoargs\in@{,\detokenize\expandafter{\key@type},}% - {,\detokenize{ord,cmd,bool,choice},}% + \@expandtwoargs\in@ + {,\krdoxdetok\krd@type,} + {,\detokenize{ord,cmd,bool,bool+,choice,choice+},}% \ifin@\else - \@latex@error{Unknown key type '\key@type'}\@ehc + \krd@err{Unknown key type '\krd@type'}\krd@ehd \fi - \edef\key@default{\expandafter\krdtrimspace\expandafter{\@gobble##3}}% - \edef\krd@resa{\krdtrimspace{##4}}% - \edef\krd@resb{\krdtrimspace{##5}}% - \@expandtwoargs\in@{,\detokenize\expandafter{\key@default},}% - {,\detokenize{true,false},}% - \edef\key@vals{% - \ifx\key@vals\@empty\else\krdexpandonce\key@vals,\fi - \ifx\key@default\krd@rej\else - \key@name=\ifin@ false\else\krdexpandonce\key@default\fi + \@expandtwoargs\in@ + {,\krdoxdetok\krd@default,}{,\detokenize{true,false},}% + \edef\krd@vals{% + \ifx\krd@vals\@empty\else\krdexpandonce\krd@vals,\fi + \ifx\krd@default\krd@rej\else + \krd@name=\ifin@ false\else\krdexpandonce\krd@default\fi \fi }% - \def\reserved@a####1{% - \def\reserved@a########1####1########2########3\krd@nil{% - \def\key@typenr{########2}% - \ifx\key@typenr\krd@nnil - \@latex@error{Invalid key type '####1'}\@ehc - \fi + % ord{0}cmd{1}bool{2}bool+{3}choice{4}choice+{5} + \krdusearg\krd@gettypenr{\krd@type}% + \ifnum\krd@typenr>\thr@@ + \def\reserved@a{% + \krd@err{Empty nominations for choice key \krd@name}\krd@ehd }% - \reserved@a ord{0}cmd{1}bool{2}choice{3}####1{\krd@nil}\krd@nil - }% - \expandafter\reserved@a\expandafter{\key@type}% - \ifnum\key@typenr=\thr@@ - \edef\reserved@a{\unexpanded{##4}}% - \krdifx\reserved@a\@empty{% - \@latex@error{Empty alternate list for choice key \key@name}\@ehc - }{% - \krdifx\reserved@a\krd@rej{% - \@latex@error{Empty alternate list for choice key \key@name}\@ehc - }{% + \ifx\krd@itemfour\@empty + \reserved@a + \else + \ifx\krd@itemfour\krd@rej + \reserved@a + \else \krd@getaltlist{##4}% - }% - }% + \fi + \fi \fi \krdexpanded{% \toks@{\the\toks@ - \krdnoexpandcsn{define@\ifnum\key@typenr>\z@\key@type\fi key}% - \ifnum\key@typenr=\thr@@*\fi - \ifnum\key@typenr>\@ne+\fi - [\key@prefix]{\key@family}% - \ifnum\key@typenr>\z@[\macro@prefix]\fi - {\key@name}% - \ifnum\key@typenr=\thr@@ + \krdnoexpandcs{define@\krd@typefordef key}% + \ifnum\krd@typenr>\thr@@*\fi + \if\krd@plustype+\fi + [\krd@prefix]{\krd@family}% + \ifnum\krd@typenr>\krdz@[\krd@macpref]\fi + {\krd@name}% + \ifnum\krd@typenr>\thr@@ [\unexpanded{\krduserinput\krdorder}]% - {\krdexpandonce\krd@altlista}% + {\krdexpandonce\krd@altlist@a}% \fi - \krdifx\key@default\krd@rej{}{% - [{\expandafter\krdifbraced\expandafter{\key@default}% - {{{\krdexpandonce\key@default}}}{\krdexpandonce\key@default}}]% - }% - {% - \ifnum\key@typenr=\thr@@ - \krdifx\krd@resb\krd@rej{}{\unexpanded{##5}}% - \krd@executealt{########1}{\krdexpandonce\krd@altlistb}% + \ifx\krd@default\krd@rej\else\XKV@afterfi + [{\expandafter\krdifbraced\expandafter{\krd@default}% + {{{\krdexpandonce\krd@default}}}{\krdexpandonce\krd@default}}]% + \fi + {% callback1 + \ifnum\krd@typenr>\thr@@ + \ifx\krd@itemfive\krd@rej\else\krdexpandonce\krd@itemfive\fi + \krd@executealt{########1}{\krdexpandonce\krd@altlist@b}% \else - \krdifx\krd@resa\krd@rej{}{\unexpanded{##4}}% + \ifx\krd@itemfour\krd@rej\else\krdexpandonce\krd@itemfour\fi \fi }% - \ifnum\key@typenr>\@ne{\noexpand\krd@keyvalerr}\fi + \if\krd@plustype + {% + \ifnum\krd@typenr>\thr@@ + \ifx\krd@itemsix\krd@rej + \noexpand\krd@keyvalerr + \else + \krdexpandonce\krd@itemsix + \fi + \else + \ifx\krd@itemfive\krd@rej + \noexpand\krd@keyvalerr + \else + \krdexpandonce\krd@itemfive + \fi + \fi + }% + \fi }% }% }% - \edef\key@list{\unexpanded{#4}}% - \krdlistloop*[;]\key@list\ifx\end\@undefined\fi{}{}{% - \krd@splita##1/^?^/^?^/^?^/^?^/\krd@nil + \edef\krd@list{\unexpanded{#4}}% + % Don't normalize for slash, since double slash (meaning, eg, + % "no value") will be made one slash. + \krdforeach*[;]\krd@list\if01\fi{}{}{% + \krd@splita##1/^?^/^?^/^?^/^?^/^?^/^?^/^?^/\krd@nil }% \krdexpanded{\endgroup \the\toks@ - \noexpand\krdsetkeys[\key@prefix]% - {\key@family}{\krdexpandonce\key@vals}% + \noexpand\krdsetkeys[\krd@prefix]% + {\krd@family}{\krdexpandonce\krd@vals}% + }% + \krdindeffalse +} +\protected\def\krd@gettypenr#1{% + \def\reserved@a##1#1##2##3\krd@nil{% + \def\krd@typenr{##2}% + \ifx\krd@typenr\krd@nnil + \krd@err{Invalid key type '#1'}\krd@ehd + \else + \edef\krd@typefordef{% + % Using \numexpr will remove \relax, which is needed + % to stop \ifcase's search for number. + \ifcase\numexpr\krd@typenr\relax\or + cmd\or bool\or bool\or choice\or choice\fi + }% + \fi }% - \krddeffalse + \reserved@a ord{0}cmd{1}bool{2}bool+{3}choice{4}choice+{5}% + #1{\krd@nil}\krd@nil + \@expandtwoargs\in@{+\relax}{\krdoxdetok\krd@type\relax}% + \edef\krd@plustype{0\ifin@ 0\else 1\fi}% } \protected\def\krd@keyvalerr{% \krd@getinnoval - \@latex@error{Erroneous value '\krd@ival' for key or option - \MessageBreak'\XKV@tkey'}{Invalid key value encountered.}% + \krd@err{Erroneous value '\krd@ival' + \MessageBreak for key or option '\XKV@tkey'} + {Invalid value for key '\XKV@tkey'.}% } \protected\def\krd@getaltlist#1{% - \def\krd@g@taltlist##1.do=##2\krd@nil{% - \edef\krd@tempa{\krdtrimspace{##1}}% - \edef\krd@tempb{\detokenize\expandafter{\krd@tempa}{\krdtrimspace{##2}}}% - \krdaddtolist*\krd@altlista\krd@tempa - \krdaddtolist*\krd@altlistb\krd@tempb - }% - \krdlistloop[,]{#1}\ifx\end\@undefined\fi{}{}{% - \@expandtwoargs\in@{\detokenize{.do=}}{\detokenize{##1}}% - \krdifbool{in@}{% - \krd@g@taltlist##1\krd@nil - }{% - \krd@g@taltlist##1.do=\krd@nil + \begingroup + \def\krd@g@taltlist##1.do=##2.do=##3\krd@nil{% + \edef\XKV@tempa{\krdtrimspace{##1}}% + \edef\XKV@tempb{\krdoxdetok\XKV@tempa{\krdtrimspace{##2}}}% + \def\@do####1####2{% + \edef####1{% + \krdexpandonce####1\ifx####1\@empty\else,\fi + \krdexpandonce####2% + }% }% + \@do\krd@altlist@a\XKV@tempa + \@do\krd@altlist@b\XKV@tempb + }% + \def\do##1{% + \krd@g@taltlist##1.do=.do=\krd@nil }% + \krdfor{#1}% + \global\let\krd@altlist@a\krd@altlist@a + \global\let\krd@altlist@b\krd@altlist@b + \endgroup } \protected\def\krd@executealt#1#2{% \edef\reserved@a{\krdtrimspace{#1}}% - \edef\reserved@a{\detokenize\expandafter{\reserved@a}}% - \krdexpandsecond{\def\reserved@a##1}\reserved@a##2##3\krd@nil{% - \edef\reserved@a{\unexpanded{##2}}% - \krdifx\reserved@a\krd@nnil{% - \@latex@error{No alternate list match for key '\XKV@tkey'}\@ehc - }{% - ##2% + \edef\reserved@a{\krdoxdetok\reserved@a}% + \def\reserved@b##1{% + \def\reserved@a####1##1####2####3\krd@nil{% + \edef\reserved@a{\unexpanded{####2}}% + \krdifx\reserved@a\krd@nnil{% + \krd@err{No choice match for key '\XKV@tkey'}\krd@ehd + }{% + ####2% + }% }% + \reserved@a#2#1{\krd@nil}\krd@nil }% - \reserved@a#2#1{\krd@nil}\krd@nil + \krdusearg\reserved@b{\reserved@a}% } +\def\krd@lengthofival{20} \protected\def\krd@getinnoval{% \begingroup \def\reserved@a##1=##2=##3\krd@nil{% @@ -870,12 +1074,12 @@ \def\krd@ival{???}% }{% \def\krd@ival{}% - \@tempcnta\z@ + \@tempcnta\krdz@ \def\do##1{% \def\reserved@a{##1}% \krdifx\reserved@a\krd@nnil{}{% \advance\@tempcnta\@ne - \ifnum\@tempcnta<20\relax + \ifnum\@tempcnta<\krd@lengthofival\relax \edef\krd@ival{\krd@ival##1}% \expandafter\do \else @@ -890,11 +1094,84 @@ \def\noexpand\krd@ival{\krd@ival}% }% } +\def\XKV@testopte#1{% + \XKV@ifstar{\XKV@sttrue\XKV@t@stopte#1}{\XKV@stfalse\XKV@t@stopte#1}% +} +\def\XKV@t@stopte#1{\@testopt{\XKV@t@st@pte#1}{KV}} +\def\XKV@t@st@pte#1[#2]{% + \XKV@makepf{#2}% + \@ifnextchar<{\XKV@@t@st@pte#1}% + {\XKV@@t@st@pte#1<\@currname.\@currext>}% +} +\def\XKV@@t@st@pte#1<#2>{% + \XKV@sp@deflist\XKV@fams{#2}% + \@testopt#1{}% +} +\def\DeclareOptionX{% + \let\@fileswith@pti@ns\@badrequireerror + \XKV@ifstar\XKV@dox\XKV@d@x +} +\long\def\XKV@dox#1{\XKV@toks{#1}\edef\XKV@doxs{\the\XKV@toks}} +\def\XKV@d@x{\@testopt\XKV@@d@x{KV}} +\def\XKV@@d@x[#1]{% + \@ifnextchar<{\XKV@@@d@x[#1]}{\XKV@@@d@x[#1]<\@currname.\@currext>}% +} +\def\XKV@@@d@x[#1]<#2>#3{\@testopt{\define@key[#1]{#2}{#3}}{}} +\def\ExecuteOptionsX{\XKV@stfalse\XKV@plfalse\XKV@t@stopte\XKV@setkeys} +\def\ProcessOptionsX{\XKV@plfalse\XKV@testopte\XKV@pox} +\def\XKV@pox[#1]{% + \let\XKV@tempa\@empty + \XKV@inpoxtrue + \let\@fileswith@pti@ns\@badrequireerror + \edef\XKV@testclass{\@currname.\@currext}% + \ifx\XKV@testclass\XKV@documentclass + \let\@unusedoptionlist\XKV@classoptionslist + \XKV@ifundefined{ver@xkvltxp.sty}{}{% + \@onelevel@sanitize\@unusedoptionlist + }% + \else + \ifXKV@st + \def\XKV@tempb##1,{% + \def\CurrentOption{##1}% + \ifx\CurrentOption\@nnil\else + \XKV@g@tkeyname##1=\@nil\CurrentOption + \XKV@key@if@ndefined{\CurrentOption}{}{% + \XKV@useoption{##1}% + \XKV@addtolist@n\XKV@tempa{##1}% + }% + \expandafter\XKV@tempb + \fi + }% + \expandafter\XKV@tempb\XKV@classoptionslist,\@nil,% + \fi + \fi + \expandafter\XKV@addtolist@o\expandafter + \XKV@tempa\csname opt@\@currname.\@currext\endcsname + \def\XKV@tempb{\XKV@setkeys[#1]}% + \expandafter\XKV@tempb\expandafter{\XKV@tempa}% + \let\XKV@doxs\relax + \let\XKV@rm\@empty + \XKV@inpoxfalse + \let\@fileswith@pti@ns\@@fileswith@pti@ns + \AtEndOfPackage{\let\@unprocessedoptions\relax}% +} +\def\XKV@useoption#1{% + \def\XKV@resa{#1}% + \XKV@ifundefined{ver@xkvltxp.sty}{}{% + \@onelevel@sanitize\XKV@resa + }% + \@expandtwoargs\@removeelement{\XKV@resa}% + {\@unusedoptionlist}\@unusedoptionlist +} \krdnewlet\krdDeclareOption\DeclareOptionX \krdnewlet\krdExecuteOptions\ExecuteOptionsX \krdnewlet\krdProcessOptions\ProcessOptionsX +\krdDeclareOption[KV]<keyreader>{lengthofival}[20]{% + \edef\krd@lengthofival{\number#1}% +} \krdDeclareOption*{\PackageWarning{keyreader}{Unknown option '\CurrentOption' ignored}} +\krdExecuteOptions[KV]<keyreader>{lengthofival} \krdProcessOptions[KV]<keyreader>\relax \endinput |