diff options
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/keyreader/README | 38 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/keyreader/keyreader-guide.pdf | bin | 0 -> 240486 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/keyreader/keyreader-guide.tex | 213 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/keyreader/keyreader-guide.cfg | 38 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/keyreader/keyreader.sty | 655 |
5 files changed, 944 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/keyreader/README b/Master/texmf-dist/doc/latex/keyreader/README new file mode 100644 index 00000000000..a0626c718e1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/keyreader/README @@ -0,0 +1,38 @@ +This is the README file for the 'keyreader' package. + +AUTHOR + +Ahmed Musa + +VERSION + +Version 0.4, December 2011 + +SUMMARY + +The keyreader package provides commands for compactly defining and +initializing all types of key (ordinary, command, boolean, and choice). +Keys are automatically set/initialized as soon as they are defined. +It provides a compact and robust interface to the xkeyval package. +The xkeyval package's commands for setting keys are made more robust, +in the sense that outer braces in key values are preserved throughout +parsing. In the case of choice keys, each admissible value of the key +can be associated with a callback, unlike in the xkeyval package. + +The keyreader package has been used as a development platform for the +ltxkeys package because the xkeyval package, on which the keyreader +package is based, has been quite stable for some years (its inherent +shortcomings not withstanding). + +LICENSE + +Copyright (c) 2011 Ahmed Musa. + +This software is author-maintained. Permission is granted to copy, +distribute and/or modify this software under the terms of the +LaTeX Project Public License, version 1.3 or higher. This software +is provided 'as it is', without warranty of any kind, either +expressed or implied, including, but not limited to, the implied +warranties of merchantability and fitness for any particular purpose. + +% End of file
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.pdf b/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.pdf Binary files differnew file mode 100644 index 00000000000..23c6662cab0 --- /dev/null +++ b/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.pdf diff --git a/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.tex b/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.tex new file mode 100644 index 00000000000..86a969ec46e --- /dev/null +++ b/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.tex @@ -0,0 +1,213 @@ +\documentclass[ + use-a4-paper, + use-10pt-font, + final-version, + use-UK-English, + fancy-section-headings, + frame-section-numbers, + para-abstract-style, + inputfile, + input-config-file, + no-hyperref-messages, + wrapquote +]{amltxdoc} + +\makeatletter +\hfuzz1pt\vfuzz2pt +\makeindex +\WrapQuotes +\AfterAfterStartOfDocument{% + \def\amd@sectitlefmt{\centering\Large\sffamily\color{secheadcolor}}% +} +\let\footnote\ltsfootnote +\extrarowheight=2pt +\arrayrulecolor{yellow} + +\begin{document} + +\begin{frontmatter} +\title{The \texttt{\color{blue}keyreader} Package\titleref{t1,t2}} +\titlenotes[t1,t2]{% + The package is available at \url{\titleurltext}.\sep + This user manual corresponds to version~0.4 of the package. +} +\subtitle{A robust interface to \pkg'{xkeyval}} +\titleurl{http://mirror.ctan.org/macros/latex/contrib/keyreader/} +\author{Ahmed Musa\authorref{a1}} +\authornotes[a1]{% + The University of Central Lancashire, Preston, UK. \email{amusa22@gmail.com}. +} +\def\abstractname{\textsf{Summary}} +\begin{abstract} + \small + The \pkg'{keyreader} provides robustness and some extensions to the \pkg'{xkeyval}. It preserves braces in key values and saves estate when defining keys. Also, keys are initialized as soon as they are defined, and, unlike in the \pkg'{xkeyval}, admissible alternate values of choice keys can have individual callbacks. This user manual assumes that the reader is familiar with some of the functions and user interfaces of the \pkg'{xkeyval}. +\end{abstract} + +\let\licensename\relax +\begin{license} +\xwmcolorbox[textalign=justified,outerframecolor=blue,innerframecolor=orange,width=.985\hsize]{% + This work (\ie, all the files in the \pkg'{keyreader} bundle) may be distributed and/or modified under the conditions of the \lppl, either version~1.3 of this license or any later version. + \endgraff + The \lppl maintenance status of this software is \quoted{author-maintained}. This software is provided \quoted{as it 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. + \endgraf + \centerline{\makered{\CopyrightYear}}\vspace{-.8\baselineskip}\relax +} +\end{license} +\end{frontmatter} + +\begingroup +\normalcolor\normalfont +\hrule +\vskip 1ex plus 1pt minus 1pt +\def\contentsname{\centerline{\Large\sffamily\textcolor{blue}{Contents}}}% +\hypersetup{linkcolor=blue}\tableofcontents +\hrule +\endgroup + +\vspace{3\baselineskip} +\newpage +\docsection(sec:motivation){Motivation} + +The \pkg'{keyreader} predated the \pkg'{ltxkeys} and was developed to make key parsing by the \pkg'{xkeyval} robust (in the sense of preserving outer braces in key values throughout parsing), as well as reduce the amount of typing that is required for defining several keys. To achieve robustness in key parsing, the \fx{\setkeys} command of the \pkg'{xkeyval} has been patched. The \pkg'{keyreader} provides commands for compactly defining and setting all types of key (ordinary, command, boolean, and choice). Also, the \pkg'{keyreader} introduces the concept of callbacks for the alternate/admissible values of choice keys. Moreover, keys are automatically set/initialized as soon as they are defined. This provides default definitions for the key macros and functions. Boolean keys are initialized with a value of \hx{false} irrespective of their default values. + +The \pkg'{keyreader} has been used as a development platform for the \pkg'{ltxkeys} because the \pkg'{xkeyval}, on which the \pkg'{keyreader} is based, has been quite stable for some years, its inherent +shortcomings not withstanding. Because the \pkg'{keyreader} is based on the \pkg'{xkeyval}, it inherits some of the limitations of the \pkg'{xkeyval}. Has the user ever tried to pass to \pkg'{xkeyval}'s \fx{\setkeys} an unbalanced conditional (\eg, \hhx{\iftrue,\iffalse,\ifx}, or \hx{\fi}) as the value of a key? He/she will quickly be hit by the error message \quoted{! Incomplete \hx{\ifx}; all text was ignored after line \ldots}, or something similar. The same limitation applies to the \pkg'{keyreader}. + + +\docsection(sec:user-commands)<user commands>{User commands} + +The syntax for defining new keys is: + +\start{newmacro}[\krddefinekeys] +\krddefinekeys|*[|A(kprefix)]{|A(kfamily)}[|A(mprefix)]{|A(keylist)} +\finish{newmacro} +\fxim*{\krddefinekeys} + +The optional \ang{kprefix} and mandatory \ang{kfamily} have unambiguous connotations. The optional \ang{mprefix} is the macro prefix, in the parlance of the \pkg'{xkeyval}. The default values of \ang{kprefix} and \ang{mprefix} are \ffx'{KRD,krdmp@}, respectively. + +In the case of ordinary, command and boolean keys, \ang{keylist} has the syntax + +\start'{newmacro}[Syntax of key keylist] +{ + |A(keytype1)/|A(keyname1)/|A(default1)/|A(callback1); + |A(keytype2)/|A(keyname2)/|A(default2)/|A(callback2); + etc. +} +\finish{newmacro} + +The list parser for \ang{keylist} is invariably \qsemicolon. Hence, if the user has \qsemicolon in \ang{callback}, it has to be wrapped in curly braces, to hide it from \tex's scanner. \ang{keytype} can be any member of the list \leftbrace\fx{ord} (ordinary key), \fx{cmd} (command key), \fx{bool} (boolean key), \fx{choice} (choice key)\rightbrace. + +For choice keys, \ang{keylist} has the syntax + +\start'{newmacro}[Syntax of key keylist] +{ + |A(keytype1)/|A(keyname1)/|A(default1)/|A(alt)/|A(callback1); + |A(keytype2)/|A(keyname2)/|A(default2)/|A(alt)/|A(callback2); + etc. +} +\finish{newmacro} + +The alternate (admissible list of) values \ang{alt} has the syntax + +\start'{newmacro}[Syntax of alternate list for choice keys] +|A(value1).code=|A(callback1), +|A(value1).code=|A(callback1), +etc. +\finish{newmacro} + +The list parser in this case is invariably \qcomma. + +The star (\redstar*) is an optional prefix. If it is present, then only definable (\ie, non-existent) keys will be defined. The existence of a key depends on \ang{kprefix} and \ang{kfamily}, since keys are name-spaced. + +The command \fx{\setkeys} of the \pkg'{xkeyval} is made more robust, in the sense that it now preserves all outer braces in the values of keys. The patched command \fx{\setkeys} has the same syntax as the original \fx{\setkeys} of the \pkg'{xkeyval}, namely + +\start{macro}[\setkeys] +\setkeys|*|+[|A(kprefix)]{|A(families)}[|A(na)]{|A(|verbkeyval pairs)} +\finish{macro} + +As usual, the star (\redstar) and plus sign (\redplus) are optional prefixes. The \stform will save all undeclared keys in the list \fx{\XKV@rm}, possibly for setting later with the command \fx{\setrmkeys}, and will not report any unknown key as undeclared. The \plform will set the given keys in all the given families, instead of in just one family. The combination \redstar\redplus* will set the listed keys in all the given families and append unknown keys to the container \fx{\XKV@rm}. \ang{na} is the list of keys that shouldn't be set in the current run. + +Actually, it isn't \fx{\setkeys} that is patched directly by the \pkg'{keyreader}, but some of the macros that it calls. Since a package might redefine \fx{\setkeys}, we also saved the patched \fx{\setkeys} in \fx{\krdsetkeys}. Indeed, \fx{\krdsetkeys} isn't exactly \fx{\setkeys}, since the former avoids the selective sanitization of \keyval list that is done by \fx{\setkeys}. Instead \fx{\krdsetkeys} \quoted{normalizes} the \keyval or comma-separated list. Therefore, users of the \pkg'{keyreader} should always call the command \fx{\krdsetkeys} instead of \fx{\setkeys}. Both have the same user interface. + +The \pkg'{xkeyval}'s command \fxi{\setrmkeys}, which sets \quoted{remaining keys}, has been modified to \fxi{\krdsetrmkeys}. Users of the \pkg'{keyreader} should use \fx{\krdsetrmkeys} in place of \fx{\setrmkeys}. + + +\docsection(sec:examples)<examples>{Examples} + +\start+{example}[\krddefinekeys, \krdsetkeys] +\krddefinekeys*[KV]{fam}[pnt@]{% + |com(`#1' here refers to the user input for the key.) + ord/keya/{black}/\def\xx##1{#1##1}; + cmd/keyb/\@fisrtofone/\def\y##1{#1##1}; + bool/keyc/true/\def\z##1{#1##1}; + choice/keyd/center/ + center.code=\def\my@align{center}\def\w##1{#1##1}, + left.code=\def\my@align{flushleft}, + right.code=\def\my@align{flushright}, + justified.code=\def\my@align{relax}% + /\def\xa##1{#1##1}; +} +\krdsetkeys[KV]{fam}[keyb]{keya={green},keyb=\@iden,keyc=false,keyd=left} +\finish{example} +\fxi*{\krddefinekeys,\setkeys,\krdsetkeys} + +The braces around \quoted{green}, the value of \fx{keya}, will be preserved throughout parsing. It should be remembered that keys are automatically set as soon as they are defined by \fx{\krddefinekeys}. + +Using the keys defined in the above example, let us make \qcomma and \qequal active and see how the \pkg'{keyreader} will deal with them. + +\start{example}[Active comma and equal sign] +|com(Make comma (`,') and equal `=' active to test the list normalization) +|com(scheme of `keyreader' pacakge:) +\begingroup +\catcode`\,=13 +\catcode`\==13 +\gdef\keylista{{fam,famb}[keyb , keyc]{keya = {green} , keyb = \@iden , + keyc = false , keyd = left, keye = somevalue}} +\gdef\keylistb{\krdsetrmkeys|*|+[KV]{fam,famb}} +\endgroup +\def\reserved@a{\krdsetkeys|*|+[KV]} +\expandafter\reserved@a\keylista +\keylistb +\finish{example} +\aidx*{active comma and equal sign} + + +\docsection(sec:disable-keys)<disabling keys>{Disabling keys} + +The command \fxim{\krddisablekeys} has the same use syntax as \pkg'{xkeyval}'s command \fxi{\disable@keys} but will issue an error (instead of a warning) when an attempt is made to set a disabled key. + + +\docsection(sec:options-processing)<options processing>{Options processing} + +The commands \ffxi'{\krdDeclareOption, \krdExecuteOptions, \krdProcessOptions} are aliases for +\ffxi'{\DeclareOptionX, \ExecuteOptionsX, \ProcessOptionsX} of the \pkg'{xkeyval}. + + +\docsection(sec:version-hist){Version history} + +The following change history highlights significant changes that affect user utilities and interfaces; changes of technical nature are not documented in this section. + +\begin{versionhist} + \begin{version}{0.4}{2011/12/20} + \item Several of the former functions of the package have been transferred to the \pkg'{ltxkeys} with even more robustness. The package now provides mainly a compact and robust interface to the features of the \pkg'{xkeyval}. + \end{version} + \begin{version}{0.3}{2011/03/26} + \item Bug fix. + \end{version} + \begin{version}{0.2}{2011/02/25} + \item The interface for defining new keys now accepts conditionals in key macros/functions. + \item A mechanism is provided for automatic setting up and execution of key functions with default key values. + \end{version} + \begin{version}{0.1}{2010/01/10} + \item First public release. + \end{version} + +\end{versionhist} + +\newpage +\ltsindexpreamble{Index numbers refer to page numbers.} +\ltsindexpreambleformat{\centering} +\ltsindexcolumns\tw@ +\printindex + +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/keyreader/keyreader-guide.cfg b/Master/texmf-dist/tex/latex/keyreader/keyreader-guide.cfg new file mode 100644 index 00000000000..a43780b1f25 --- /dev/null +++ b/Master/texmf-dist/tex/latex/keyreader/keyreader-guide.cfg @@ -0,0 +1,38 @@ +\ProvidesFile{keyreader-guide.cfg}% + [2011/12/20 v0.0.3 Configuration file for keyreader-guide (AM)] + +\amltxoptions{% + geometryoptions = {left=3cm,right=3cm,top=2.5cm,% + bottom=2.5cm,includeheadfoot}, + reviewdocument = false, + parindent = false, + toc = false, + frontpagestyle = empty, + pretitleskip = 0ex, + posttitleskip = 1ex, + presuptitleskip = 15ex, + postsuptitleskip = 0ex, + presubtitleskip = 0ex, + postsubtitleskip = 0ex, + natbiboptions = {numbers,sort&compress}, + cmdcolor = xmagenta1, + stylecolor = xgreen1, + speccolor = teal, + sectionheadcolor = blue +} +\fancypagenos[% + textalign = center, + show-on-page-one = false, + show-page-numbers = true, + show-headrule = true, + show-footrule = false, + y-position = -.44\paperheight, + x-position = 0, + scale = 1, + angle = 0, + style = \textsc{Page~\thepage~of~\pageref{xwmlastpage}}, + left-header = The \textcolor{macrocolor}{keyreader} package, + right-header = \ttcl{black}{\today} +] + +\endinput diff --git a/Master/texmf-dist/tex/latex/keyreader/keyreader.sty b/Master/texmf-dist/tex/latex/keyreader/keyreader.sty new file mode 100644 index 00000000000..3cefcf964ab --- /dev/null +++ b/Master/texmf-dist/tex/latex/keyreader/keyreader.sty @@ -0,0 +1,655 @@ +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% +% % +% This is file 'keyreader.sty', version 0.4, December 2011. % +% % +% This package and accompanying files may be distributed and/or % +% modified under the conditions of the LaTeX Project Public License, % +% either version 1.3 of this license or 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. % +% % +% The LPPL maintenance status of this software is 'author-maintained'. % +% % +% This software is provided 'as it 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. % +% % +% Copyright (c) 2011 Ahmed Musa (amusa22@gmail.com). % +% % +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% + +\ProvidesPackage{keyreader} + [2011/12/20 v0.4 Robust xkeyval package interface (AM)] +\ifcase + \ifx\eTeXversion\@undefined\z@\else + \ifnum\eTeXversion<\tw@\z@\else\@ne\fi\fi + \PackageError{keyreader} + {eTeX not loaded or old version} + {This package requires eTeX version 2 or higher.}% + \expandafter\endinput +\fi +\NeedsTeXFormat{LaTeX2e}[2011/06/27] +\begingroup +\catcode064 11% @ +\catcode123 01% { +\catcode125 02% } +\catcode044 12% , +\def\reserved@a{\endgroup + \def\do##1,{% + \ifx##1\end\else + \catcode##1\string=\the\catcode##1\expandafter\do\fi + }% + \edef\krd@restorecodes{\do035,064,123,125,061,059,\end,}% +} +\reserved@a +\catcode035 06% # +\catcode064 11% @ +\catcode123 01% { +\catcode125 02% } +\catcode061 12% = +\catcode044 12% , +\def\do#1=#2,{% + \ifx#1\end\else + \edef\krd@restorecodes{% + \krd@restorecodes + \catcode#1=\the\catcode#1\relax + }% + \catcode#1=#2\relax + \expandafter\do + \fi +} +\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 + }% +} +\RequirePackage{xkeyval}[2008/08/13] +\def\@space{ } +\protected\def\krdnewlet#1{\@ifdefinable#1\relax\let#1} +\krdnewlet\krd@nil\relax +\def\krd@nnil{\krd@nil} +\protected\def\krdAfterEndPackage{% + \krdifcsndef{\@currname.\@currext-krd@endpkghook}{}{% + \@namedef{\@currname.\@currext-krd@endpkghook}{}% + }% + \expandafter\g@addto@macro + \csname\@currname.\@currext-krd@endpkghook\endcsname +} +\xdef\@popfilename{% + \unexpanded{% + \csname\@currname.\@currext-krd@endpkghook\endcsname + \expandafter\let + \csname\@currname.\@currext-krd@endpkghook\endcsname + \relax + }% + \unexpanded\expandafter{\@popfilename}% +} +\newcommand*\krd@quark{\@gobble\krd@quark} +\newcommand*\krdifdef[1]{% + \krdifblank{#1}\@secondoftwo{% + \ifx#1\@undefined + \expandafter\@secondoftwo + \else + \ifx#1\relax + \expandafter\expandafter\expandafter\@secondoftwo + \else + \expandafter\expandafter\expandafter\@firstoftwo + \fi + \fi + }% +} +\newcommand*\krdifcsndef[1]{% + \krdifblank{#1}{% + \expandafter\@secondoftwo\@gobble + }{% + \ifcsname#1\endcsname + \expandafter\@firstofone + \else + \expandafter\expandafter\expandafter + \@secondoftwo\expandafter\@gobble + \fi + }{% + \expandafter\krdifdef\csname#1\endcsname + }% +} +\newcommand\krdifx[2]{% + \ifx#1#2\krd@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 + }{% + \krdifcsndef{if#1}{% + \csname @\csname if#1\endcsname + first\else second\fi oftwo\endcsname + }{% + \@latex@error{Undefined boolean '#1'}\@ehc + }% + }% +} +\def\krdifswitch@aux#1#2\krd@nil{% + \krdifblank{#2}\@secondoftwo\@firstoftwo +} +\def\krdifswitch#1{% + \krdifblank{#1}{% + \@secondoftwo + }{% + \expandafter\krdifswitch@aux\romannumeral-`\q#1\krd@nil{% + \if#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi + }{% + \@latex@error{Invalid switch '#1'}\@ehc + }% + }% +} +\krdifx\pdfstrcmp\@undefined{% + \RequirePackage{pdftexcmds}% + \krdifx\pdf@strcmp\@undefined{% + \cpt@err{Neither \string\pdfstrcmp nor \string\pdf@strcmp exists}\@ehc + }{% + \let\krd@pdfstrcmp\pdf@strcmp + }% +}{% + \let\krd@pdfstrcmp\pdfstrcmp +} +\newcommand\krdifstrcmp[2]{% + \csname @\ifnum\krd@pdfstrcmp{\detokenize{#1}}% + {\detokenize{#2}}=0first\else second\fi oftwo\endcsname +} +\def\krdifbraced#1{\krd@ifbraced#1\krd@nil{#1}} +\def\krd@ifbraced#1\krd@nil#2{% + \krdifstrcmp{#1}{#2}\@secondoftwo\@firstoftwo +} +\def\krdexpandonce#1{\unexpanded\expandafter{#1}} +\def\krdnoexpandcsn#1{\krdexpandonce{\csname#1\endcsname}} +\protected\def\krdexpanded#1{% + \begingroup + \protected@edef\reserved@a{\endgroup#1}\reserved@a +} +\protected\def\krdexpandarg#1#2{\krdexpanded{\unexpanded{#1}{#2}}} +\protected\def\krdexpandargonce#1#2{% + \krdexpanded{\unexpanded{#1}{\krdexpandonce{#2}}}% +} +\protected\def\krdexpandsecond#1#2{\krdexpanded{\unexpanded{#1}#2}} +\protected\def\krdexpandsecondonce#1#2{% + \krdexpanded{\unexpanded{#1}\krdexpandonce{#2}}% +} +\newcount\krd@csvdepth +\newif\ifkrd@lb +\newif\ifkrd@st +\krdnewlet\krdloopbreak\krd@lbtrue +\begingroup +\catcode`\&=7 +\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}% +} +\endgroup + +\def\krdfor#1{\krd@for@a#1,\krd@nnil,\krd@nil} +\def\krd@for@a#1,#2\krd@nil{% + \krdifblank{#1}{% + \krd@for@a#2\krd@nil + }{% + \expandafter\krdifx\@car#1\@nil\krd@nnil + {}{\do{#1}\krd@for@a#2\krd@nil}% + }% +} +\def\krd@loopdostack{} +\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@loopdostack{% + \krdfor{\krd@loopdo,\ifkrd@lb,\krd@loopact@a,\krd@loopact@b}% + {\krdexpandonce\krd@loopdostack}% + }% + \def\do##1{\let\krdnoexpandcsn{\reserved@a{##1}}\noexpand##1}% + \krdexpanded{% + \krdfor{\krd@loopdo,\ifkrd@lb,\krd@loopact@a,\krd@loopact@b}% + }% +} +\protected\def\krd@poploopdo{% + \begingroup + \def\reserved@a##1##{\endgroup##1\gdef\krd@loopdostack}% + \expandafter\reserved@a\krd@loopdostack + \global\advance\krd@csvdepth\m@ne +} +\protected\def\krd@testst#1{\@ifstar{\krd@sttrue#1}{\krd@stfalse#1}} +\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@loopact@a##1{#5}% + \def\krd@loopact@b##1{#6}% + #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@loopact@a\expandafter{\krd@csvarg}\relax + }{% + \expandafter\krd@loopact@b\expandafter{\krd@csvarg}\relax + \krd@loopdo.##2\krd@nnil + }% + }% + }% + \expandafter\krd@loopdo\expandafter.\krd@csvarg#1\krd@nil#1\krd@nnil + \krd@poploopdo +} +\protected\def\krdaddtolist{\krd@testst{\@testopt{\krd@addtolist{e}},}} +\protected\def\krdgaddtolist{\krd@testst{\@testopt{\krd@addtolist{x}},}} +\protected\def\krd@addtolist#1[#2]#3#4{% + \@nameuse{#1def}#3{% + \krdifdef#3{% + \krdifx#3\@empty{}{\krdexpandonce#3#2}% + }{}% + \krdifbool{krd@st}\krdexpandonce\unexpanded{#4}% + }% +} +\protected\def\krdcsvnormalize{\@testopt\krd@csvnormalize,} +\protected\def\krd@csvnormalize[#1]#2{% + \begingroup + \krd@setupnormalize{#1}% + \def\krd@inkv{01}% + \edef#2{\expandafter\krd@normalizelist\expandafter{#2}}% + \krdexpanded{\endgroup + \edef\noexpand#2{\noexpand\unexpanded{\krdexpandonce{#2}}}% + }% +} +\protected\def\krdkvnormalize#1{% + \begingroup + \krd@setupnormalize{,}% + \def\krd@inkv{00}% + \edef#1{\expandafter\krd@normalizelist\expandafter{#1^?^}}% + \def\reserved@b##1^?^##2\krd@nil{% + \edef#1{\unexpanded{##1##2}}% + }% + \expandafter\reserved@b#1\krd@nil + \krdexpanded{\endgroup + \edef\noexpand#1{\noexpand\unexpanded{\krdexpandonce{#1}}}% + }% +} +\begingroup +\catcode`\~=13 +\catcode`\!=13 +\protected\gdef\krd@setupnormalize#1{% + \begingroup + \uccode`\~=`#1% + \uccode`\!=`\=% + \uppercase{\endgroup + \def\krd@normalizelist##1{% + \unexpanded\expandafter{\romannumeral-`\q + \krd@activeparser#1##1#1~\krd@nil}% + }% + \def\krd@activeparser##1~##2\krd@nil{% + \krdifblank{##2}{% + \krdifswitch\krd@inkv{% + \krd@activeequal##1!\krd@nil + }{% + \krd@spaceparser##1 #1\krd@nil + }% + }{% + \krd@activeparser##1#1##2\krd@nil + }% + }% + }% + \begingroup + \uccode`\~=`\=% + \uppercase{\endgroup + \def\krd@activeequal##1~##2\krd@nil{% + \krdifblank{##2}{% + \krd@spaceparser##1 #1\krd@nil + }{% + \krd@activeequal##1=##2\krd@nil + }% + }% + }% + \def\krd@spaceparser##1 #1##2\krd@nil{% + \krdifblank{##2}{% + \krd@parserspace##1#1 \krd@nil + }{% + \krd@spaceparser##1#1##2\krd@nil + }% + }% + \def\krd@parserspace##1#1 ##2\krd@nil{% + \krdifblank{##2}{% + \krdifswitch\krd@inkv{% + \krd@spaceequal##1 =\krd@nil + }{% + \krd@doubleparser##1#1#1\krd@nil + }% + }{% + \krd@parserspace##1#1##2\krd@nil + }% + }% + \def\krd@spaceequal##1 =##2\krd@nil{% + \krdifblank{##2}{% + \krd@equalspace##1= \krd@nil + }{% + \krd@spaceequal##1=##2\krd@nil + }% + }% + \def\krd@equalspace##1= ##2\krd@nil{% + \krdifblank{##2}{% + \krd@doubleparser##1#1#1\krd@nil + }{% + \krd@equalspace##1=##2\krd@nil + }% + }% + \def\krd@doubleparser##1#1#1##2\krd@nil{% + \krdifblank{##2}{% + \krdifswitch\krd@inkv{% + \krd@doubleequal##1==\krd@nil + }{% + \krdifblank{##1}{}{% + \krd@remleadparser##1\krd@nil + }% + }% + }{% + \krd@doubleparser##1#1##2\krd@nil + }% + }% + \def\krd@doubleequal##1==##2\krd@nil{% + \krdifblank{##2}{% + \krdifblank{##1}{}{% + \krd@remleadparser##1\krd@nil + }% + }{% + \krd@doubleequal##1=##2\krd@nil + }% + }% + \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 + }% + }% +} +\endgroup +\krd@setupnormalize{,} +\protected\def\XKV@define@key#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}}% + \afterassignment\reserved@a\toks0=% + }% +} +\def\XKV@d@fine@k@y#1[#2]#3{% + \XKV@define@default{#1}{#2}% + \expandafter\def\csname\XKV@header#1\endcsname##1{#3}% +} +\protected\def\XKV@checksanitizea#1#2{% + \XKV@ch@cksanitize{#1}#2=% + \ifin@\else\XKV@ch@cksanitize{#1}#2,\fi + \krdifbool{in@}{\krdkvnormalize#2}{}% +} +\protected\def\XKV@checksanitizeb#1#2{% + \XKV@ch@cksanitize{#1}#2,% + \krdifbool{in@}{\krdcsvnormalize[,]#2}{}% +} +\protected\def\krdsetkeys{\XKV@testopta{\XKV@testoptc\krd@setkeys}} +\protected\def\krd@setkeys[#1]#2{% + \edef\krd@na{\unexpanded{#1}}% + \krdifx\krd@na\@empty{}{\krdcsvnormalize\krd@na}% + \edef\XKV@resb{\unexpanded{#2}}% + \krdkvnormalize\XKV@resb + \let\XKV@naa\@empty + \XKV@for@o\XKV@resb\XKV@tempa{% + \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 + \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{preseth}% + \krdexpandsecond\XKV@s@tkeys + {{\krdexpandonce\XKV@resb}{\krdexpandonce\krd@na}}% + \expandafter\XKV@usepresetkeys\expandafter{\krd@na}{presett}% + \let\CurrentOption\@empty +} +\protected\def\XKV@s@tkeys#1#2{% + \edef\key@list{\unexpanded{#1}}% + \krdkvnormalize\key@list + \edef\XKV@na{\unexpanded{#2}}% + \krdifx\XKV@na\@empty{}{\krdcsvnormalize\XKV@na}% + \def\XKV@s@tkeys@a##1={% + \def\reserved@a####1=####2\@nil{% + \edef\reserved@a{\expandafter\krdtrimspace\expandafter{\@gobble####1}}% + \krdifx\reserved@a\@empty{% + \expandafter\XKV@s@tk@ys##1==\@nil + }{% + \expandafter\krdifbraced\expandafter{\reserved@a}{% + \edef\CurrentOption{% + \unexpanded{##1}={{{\krdexpandonce\reserved@a}}}% + }% + }{% + \edef\CurrentOption{\unexpanded{##1}=\krdexpandonce\reserved@a}% + }% + \expandafter\XKV@s@tk@ys\CurrentOption==\@nil + }% + }% + \reserved@a.% + }% + \XKV@for@o\key@list\CurrentOption{% + \expandafter\XKV@s@tkeys@a\CurrentOption==\@nil + }% +} +\protected\def\krdsetrmkeys{\XKV@testopta{\XKV@testoptc\krd@setrmkeys}} +\protected\def\krd@setrmkeys[#1]{% + \krdexpandargonce{\krd@setkeys[#1]}\XKV@rm +} +\protected\def\krd@disabledkey@err#1{% + \@latex@error{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: + couldn't be disabled}% + }% + \krdifcsndef{\XKV@header\krd@tempa @default}{% + \edef\krd@tempb{\noexpand\XKV@define@key{\krd@tempa}[]}% + }{% + \edef\krd@tempb{\noexpand\XKV@define@key{\krd@tempa}}% + }% + \krdexpandarg{\expandafter\krd@tempb\expandafter}% + {\krd@disabledkey@err{\krd@tempa}}% + }% +} +\edef\krd@hashchar{\string#} +\protected\def\krddefinekeys{\krd@testst{\@testopt\krd@d@finekeys{KRD}}} +\protected\def\krd@d@finekeys[#1]#2{\@testopt{\krd@d@f@nekeys{#1}{#2}}{krdmp@}} +\protected\def\krd@d@f@nekeys#1#2[#3]#4{% + \begingroup + \let\ifkrd@keyst\ifkrd@st + \edef\key@prefix{\krdtrimspace{#1}}% + \edef\key@family{\krdtrimspace{#2}}% + \edef\macro@prefix{\krdtrimspace{#3}}% + \toks@{}% + \def\krd@rej{^?^}% + \def\key@vals{}% + \def\krd@altlista{}% + \def\krd@altlistb{}% + \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}}% + \@expandtwoargs\in@{\krd@hashchar}{\detokenize{##2}}% + \ifin@ + \@latex@error{Bad key name '\detokenize{##2}'}\@ehc + \fi + \ifkrd@keyst + \krdifcsndef{\key@prefix @\key@family @##2}{% + \@latex@error{Key '##2' already exists in + family '\key@family'}\@ehc + }{}% + \fi + \@expandtwoargs\in@{,\detokenize\expandafter{\key@type},}% + {,\detokenize{ord,cmd,bool,choice},}% + \ifin@\else + \@latex@error{Unknown key type '\key@type'}\@ehc + \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 + \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 + }% + \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 + }{% + \krd@getaltlist{##4}% + }% + }% + \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@ + \ifnum\key@typenr<\thr@@[\macro@prefix]\fi + \fi + {\key@name}% + \ifnum\key@typenr=\thr@@ + [\unexpanded{\userinput\order}]{\krdexpandonce\krd@altlista}% + \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}% + \else + \krdifx\krd@resa\krd@rej{}{\unexpanded{##4}}% + \fi + }% + \ifnum\key@typenr>\@ne{\noexpand\krd@keyvalerr}\fi + }% + }% + }% + \edef\key@list{\unexpanded{#4}}% + \krdcsvnormalize[/]\key@list + \krdlistloop*[;]\key@list\ifx\end\@undefined\fi{}{}{% + \krd@splita##1/^?^/^?^/^?^/^?^/\krd@nil + }% + \krdexpanded{\endgroup + \the\toks@ + \noexpand\krdsetkeys[\key@prefix]% + {\key@family}{\krdexpandonce\key@vals}% + }% +} +\protected\def\krd@keyvalerr{% + \krd@getinnoval + \@latex@error{Erroneous value '\krd@ival' for key or option + \MessageBreak'\XKV@tkey'}{Invalid key value encountered.}% +} +\protected\def\krd@getaltlist#1{% + \def\krd@g@taltlist##1.code=##2\krd@nil{% + \edef\krd@tempa{\krdtrimspace{##1}}% + \edef\krd@tempb{\krdexpandonce\krd@tempa{\krdtrimspace{##2}}}% + \krdaddtolist*\krd@altlista\krd@tempa + \krdaddtolist*\krd@altlistb\krd@tempb + }% + \krdlistloop[,]{#1}\ifx\end\@undefined\fi{}{}{% + \@expandtwoargs\in@{\detokenize{.code=}}{\detokenize{##1}}% + \krdifbool{in@}{% + \krd@g@taltlist##1\krd@nil + }{% + \krd@g@taltlist##1.code=\krd@nil + }% + }% +} +\protected\def\krd@executealt#1#2{% + \krdexpandsecond{\def\reserved@a##1}{\krdtrimspace{#1}}##2##3\krd@nil{% + \edef\reserved@a{\unexpanded{##2}}% + \krdifx\reserved@a\krd@nnil{% + \@latex@error{No alternate list for key '\XKV@tkey'}\@ehc + }{% + ##2% + }% + }% + \reserved@a#2#1{\krd@nil}\krd@nil +} +\protected\def\krd@getinnoval{% + \begingroup + \def\reserved@a##1=##2=##3\krd@nil{% + \def\krd@tval{##2}% + }% + \expandafter\reserved@a\CurrentOption==\krd@nil + \krdifx\krd@tval\@empty{% + \def\krd@ival{???}% + }{% + \def\krd@ival{}% + \@tempcnta\z@ + \def\do##1{% + \def\reserved@a{##1}% + \krdifx\reserved@a\krd@nnil{}{% + \advance\@tempcnta\@ne + \ifnum\@tempcnta<20\relax + \edef\krd@ival{\krd@ival##1}% + \expandafter\do + \else + \def\do####1\krd@nil{}% + \expandafter\do + \fi + }% + }% + \expandafter\do\detokenize\expandafter{\krd@tval}\krd@nil + }% + \krdexpanded{\endgroup + \def\noexpand\krd@ival{\krd@ival}% + }% +} +\krdnewlet\krdDeclareOption\DeclareOptionX +\krdnewlet\krdExecuteOptions\ExecuteOptionsX +\krdnewlet\krdProcessOptions\ProcessOptionsX +\krdDeclareOption*{\PackageWarning{keyreader}{Unknown option + '\CurrentOption' ignored.}} +\krdProcessOptions[KRD]<keyreader>\relax + +\endinput |