diff options
author | Karl Berry <karl@freefriends.org> | 2011-08-15 23:04:13 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-08-15 23:04:13 +0000 |
commit | 5c9d629f843570179358708a673501e5a647a617 (patch) | |
tree | 69bc8e44446b946194971933ac3756bdb60b9c30 /Master/texmf-dist | |
parent | c94e2deaaa21a46bcd63069cb63f3f6a807139a9 (diff) |
ltxkeyx (15aug11)
git-svn-id: svn://tug.org/texlive/trunk@23566 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/ltxkeys/README | 43 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.tex | 769 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.txt | 530 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ltxkeys/ltxkeys.sty | 915 |
4 files changed, 1358 insertions, 899 deletions
diff --git a/Master/texmf-dist/doc/latex/ltxkeys/README b/Master/texmf-dist/doc/latex/ltxkeys/README index a0d9804f9e3..ead54ad2089 100644 --- a/Master/texmf-dist/doc/latex/ltxkeys/README +++ b/Master/texmf-dist/doc/latex/ltxkeys/README @@ -1,5 +1,9 @@ This is the README file for the ltxkeys package. +VERSION + +Version 0.0.1, July 2011 + SUMMARY The ltxkeys package provides facilities for creating and managing @@ -7,40 +11,35 @@ keys in the sense of the keyval and xkeyval packages, but it is intended to be more robust and faster. Its robustness emanates from its ability to preserve braces in key values throughout parsing. The need to preserve braces in key values emerges often -in parsing keys. This is often the case in, eg, the xwatermark -package. The package is faster than the xkeyval package because, -among other features, it avoids character-wise parsing of key -values (which is called selective sanitization by the xkeyval +in parsing keys. This is often the case in, eg, the xwatermark +package. The package is faster than the xkeyval package because, +among other features, it avoids character-wise parsing of key +values (which is called selective sanitization by the xkeyval package). -It also provides additional functionalities for defining and +It also provides additional functions for defining and managing keys. In the ltxkeys package, the notion of 'presetting' keys differs from that of the xkeyval package. Only 'launched keys' are preset in the ltxkeys package. -AUTHOR - -Ahmed Musa (amusa22@gmail.com) - -RELATED PACKAGES - -xkeyval.sty - 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. -VERSION +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. -Version 0.1.0, July 2011 +RELATED PACKAGES + +keyval.sty, xkeyval.sty + +AUTHOR +Ahmed Musa (amusa22@gmail.com)
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.tex b/Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.tex new file mode 100644 index 00000000000..739845562d3 --- /dev/null +++ b/Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.tex @@ -0,0 +1,769 @@ +\documentclass[ + use-a4-paper, + use-10pt-font, + final-version, + use-UK-English, + fancy-section-headings, + frame-section-numbers, + para-abstract-style, + input-config-file, + no-hyperref-messages +]{amltxdoc} + +\hfuzz1pt +\makeatletter +\WrapQuotes +\def\xdecs{\fx{\XDeclareOption}\RedStar\sspace} +\makeindex + +% Move to config file: +\def\keydotchoice#1#2{\fx{#1}\unskip\makered{.}\unskip\fx{{#2}}} +\def\preffamkey{\fnl{{pref}{fam}{key}}\sspace} +\def\mpkey{\fnl{{mp}{key}}\sspace} +\def\ifmpkey{\fnl{{if}{mp}{key}}\sspace} +\def\ipreffamkey#1{\fnl{{#1}{pref}{fam}{key}}} +\def\ipreffam#1{\fnl{{pref}{fam}}\unskip\tcl{cmdcolor}{\texttt{@#1}}} + +\begin{document} + +\begin{frontmatter} +\title{The \texttt{\color{blue}ltxkeys} Package\titleref{t1}} +\titlenote[t1]{% + The package is available at \iftogTF{pdf}{\url{\@titleurl}} + {\url{\@shorttitleurl}}. +} +\version{0.0.1} +\titleurl{http://www.ctan.org/tex-archive/macros/latex/contrib/ltxkeys/} +\shorttitleurl{http://www.ctan.org/} +\author{Ahmed Musa \Email{amusa22@gmail.com}\\Preston, Lancashire, UK} + +\def\abstractname{\textsc{Summary}} +\begin{abstract} +The \pkg'{ltxkeys} provides facilities for creating and managing keys in the sense of the \pkg'{keyval, xkeyval}, but it is intended to be more robust and faster than these earlier packages. Its robustness emanates from, inter alia, its ability to preserve braces in key values throughout parsing. The need to preserve braces in key values emerges often in parsing keys. This is the case in, eg, the \pkg'{xwatermark}. The package is faster than the \pkg'{xkeyval} mainly because it avoids character-wise parsing of key values (which is called \quoted{selective sanitization} by the \pkg'{xkeyval}). Moreover, it is faster to normalize a comma-separated or key-value list than trim leading and trailing spaces of each element of the list (the \pkg'{xkeyval} as does), since not all the elements of the list will normally have leading and trailing spaces. In fact, the chances are that only a few elements of the list will have such spaces. As another example of optimization, anyone familiar with the implementation of the \pkg'{xkeyval} would have noticed that the macro \hx{\XKV@srstate}, which (in order to allow \hx{\setkeys} to be re-entrant) pushes and pops the states of some important functions in the package, loops over all the functions both when pushing and popping. In the \pkg'{ltxkeys}, pushing and popping functions together involve only one loop. And, unlike in the \pkg'{xkeyval}, higher order functions are undefined as soon as they are no longer needed, to avoid clogging up the stack. In setting keys, the \pkg'{ltxkeys} loops over not only families, as in the \pkg'{xkeyval}, but also over key prefixes. The same strategy applies when the \pkg'{ltxkeys} tries to establish if a key is defined or not. While many aspects of the \pkg'{ltxkeys} are similar to those of the \pkg'{xkeyval}, there are important differences in several areas of syntax, semantics, and internal implementation. The \pkg'{ltxkeys} also provides additional facilities (beyond the \pkg'{xkeyval}) for defining and managing keys. Several types of keys (including ordinary keys, command keys, style keys, choice keys, boolean and biboolean keys) can be efficiently created and managed. In the \pkg'{ltxkeys}, the notions of \quoted{pre-setting} and \quoted{post-setting} keys are similar to those of the \pkg'{xkeyval}. But the \pkg'{ltxkeys} introduces additional concepts in this respect: \quoted{initialized} and \quoted{launched} keys. The latter are special preset keys. +\end{abstract} + +\let\licensename\relax +\begin{license} + \small +\xwmcolorbox[textalign=justified, outerframecolor=blue, innerframecolor=orange, + width=.985\hsize]{% + This work (\ie, all the files in the \pkg'{ltxkeys} bundle) may be distributed and/or modified under the conditions of the \lppl, either version~1.3 of this license or any later version. + 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} + +\begin{xwmshade}[fillcolor=white,framecolor=orange,framerule=1pt,framesep=2pt, + width=1.0\hsize]\tableofcontents +\end{xwmshade} + + +\docsection{Motivation} + +What are the \emph{raison d'etre} and origins of the \pkg'{ltxkeys}? Well, I decided to write this package as I grabbled with some practical problems of key parsing while developing version~1.5.0 of the \pkg'{xwatermark}. The tasks proved more challenging than I had predicted and, despite its commendable and widely deployed facilities, I found the \pkg'{xkeyval} inadequate in some respects. As mentioned earlier, the several functionalities of the \pkg'{ltxkeys} can be employed for general key management in \latex beyond the \pkg'{xwatermark}. Indeed the \pkg'{ltxkeys} can be used as a more robust replacement for the \pkg'{xkeyval}, of course with some adaptation. + + +\docsection{Package options} + +Wherever the semicolon \quoted{;} is indicated as a list parser in this guide, it can be replaced by any user-specified one character parser via the package option \fx{keyparser}. To avoid confusing the user-supplied parser with internal parsers, it is advisable to enclose the chosen character in curly braces, \eg, as in the following example. The braces will be stripped off internally. + +\start{example}[keyparser] +\documentclass[verbose,keyparser={|}]{article} +|orr +\usepackage[keyparser={|}]{ltxkeys} +\finish{example} + +The other package options are listed in \amref{tab:pkgoptions}. + +\extrarowheight=2pt +\arrayrulecolor{yellow} +\begin{tabularx}{\linewidth}{|m{3cm}|m{2.5cm}|X|} +\caption{Package options\xwmlabel{tab:pkgoptions}}\\\hline +\rowcolor{pink} +\bfseries Option&\bfseries Default&\bfseries Meaning\\\hline +\endfirsthead +\hline +\multicolumn{3}{|l|}{\emph{Continued from last page}}\\\hline +\bfseries Option&\bfseries Default&\bfseries Meaning\\\hline +\endhead +\multicolumn{3}{|r|}{\emph{Continued on next page}}\\\hline +\endfoot +\hline +\endlastfoot +\fx{verbose} & \hx{false} & The global boolean switch that determines if information should be logged for some tasks in the package. The speed of compilation is affected by this option.\\\hline +\fx{keyparser} & \texttt{;} & The list parser used for some loops in defining keys. See note above.\\\hline +\fx{keystacklimit} & \hx{4} & This is used to guard against erroneous infinite re-entrance of \fx{\ltxkeys@setkeys}. The default value of~4 means that \fx{\ltxkeys@setkeys} can't ordinarily be nested beyond level~4. If you must nest \fx{\ltxkeys@setkeys} beyond this level, you have to raise the \fx{keystacklimit} as a package option.\\\hline +\end{tabularx} + +\end{document} + + +\docsection{Defining keys} + +In the following, quantities in square brackets---\eg, [yyy]---and those in parenthesis---\eg, (yyy)---are optional. + + +\docsubsection{Ordinary keys} + + \ltxkeys@ordkey[<pref>]{<fam>}{<key>}[<default>]{<callback>} + +This defines a macro of the form \preffamkey of one argument that holds the key function <callback>. The default value for <pref> is always \fx{KV}, as in the \pkg'{xkeyval}. When \ang{key} is used in a \fx{\ltxkeys@setkeys} command (see \amref{sec:}) containing key=value, the macro \preffamkey takes the value as its argument and is then executed. The given argument or key value can be accessed in <callback> by using \fx{#1} inside the function. The optional <default>, if available, will be used by \preffamkey when the user hasn't provided a value for the key at \fx{\ltxkeys@setkeys}. If <default> was absent at key definition and the key user hasn't provided a value for the key, an error message will be flagged. + + +\docsubsection{Command keys} + + \ltxkeys@cmdkey[<pref>]{<fam>}[<mp>]{<key>}[<default>]{<callback>} + +The optional <mp> is called the \quoted{macro prefix} (in the parlance of the \pkg'{xkeyval}). If <mp> is given, the command \mpkey will hold the current user input; otherwise (if <mp> is absent) the user input will be available in \ipreffamkey{cmd}. The command \preffamkey, called the \quoted{key macro} by the \pkg'{xkeyval}, will hold the <callback>. + + +\docsubsection{Style keys---keys with dependants} + +Style keys have the following syntaxes: + + \ltxkeys@stylekey[<pref>]{<fam>}[<mp>]{<key>}[<default>](<dependants>){<callback>} + + \ltxkeys@stylekey*[<pref>]{<fam>}[<mp>]{<key>}[<default>](<dependants>){<callback>} + +The <dependants> have the syntax: + + {<keytype>/<keyname>/<default>/<callback>; another set of dependant; etc} + + <default> and <callback> can be absent. <keytype> can be \quoted{ord} (ordinary key), \quoted{cmd} (command key), \quoted{bool} (boolean key), or \quoted{choice} (choice key). + +Dependants keys always share the same key prefix <pref>, family <fam>, and macro prefix <mp> with the parent key. + +If <mp> is given, the command \mpkey will hold the current user input for the parent key; otherwise the user input will be available in \ipreffamkey{style}. The command \preffamkey will always hold the <callback>. + +If the \stform is used, all undefined dependants will be defined and set on the fly as the parent is being set. If the \stform isn't used and undefined dependants occur, then an error message will be flagged at the time the parent is being set. + +At most times it is possible to access the parent key's current value with \parentval. Within <default> and <callback> of <dependants>, it is possible to refer to the parent key's callback with its full macro name (\ie, \preffamkey). \parentval is always available for use as the default value of dependant keys, but it may be lost in the callbacks of dependant keys, because a dependant key, once defined, may be set independent of, and long after, the parent key has been executed. It is therefore more reliable to refer to the macro \fnl{{pref}{fam}{key}{value}}, which is recorded for only the parent key of style keys and which holds the current user input for the parent key. The macro \fnl{{pref}{fam}{key}{value}} is recorded only if it appears at least once in the attributes of dependant keys. The macro \fnl{{pref}{fam}{key}{value}} has a more unique name than \mpkey but they always contain the same value of a style key. As mentioned above, if <mp> is not given, the user input for a style key will be available in the macro \ipreffamkey{style}, instead of \mpkey. + +Note: \fx{#1} in the callback of parent key refers to the current value of the parent key, while \fx{#1} in the callback of any dependant key refers to the current value of that dependant key. + +Example (define and set all undefined dependants on the fly): + + \ltxkeys@stylekey*[KV]{fam}[mp@]{keya}[{left}](% + % `#1' here refers to the value of the DEPENDANT key + % at the time it is being set. Use \parentkey and \parentval + % here to access the parent key name and its current value: + ord/keyb/{right}/\def\y##1{#1##1}; + % The default of keyc is the current value of parent (keya): + cmd/keyc/\parentval; + % Because \KV@fam@keya@value appears below, it will be saved + % when the parent key (keya) is being set, otherwise it would be + % unavailable: + bool/keyd/true/\ifmp@keyd\edef\x##1{##1\KV@fam@keya@value}\fi + ){ + % `#1' here refers to the value of the PARENT key + % at the time it is being set: + \def\x##1{##1xx#1xx}% + % Check the value of parent key: + \ltxkeys@checkchoice[\userinput\nr]{#1}{left,right,center}% + } + +In this example, \fx{\userinput} corresponds to \fx{#1}, and \fx{\nr} is the numerical order of the user input in the nominations \fnz{{left}{right}{center}}. See more about the commands \ffx'{\ltxkeys@checkchoice, \CheckInput} in \amref{sec:}. + +You can try setting \fx{keya} as follows to see what happens to keys \ffx'{keyb,keyc,keyd}: + + \ltxkeys@setkeys[KV]{fam}{keya={right}} + +The braces in the key values above are just to exemplify the fact that braces in key values are preserved throughout key parsing. This is essential in, for example, the \pkg'{xwatermark}. + + +\docsubsection{Boolean keys} + + \ltxkeys@boolkey[<pref>]{<fam>}[<mp>]{<key>}[<default>]{<callback>} + + \ltxkeys@boolkey+[<pref>]{<fam>}[<mp>]{<key>}[<default>]{<callback>}{<fn>} + +If <mp> is given, the command \mpkey will hold the current user input for the key at key setting time; otherwise the user input will be available in \ipreffamkey{bool}\footnote{This differs from the system in the \pkg'{xkeyval}.}. If <mp> is specified, a boolean of the form \ifmpkey will be created at key definition, which will be set by \fx{\ltxkeys@setkeys} according to the user input. If <mp> is not specified, a boolean of the form \ipreffamkey{ifbool} will instead be created. + +The user input for boolean keys must be in the set {true | false}. The command \preffamkey will always hold the <callback>, which will be executed if the user input is valid. + +The \plform of \fx{\ltxkeys@boolkey} will execute <fn> in place of <callback> if the user input isn't in {true | false}; the plain form will issue an error in this case. + + +\docsubsubsection{Biboolean keys} + + \ltxkeys@biboolkeys[<pref>]{<fam>}[<mp>]{<bool1>,<bool2>} + [<default>]{<callback1>}{<callback2>} + + \ltxkeys@biboolkeys+[<pref>]{<fam>}[<mp>]{<bool1>,<bool2>} + [<default>]{<callback1>}{<callback2>}{<fn>} + +Biboolean keys always assume opposite states: when one is true, the other is automatically toggled to false; and vice versa. Think of the options \hx{draft} and \hx{final} in a document class, but note that traditional document classes don't currently use biboolean keys. + + <callback1> belongs to the boolean key <bool1>, while <callback2> belongs to <bool2>. + +The \plform of \ltxkeys@biboolkeys will execute <fn> in place of <callback1> or <callback2> if the input is not in {true | false}; the plain form will issue an error in this case. + +Biboolean keys have equal symmetry (\ie, they can call each other with equal propensity) and they won't bomb out in an infinite reentrance. They normally would know if they're calling each other. + + Example: + + \ltxkeys@biboolkeys+[KV]{fam}[mp@]{keya,keyb}[true]{% + \ifmp@keya\def\x##1{##1x#1x##1}\fi + }{% + \ifmp@keyb\def\y##1{##1y#1y##1}\fi + }{% + \@latex@error{Invalid value '\string#1' for keya or keyb}\@ehc + } + + +\docsubsection{Choice keys} + +The choice keys of the \pkg'{ltxkeys} differ from those of the \pkg'{xkeyval} in at least one respects, namely, the presence of the macro prefix for choice keys in the \pkg'{ltxkeys}. + + \ltxkeys@choicekey[<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<default>]{<callback>} + + \ltxkeys@choicekey*[<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<default>]{<callback>} + + \ltxkeys@choicekey*+[<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<default>]{<callback>}{<fn>} + + \ltxkeys@choicekey*+![<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<default>]{<callback>}{<fn>} + +Choice keys check the user input against the nominations suggested by the author of the key. The \stform will convert user input to lowercase before checking it against the list of nominations in \ang{alt}. In all the above variants, if the input is valid, then \ang{callback} will be executed. If the user input isn't valid, the \nonplform+ will flag an error, while the \plform will execute \ang{fn}. The \clform will fully expand the user input before checking it against the nominations in \ang{alt}. The \clform arises from the fact that sometimes macros are passed as the values of choice keys. + +If <mp> is absent, then \fx{\ltxkeys@choicekey} uses \ipreffamkey{chc} to hold the user input. + +<alt> is the list of nominations for the key value, \ie, admissible values of the key. When <alt> has no \fx{/.code} or forward slash \fx{/} in it, then it is expected to be of the familiar \pkg'{xkeyval} syntax: + + {choice1, choice2, etc} + +If \ang{alt} it has \fx{/.code} or \fx{/} in it, then it is expected to have one of the following syntaxes: + + {choice1/.code=callback1|A(keyparser) choice2/.code=callback2|A(keyparser) etc} + + {choice1/callback1|A(keyparser) choice2/callback2|A(keyparser) etc} + +This means that if you have \fx{/.code} or \fx{/} in any of the callbacks, it has to be enclosed in curly braces. Please recall that the default value of \ang{keyparser} is \qsemicolon. \fx{keyparser} is a package option. This syntax also implies that if you have the \ang{keyparser} in \ang{defn}, it has to be wrapped in curly braces. The \ang{keyparser} in this syntax can also be \qcomma. + +\Note Here is the rule for parsing the \ang{alt} list. First the package checks if the declared key parser (\ie, \ang{keyparser}) is in the \ang{alt} list. If the parser exists in \ang{alt}, then the list is parsed using this parser. Otherwise the list is parsed using comma as the parser. Moreover, the package checks if \fx{.code} separates \ang{choice} from \ang{callback}. If no \fx{.code} is found, then \fx{/} is assumed to be the separator. But note that when there is no \ang{callback}, then neither \fx{.code} nor \fx{/} is necessary. + +It is possible to refer to the current value of \ang{key} as \fx{#1} in <alt>. + +The \stform of \fx{\ltxkeys@choicekey} will convert the user input to lowercase before checking <alt> and executing the callbacks. The \plform will execute <fn> in place of <callback> if the user input isn't in <alt>. + +<bin> has, \eg, the syntax \fx{[\userinput\nr]}, where \fx{\userinput} will hold the user input (in lowercase if the \stform of \fx{\ltxkeys@choicekey} is called), and \fx{\nr} will hold the serial number of the value in the list of nominations <alt>, starting from 0. If the input isn't valid, \fx{\userinput} will still hold the user input, but \fx{\nr} will be~-1. + +Example (defining choice key): + + \ltxkeys@choicekey[KV]{fam}{keya}{% + % There are no callbacks for these simple nominations: + center,right,left,justified + }[center]{% <- default value + \def\x##1##2{==##1++#1++##2==}% + } + + \ltxkeys@choicekey*+[KV]{fam}[mp@]{keya}[\userinput\nr]{% + center,right,left,justified + }[center]{% + \def\x##1##2{==##1++#1++##2==}% + }{% + \@latex@error{Inadmissible value '\string#1' for keya}\@ehc + } + + \ltxkeys@choicekey*+[KV]{fam}[mp@]{keyb}[\userinput\nr]{% + % There are callbacks for these nominations: + center/.code=\def\x##1{*##1*#1*##1}; + right/.code=\edef\z{\expandcsonce\ltxkeys@tval}; + left/.code=\edef\myinput{\cpttrimspaces{#1}}; + justified/.code=\letcsntocs{#1@align}\relax + }[center]{% + \def\x##1##2{==##1++#1++##2==}% + }{% + \@latex@error{Inadmissible value '\string#1' for keya}\@ehc + } + + \ltxkeys@choicekey[KV]{fam}[mp@]{keyb}[\userinput\nr]{% + % The callbacks can also take the following form: + center/\def\x##1{*##1*#1*##1}, + right/\edef\z{\expandcsonce\ltxkeys@tval}, + left/\edef\userinput{\cpttrimspaces{#1}}, + justified/\letcsntocs{#1@align}\relax + }[center]{% + \def\x##1##2{==##1++#1++##2==}% + } + + +\docsubsection{Defining boolean and command keys with one command} + +More than one boolean and command keys can be defined simultaneously by the following command: + + \ltxkeys@definekeys[pref]<fam>[macro-pref]{% + <key>=<default>/<callback>; another set of key; etc + } + + \ltxkeys@definekeys*[pref]<fam>[macro-pref]{% + <key>=<default>/<callback>; another set of key; etc + } + +<default> can be absent in the case of command keys, and <callback> can be absent for the two types of key. Boolean keys must, however, have default values {true | false}, to be distinguishable from command keys. The \plsign that separates the key name from the default value can be replaced with forward slash (/). That is, the following syntax is also permitted: + + \ltxkeys@definekeys[pref]<fam>[macro-pref]{% + <key>/<default>/<callback>; another set of key; etc + } + + \ltxkeys@definekeys*[pref]<fam>[macro-pref]{% + <key>/<default>/<callback>; another set of key; etc + } + +You can use the command \fx{\CheckInput} in \ang{callback} to introduce choice keys as command keys (see example below). + +Ordinary keys and conventional choice keys can't be introduced directly by this command (use \fx{\ltxkeys@declarekeys} instead). + +The \stform can be used to define new keys (in the sense of \hx{\newcommand}). + +\Note Keys defined by \fx{\ltxkeys@definekeys} are automatically set/initialized instantly, to provide default values for immediate use. Boolean keys are preset with value \quoted{false}, so that they aren't turned \quoted{true} prematurely. + +\Note In \ffx'{\ltxkeys@definekeys, \ltxkeys@declarekeys} every line is assumed to end with a comment sign. This is to be specially noted if a space is desired at the end of line. You can insert such a space with a comment sign, or, if appropriate, use \hx{\space}. + + Example (\stform -> new keys): + + \ltxkeys@definekeys*[KV]<fam>[mp@]{% + % command key with callback: + keya={keepbraced}/\def\x##1{##1*#1*##1}; + % boolean key: + keyb=true/\def\y##1{##1yyy#1}; + % command key with no callback: + keyc=xxx; + % choice-like command key: + keyd=center/\CheckInput{#1}{left,right,center} + \ifinputvalid + \edef\myval{\expandcsonce\userinput} + \edef\numberinlist{\number\nr} + \edef\mychoices{\expandcsonce\nominations} + \else + \@latex@error{Input `#1' not valid}\@ehd + \fi; + % boolean key with no callback: + keyc=false; + } + +In this example, \fx{\userinput} corresponds to \fx{#1}; \fx{\nr} is the numerical order of the user input in \fx{\nominations}; the list of valid values suggested at key definition time (\fnz{{left}{right}{center}} in this example). The boolean \fx{inputvalid} is associated with the command \fx{\CheckInput} and is available to the user. It is set \hx{true} when the user input is valid, and \hx{false} otherwise. + + +\docsubsection{Defining all types of key with one command} + +\start{newmacro}[\ltxkeys@declarekeys] +\ltxkeys@declarekeys[|A(pref)]<|A(fam)>[|A(mp)]{% |label(mac:declarekeys) + <|A(keytype)>/<|A(keyname)>/<|A(default)>/<|A(callback)>; another set of key; etc +} +\ltxkeys@declarekeys|*[|A(pref)]<|A(fam)>[|A(mp)]{% + <|A(keytype)>/<|A(keyname)>/<|A(default)>/<|A(callback)>; another set of key; etc +} +\finish{newmacro} + +Here, \ang{default} and \ang{callback} can be absent in all cases. \ang{keytype} may be any one of \fnz{{ord}{cmd}{sty}{sty*}{bool}{choice}}. + +The star (\redstar) in <sty\RedStar> has the same meaning as in \fx{\ltxkeys@stylekey} above. + +Choice keys must have their names associated with their admissible <alt> values in the format <keyname.{<alt>}> (see example below). + +The \stform can be used to define new keys (in the sense of \hx{\newcommand}). + +\Note Keys defined by \fx{\ltxkeys@declarekeys} are automatically set instantly, to provide default values for immediate use. Boolean keys are always initialized in this sense with \quoted{false}, so that they aren't turned \quoted{true} prematurely. + +\start{example}[\ltxkeys@declarekeys] +\ltxkeys@declarekeys*[KV]<fam>[mp@]{% + cmd/keya/mm/\def\x##1{##1*#1*##1}; + bool/keyb; + sty/keyc/xxx/\def\y##1{##1yyy#1}; + sty*/keyd/blue/\def\y##1{##1#1}/ + cmd>keye>\parentval>\def\z####1{####1+##1+####1}; + choice/keyf.{left,right,center}/ + \ifcase\nr\def\shoot{0}\or\def\shoot{1}\or\def\shoot{2}\fi; +} +\finish{example} + +Notice the \fx{>...>} used for the dependant key (\emph{keye}) attributes of style key \emph{keyd}. The default value of the dependant key \emph{keye} will in this example be whatever is submitted for \emph{keyd}. Notice also the syntax \keydotchoice{keyf}{left,right,center} for the choice key \emph{keyf}. It says that the alternate admissible values for \emph{keyf} are \emphlist'{left,right,center}. + + +\docsubsection{Need-value keys} + +Sometimes you may want to create keys for which the user must always supply his/her own values, even if the keys originally have default values. The default values of keys may not always be suitable. Take, for example, the height and width of a graphics image. For functions that are meant to handle generic images, it would certainly be inappropriate to relieve the user of the need to call picture height and width without corresponding values. + +To make a key a need-value key, simply attach the pointer \fx{\needvalue} to the key at definition time. This pointer can be used only when defining keys, and not when setting keys. + + Example: + + \ltxkeys@cmdkey[KV]{fam}[mp@]{\needvalue{keya}}[blue]{% + \def\x##1{##1x#1x##1}% + } + \ltxkeys@setkeys[KV]{fam}{keya} + % -> Error: the author of 'keya' designed it to require a user value. + +See more about key pointers in Section \amref{sec:}. + + +\docsection{Setting keys} + +Keys can be set by the following utilities: + +\docsubsection{Set defined keys} + + \ltxkeys@setkeys[|A(pref)]{|A(pref)}[|A(na)]{|A(keyvals)} + \ltxkeys@setkeys*+[|A(prefs)]{|A(fams)}[|A(na)]{|A(keyvals)} + +Here, \ang{prefs}, \ang{fams} and \ang{keyvals} are comma-separated list of key prefixes, families and \keyval pairs, respectively. Keys listed in the comma-separated list \ang{na} are ignored. The \stform will save all undefined keys with prefix \ang{pref} and in family \ang{fam} in the macro \fnl{pref}{fam}{rmkeys}, to be set later, perhaps with \fx{\ltxkeys@setrmkeys}. The \plform will search in all the prefixes in \ang{prefs} and all families in \ang{fams} for a key before logging the key in \fnl{pref}{fam}{rmkeys} (if the \makered{$*+$}-form is used) or reporting it as undefined. + +To avoid infinite re-entrance in \fx{\ltxkeys@setkeys} and the consequent bombing out of \fx{\ltxkeys@setkeys}, the package option \fx{keystacklimit} is introduced. Its default value is~4, meaning that \fx{\ltxkeys@setkeys} can't ordinarily be nested beyond level~4. If you must nest \fx{\ltxkeys@setkeys} beyond this level, you can raise the \fx{keystacklimit} as a package option via \hx{\usepackage} or, if \pkg'{catoptions} is loaded before \hx{\documentclass}, via \hx{\documentclass}. For example, + +\start{example} +\usepackage[keystacklimit=6]{ltxkeys} +\finish{example} +\fxim*{keystacklimit} + + +\docsubsection{Setting `remaining' keys} + +The command \fx{\ltxkeys@setrmkeys}, which has both star (\redstar) and plus (\redplus) variants is the counterpart of \fx{\setrmkeys} of the \pkg'{xkeyval}: + + \ltxkeys@setrmkeys[|A(pref)]{|A(pref)}[|A(na)] + \ltxkeys@setrmkeys*+[|A(prefs)]{|A(fams)}[|A(na)] + + +\docsubsection{Setting aliased keys} + +Alias and aliased keys differ from style keys. Two keys may be aliased to each other, such that when one is set, the alias is automatically set with the same or a different value. The concept is similar to, but not identical with, that of style keys. The two aliases must all be in the same family and have the same key and macro prefixes. + +\ltxkeys@setmnkey{<key>}[<value>] + +Here, \ang{value} is optional; if it is not given, \ang{key} will be set with the current value of its alias. The commands \ffx'{\setmnkey, \setaliaskey} are shortened variants of \fx{\ltxkeys@setmnkey}. + + Example: + + \ltxkeys@definekeys*[KV]<fam>[mp@]{% + printsign=true; + printmark=true/\ltxkeys@setmnkey{printsign}[false]; + keya=$+++$; + keyb=star/\ltxkeys@setmnkey{keya}[$***$] + } + \ltxkeys@definekeys*[KV]<fam>[mp@]{% + keya=sun/\CheckInput{#1}{star,sun,moon} + \ifinputvalid + \edef\givenval{\userinput} + \edef\found{\ifcase\nr star@\or sun@\or moon@\fi} + \else + \@latex@error{Input `#1' not valid}\@ehd + \fi; + keyb=star/\ltxkeys@setmnkey{keya}; + } + + +The boolean \fx{inputvalid} associated with the command \fx{\CheckInput} is described above in \amref{sec:}. + +The example of 'printsign' and 'printmark' is similar, but not equivalent, to the notion of biboolean keys. Biboolean keys have equal symmetry (\ie, they can call each other with equal propensity) and they won't bomb out in an infinite reentrance. This is not the case with aliased keys: only slave/alias can set or call master/main key. If they both call each other, the user will be alerted to the fact that there is an infinite reentrance of keys. The notion of 'slave' and 'master' used in the \pkg'{ltxkeys} may be counterintuitive but in reality it is quite logical. + +Schemes like the following are disallowed for obviously reasons; the package will flag an error if they occur: + +\start{example}[Nested \setmnkey] +\ltxkeys@ordkey[XWM]{main}{testa}[true]{\setmnkey{testb}} +\ltxkeys@ordkey[XWM]{main}{testb}[true]{\setmnkey{testa}} +\ltxkeys@setkeys[XWM]{main}{testa} +\finish{example} +\aidx*{Nested \headfx{\setmnkey}} + + +\docsubsection{Using key pointers} + +The \ffx'{\savevalue,\usevalue} pointers of the \pkg'{xkeyval} are still available at key setting time, but with increased robustness and optimization. Curly braces in values are preserved throughout, and instead of saving the value of each key tagged with \fx{\savevalue} in a separate macro, we save all such keys and their values in only one macro (for each combination of <pref> and <fam>) and use a fast search technique to find the values when they are needed later (by any key tagged with \fx{\usevalue}). + +Here is an interesting example (and test) of use of pointers: + + \ltxkeys@stylekey*[KV]{fam}{\needvalue{keya}}[{left}](% + % #1 here refers to the value of the dependant key + % at the time it is being set. + ord/\needvalue{keyb}/\parentval/\edef\y##1{##1xx\unexpanded{#1}}; + cmd/keyc/{center} + ){% + % #1 here refers to the value of the parent key + % at the time it is being set: + \def\x##1{##1xx#1} + } + \ltxkeys@setkeys[KV]{fam}{\savevalue{keya}={\def\y##1{##1}}, + \savevalue{keyb}=\usevalue{keya},keyc=\usevalue{keyb}} + + +\docsubsection{Accessing the saved value of a key} + +As mentioned earlier, the pointers \ffx'{\savevalue, \usevalue} are available only within \fx{\ltxkeys@setkeys}. But suppose you have used \fx{\savevalue} within \fx{\ltxkeys@setkeys} to set the value of a key, how do you access that value outside of \fx{\ltxkeys@setkeys}? You can do this by using the following \fx{\ltxkeys@storevalue} command: + + \ltxkeys@storevalue[<pref>]{<fam>}{<key>}<cs> + \ltxkeys@storevalue+[<pref>]{<fam>}{<key>}<cs><fallback> + +Here, <cs> is the macro (defined or undefined) that will receive the saved value of \ang{key}. The plain variant of this command will raise an error message if the value of the key wasn't previously saved, while the \plform will resort to the user-supplied function <fallback>. Only saved key values can be recovered by this command. + + Examples: + + \ltxkeys@cmdkey[KV]{fam}{\needvalue{keya}}[{left}]{% + \def\x##1{##1xx#1} + } + \ltxkeys@setkeys[KV]{fam}{\savevalue{keya}={\def\y##1{##1}}} + \ltxkeys@storevalue[KV]{fam}{keya}\tempa + \ltxkeys@storevalue+[KV]{fam}{keya}\tempb{% + \@latex@error{No value saved for key 'keya'}\@ehc + } + + +\docsubsection{Pre-setting and post-setting keys} + +\ltxkeys@presetkeys|![pref]{fam}{keys} +\ltxkeys@removepresetkeys|![pref]{fam}{keys} +\ltxkeys@undefpresetkeys|![pref]{fam} +\ltxkeys@postsetkeys|![pref]{fam}{keys} +\ltxkeys@removepostsetkeys|![pref]{fam}{keys} +\ltxkeys@undefpostsetkeys|![pref]{fam} + +\fx{\ltxkeys@presetkeys} means \quoted{these keys should be set before setting other keys in any run of \fx{\ltxkeys@setkeys}}. \fx{\ltxkeys@postsetkeys} means \quoted{these keys are to be set after setting other keys in any run of \fx{\ltxkeys@setkeys}}. \ffx'{\ltxkeys@removepresetkeys, \ltxkeys@removepostsetkeys} remove \ang{keys} from preset and post-set lists, respectively. \ffx'{\ltxkeys@undefpresetkeys,\ltxkeys@undefpostsetkeys}, respectively, undefine all preset and post-set keys in the given family. The \RedPrime means that the assignments would be done (and the lists built) globally rather than locally. + +Logically, you can't enter the same key twice in either preset or post-set list in the same family and prefix. + +\start+{example}[\ltxkeys@presetkeys, \ltxkeys@postsetkeys, etc.] +\ltxkeys@definekeys*[KV1]<fam1>[mp@]{% + keya/left/\def\x##1{#1x##1}; + \needvalue{keyb}/right; + keyc/center; + keyd +} +\ltxkeys@presetkeys|![KV1]{fam1}{keya=\flushleft,keyb=\flushright} +\ltxkeys@postsetkeys|![KV1]{fam1}{keyd=\flushleft} +... +|com(Eventually, only `keya' will be preset:) +\ltxkeys@removepresetkeys|![KV1]{fam1}{keyb=\flushright} +... +|com(Because of the |* and |+ signs, all unknown keys |(those in family `fam2'|)) +|com(will be saved in the list of remaining keys, and can be set later) +|com(with \ltxkeys@setrmkeys:) +\ltxkeys@setkeys|*|+[KV1,KV2]{fam1,fam2}[keyd]{keya=xxx,keyb=yyy,keyc} +\finish{example} + + +\docsubsection{Initializing keys} + + \ltxkeys@initializekeys[<prefs>]{<fams>}[<na>] + +This presets ALL keys previously defined in families \ang{fams} with their default values; it ignores keys listed in \ang{na}. If \ang{na} is a list of key-value pairs, the key names are extracted from the list before the family keys are initialized. Any key-value pairs in \ang{na} are not set at all. All keys defined by \ffx'{\ltxkeys@definekeys, \ltxkeys@declarekeys} are automatically instantly initialized, except slave/alias and dependant keys. Alias and dependant keys aren't initialized in this case in order to avoid cyclic re-entrance of \fx{\ltxkeys@setkeys}. + +The command \fx{\ltxkeys@initializekeys} can be used in place of \fx{\ltxkeys@executeoptions}, since \fx{\ltxkeys@executeoptions} (similar to \latex kernel's \hx{\ExecuteOptions}) fulfils the sole purpose of setting up default values of options. Keys defined via \ffx'{\ltxkeys@definekeys, \ltxkeys@declarekeys} don't have to be initialized, since they're automatically initialized at definition time. + + +\docsubsection{Launching keys} + + \ltxkeys@launchkeys[<pref>]{<fam>}[<curr>] + +This presets ALL keys defined in family <fam> with their default values; it ignores keys listed in <curr>. <curr> is actually the list of key-value pairs that the user wants to use as current values of keys. Their keys are to be ignored when setting up defaults, \ie, when initializing the family keys. One major difference between \ffx'{\ltxkeys@launchkeys, \ltxkeys@initializekeys} is that in \fx{\ltxkeys@launchkeys} the key-value pairs in <curr> are immediately set after the family keys are initialized. + +Note: Keys with multiple prefixes and from multiple families can't be launched at the same time. + + +\docsubsection{Handling undefined or unknown keys} + +You can use the macro \fx{\ltxkeys@unknownkeyhandler} to declare to the \pkg'{ltxkeys} the course of action to take if, while setting keys, it discovers that a key is undefined or unknown. The syntax of this command is + + \ltxkeys@unknownkeyhandler[<prefs>]{<fams>}{<callback>} + +where <callback> signifies the action to take. The default <callback> is to log the keys and warn the user, in each run, of the presence of unknown keys. The same <callback> can be used across key prefixes <prefs> and families \ang{fams}. You can use \fx{#1} (or \fx{\CurrentPref}) in this macro to represent the current key prefix, \fx{#2} (or \fx{\CurrentFam}) for the current family, #3 (or \fx{\CurrentKey}) for the current key name, and #4 (or \fx{\CurrentVal}) for the value of the current key. If \fx{\CurrentVal} contains undefined macros or active characters, then attempting to print it may cause problems. Therefore, when making entries in the transcript file, it will sometimes be preferable to use \fx{\InnocentVal} instead of \fx{\CurrentVal}. However, \fx{\InnocentVal} will give only the first eight characters of a key's value. + +The following example provides an unknown key handler for two key prefixes (\ffx'{KVA, KVB}) and two key families (\ffx'{fam1,fam2}): + +\start{example}[\ltxkeys@unknownkeyhandler] +\ltxkeys@unknownkeyhandler[KVA,KVB]{fam1,fam2}{% + \@expandtwoargs\in@{,#3,}{,\myspecialkeylist,}%|amref(mac:handledkey) + \ifin@ + % The reader may want to investigate what the parameter + % characters ##1 and ####1 here stand for: + \ltxkeys@ordkey[#1]{#2}{#3}[#4]{\def\x####1{####1xx##1}}% + \else + \@ltx@warn{Unknown key `#3' with value `#4' in family `#2' ignored}\@ehd + % \@ltx@warn{Unknown key `\CurrentKey' with value + % `\InnocentVal' in family `\CurrentFam' ignored}\@ehd + \fi +} +\finish{example} + +The macro \fx{\myspecialkeylist} in the above example doesn't actually exist; it is only meant for illustration here. But \quoted{handled keys} may be introduced by the user to serve this purpose. This will be the set of keys for which special actions may apply at key setting time (see \amref{sec:}). + + +\Note Similar to \fx{\ltxkeys@unknownkeyhandler} (which applies to keys), there is also the \fxi{\ltxkeys@unknownoptionhandler} (which applies to package or class options---see \amref{sec:}). + + +\docsection{Checking if a key is defined} + + \ltxkeys@ifkeydefTF[<prefs>]{<fams>}{<key>}{<true text>}{<false text>} + \ltxkeys@ifkeydefFT[<prefs>]{<fams>}{<key>}{<false text>}{<true text>} + +These check if \ang{key} is defined with a prefix in <prefs> and in family in \ang{fams}. + + + +\docsection{Disabling keys} + + \ltxkeys@disablekeys[<prefs>]{<fams>}{<keys>} + \ltxkeys@disablekeys*[<prefs>]{<fams>}{<keys>} + +The command \fx{\ltxkeys@disablekeys} causes an error to be issued when a disabled key is invoked. If the package option 'verbose' is true, undefined keys are highlighted by \fx{\ltxkeys@disablekeys} with a warning message. Because it is possible to mix prefixes and families in \fx{\ltxkeys@disablekeys}, undefined keys may be readily encountered. To see those undefined keys, enable the package option 'verbose'. + +The plain form of \fx{\ltxkeys@disablekeys} disables the given keys instantly, while the \stform variant disables the keys at \hx{\AtBeginDocument}. Authors can use this command to bar users of their keys from calling those keys after a certain point. + + +\docsection{Option and non-option keys} + +Sometimes you want to create keys that can only appear in \hx{\documentclass}, \hx{\RequirePackage} or \hx{\usepackage}, and at other times you may not want the user to submit a certain set of keys via these commands. The \pkg'{xwatermark}, for example, uses this concept. + + \option@keys[<pref>]{<fam>}{<keys>} + \option@keys*[<pref>]{<fam>}{<keys>} + \notoption@keys[<pref>]{<fam>}{<keys>} + +Keys listed in \option@keys can appear only in arguments of \hx{\documentclass}, \hx{\RequirePackage} or \hx{\usepackage}, while keys listed in \notoption@keys can't appear in these macros. The \stform of \option@keys is equivalent to \notoption@keys. Only defined keys may appear in \option@keys and \notoption@keys. + + \makeoption@keys[<pref>]{<fam>} + \makeoption@keys*[<pref>]{<fam>} + +The command \makeoption@keys makes all the keys with prefix <pref> and in family <fam> options keys. The \stform of \makeoption@keys is equivalent to \makenotoption@keys. + + +\docsection{Declaring and processing options} + + \ltxkeys@declareoption[<pref>]<<fam>>{<key>}[<default>]{<callback>} + \ltxkeys@declareoption*[<pref>]<<fam>>{<key>}[<default>]{<callback>} + +The command \fx{\ltxkeys@declareoption} is simply a form of \fx{\ltxkeys@ordkey}, with the difference that the key family <fam> is now optional and, when specified, must be given in angled brackets. The default family name is \quotedhx{\@currname.\@currext}, \ie, the name of the class file or package and its file extension. + +The \stform of \fx{\ltxkeys@declareoption} prescribes the default action to be taken when undefined options with prefix <pref> and in family <fam> are passed to class or package. You may use \fx{\CurrentKey} and \fx{\CurrentVal} within this macro to pass the unknown option and its value to another class or package or to specify other actions. In fact, you can use \fx{#1} in this macro to represent the current key prefix, \fx{#2} for the current family, #3 for the current key name, and #4 for the value of the current key. The command \fx{\ltxkeys@unknownoptionhandler} is equivalent to the \stform of \fx{\ltxkeys@declareoption}. + +\Note The \stform of \fx{\ltxkeys@declareoption} differs from the \stform of LaTeX's \hx{\DeclareOption} and the \stform of \pkg'{xkeyval}'s \hx{\DeclareOptionX}. + + +++ + Examples (of use of \stform of \fx{\ltxkeys@declareoption}): + + \ltxkeys@declareoption*[KV]<mypackage>{% + \PackageWarning{mypackage}{% + Unknown option `\CurrentKey' with value `\CurrentVal' ignored}% + } + + \ltxkeys@declareoption*{\PassOptionsToClass{#3}{article}} + + \ltxkeys@unknownoptionhandler[KV]<mypackage>{% + % The macro \myextraoptions doesn't actually exist; + % it is only meant for illustration here: + \@expandtwoargs\in@{,#3,}{,\myextraoptions,}% + \ifin@ + % The reader may want to investigate what the parameter characters + % ##1 and ####1 here stand for: + \ltxkeys@ordkey[#1]{#2}{#3}[#4]{\def\x####1{####1xx##1}}% + \else + \PassOptionsToClass{#3}{myclass}% + \fi + } + +++ + + \ltxkeys@declarecmdoption[<pref>]<<fam>>[<mp>]{<key>}[<default>]{<callback>} + \ltxkeys@declarebooloption[<pref>]<<fam>>[<mp>]{<key>}[<default>]{<callback>} + \ltxkeys@declarechoiceoption[<pref>]<<fam>>[<mp>]{<key>}[<default>]{<callback>} + +These are the equivalents of \ffx'{\ltxkeys@cmdkey, \ltxkeys@boolkey, \ltxkeys@choicekey}, respectively, but now the family <fam> is optional (as is \ang{pref}) and, when specified, must be given in angled brackets. The default family name for these new commands is \quotedhx{\@currname.\@currext}, \ie, the current style or class filename and filename extension. + + + \ltxkeys@executeoptions[<pref>]<<fams>>[<na>]{<key-val>} + +This executes/sets the key-value pairs given in \keyval. The optional \ang{na} specifies the list of keys (without values) to be ignored. \ang{fams} signifies families in which the keys suggested in \keyval have been defined. The command \fx{\ltxkeys@executeoptions} can thus be used to process keys from several families. + + + \ltxkeys@processoptions[<pref>]<<fams>>[<na>] + \ltxkeys@processoptions*[<pref>]<<fams>>[<na>] + +The command \fx{\ltxkeys@processoptions} processes the keys and values passed by the user to the class or package. The optional argument \ang{na} can be used to specify keys that should be ignored. The optional argument \ang{fams} can be used to specify the families that have been used to define the keys. This macro doesn't protect expandable macros in the user inputs unless the \pkg'{catoptions} is loaded before \hx{\documentclass}, in which case it might be better using the command \hx{\XProcessOptions} of the \pkg'{catoptions}. When used in a class file, the macro \fx{\ltxkeys@processoptions} will ignore unknown keys or options. This allows the user to use global options in the \hx{\documentclass} command which can be inherinted by packages loaded afterwards. + +The \stform of \fx{\ltxkeys@processoptions} works like the plain variant except that it also copies user input from the \hx{\documentclass} command. When the user specifies an option in the \hx{\documentclass} which also exists in the local family or families of the package issuing \fx{\ltxkeys@processoptions}\RedStar, the local key too will be set. In this case, \fx{#1} in the \fx{\ltxkeys@declareoption} (or a similar command) will be the value entered in the \hx{\documentclass} command for this key. First the global options from \hx{\documentclass} will set local keys and afterwards the local options, specified via \hx{\usepackage}, \hx{\RequirePackage} or \hx{\LoadClass}, will set local keys, which could overwrite the previously set global options, depending on the way the options sections are constructed. + + +\docsection{Handled keys} + +As mentioned in \amref{sec:}, handled keys are keys defined in a macro that is key-prefix and key-family dependent. They are defined as a list in a macro so that they can be used for future applications, such as deciding if a dependant key of a style key should be defined or redefined on the fly. Handled keys should be defined, or added to, using key prefix, family and key names. You can define or add to handled keys by the following command: + +\start{newmacro}[\ltxkeys@handledkeys] +\ltxkeys@handledkeys[|A(pref)]{|A(fam)}{|A(list)} +\finish{newmacro} +\fxim*{\ltxkeys@handledkeys} + +where \ang{list} is a comma-separated list of key names. This command can be issued more than once for the same key prefix \ang{pref} and family \ang{fam}, since the content of \ang{list} is usually merged with the existing list rather than being merely added or overwritten. + +\start{example}[\ltxkeys@handledkeys] +\ltxkeys@handledkeys[KVA,KVB]{fam1,fam2}{keya,keyb,keyc} +\finish{example} + +For a given key prefix \ang{pref} and family \ang{fam}, you can recall the full list of handled keys (set up earlier by \fx{\ltxkeys@handledkeys}) by the command + +\start{macro}[List of handled keys] +\|A(pref)@|A(fam)@handledkeys +\finish{macro} +\aidx*{Recalling the list of handled keys} +% \ipreffam{handledkeys} + +If handled keys have been set up in, \eg, \fx{\KV@fam@handledkeys}, the example at \amref{mac:handledkey} can be recast as follows: + +\start{example}[\ltxkeys@handledkeys] +\ltxkeys@unknownkeyhandler[KVA,KVB]{fam1,fam2}{% + \@expandtwoargs\in@{,#3,}{,\KV@fam@handledkeys,}% + \ifin@ + \ltxkeys@ordkey[#1]{#2}{#3}[#4]{\def\x####1{####1xx##1}}% + \else + \@ltx@warn{Unknown key `#3' with value `#4' in family `#2' ignored}\@ehd + \fi +} +\finish{example} + +You can remove handled keys from a given list of handled keys (in a family) by the following command: + +\start{newmacro}[\ltxkeys@removehandledkeys] +\ltxkeys@removehandledkeys[|A(pref)]{|A(fam)}{|A(list)} +\finish{newmacro} +\fxim*{\ltxkeys@removehandledkeys} + +Rather than remove individual handled keys from a list, you might prefer or need to simply undefine or \quoted{emptify} the entire list of handled keys in a family. You can do these with the following commands: + +\start+{newmacro}[\ltxkeys@undefhandledkeys,\ltxkeys@emptifyhandledkeys] +\ltxkeys@undefhandledkeys[|A(pref)]{|A(fam)} +\ltxkeys@emptifyhandledkeys[|A(pref)]{|A(fam)} +\finish{newmacro} +\fxim*{\ltxkeys@undefhandledkeys,\ltxkeys@emptifyhandledkeys} + + +\docsection{Bad key names} + +Some key names are indeed inadmissible. The \pkg{ltxkeys} considers the following key names as inadmissible: + +\start'{macro}[default bad keys] +.code,ordkey,cmdkey,stylekey,choicekey,boolkey,handledkeys,presetkeys,postsetkeys +\finish{macro} + +For reasons of efficiency, the \pkg{ltxkeys} will attempt to catch bad key names only if the package option \fx{verbose} is enabled. + +You can add to the list of invalid key names by the following command: + +\start{newmacro}[\ltxkeys@badkeynames] +\ltxkeys@badkeynames{|A(list)} +\finish{newmacro} +\fxim*{\ltxkeys@badkeynames} + +where \ang{list} is a comma-separated list of inadmissible names. The updating is done by merging, so that entries are not repeated in the internal list of bad key names. + +You can remove from the list of bad key names by using the following command: + +\start{newmacro}[\ltxkeys@badkeynames] +\ltxkeys@removebadkeynames{|A(list)} +\finish{newmacro} +\fxim*{\ltxkeys@removebadkeynames} + +where, again, \ang{list} is comma-separated. + +TO-DO: + +1. Reserved key names, reserved key prefixes, reserved key families. + + +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.txt b/Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.txt deleted file mode 100644 index f6428e5d497..00000000000 --- a/Master/texmf-dist/doc/latex/ltxkeys/ltxkeys-guide.txt +++ /dev/null @@ -1,530 +0,0 @@ -This is ltxkeys-guide.tex, a minimal guide to the ltxkeys package. - -Version 0.1.0, July 2011 - -Ahmed Musa (amusa22@gmail.com) - - -SUMMARY - -The ltxkeys package provides facilities for creating and managing keys in the sense of the keyval and xkeyval packages, but it is intended to be more robust and faster than these earlier packages. Its robustness emanates from, inter alia, its ability to preserve braces in key values throughout parsing. The need to preserve braces in key values emerges often in parsing keys. This is the case in, eg, the xwatermark package. The package is faster than the xkeyval package because it avoids character-wise parsing of key values (which is called 'selective sanitization' by the xkeyval package). - -Anyone familiar with the implementation of the xkeyval package would have noticed that the macro \XKV@srstate, which (in order to allow \setkeys to be re-entrant) pushes and pops the states of some important functions in the package, loops over all the functions both when pushing and popping. In the ltxkeys package, pushing and popping functions together involve only one loop. And, unlike in the xkeyval package, higher order functions are undefined as soon as they are no longer needed, to avoid clogging up the stack. - -In setting keys, the ltxkeys package loops over not only families, as in the xkeyval package, but also over key prefixes. The same strategy applies when the xkeyval package tries to establish if a key is defined or not. - -Note: While many aspects of the ltxkeys package are similar to those of the xkeyval package, there are important differences in several areas of syntax, semantics, and internal implementation. - -The ltxkeys package also provides additional facilities (beyond the xkeyval package) for defining and managing keys. Several types of keys (including ordinary keys, command keys, style keys, choice keys, boolean and biboolean keys) can be efficiently created and managed. - -In the ltxkeys package, the notion of 'presetting' keys differs from that of the xkeyval package. Only 'initialized' or 'launched' keys (see \autoref{sec:xxx})' are preset in the ltxkeys package. - -What is the origin of 'ltxkeys'? Well, I decided to write this package as I grabbled with some practical problems of key parsing while developing version 1.5.0 of the xwatermark package. The tasks proved more challenging than I had predicted and, despite its commendable facilities, I found the xkeyval package inadequate in some respects. As mentioned earlier, the functionalities of the ltxkeys can be employed for general key management in \latex beyond the xwatermark package. - - -NOTE - -This user manual doesn't describe the full range of features of the ltxkeys package. -I will produce a pdf version of this guide with suitable markups in the near future, especially if someone informs me that he/she is using, or intends to use, this package. This sounds unconventional but there is no point in spending precious time now preparing a documentation that no one has a need for or is unlikely to be needed. The reason why I am releasing this documentation now is that users of the xwatermark package need an update immediately, to address some shortcomings of the current public version. But the new version of the xwatermark package relies on the ltxkeys package. - - -DEFINING KEYS - - In the following, quantities in square brackets --- eg '[yyy]' --- and those in parenthesis --- eg (yyy) --- are optional. - -1. Ordinary keys: - - \ltxkeys@ordkey[<pref>]{<fam>}{<key>}[<default>]{<callback>} - - This defines a macro of the form \<pref>@<fam>@<key> of one argument that holds the key function <callback>. The default value for <pref> is always KV, as in the xkeyval package. When <key> is used in a \ltxkeys@setkeys command (see \autoref{sec:}) containing key=value, the macro \<pref>@<fam>@<key> takes the value as its argument and is then executed. The given argument or key value can be accessed in <callback> by using #1 inside the function. The optional <default>, if available, will be used by \<pref>@<fam>@<key> when the user hasn't provided a value for the key at \ltxkeys@setkeys. If <default> was absent at key definition and the key user hasn't provided a value for the key, an error message will be flagged. - - -2. Command keys: - - \ltxkeys@cmdkey[<pref>]{<fam>}[<mp>]{<key>}[<default>]{<callback>} - - The optional <mp> is called the 'macro prefix' (in the parlance of the xkeyval package). If <mp> is given, the command \<mp><key> will hold the current user input; otherwise (if <mp> is absent) the user input will be available in \cmd<pref>@<fam>@key. The command \<pref>@<fam>@key, called the \quoted{key macro} by the xkeyval package, will hold the <callback>. - - -3. Style keys (keys with dependant keys): - - \ltxkeys@stylekey[<pref>]{<fam>}[<mp>]{<key>}[<default>](<dependants>){<callback>} - - \ltxkeys@stylekey*[<pref>]{<fam>}[<mp>]{<key>}[<default>](<dependants>){<callback>} - - The <dependants> have the syntax: - - {<keytype>/<keyname>/<default>/<callback>; another set of dependant; etc} - - <default> and <callback> can be absent. <keytype> can be 'ord' (ordinary key), 'cmd' (command key), 'bool' (boolean key), or 'choice' (choice key). - - Dependants keys always share the same key prefix <pref>, family <fam>, and macro prefix <mp> with the parent key. - - If <mp> is given, the command \<mp><key> will hold the current user input for the parent key; otherwise the user input will be available in \style<pref>@<fam>@key. The command \<pref>@<fam>@key will always hold the <callback>. - - If the *-form is used, all undefined dependants will be defined and set on the fly as the parent is being set. If the *-form isn't used and undefined dependants occur, then an error message will be flagged at the time the parent is being set. - - At most times it is possible to access the parent key's current value with \parentval. Within <default> and <callback> of <dependants>, it is possible to refer to the parent key's callback with its full macro name (ie, \<pref>@<fam>@<key>). \parentval is always available for use as the default value of dependant keys, but it may be lost in the callbacks of dependant keys, because a dependant key, once defined, may be set independent of, and long after, the parent key has been executed. It is therefore more reliable to refer to the macro \<pref>@<fam>@<key>@value, which is recorded for only the parent key of style keys and which holds the current user input for the parent key. The macro \<pref>@<fam>@<key>@value is recorded only if it appears at least once in the attributes of dependant keys. The macro \<pref>@<fam>@<key>@value has a more unique name than \<mp>@<key> but they always contain the same value of a style key. As mentioned above, if <mp> is not given, the user input for a style key will be available in the macro \style<pref>@<fam>@key, instead of \<mp>@<key>. - - Note: '#1' in the callback of parent key refers to the current value of the parent key, while '#1' in the callback of any dependant key refers to the current value of that dependant key. - - Example (define and set all undefined dependants on the fly): - - \ltxkeys@stylekey*[KV]{fam}[mp@]{keya}[{left}](% - % '#1' here refers to the value of the DEPENDANT key - % at the time it is being set. Use \parentkey and \parentval - % here to access the parent key name and its current value: - ord/keyb/{right}/\def\y##1{#1##1}; - % The default of keyc is the current value of parent (keya): - cmd/keyc/\parentval; - % Because \KV@fam@keya@value appears below, it will be saved - % when the parent key (keya) is being set, otherwise it would be - % unavailable: - bool/keyd/true/\ifmp@keyd\edef\x##1{##1\KV@fam@keya@value}\fi - ){ - % '#1' here refers to the value of the PARENT key - % at the time it is being set: - \def\x##1{##1xx#1xx}% - % Check the value of parent key: - \ltxkeys@checkchoice[\val\nr]{#1}{left,right,center}% - } - - \ltxkeys@setkeys[KV]{fam}{keya={right}} - - The braces in the values are just to exemplify the fact that braces in key values are preserved throughout key parsing. This is essential in, for example, the xwatermark package. - - -4.1 Boolean keys: - - \ltxkeys@boolkey[<pref>]{<fam>}[<mp>]{<key>}[<default>]{<callback>} - - \ltxkeys@boolkey+[<pref>]{<fam>}[<mp>]{<key>}[<default>]{<callback>}{<fn>} - - If <mp> is given, the command \<mp><key> will hold the current user input for the key at key setting time; otherwise the user input will be available in \bool<pref>@<fam>@key\footnote{This differs from the system in the xkeyval package.}. If <mp> is specified, a boolean of the form \if<mp><key> will be created at key definition, which will be set by \ltxkeys@setkeys according to the user input. If <mp> is not specified, a boolean of the form \ifbool<pref>@<fam>@key will instead be created. - - The user input for boolean keys must be in the set {true | false}. The command \<pref>@<fam>@key will always hold the <callback>, which will be executed if the user input is valid. - - The +-form of \ltxkeys@boolkey will execute <fn> in place of <callback> if the user input isn't in {true | false}; the plain form will issue an error in this case. - - -4.2 Biboolean keys: - - \ltxkeys@biboolkeys[<pref>]{<fam>}[<mp>]{<bool1>,<bool2>} - [<default>]{<callback1>}{<callback2>} - - \ltxkeys@biboolkeys+[<pref>]{<fam>}[<mp>]{<bool1>,<bool2>} - [<default>]{<callback1>}{<callback2>}{<fn>} - - Biboolean keys always assume opposite states: when one is true, the other is automatically toggled to false; and vice versa. Think of the options 'draft' and 'final' in a document class. Note: this is currently not the case with traditional document classes. - - <callback1> belongs to the boolean key <bool1>, while <callback2> belongs to <bool2>. - - The +-form of \ltxkeys@biboolkeys will execute <fn> in place of <callback1> or <callback2> if the input is not in {true | false}; the plain form will issue an error in this case. - - Biboolean keys have equal symmetry (ie, they can call each other with equal propensity) and they won't bomb out in an infinite reentrance. They normally would know if they're calling each other. - - Example: - - \ltxkeys@biboolkeys+[KV]{fam}[mp@]{keya,keyb}[true]{% - \ifmp@keya\def\x##1{##1x#1x##1}\fi - }{% - \ifmp@keyb\def\y##1{##1y#1y##1}\fi - }{% - \@latex@error{Invalid value '\string#1' for keya or keyb}\@ehc - } - - -5. Choice keys (with macro prefix, unlike in xkeyval package): - - \ltxkeys@choicekey[<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<default>]{<callback>} - - \ltxkeys@choicekey*+[<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<default>]{<callback>}{<fn>} - - If <mp> is absent, then \ltxkeys@choicekey uses \chc<pref>@<family>@<key> to hold the user input. - - <alt> is the list of nominations for the key value, ie, admissible values of the key. When <alt> has no /.code in it, it has the familiar syntax: - - {choice1, choice2, etc} - - while if it has /.code in it, it has the syntax: - - {choice1/.code=callback1; choice2/.code=callback2; etc} - - It is possible to refer to the current value of <key> as '#1' in <alt>. - - The *-form will convert the user input to lowercase before checking <alt> and executing the callbacks. - - The +-form will execute <fn> in place of <callback> if the user input isn't in <alt>. - - <bin> has, eg, the syntax [\val\nr], where \val will hold the user input (in lowercase if the *-form of \ltxkeys@choicekey is called), and \nr will hold the serial number of the value in the list of nominations <alt>, starting from 0. If the input isn't valid, \val will still hold the user input, but \nr will be -1. - - Example (defining choice key): - - \ltxkeys@choicekey*+[KV]{fam}[mp@]{keya}[\val\nr]{% - % There are no callbacks for these simple nominations: - center,right,left,justified - }[center]{% <- default value - \def\x##1##2{==##1++#1++##2==}% - }{% - \@latex@error{Inadmissible value '\string#1' for keya}\@ehc - } - - \ltxkeys@choicekey*+[KV]{fam}[mp@]{keyb}[\val\nr]{% - % There are callbacks for these nominations: - center/.code=\def\x##1{*##1*#1*##1}; - right/.code=\edef\z{\expandcsonce\ltxkeys@tval}; - left/.code=\edef\userinput{\cpttrimspaces{#1}}; - justified/.code=\letcsntocs{#1@align}\relax - }[center]{% - \def\x##1##2{==##1++#1++##2==}% - }{% - \@latex@error{Inadmissible value '\string#1' for keya}\@ehc - } - - -6. Defining boolean and command keys with one command: - - More than one boolean and command keys can be defined simultaneously by the following command: - - \ltxkeys@definekeys[pref]<fam>[macro-pref]{% - <key>=<default>/<callback>; another set of key; etc - } - - \ltxkeys@definekeys*[pref]<fam>[macro-pref]{% - <key>=<default>/<callback>; another set of key; etc - } - - <default> can be absent in the case of command keys, and <callback> can be absent for the two types of key. Boolean keys must, however, have default values {true | false}, to be distinguishable from command keys. - - You can use \CheckInput in <callback> to introduce choice keys as command keys (see example below). - - Ordinary keys and conventional choice keys can't be introduced directly by this command (use \ltxkeys@declarekeys instead). - - The *-form can be used to define new keys (in the sense of \newcommand). - - Note: Keys defined by \ltxkeys@definekeys are automatically set instantly, to provide default values for immediate use. Boolean keys are set with 'false', so that they aren't turned 'true' prematurely. - - In \ltxkeys@definekeys and \ltxkeys@declarekeys every line is assumed to end with a comment sign. - - Example (*-form -> new keys): - - \ltxkeys@definekeys*[KV]<fam>[mp@]{% - % command key with callback: - keya={keepbraced}/\def\x##1{##1*#1*##1}; - % boolean key: - keyb=true/\def\y##1{##1yyy#1}; - % command key with no callback: - keyc=xxx; - % choice-like key: - keyd=center/\CheckInput{#1}{left,right,center} - \ifinputvalid - \edef\myval{\expandcsonce\userinput} - \edef\numberinlist{\number\nr} - \else - \@latex@error{Input '#1' not valued}\@ehd - \fi; - } - - -7. Defining all types of key with one command: - - \ltxkeys@declarekeys[pref]<fam>[macro-pref]{% - <keytype>/<keyname>/<default>/<callback>; another set of key; etc - } - \ltxkeys@declarekeys*[pref]<fam>[macro-pref]{% - <keytype>/<keyname>/<default>/<callback>; another set of key; etc - } - - Here, <default> and <callback> can be absent in all cases. - - <keytype> may be any one of - - <ord> | <cmd> | <sty> | <sty*> | <bool> | <choice> - - The star (*) in <sty*> has the same meaning as in \ltxkeys@stylekey above. - - Choice keys must have their names associated with their admissible <alt> values in the format <keyname.{<alt>}> (see example below). - - The *-form can be used to define new keys (in the sense of \newcommand). - - Note: Keys defined by \ltxkeys@declarekeys are automatically set instantly, to provide default values for immediate use. Boolean keys are always initialized in this sense with 'false', so that they aren't turned 'true' prematurely. - - Example: - - \ltxkeys@declarekeys*[KV]<fam>[mp@]{% - cmd/keya/mm/\def\x##1{##1*#1*##1}; - bool/keyb; - sty/keyc/xxx/\def\y##1{##1yyy#1}; - sty*/keyd/blue/\def\y##1{##1#1}/ - cmd>keye>\parentval>\def\z####1{####1+##1+####1}; - choice/keyf.{left,right,center}/ - \ifcase\nr\def\shoot{0}\or\def\shoot{1}\or\def\shoot{2}\fi; - } - - Notice the >...> used for the dependant key ('keye') attributes of style key 'keyd'. The default value of the dependant key keye will in this example be whatever is submitted for keyd. - - -6. Need-value keys: - - Sometimes you may want to create keys for which the user must always supply his/her own values, even if the keys originally have default values. The default values of keys may not always be suitable. Take, for example, the height and width of a graphics image. For functions that are meant to handle generic images, it would certainly be inappropriate to relieve the user of the need to call picture height and width without corresponding values. - - To make a key a need-value key, simply attach the pointer \needvalue to the key at definition time. This pointer can be used only when defining keys, and not when setting keys. - - Example: - - \ltxkeys@cmdkey[KV]{fam}[mp@]{\needvalue{keya}}[blue]{% - \def\x##1{##1x#1x##1}% - } - \ltxkeys@setkeys[KV]{fam}{keya} - % -> Error: the author of 'keya' designed it to require a user value needed - - See more about key pointers in Section \autoref{sec:xxx}. - - -SETTING KEYS - - Keys can be set by the following utilities: - -1. Set defined keys: - - \ltxkeys@setkeys[<pref>]{<fam>}[<na>]{<key-val>} - \ltxkeys@setkeys*+[<prefs>]{<fams>}[<na>]{<key-val>} - - Keys in <na> are ignored. The *-form will save all undefined keys with prefix <pref> and in family <fam> in \<pref>@<fam>@rmkeys, to be set later, perhaps with \ltxkeys@setrmkeys. The +-form will search in all the prefixes in <prefs> and all families in <fams> for a key before logging the key in \<pref>@<fam>@rmkeys (if the *+-form is used) or reporting it as undefined. - - -2. Set 'remaining' keys after defined keys have been set: - - The command \ltxkeys@setrmkeys, which has both star (*) and plus (+) variants is the counterpart of \setrmkeys of the xkeyval package: - - \ltxkeys@setkeys[<pref>]{<fam>}[<na>] - \ltxkeys@setkeys*+[<prefs>]{<fams>}[<na>] - - -3. Set a 'main' (master) key from its 'alias' (slave): - - Aliased/alias keys differ from style keys. Two keys may be aliased to each other, such that when one is set, the alias is automatically set with the same or a different value. The concept is similar to, but not identical with, that of style keys. The two aliases must all be in the same family and have the same key and macro prefixes. - - \ltxkeys@setmnkey{<key>}[<value>] - - Here, <value> is optional; if it is not given, <key> will be set with the current value of its alias. The commands \setmnkey and \setaliaskey are a shortened variants of \ltxkeys@setmnkey. - - Example: - - \ltxkeys@definekeys*[KV]<fam>[mp@]{% - printsign=true; - printmark=true/\ltxkeys@setmnkey{printsign}[false]; - keya=$+++$; - keyb=star/\ltxkeys@setmnkey{keya}[$***$] - } - \ltxkeys@definekeys*[KV]<fam>[mp@]{% - keya=sun/\CheckInput{#1}{star,sun,moon} - \ifinputvalid - \edef\givenval{\userinput} - \edef\found{\ifcase\nr star@\or sun@\or moon@\fi} - \else - \@latex@error{Input '#1' not valid}\@ehd - \fi; - keyb=star/\ltxkeys@setmnkey{keya}; - } - - The macro \userinput is the value given by the user at the time of calling/using the key, always converted internally to lower case; and \nr is the serial number of the user input in the nominations, starting from 0. 'inputvalid' is an internal boolean, available to the user. - - The example of 'printsign' and 'printmark' is similar, but not equivalent, to the notion of biboolean keys. Biboolean keys have equal symmetry (ie, they can call each other with equal - propensity) and they won't bomb out in an infinite reentrance. This is not the case with aliased keys: only slave/alias can set or call master/main key. If they both call each other, the user will be alerted to the fact that there is an infinite reentrance of keys. The notion of 'slave' and 'master' used in the ltxkeys package may be counterintuitive but in reality it is quite logical. - - -4. Using key pointers: - - The \savevalue and \usevalue pointers of the xkeyval package are still available at key setting time, but with increased robustness and optimization. Curly braces in values are preserved throughout, and instead of saving the value of each key tagged with \savevalue in a separate macro, we save all such keys and their values in only one macro (for each combination of <pref> and <fam>) and use a fast search technique to find the values when they are needed later (by any key tagged with \usevalue). - - Here is an interesting example (and test) of use of pointers: - - \ltxkeys@stylekey*[KV]{fam}{\needvalue{keya}}[{left}](% - % #1 here refers to the value of the dependant key - % at the time it is being set. - ord/\needvalue{keyb}/\parentval/\edef\y##1{##1xx\unexpanded{#1}}; - cmd/keyc/{center} - ){% - % #1 here refers to the value of the parent key - % at the time it is being set: - \def\x##1{##1xx#1} - } - \ltxkeys@setkeys[KV]{fam}{\savevalue{keya}={\def\y##1{##1}}, - \savevalue{keyb}=\usevalue{keya},keyc=\usevalue{keyb}} - - -5. Accessing the saved value of a key: - - As mentioned earlier, the pointers \savevalue and \usevalue are available only within \ltxkeys@setkeys. But suppose you have used \savevalue within \ltxkeys@setkeys to set the value of a key, how do you access that value outside of \ltxkeys@setkeys? You can do this by using the following \ltxkeys@storevalue command: - - \ltxkeys@storevalue[<pref>]{<fam>}{<key>}<cs> - \ltxkeys@storevalue+[<pref>]{<fam>}{<key>}<cs><fallback> - - Here, <cs> is the macro (defined or undefined) that will receive the saved value of <key>. The plain variant of this command will raise an error message if the value of the key wasn't previously saved, while the +-form will resort to the user-supplied function <fallback>. Only saved key values can be recovered by this command. - - Examples: - - \ltxkeys@cmdkey[KV]{fam}{\needvalue{keya}}[{left}]{% - \def\x##1{##1xx#1} - } - \ltxkeys@setkeys[KV]{fam}{\savevalue{keya}={\def\y##1{##1}}} - \ltxkeys@storevalue[KV]{fam}{keya}\tempa - \ltxkeys@storevalue+[KV]{fam}{keya}\tempb{% - \@latex@error{No value saved for key 'keya'}\@ehc - } - - - -INITIALIZING KEYS - - \ltxkeys@initializekeys[<prefs>]{<fams>}[<na>] - - This presets ALL keys previously defined in families <fams> with their default values; it ignores keys listed in <na>. If <na> is a list of key-value pairs, the key names are extracted from the list before the family keys are initialized. Any key-value pairs in <na> are not set at all. All keys defined by \ltxkeys@definekeys and \ltxkeys@declarekeys are automatically instantly initialized, except slave/alias and dependant keys. - - The command \ltxkeys@initializekeys can be used to save estate when listing keys in \ltxkeys@executeoptions. - - -LAUNCHING KEYS - - \ltxkeys@launchkeys[<pref>]{<fam>}[<curr>] - - This presets ALL keys defined in family <fam> with their default values; it ignores keys listed in <curr>. <curr> is actually the list of key-value pairs that the user wants to use as current values of keys. Their keys are to be ignored when setting up defaults, ie, when initializing the family keys. One major difference between \ltxkeys@launchkeys and \ltxkeys@initializekeys is that in \ltxkeys@launchkeys the key-value pairs in <curr> are immediately set after the family keys are initialized. - - Note: Keys with multiple prefixes and from multiple families can't be launched at the same time. - - -HANDLING UNDEFINED OR UNKNOWN KEYS - - You can use the macro \ltxkeys@unknownkeyhandler declare to the ltxkeys package the course of action to take if, while setting keys, it discovers that a key is undefined or unknown. The syntax of this command is - - \ltxkeys@unknownkeyhandler[<prefs>]{<fams>}{<callback>} - - where <callback> signifies the action to take. The default <callback> is to log the keys and warn the user, in each run, of the presence of unknown keys. The same <callback> can be used across key prefixes <prefs> and families <fams>. You can use #1 (or \CurrentPref) in this macro to represent the current key prefix, #2 (or \CurrentFam) for the current family, #3 (or \CurrentKey) for the current key name, and #4 (or \CurrentVal) for the value of the current key. If \CurrentVal contains undefined macros or active characters, then attempting to print it may cause problems. Therefore, when making entries in the transcript file, it will sometimes be preferable to use \InnocentVal instead of \CurrentVal. However, \InnocentVal will give only the first eight characters of a key's value. - - Example: - - \ltxkeys@unknownkeyhandler[KVA,KVB]{fam1,fam2}{% - \@expandtwoargs\in@{,#3,}{,\myspecialkeylist,}% - \ifin@ - % The reader may want to investigate what the parameter - % characters ##1 and ####1 here stand for: - \ltxkeys@ordkey[#1]{#2}{#3}[#4]{\def\x####1{####1xx##1}}% - \else - \@ltx@warn{Unknown key `#3' with value `#4' in family `#2' ignored}\@ehd - % \@ltx@warn{Unknown key `\CurrentKey' with value - % `\InnocentVal' in family `\CurrentFam' ignored}\@ehd - \fi - } - - The macro \myspecialkeylist in the above example doesn't actually exist; it is only meant for illustration here. But 'handled keys' may be introduced in this way. This will be the set of keys for which a special action may apply at key setting time. - - Similar to \ltxkeys@unknownkeyhandler (which applies to keys), there is also the \ltxkeys@unknownoptionhandler (which applies to package or class options---see \autoref{sec:}). - - -CHECKING IF A KEY IS DEFINED - - \ltxkeys@ifkeydefTF[<prefs>]{<fams>}{<key>}{<true>}{<false>} - \ltxkeys@ifkeydefFT[<prefs>]{<fams>}{<key>}{<false>}{<true>} - - These check if <key> is defined with a prefix in <prefs> and in family in <fams>. - - - -DISABLING KEYS - - \ltxkeys@disablekeys[<prefs>]{<fams>}{<keys>} - \ltxkeys@disablekeys*[<prefs>]{<fams>}{<keys>} - - The command \ltxkeys@disablekeys causes an error to be issued when a disabled key is invoked. If the package option 'verbose' is true, undefined keys are highlighted by \ltxkeys@disablekeys with a warning message. Because it is possible to mix prefixes and families in \ltxkeys@disablekeys, undefined keys may be readily encountered. To see those undefined keys, enable the package option 'verbose'. - - The plain form of \ltxkeys@disablekeys disables the given keys instantly, while the starred (*) variant disables the keys at \AtBeginDocument. Authors can use this command to bar users of their keys from calling those keys after a certain point. - - -OPTION AND NON-OPTION KEYS - - Sometimes you want to create keys that can only appear in \documentclass, \RequirePackage or \usepackage, and at other times you may not want the user to submit a certain set of keys via these commands. The xwatermark package, for example, uses this concept. - - \option@keys[<pref>]{<fam>}{<keys>} - \option@keys*[<pref>]{<fam>}{<keys>} - \notoption@keys[<pref>]{<fam>}{<keys>} - - Keys listed in \option@keys can appear only in arguments of \documentclass, \RequirePackage or \usepackage, while keys list in \notoption@keys can't appear in these macros. The *-form of \option@keys is equivalent to \notoption@keys. Only defined keys may appear in \option@keys and \notoption@keys. - - \makeoption@keys[<pref>]{<fam>} - \makeoption@keys*[<pref>]{<fam>} - - The command \makeoption@keys makes all the keys with prefix <pref> and in family <fam> options keys. The *-form of \makeoption@keys is equivalent to \makenotoption@keys. - - -DECLARING AND PROCESSING OPTIONS - - \ltxkeys@declareoption[<pref>]<<fam>>{<key>}[<default>]{<callback>} - \ltxkeys@declareoption*[<pref>]<<fam>>{<key>}[<default>]{<callback>} - - The command \ltxkeys@declareoption is simply a form of \ltxkeys@ordkey, with the difference that the key family <fam> is now optional and, when specified, must be given in angled brackets. The default family name is '\@currname.\@currext', ie, the name of the class file or package and its file extension. - - The starred (*) form of \ltxkeys@declareoption prescribes the default action to be taken when undefined options with prefix <pref> and in family <fam> are passed to class or package. You may use \CurrentKey and \CurrentVal within this macro to pass the unknown option and its value to another class or package or to specify other actions. In fact, you can use #1 in this macro to represent the current key prefix, #2 for the current family, #3 for the current key name, and #4 for the value of the current key. The command \ltxkeys@unknownoptionhandler is equivalent to the *-form of \ltxkeys@declareoption. - - Note: The *-form of \ltxkeys@declareoption differs from the *-form of LaTeX's \DeclareOption and the *-form of xkeyval package's \DeclareOptionX. - - +++ - Examples (of use of *-form of \ltxkeys@declareoption): - - \ltxkeys@declareoption*[KV]<mypackage>{% - \PackageWarning{mypackage}{% - Unknown option `\CurrentKey' with value `\CurrentVal' ignored}% - } - - \ltxkeys@declareoption*{\PassOptionsToClass{#3}{article}} - - \ltxkeys@unknownoptionhandler[KV]<mypackage>{% - % The macro \myextraoptions doesn't actually exist; - % it is only meant for illustration here: - \@expandtwoargs\in@{,#3,}{,\myextraoptions,}% - \ifin@ - % The reader may want to investigate what the parameter characters - % ##1 and ####1 here stand for: - \ltxkeys@ordkey[#1]{#2}{#3}[#4]{\def\x####1{####1xx##1}}% - \else - \PassOptionsToClass{#3}{myclass}% - \fi - } - +++ - - \ltxkeys@declarecmdoption[<pref>]<<fam>>[<mp>]{<key>}[<default>]{<callback>} - \ltxkeys@declarebooloption[<pref>]<<fam>>[<mp>]{<key>}[<default>]{<callback>} - \ltxkeys@declarechoiceoption[<pref>]<<fam>>[<mp>]{<key>}[<default>]{<callback>} - - These are equivalent to \ltxkeys@cmdkey, \ltxkeys@boolkey and \ltxkeys@choicekey, respectively, but now the family <fam> is optional and, when specified, must be given in angled brackets. The default family name is '\@currname.\@currext'. - - - \ltxkeys@executeoptions[<pref>]<<fams>>[<na>]{<key-val>} - - This executes/sets the key-value pairs given in <key-val>. The optional <na> specifies the list of keys (without values) to be ignored. <fams> signifies families in which the keys suggested in <key-val> have been defined. The command \ltxkeys@executeoptions can thus be used to process keys from several families. - - - \ltxkeys@processoptions[<pref>]<<fams>>[<na>] - \ltxkeys@processoptions*[<pref>]<<fams>>[<na>] - - The command \ltxkeys@processoptions processes the keys and values passed by the user to the class or package. The optional argument <na> can be used to specify keys that should be ignored. The optional argument <fams> can be used to specify the families that have been used to define the keys. This macro doesn't protect expandable macros in the user inputs unless the catoptions package is loaded before \documentclass, in which case it might be better using the command \XProcessOptions of the catoptions package. When used in a class file, the macro \ltxkeys@processoptions will ignore unknown keys or options. This allows the user to use global options in the \documentclass command which can be inherinted by packages loaded afterwards. - - The starred (*) version \ltxkeys@processoptions works like the plain variant except that it also copies user input from the \documentclass command. When the user specifies an option in the \documentclass which also exists in the local family or families of the package issuing \ltxkeys@processoptions*, the local key too will be set. In this case, #1 in the \ltxkeys@declareoption (or a similar command) will be the value entered in the \documentclass command for this key. First the global options from \documentclass will set local keys and afterwards the local options, specified with \usepackage, \RequirePackage or \LoadClass, will set local keys, which could overwrite the global options, depending on the way the options sections are constructed. - -NOTES - - Wherever semicolon ';' is indicated as a list parser in this guide, it can be replaced by any user-specified one character parser via the package option 'keyparser'. It is advisable to enclose the chosen character in curly braces, eg, as in - - \documentclass[verbose,keyparser={|}]{article} - - or - - \usepackage[keyparser={|}]{ltxkeys} - - -TO-DO - - Patching the callback of an existing key. Sometimes you might want to modify the callback of a key defined in another style file. Rather than redefine the key with another callback, it may be possible to simply patch the callback of the key, provided the key's callback is patchable. This facility has been delayed because I am still experimenting the scannability of callbacks with doubled hash character. - - -% End of ltxkeys-guide.tex %
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/ltxkeys/ltxkeys.sty b/Master/texmf-dist/tex/latex/ltxkeys/ltxkeys.sty index 62cb38a1a3a..a1ff1d3b98a 100644 --- a/Master/texmf-dist/tex/latex/ltxkeys/ltxkeys.sty +++ b/Master/texmf-dist/tex/latex/ltxkeys/ltxkeys.sty @@ -1,6 +1,6 @@ %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% % % -% This is file 'ltxkeys.sty', version 0.1.0, July 2011. % +% This is file 'ltxkeys.sty', version 0.0.1, July 2011. % % % % This package and accompanying files may be distributed and/or % % modified under the conditions of the LaTeX Project Public License, % @@ -19,16 +19,24 @@ % Copyright (c) 2011 Ahmed Musa (amusa22@gmail.com). % % % %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% -\RequirePackage{catoptions}[2011/07/07] + +\RequirePackage{catoptions}[2011/07/30] \UseNormalCatcodes \StyleFilePurpose{Robust and fast key-value parser} \StyleFileRCSInfo -$Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ +$Id: ltxkeys.sty,v 0.0.1 2011/07/30 09:00:00 Ahmed Musa Exp $ \ProvidesPackage{ltxkeys}[\StyleFileInfo] \NeedsTeXFormat{LaTeX2e}[1996/12/01] \SetStyleFileMessages[ltxkeys@]{info}{warn}{err} -\newvariables{if}[ltxkeys@]{break,st,pl,sw,sv,noval,pxop,exop,kf, - rm,ssk,dec,dep,twk,verbose,inputvalid}[false] +\robust@def*\ltxkeys@error#1#2{\ltxkeys@err{#1}{#2}\@gobble} +\robust@def*\ltxkeys@vwarn#1{% + \ifltxkeys@verbose\wlog{[ltxkeys debug] -- #1.}\fi +} +\robust@def*\ltxkeys@vinfo#1{% + \ifltxkeys@verbose\wlog{[ltxkeys debug] ++ #1.}\fi +} +\newvariables{if}[ltxkeys@]{break,st,pl,sw,sv,nv,noval,pxop,exop,% + inpreset,kf,rm,ssk,dec,dep,twk,verbose,swa}[false] \newvariables{if}{inputvalid}[false] \robust@def*\SetSlaveWithMaster{\global\ltxkeys@ssktrue} \robust@def*\SetNoSlaveWithMaster{\global\ltxkeys@sskfalse} @@ -40,10 +48,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ltxkeys@err{No \string\documentclass}\@ehc \emptifycsset{\cpt@documentclass,\cpt@classoptionslist}% } -\robust@def*\ltxkeys@gobble@to@nil{% - \begingroup - \defpass\reserved@a##1\ltxkeys@nil{\endgroup}% -} \robust@def*\ltxkeys@testst#1{\cpt@ifstar{\ltxkeys@sttrue#1}{\ltxkeys@stfalse#1}} \robust@def*\ltxkeys@testpl#1{\cpt@ifplus{\ltxkeys@pltrue#1}{\ltxkeys@plfalse#1}} \robust@def*\ltxkeys@teststpl#1{\ltxkeys@testst{\ltxkeys@testpl{#1}}} @@ -75,101 +79,11 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \expandafter\noexpand\@gobble##1% }% }{ } -\newvariables{tog}{rem@repl,rem@repl@all} -\robust@def*\ltxkeys@removeoneelement{\cpt@testopt\ltxkeys@rem@veoneelement,} -\robust@def\ltxkeys@rem@veoneelement[#1]#2#3{% - \ifcpt@check\cpt@checklistparser{#1}\relax\fi - \begingroup - \edef\parser{\detokenize{#1}}% - \def\ltxkeys@tempa##1{% - \def\ltxkeys@remove####1#1##1#1####2\remove@nil{% - \def#2{####1#1####2}% - \cpt@trimparser[#1]#2% - }% - \xifinsetTF{\detokenize{#1##1#1}}{\parser\cptoxdetok{#2}\parser}{% - \expandafter\ltxkeys@remove\expandafter#1#2#1\remove@nil - \iftogFT{rem@repl@all}{}{% - \expandafter\ltxkeys@tempa\expandafter{\ltxkeys@tempb}% - }% - }{}% - }% - \iftogTF{rem@repl}{% - \edef\ltxkeys@tempb{\unexpanded{#3}}% - }{% - \cpt@sttrue\cpt@csvnormalize[#1]#2% - \ltxkeys@trimspaces{#3}\ltxkeys@tempb - }% - \expandafter\ltxkeys@tempa\expandafter{\ltxkeys@tempb}% - \postgroupdef#2\endgroup -} -\robust@def*\ltxkeys@removeelements{\cpt@testopt\ltxkeys@rem@veelements,} -\robust@def\ltxkeys@rem@veelements[#1]#2#3{% - \begingroup - \cpt@sttrue\cpt@csvnormalize[#1]#2% - \cpt@checkfalse - \togtrue{rem@repl}% - \long\def\csv@do##1{% - \ltxkeys@removeoneelement[#1]#2{##1}% - }% - \csv@@parse[#1]{#3}% - \postgroupdef#2\endgroup -} -% \ltxkeys@replaceoneelement[<parser>]{<cs>}{<search>}{<replace>} -\robust@def*\ltxkeys@replaceoneelement{% - \cpt@testopt\ltxkeys@repl@ceoneelement,% -} -\robust@def\ltxkeys@repl@ceoneelement[#1]#2#3#4{% - \ifcpt@check\cpt@checklistparser{#1}\relax\fi - \begingroup - \edef\parser{\detokenize{#1}}% - \def\ltxkeys@tempa##1{% - \def\ltxkeys@replace####1#1##1#1####2\rep@nil{% - \def#2{####1#1#4#1####2}% - \cpt@trimparser[#1]#2% - }% - \xifinsetFT{\detokenize{#1##1#1}}{\parser\cptoxdetok#2\parser}{}{% - \expandafter\ltxkeys@replace\expandafter#1#2#1\rep@nil - \iftogFT{rem@repl@all}{}{% - \expandafter\ltxkeys@tempa\expandafter{\ltxkeys@tempb}% - }% - }% - }% - \iftogTF{rem@repl}{% - \edef\ltxkeys@tempb{\unexpanded{#3}}% - }{% - \cpt@sttrue\cpt@csvnormalize[#1]#2% - \ltxkeys@trimspaces{#3}\ltxkeys@tempb - }% - \expandafter\ltxkeys@tempa\expandafter{\ltxkeys@tempb}% - \postgroupdef#2\endgroup -} -\robust@def*\ltxkeys@replaceelements{\cpt@testopt\ltxkeys@repl@ceelements,} -\robust@def\ltxkeys@repl@ceelements[#1]#2#3#4{% - \begingroup - \edef\ltxkeys@tempa{\unexpanded{#3}}% - \edef\ltxkeys@tempb{\unexpanded{#4}}% - \def\csv@do##1{\cpt@sttrue\cpt@csvnormalize[#1]##1}% - \csv@@loop[,]{#2,\ltxkeys@tempa,\ltxkeys@tempb}% - \def\ltxkeys@tempc##1#1##2\noboundary##3#1##4\noboundary{% - \ltxkeys@replaceoneelement[#1]#2{##1}{##3}% - \ifblankTF{##2}{}{% - \ifblankTF{##4}{}{% - \ltxkeys@tempc##2\noboundary##4\noboundary - }% - }% - }% - \cpt@checkfalse - \togtrue{rem@repl}% - \cptexpandsecond\ltxkeys@tempc{% - \expandcsonce\ltxkeys@tempa#1\noboundary - \expandcsonce\ltxkeys@tempb#1\noboundary - }% - \postgroupdef#2\endgroup -} \robust@def*\ltxkeys@oneoftwo#1\endgroup{% \let\@firstoftwo\relax \let\@secondoftwo\relax - \edefpass\ltxkeys@tempa{\endgroup + \cptpassexpanded{% + \endgroup \ifcase#1\relax \if@boolTF{cpt@choicefd}\@firstoftwo\@secondoftwo \or @@ -190,7 +104,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \cptexpanded{% \toks@{\def\noexpand\ltxkeys@order{\the\@tempcnta}}% }% - \ltxkeys@breaktrue + \loopbreaktrue }% \advance\@tempcnta\@ne }% @@ -200,19 +114,18 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def*\ltxkeys@ifeltcountTF{\cpt@testopt\ltxkeys@ifeltcount{=}} \robust@def*\ltxkeys@ifeltcount[#1]#2#3{% \begingroup - \def\ltxkeys@do##1{\advance\@tempcnta by1}% \@tempcnta\z@pt + \def\ltxkeys@do##1{% + \advance\@tempcnta by1 + }% \ltxkeys@csvloop{#2}% - \expandafter\endgroup\csname @\ifnum\@tempcnta#1\numexpr#3% - first\else second\fi oftwo\endcsname + \aftercsname\endgroup{@\ifnum\@tempcnta#1\numexpr#3% + first\else second\fi oftwo}% } \robust@def*\ltxkeys@nomatcherr{% - \ltxkeys@err{User input '\reserved@e' not in list: + \ltxkeys@error{User input '\reserved@e' not in list: \MsgBrk '\reserved@f'}\@ehc - \@gobble } -% A re-implementation of xkeyval's \XKV@checkchoice for -% arbitrary parser and more robustness: \robust@def*\ltxkeys@checkchoice{% \cpt@teststpl{\cpt@testopt\ltxkeys@cc@a,}% } @@ -220,7 +133,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ifcpt@check\cpt@checklistparser{#1}{}\fi \cpt@testopt{\ltxkeys@cc@b#1}{}% } -\robust@def*\comma@cc{% +\robust@def*\ltxkeys@commacheckchoice{% \cpt@teststpl{\cpt@testopt{\ltxkeys@cc@b,}{}}% } \robust@def*\CheckInput#1#2{% @@ -235,15 +148,15 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def*\ltxkeys@cc@b#1[#2]#3#4{% \begingroup \ifcpt@st\lowercase{\fi - \ltxkeys@trimspaces{#3}\user@input - \edef\valid@vals{\unexpanded{#4}}% + \ltxkeys@trimspaces{#3}\us@rinput + \edef\nomin@tions{\unexpanded{#4}}% \ifcpt@st}\fi \def\ltxkeys@ccparser{#1}% - \cpt@sttrue\cpt@csvnormalize[#1]\valid@vals + \cpt@sttrue\cpt@csvnormalize[#1]\nomin@tions \cptexpandsecond{% \ifblankTF{#2}\ltxkeys@cc@d{\ltxkeys@cc@c#2}\ltxkeys@nil }{% - {\expandcsonce\user@input}{\expandcsonce\valid@vals}% + {\expandcsonce\us@rinput}{\expandcsonce\nomin@tions}% }% } \robust@def*\ltxkeys@cc@c#1#2\ltxkeys@nil#3#4{% @@ -275,8 +188,8 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% \cptpassexpanded{% \endgroup - \def\noexpand\reserved@e{\expandcsonce\user@input}% - \def\noexpand\reserved@f{\expandcsonce\valid@vals}% + \def\noexpand\reserved@e{\expandcsonce\us@rinput}% + \def\noexpand\reserved@f{\expandcsonce\nomin@tions}% \expandcsonce\ltxkeys@tempa }% } @@ -286,7 +199,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \def\csv@do##1{% \def#1{##1}% \ifstrcmpTF{##1}{#3}{% - \cpt@choicefdtrue\cptbreakloop + \cpt@choicefdtrue\loopbreak }{% \pushnumber#2% }% @@ -304,15 +217,13 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ifcpt@pl \noexpand\@secondoftwo \else - \def\noexpand\reserved@e{\expandcsonce\user@input}% - \def\noexpand\reserved@f{\expandcsonce\valid@vals}% + \def\noexpand\reserved@e{\expandcsonce\us@rinput}% + \def\noexpand\reserved@f{\expandcsonce\nomin@tions}% \unexpanded{\expandafter\ltxkeys@nomatcherr\@gobble}% \fi \fi }% } - -% \ltxkeys@ifincsvlistTF*[parser](no.){sublist}{mainlist}{true}{false} \robust@def*\ltxkeys@ifincsvlistTF{\cpt@teststopt\ltxkeys@ifincsvlist,} \robust@def*\ltxkeys@ifincsvlist[#1]{% \cpt@testpnopt{\ltxkeys@if@ncsvlist#1}{1}% @@ -325,28 +236,29 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \edef\ltxkeys@tempb{\unexpanded{#4}}% \ifcpt@st}\fi \cpt@sttrue\cpt@csvnormalize[#1]\ltxkeys@tempb - \cpt@cnta\z@pt\def\itemspresent{}% + \cpt@cnta\z@pt\def\ltxkeys@itemspresent{}% \def\csv@do##1{% \xifinsetFT{\detokenize{#1##1#1}} {\parser\cptoxdetok\ltxkeys@tempb\parser}{}{% - \edef\itemspresent{\cptliststack,\itemspresent\unexpanded{##1}}% + \edef\ltxkeys@itemspresent + {\cptliststack,\ltxkeys@itemspresent\unexpanded{##1}}% \advance\cpt@cnta\@ne }% - \ifnum\cpt@cnta>\numexpr#2-1\relax\cptbreakloop\fi + \ifnum\cpt@cnta>\numexpr#2-1\relax\loopbreak\fi }% \csv@@parse*[#1]\ltxkeys@tempa \ifnum\cpt@cnta>\numexpr#2-1\relax - \edef\nritems{\the\cpt@cnta}% + \edef\ltxkeys@nritems{\the\cpt@cnta}% \else - \def\itemspresent{}\def\nritems{-1}% + \def\ltxkeys@itemspresent{}\def\ltxkeys@nritems{-1}% \fi \cptexpandsecond\endgroup{% - \cpt@csexit\itemspresent\cpt@csexit\nritems - \ifx\itemspresent\@empty\noexpand\@secondoftwo\else + \cpt@csexit\ltxkeys@itemspresent + \cpt@csexit\ltxkeys@nritems + \ifx\ltxkeys@itemspresent\@empty\noexpand\@secondoftwo\else \noexpand\@firstoftwo\fi }% } -% \ltxkeys@ifintsvlistTF(no){sublist}{mainlist}{true}{false} \robust@def*\ltxkeys@ifintsvlistTF{% \cpt@testst{\cpt@testpnopt\ltxkeys@ifintsvlist{1}}% } @@ -356,68 +268,65 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \edef\ltxkeys@tempa{\unexpanded{#2}}% \edef\ltxkeys@tempb{\unexpanded{#3}}% \ifcpt@st}\fi - \def\itemspresent{}\cpt@cnta\z@pt + \def\ltxkeys@itemspresent{}\cpt@cnta\z@pt \def\tsv@do##1{% \xifinsetFT{\detokenize{##1}}{\cptoxdetok\ltxkeys@tempb}{}{% - \edef\itemspresent{\cptliststack{}\itemspresent\unexpanded{##1}}% + \edef\ltxkeys@itemspresent + {\cptliststack{}\ltxkeys@itemspresent\unexpanded{##1}}% \advance\cpt@cnta\@ne }% - \ifnum\cpt@cnta>\numexpr#1-1\relax\cptbreakloop\fi + \ifnum\cpt@cnta>\numexpr#1-1\relax\loopbreak\fi }% \s@expandarg\tsv@@parse\ltxkeys@tempa \ifnum\cpt@cnta>\numexpr#1-1\relax - \edef\nritems{\the\cpt@cnta}% + \edef\ltxkeys@nritems{\the\cpt@cnta}% \else - \def\itemspresent{}\def\nritems{-1}% + \def\ltxkeys@itemspresent{}\def\ltxkeys@nritems{-1}% \fi \cptexpandsecond\endgroup{% - \cpt@csexit\itemspresent\cpt@csexit\nritems - \ifx\itemspresent\@empty\noexpand\@secondoftwo\else + \cpt@csexit\ltxkeys@itemspresent + \cpt@csexit\ltxkeys@nritems + \ifx\ltxkeys@itemspresent\@empty\noexpand\@secondoftwo\else \noexpand\@firstoftwo\fi }% } -% \ltxkeys@ifinTF*(no.){sublist}{mainlist}{true}{false} -\robust@def*\ltxkeys@ifinTF{% - \cpt@testst{\cpt@testpnopt\ltxkeys@ifin{1}}% +\robust@def*\ltxkeys@ifinlistTF{% + \cpt@testst{\cpt@testpnopt\ltxkeys@ifinlist{1}}% } -\robust@def*\ltxkeys@ifin(#1)#2#3{% +\robust@def*\ltxkeys@ifinlist(#1)#2#3{% \begingroup \ifcpt@st\lowercase{\fi \edef\ltxkeys@tempa{\unexpanded{#2}}% \edef\ltxkeys@tempb{\unexpanded{#3}}% \ifcpt@st}\fi - \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@tempa - \cpt@cnta\z@pt\def\itemspresent{}% - \def\do##1,{% - \ifnot@nil{##1}{% - \xifinsetFT{\detokenize{##1}}{\cptoxdetok\ltxkeys@tempb}{}{% - \edef\itemspresent{\cptliststack,\itemspresent\unexpanded{##1}}% - \advance\cpt@cnta\@ne - }% - \ifnumcmpTF\cpt@cnta>\numexpr#1-1{\gobble@to@sentinel\@nil,}{\do}% + \def\ltxkeys@itemspresent{}\cpt@cnta\z@pt + \s@expandarg\docommalist\ltxkeys@tempa{% + \xifinsetFT{\detokenize{##1}}{\cptoxdetok\ltxkeys@tempb}{}{% + \edef\ltxkeys@itemspresent + {\cptliststack,\ltxkeys@itemspresent\unexpanded{##1}}% + \advance\cpt@cnta\@ne }% + \ifnum\cpt@cnta>\numexpr#1-1\relax\loopbreak\fi }% - \expandafter\do\ltxkeys@tempa,\@nil,% \ifnum\cpt@cnta>\numexpr#1-1\relax - \edef\nritems{\the\cpt@cnta}% + \edef\ltxkeys@nritems{\the\cpt@cnta}% \else - \def\itemspresent{}\def\nritems{-1}% + \def\ltxkeys@itemspresent{}\def\ltxkeys@nritems{-1}% \fi \cptexpandsecond\endgroup{% - \cpt@csexit\itemspresent\cpt@csexit\nritems - \ifcsemptyTF\itemspresent{\noexpand\@secondoftwo} + \cpt@csexit\ltxkeys@itemspresent + \cpt@csexit\ltxkeys@nritems + \ifcsemptyTF\ltxkeys@itemspresent{\noexpand\@secondoftwo} {\noexpand\@firstoftwo}% }% } -\robust@def*\ltxkeys@inpkgcls#1{% +\robust@def*\ltxkeys@notinpkgclserr#1{% \ifinstylefileTF{}{% \ltxkeys@err{Command '\detokenize{#1}' issued outside style file}{The command '\detokenize{#1}' is available only in style files.}% }% } -\new@def*\ltxkeys@parsestack{} -\newletcs\ltxkeys@break\ltxkeys@breaktrue \robust@def*\ltxkeys@csvloop{% \let\ltxkeys@nlz\cptfalse \let\ltxkeys@inkv\cptfalse @@ -440,45 +349,36 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ } \robust@def*\ltxkeys@parse@a#1{% \cpt@stchoose{cpt@st}{#1}\ltxkeys@arg\ltxkeys@parse@a - \global\advance\ltxkeys@csvdepth\@ne - \letcsntocsn{ifltxkeys@break@\romannumeral\ltxkeys@csvdepth} - {ifltxkeys@break}% - \letcsntocs{ltxkeys@doo@\romannumeral\ltxkeys@csvdepth}\ltxkeys@doo - \xdef\ltxkeys@parsestack{% - \letcsntocsn{ifltxkeys@break} - {ifltxkeys@break@\romannumeral\ltxkeys@csvdepth}% - \letcsntocsn{ltxkeys@doo}{ltxkeys@doo@\romannumeral\ltxkeys@csvdepth}% - \ltxkeys@nil{\expandcsonce\ltxkeys@parsestack}% - }% + \pushfunctions\ltxkeys@parse + {\ifloopbreak,\ltxkeys@doo}\ltxkeys@csvdepth \ifdefTF\ltxkeys@do {\let\ltxkeys@doo\ltxkeys@do}{\cpt@notdeferr\ltxkeys@do}% \def\ltxkeys@parse@b{% - \if@boolTF{ltxkeys@break}{% - \defpass\reserved@a####1\ltxkeys@nil,{}% + \if@boolTF{loopbreak}{% + \gobble@to@sentinel\ltxkeys@nil,% }{% \ltxkeys@parse@c.% }% }% - \long\def\ltxkeys@parse@c##1,{% - \edef\ltxkeys@arg{\expandcsonce{\@gobble##1}}% - \ifxTF\ltxkeys@arg\ltxkeys@nnil{}{% - \ifxTF\@empty\ltxkeys@arg{}{% - \expandafter\ltxkeys@doo\expandafter{\ltxkeys@arg}\relax - }% - \ltxkeys@parse@b - }% - }% - \ifpsiboolTF{ltxkeys@nlz}{% + \ifswitchTF{ltxkeys@nlz}{% \cpt@sttrue - \usename{cpt@\if\ltxkeys@inkv kv\else csv\fi normalize}[,]\ltxkeys@arg + \usename{cpt@\if\ltxkeys@inkv kv\else + csv\fi normalize}[,]\ltxkeys@arg }{}% - \ltxkeys@breakfalse + \loopbreakfalse \expandafter\ltxkeys@parse@b\ltxkeys@arg,\ltxkeys@nil,% - \def\reserved@a##1\ltxkeys@nil{##1\gdef\ltxkeys@parsestack}% - \expandafter\reserved@a\ltxkeys@parsestack - \global\advance\ltxkeys@csvdepth\m@one + \popfunctions\ltxkeys@parse\ltxkeys@csvdepth \ifnum\ltxkeys@csvdepth=\z@pt\undefcs\ltxkeys@do\fi } +\robust@def*\ltxkeys@parse@c#1,{% + \edef\ltxkeys@arg{\expandcsonce{\@gobble#1}}% + \ifxTF\ltxkeys@arg\ltxkeys@nnil{}{% + \ifxTF\@empty\ltxkeys@arg{}{% + \expandafter\ltxkeys@doo\expandafter{\ltxkeys@arg}\relax + }% + \ltxkeys@parse@b + }% +} \robust@def*\ltxkeys@testopt@a#1{\cpt@testopt{\ltxkeys@testopt@b#1}{KV}} \robust@def*\ltxkeys@testopt@b#1[#2]#3{% \ltxkeys@makepf{#2}% @@ -527,6 +427,9 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def*\ltxkeys@testopt@g#1#2{% \cptexpandarg\ltxkeys@testopt@a{\noexpandcsn{ltxkeys@#1}{#2}}% } +\robust@def*\ltxkeys@testopt@h#1{% + \cptexpandarg\ltxkeys@testopt@a{\noexpandcsn{ltxkeys@#1}}% +} \robust@def*\ltxkeys@bracedefault#1[{% \begingroup \toks@{#1}% @@ -575,6 +478,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \csn@xdef{\ltxkeys@hdr#1@keys}{\expandcsonce{#2}}% }% } +\new@def*\ltxkeys@currtriple{\ltxkeys@ttpref,\ltxkeys@tfam,\ltxkeys@tkey} \robust@def*\ltxkeys@makepf#1{% \s@expandarg\ltxkeys@trimspaces{#1}\ltxkeys@ttpref \edef\ltxkeys@tpref{% @@ -587,11 +491,45 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ltxkeys@tpref\ifcsnullTF\ltxkeys@tfam{}{\ltxkeys@tfam @}% }% } +\new@def*\ltxkeys@badkeynamelist{} +\robust@def*\ltxkeys@badkeynames#1{% + \ifcsnullTF\ltxkeys@badkeynamelist{% + \edef\ltxkeys@badkeynamelist{\detokenize{#1}}% + \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@badkeynamelist + }{% + \cptexpandsecond{\cptfiltermergecsv[,]} + {\noexpand\ltxkeys@badkeynamelist{\detokenize{#1}}}\nofilter + }% +} +\robust@def*\ltxkeys@removebadkeynames#1{% + \ifcsnullTF\ltxkeys@badkeynamelist{% + \ltxkeys@info{Couldn't delete from empty + \string\ltxkeys@badkeynamelist}% + }{% + \cptexpandsecond{\cptfilterremovecsv[,]} + {\noexpand\ltxkeys@badkeynamelist{\detokenize{#1}}}\nofilter + }% +} +\ltxkeys@badkeynames{.code,ordkey,cmdkey,choicekey,boolkey,% + handledkeys,presetkeys,postsetkeys% +} +\robust@def*\ltxkeys@findbadkeyname#1{% + \begingroup + \edef\ltxkeys@tempa{\cpttrimspaces{#1}}% + \oifinset@sp@TF,\ltxkeys@tempa\ltxkeys@badkeynamelist{% + \ltxkeys@err{Bad key name '\ltxkeys@tempb'}\@ehc + }{}% + \endgroup +} \robust@def*\ltxkeys@saveinitialkeyvals#1#2#3{% \xifinsetTF{\detokenize{\savevalue}}{\cptoxdetok{#2}}{% \ltxkeys@err{\noexpand\savevalue pointer not allowed \MsgBrk when defining a key}\@ehc - }{}% + }{% + \ifltxkeys@verbose + \s@expandarg\ltxkeys@findbadkeyname{#2}% + \fi + }% \ifltxkeys@twk\else \ifltxkeys@sv \letcstocsn\ltxkeys@tempa{\ltxkeys@hdr initial@keyvals}% @@ -601,11 +539,8 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% \fi \fi - \ifltxkeys@verbose - \wlog{Key defined: \ltxkeys@ttpref, \ltxkeys@tfam, \ltxkeys@tkey.}% - \fi + \ltxkeys@vinfo{Key defined: \ltxkeys@currtriple}% } -% \ltxkeys@ordkey[pref]{fam}{key}[dft]{fn} \robust@def*\ltxkeys@ordkey{% \ltxkeys@svtrue\ltxkeys@swfalse \ltxkeys@testopt@a\ltxkeys@ordkey@a @@ -624,7 +559,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ltxkeys@saveinitialkeyvals{}{#1}{#2}% \csn@def{\ltxkeys@hdr#1}##1{#3}% } -% \ltxkeys@cmdkey[pref]{fam}[mp]{key}[dft]{fn} \robust@def*\ltxkeys@cmdkey{% \ltxkeys@svtrue\ltxkeys@swfalse \ltxkeys@testopt@e\ltxkeys@cmdkey@a{cmd}% @@ -640,8 +574,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% \expandafter\ltxkeys@tempa\ltxkeys@tempb{#4}% } -% \ltxkeys@boolkey[pref]{fam}[mp]{key}[dft]{fn} -% \ltxkeys@boolkey+[pref]{fam}[mp]{key}[dft]{fn}{keyvalerr} \robust@def*\ltxkeys@boolkey{% \ltxkeys@svtrue\ltxkeys@swtrue \ltxkeys@testpl{\ltxkeys@testopt@e\ltxkeys@boolkey@a{bool}}% @@ -670,9 +602,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ {\cpt@sttrue\ltxkeys@cc@b,[\ltxkeys@resa]{##1}{true,false}#5}% }% } -% \ltxkeys@biboolkeys[pref]{fam}[mp]{key1,key2}[dft]{key1-fn}{key2-fn} -% \ltxkeys@biboolkeys+[pref]{fam}[mp]{key1,key2}[dft]{key1-fn}{key2-fn} -% {<fallback>} \robust@def*\ltxkeys@biboolkeys{% \ltxkeys@svtrue\ltxkeys@swtrue \ltxkeys@testpl{\ltxkeys@testopt@e\ltxkeys@biboolkeys@a{}}% @@ -693,8 +622,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ } \robust@def*\ltxkeys@biboolkeys@d#1#2#3{% \ltxkeys@ifeltcountTF[=]{#2}\tw@{}{% - \ltxkeys@err{Biboolean keys '#2' not equal to 2}\@ehc - \@gobble + \ltxkeys@error{Biboolean keys '#2' not equal to 2}\@ehc }% \def\ltxkeys@keys{#2}% \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@keys @@ -750,7 +678,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \settogfalse{\ltxkeys@hdr#2}% }% } -% \ltxkeys@stylekey[<pref>]{<fam>}[<mp>]{<key>}[<dft>](<deps>){<fn>} \robust@def*\ltxkeys@stylekey{% \ltxkeys@svtrue\ltxkeys@swfalse \ltxkeys@testst{% @@ -788,7 +715,9 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def*\ltxkeys@setdependants#1#2{% \letcstocsn\ltxkeys@tempa{\ltxkeys@hdr\ltxkeys@tkey @dependants}% \ifcsemptyTF\ltxkeys@tempa{}{% - \cpt@sttrue\cpt@csvnormalize[;]\ltxkeys@tempa + \cpt@sttrue + \expandafter\cpt@csvnormalize + \expandafter[\ltxkeys@keyparser]\ltxkeys@tempa \if@boolTF{ltxkeys@dec}{}{% \cptexpandargonce{\ltxkeys@s@tdependants{#1}{#2}}\ltxkeys@tempa }% @@ -827,11 +756,13 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \@temptokena{#1}% \def\ltxkeys@splita##1/##2/{% \ifblankTF{##1##2}{% - \gobble@to@ltxkeys@nil + \ltxkeys@warn{Something wrong with dependant keys}\@ehc + \expandafter\gobble@to@sentinel\expandafter + \ltxkeys@nil\ltxkeys@keyparser }{% \ltxkeys@trimspaces{##1}\key@type - \def\stripstar####1*\@empty####2\@nil{\edef\key@type{####1}}% - \expandafter\stripstar\key@type\@empty*\@empty\@nil + \def\striplaststar####1*\@empty####2\@nil{\edef\key@type{####1}}% + \expandafter\striplaststar\key@type\@empty*\@empty\@nil \xifstrcmpFT\key@type{sty}{}{% \ltxkeys@err{A dependant key can't have dependants: \MsgBrk ||\the\@temptokena||}\@ehc @@ -875,7 +806,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \cptpassexpanded{% \ifnum\numexpr#1=\@ne \toks1{% - \the\toks1\oifblankTF{\the\toks1}{}{;}% + \the\toks1\oifblankTF{\the\toks1}{}{\ltxkeys@keyparser}% \key@type/\key@name \ifcsnullTF\key@default{}{/\expandcsonce\key@default}% \ifcsnullTF\key@macro{}{/\expandcsonce\key@macro}% @@ -887,13 +818,11 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% }% } -% \ltxkeys@choicekey -% *+[<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<dft>]{<f1>}{<f2>} \robust@def*\ltxkeys@choicekey{% \ltxkeys@svtrue\ltxkeys@swfalse - \ltxkeys@teststpl{% + \ltxkeys@teststpl{\cpt@testcl{% \ltxkeys@testopt@a{\cpt@testopt\ltxkeys@choicekey@a{chc\ltxkeys@hdr}}% - }% + }}% } \robust@def*\ltxkeys@choicekey@a[#1]#2{% \begingroup @@ -930,13 +859,24 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ifinsetTF{/.code=}{#4}{% \def\ltxkeys@tempa{\ltxkeys@executechclist}% }{% - \def\ltxkeys@tempa{\@gobble}% + \ifinsetTF{/}{#4}{% + \def\ltxkeys@tempa{\ltxkeys@executechclist}% + }{% + \def\ltxkeys@tempa{\@gobble}% + }% }% \edef#1{% - \edef\cptmakecs{#2}{\noexpand\unexpanded{####1}}% + \csn@edef{#2}{\noexpand\unexpanded{####1}}% \cptmakecs{cpt@st\ifltxkeys@st true\else false\fi}% \cptmakecs{cpt@pl\ifltxkeys@pl true\else false\fi}% - \unexpanded{\ltxkeys@cc@b,[#3]}{####1}{\expandcsonce\ltxkeys@chclist}% + \ifcpt@cl + \edef\noexpand\reserved@a{####1}% + \else + \edef\noexpand\reserved@a{\noexpand\unexpanded{####1}}% + \fi + \def\noexpand\reserved@b{\unexpanded{\ltxkeys@cc@b,[#3]}}% + \unexpanded{\expandafter\reserved@b\expandafter{\reserved@a}}% + {\expandcsonce\ltxkeys@chclist}% \unexpanded{#5}\expandcsonce\ltxkeys@tempa{\unexpanded{#4}}% }% \def\ltxkeys@tempa{\def#1####1}% @@ -946,33 +886,45 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \begingroup \def\ltxkeys@chclist{}% \def\ltxkeys@tempb##1/.code=##2\ltxkeys@nil{% - \ltxkeys@trimspaces{##1}\ltxkeys@tempa + \ltxkeys@tempd{##1}{##2}% + }% + \def\ltxkeys@tempc##1/##2/##3\ltxkeys@nil{% + \ltxkeys@tempd{##1}{##2}% + }% + \def\ltxkeys@tempd##1##2{% + \expandafter\ltxkeys@trimspaces\expandafter + {\@gobble##1}\ltxkeys@tempa \ifcase#2\relax \cptaddtolist*[,]\ltxkeys@chclist\ltxkeys@tempa \or - \cptpassexpanded{\lowercase{% + \cptexpandarg\lowercase{% \def\noexpand\ltxkeys@tempa{\expandcsonce\ltxkeys@tempa}% \def\noexpand\ltxkeys@tval{\expandcsonce\ltxkeys@tval}% - }}% - \oifstrcmpFT\ltxkeys@tempa\ltxkeys@tval{}{% - \edef\ltxkeys@chclist{\unexpanded{##2}}% - \cptbreakloop }% + \oifstrcmpTF\ltxkeys@tempa\ltxkeys@tval{% + \edef\ltxkeys@chclist{\unexpanded{##2}}% + \loopbreak + }{}% \else - \ltxkeys@err{Invalid number '#2' in \string\ltxkeys@makechclist}\@ehc + \ltxkeys@err{Invalid number '#2' while + in \string\ltxkeys@makechclist}\@ehc \fi }% \def\csv@do##1{% \ifinsetTF{/.code=}{##1}{% - \ltxkeys@tempb##1\ltxkeys@nil + \ltxkeys@tempb.##1\ltxkeys@nil }{% - \ltxkeys@tempb##1/.code=\ltxkeys@nil + \ltxkeys@tempc.##1//\ltxkeys@nil }% }% - \ifinsetTF{/.code=}{#1}{% + \expandafter\ifinsetTF\expandafter{\ltxkeys@keyparser}{#1}{% \expandafter\csv@@parse\expandafter[\ltxkeys@keyparser]{#1}% }{% - \csv@@parse[,]{#1}% + \ifinsetTF{,}{#1}{% + \csv@@parse[,]{#1}% + }{% + \csv@@parse[,]{#1,}% + }% }% \postgroupdef\ltxkeys@chclist\endgroup } @@ -992,20 +944,46 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% } \robust@def*\ltxkeys@getkeyname#1=#2\ltxkeys@nil#3{% - \ltxkeys@trimspaces{#1}#3% + \ltxkeys@findpointer\savevalue{#1}#3\ltxkeys@svtrue\ltxkeys@svfalse + \ltxkeys@findpointer\needvalue{#1}#3\ltxkeys@nvtrue\ltxkeys@nvfalse + \ifdefTF\ltxkeys@fromgetkeynames{% + \def#3{#1}% + }{% + \ltxkeys@trimspaces{#1}#3% + }% } \robust@def*\ltxkeys@getkeynames#1{% + \begingroup + \def\ltxkeys@fromgetkeynames{}% \def\ltxkeys@keynames{}% \def\ltxkeys@do##1{% - \ltxkeys@getkeyname##1=\ltxkeys@nil\ltxkeys@tkey + \ltxkeys@getkeyname##1=\ltxkeys@nil\ltxkeys@tempa \edef\ltxkeys@keynames{% - \cptliststack,\ltxkeys@keynames\expandcsonce\ltxkeys@tkey + \cptliststack,\ltxkeys@keynames\expandcsonce\ltxkeys@tempa }% }% - \ifblankTF{#1}{}{\ltxkeys@csvparse{#1}}% + \ifblankTF{#1}{}{\ltxkeys@kvparse{#1}}% + \postgroupdef\ltxkeys@keynames\endgroup +} +\robust@def*\ltxkeys@getkeyvalue#1=#2\ltxkeys@nil#3{% + \ifinsetTF{=\ltxkeys@nil}{#2\ltxkeys@nil}{% + \ltxkeys@novalfalse + \begingroup + \def\ltxkeys@tempa##1=##2\ltxkeys@nil{\endgroup + \s@expandarg\ltxkeys@trimspaces{\@gobble##1}#3% + \let\CurrentVal#3% + }% + \ltxkeys@tempa.#2\ltxkeys@nil + }{% + \ltxkeys@novaltrue\def#3{}% + }% +} +\robust@def*\ltxkeys@splitkeyval#1\ltxkeys@nil#2#3{% + \ltxkeys@getkeyname#1=\ltxkeys@nil#2% + \ltxkeys@getkeyvalue#1=\ltxkeys@nil#3% } \robust@def*\option@keys{% - \ltxkeys@inpkgcls\option@keys + \ltxkeys@notinpkgclserr\option@keys \cpt@testst\ltxkeys@optionk@ys } \robust@def*\ltxkeys@optionk@ys{% @@ -1016,7 +994,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% } \robust@def*\notoption@keys{% - \ltxkeys@inpkgcls\notoption@keys + \ltxkeys@notinpkgclserr\notoption@keys \ltxkeys@testopt@g{optionkeys}{not}% } \robust@def*\ltxkeys@optionkeys#1#2{% @@ -1024,7 +1002,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ifcsndefTF{\ltxkeys@hdr##1}{% \ifcsndefTF{\ltxkeys@hdr#1option@keys}{% \xifinsetTF{,\detokenize{##1},} - {,\cptsxdetok{\@nameuse{\ltxkeys@hdr#1option@keys}},}{}{% + {,\cptsxdetok{\usename{\ltxkeys@hdr#1option@keys}},}{}{% \csn@edef{\ltxkeys@hdr#1option@keys}{% \expandcsnonce{\ltxkeys@hdr#1option@keys},% \unexpanded{##1}% @@ -1059,12 +1037,91 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def*\makenotoption@keys{% \cpt@sttrue\cpt@testopt\ltxkeys@makeoptionkeys{KV}% } +\robust@def*\ltxkeys@handledkeys{% + \ltxkeys@testopt@h{h@ndledkeys}% +} +\robust@def*\ltxkeys@removehandledkeys{% + \ltxkeys@testopt@h{rem@vehandledkeys}% +} +\robust@def*\ltxkeys@undefhandledkeys{% + \cpt@testcl{\ltxkeys@testopt@h{undefh@ndledkeys}}% +} +\robust@def*\ltxkeys@emptifyhandledkeys{% + \cpt@testcl{\ltxkeys@testopt@h{emptifyh@ndledkeys}}% +} +\robust@def*\ltxkeys@h@ndledkeys#1{% + \letcstocsn\ltxkeys@rsvda{\ltxkeys@hdr handledkeys}% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \def\ltxkeys@tempb{##1}% + \ifdefTF\ltxkeys@rsvda{% + \oifinset@sp@TF,\ltxkeys@tempb\ltxkeys@rsvda{}{% + \edef\ltxkeys@rsvda{% + \cptliststack,\ltxkeys@rsvda\unexpanded{##1}% + }% + }% + }{% + \let\ltxkeys@rsvda\ltxkeys@tempb + }% + }{% + \ltxkeys@err{Key '##1' is undefined in family '\ltxkeys@tfam' + \MsgBrk Only defined keys can be made handled keys.}\@ehc + }% + }% + \ltxkeys@csvparse{#1}% + \letcsntocs{\ltxkeys@hdr handledkeys}\ltxkeys@rsvda +} +\robust@def*\ltxkeys@rem@vehandledkeys#1{% + \letcstocsn\ltxkeys@rsvda{\ltxkeys@hdr handledkeys}% + \ifdefTF\ltxkeys@rsvda{% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \def\ltxkeys@tempb{##1}% + \oifinset@sp@TF,\ltxkeys@tempb\ltxkeys@rsvda{% + \let\cpt@fromrem\cpttrue\cpt@sttrue + \cpt@removeoneelement[,]\ltxkeys@rsvda{##1}% + }{% + \ltxkeys@warn{Key '##1' with prefix '\ltxkeys@ttpref' in family + \MsgBrk '\ltxkeys@tfam' is not a handled key: + \MsgBrk It couldn't be deleted from handled keys list.}% + }% + }{% + \ltxkeys@err{Key '##1' is undefined in family '\ltxkeys@tfam'}% + {Key '##1' with prefix '\ltxkeys@ttpref' in family + \MsgBrk '\ltxkeys@tfam' is not defined:\MsgBrk + Can't be deleted from handled keys list.}% + }% + }% + \ltxkeys@csvparse{#1}% + }{% + \ltxkeys@err{No handled keys for family '\ltxkeys@tfam'}% + {No handled keys exist for prefix '\ltxkeys@ttpref' and + \MsgBrk family '\ltxkeys@tfam'.}% + }% + \letcsntocs{\ltxkeys@hdr handledkeys}\ltxkeys@rsvda +} +\robust@def*\ltxkeys@undefh@ndledkeys{% + \ifcsndefTF{\ltxkeys@hdr handledkeys}{% + \usename{\ifcpt@cl g\fi undefcsn}{\ltxkeys@hdr handledkeys}% + }{% + \ltxkeys@err{No handled keys for prefix '\ltxkeys@ttpref' + \MsgBrk and family '\ltxkeys@tfam': couldn't undefine}\@ehc + }% +} +\robust@def*\ltxkeys@emptifyh@ndledkeys{% + \ifcsndefTF{\ltxkeys@hdr handledkeys}{% + \usename{\ifcpt@cl g\fi emptifycsn}{\ltxkeys@hdr handledkeys}% + }{% + \ltxkeys@err{No handled keys for prefix '\ltxkeys@ttpref' + \MsgBrk and family '\ltxkeys@tfam': couldn't emptify}\@ehc + }% +} \robust@def*\ltxkeys@testoptionkey#1{% \ifcsndefFT{\ltxkeys@hdr#1option@keys}{}{% \cpt@choicefdfalse \def\ltxkeys@do##1{% \s@expandarg\ifstrcmpTF\ltxkeys@tkey{##1}{% - \cpt@choicefdtrue\ltxkeys@break + \cpt@choicefdtrue\loopbreak }{}% }% \aftercsname{\ltxkeys@csvloop*}{\ltxkeys@hdr#1option@keys}% @@ -1082,7 +1139,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \cpt@choicefdfalse \def\ltxkeys@do##1{% \s@expandarg\ifstrcmpTF\ltxkeys@tkey{##1}{% - \cpt@choicefdtrue\ltxkeys@break + \cpt@choicefdtrue\loopbreak }{}% }% \aftercsname{\ltxkeys@csvloop*}{\ltxkeys@hdr needvalue@keys}% @@ -1108,7 +1165,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% } \robust@def*\ltxkeys@accumkeyvals#1{% - \ltxkeys@ifinTF(1)% + \ltxkeys@ifinlistTF(1)% {\ltxkeys@setmnkey,\setmnkey,\setaliaskey}{#1}% \ltxkeys@twktrue\ltxkeys@twkfalse \begingroup @@ -1131,7 +1188,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \fi \endgroup } -% \ltxkeys@definekeys[pref]<fam>[macropf]{<keyname>=<dft>/<callback>; ...} \robust@def*\ltxkeys@definekeys{% \begingroup \endlinechar\m@one @@ -1152,13 +1208,20 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ltxkeys@trimspaces{#3}\macro@prefix \toks@{\undefcs\ifdefkeyst}% \def\key@vals{}% + % We want \ltxkeys@definekeys to have a slightly different + % syntax to \ltxkeys@declarekeys. So we use '=' here. But + % the equality sign can always be replaced with '/' and + % this won't cause any problems: + \def\ltxkeys@tempa##1\ltxkeys@nil{% + \expandafter\ltxkeys@splitc\reserved@a/##1//\ltxkeys@nil + }% \def\ltxkeys@splita##1={% - \begingroup - \defpass\reserved@a####1\ltxkeys@nil{\endgroup - \ltxkeys@splitb##1/####1//\ltxkeys@nil - }.% + \def\reserved@a{##1}\ltxkeys@tempa.% }% - \def\ltxkeys@splitb##1/##2/##3/##4\ltxkeys@nil{% + \def\ltxkeys@splitb##1/{% + \def\reserved@a{##1}\ltxkeys@tempa.% + }% + \def\ltxkeys@splitc##1/##2/##3/##4\ltxkeys@nil{% \ifblankTF{##1}{% \ifblankTF{##2##3}{}{% \ltxkeys@err{Empty key name while in @@ -1173,7 +1236,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \MsgBrk '#2' with prefix '#1'}\@ehc }% \fi - \ifblankTF{##2}{% + \oifblankTF{\@gobble##2}{% \def\key@default{}% }{% \s@expandarg\ltxkeys@trimspaces{\@gobble##2}\key@default @@ -1215,8 +1278,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def*\ltxkeys@keytypeerr#1{% \edef\ltxkeys@badkeytypes{\cptliststack,\ltxkeys@badkeytypes#1}% } -% \ltxkeys@declarekeys[pref]<fam>[macropf]{<keytype>/<keyname> -% /<dft>/<callback><parser> ...} \robust@def*\ltxkeys@declarekeys{% \begingroup \endlinechar\m@one @@ -1239,7 +1300,8 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \toks@{\undefcs\ifdefkeyst}% \def\ltxkeys@splita##1/##2/{% \ifblankTF{##1##2}{% - \gobble@to@ltxkeys@nil + \ltxkeys@warn{Something wrong in using \string\ltxkeys@declarekeys}\@ehc + \expandafter\gobble@to@sentinel\expandafter\ltxkeys@nil\ltxkeys@keyparser }{% \ifblankTF{##2}{% \ltxkeys@err{Empty key name in \string\ltxkeys@declarekeys}\@ehc @@ -1283,12 +1345,12 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ {\key@type}{% {sty}{% \ltxkeys@stylekey\ltxkeys@tempa - [\expandcsonce\key@default](\expandcsonce\dependant)% + [\expandcsonce\key@default](\expandcsonce\ltxkeys@dependant)% {\unexpanded{##2}}% }% {sty*}{% \ltxkeys@stylekey*\ltxkeys@tempa - [\expandcsonce\key@default](\expandcsonce\dependant)% + [\expandcsonce\key@default](\expandcsonce\ltxkeys@dependant)% {\unexpanded{##2}}% }% {cmd}{% @@ -1302,7 +1364,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% {choice}{% \ltxkeys@choicekey*+\ltxkeys@tempa - [\unexpanded{\val\nr}]{\expandcsonce\ltxkeys@alt}% + [\unexpanded{\userinput\nr}]{\expandcsonce\ltxkeys@alt}% [\expandcsonce\key@default]{\unexpanded{##2}}% {\ltxkeys@keyvalerr}% }% @@ -1339,32 +1401,149 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def\ltxkeys@declarekeys@d#1{% \begingroup \ifblankTF{#1}{% - \def\dependant{}% + \def\ltxkeys@dependant{}% }{% \ifinsetFT{>}{#1}{% \ltxkeys@err{Missing key type and name in dependant key ^^J\detokenize{#1}'}{No '>' in dependant key.}% - \def\dependant{}% + \def\ltxkeys@dependant{}% }{% \def\ltxkeys@tempa##1>##2>##3>##4>##5\ltxkeys@nil{% - \edef\dependant{\unexpanded{##1/##2/##3/##4}}% + \edef\ltxkeys@dependant{\unexpanded{##1/##2/##3/##4}}% }% \ltxkeys@tempa#1>>>>\ltxkeys@nil }% }% - \postgroupdef\dependant\endgroup + \postgroupdef\ltxkeys@dependant\endgroup +} +\robust@def*\ltxkeys@presetkeys{% + \cpt@testcl{\ltxkeys@testopt@g{ppsetkeys}{pre}}% +} +\robust@def*\ltxkeys@removepresetkeys{% + \cpt@testcl{\ltxkeys@testopt@g{removeppsetkeys}{pre}}% +} +\robust@def*\ltxkeys@undefpresetkeys{% + \cpt@testcl{\ltxkeys@testopt@g{undefppsetkeys}{pre}}% +} +\robust@def*\ltxkeys@postsetkeys{% + \cpt@testcl{\ltxkeys@testopt@g{ppsetkeys}{post}}% +} +\robust@def*\ltxkeys@removepostsetkeys{% + \cpt@testcl{\ltxkeys@testopt@g{removeppsetkeys}{post}}% +} +\robust@def*\ltxkeys@undefpostsetkeys{% + \cpt@testcl{\ltxkeys@testopt@g{undefppsetkeys}{post}}% +} +\robust@def*\ltxkeys@ppsetkeys#1#2{% + \def\ltxkeys@rsvda{}\def\ltxkeys@rsvdb{}% + \def\ltxkeys@do##1{% + \ltxkeys@splitkeyval##1\ltxkeys@nil\ltxkeys@tkey\ltxkeys@tval + \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{% + \ltxkeys@err{Key '\ltxkeys@currtriple' is undefined.}\@ehc + }{% + \ifcsndefTF{@\ltxkeys@hdr#1setkeys}{}{% + \emptifycsn{@\ltxkeys@hdr#1setkeys}% + }% + \xifinsetTF{,\cptoxdetok\ltxkeys@tkey,} + {,\cptsxdetok{\usename{@\ltxkeys@hdr#1setkeys},}}{% + \ltxkeys@err{Double entry for key '\ltxkeys@currtriple' in\MsgBrk + #1set key list}\@ehc + }{% + \edef\ltxkeys@rsvda{\cptliststack,\ltxkeys@rsvda + \ltxkeys@tkey\ifcsemptyTF\ltxkeys@tval{} + {=\expandcsonce\ltxkeys@tval}}% + \edef\ltxkeys@rsvdb{\cptliststack,\ltxkeys@rsvdb + \expandcsonce\ltxkeys@tkey}% + }% + }% + }% + \ltxkeys@kvparse{#2}% + \ifcsemptyTF\ltxkeys@rsvda{}{% + \ifcsndefTF{\ltxkeys@hdr#1setkeys}{% + \cptpassexpanded{% + \cptfiltermergekv\noexpandcsn{\ltxkeys@hdr#1setkeys}% + {\expandcsonce\ltxkeys@rsvda}\noexpand\nofilter + \cptfiltermergecsv\noexpandcsn{@\ltxkeys@hdr#1setkeys} + {\ltxkeys@rsvdb}\noexpand\nofilter + }% + }{% + \csn@edef{\ltxkeys@hdr#1setkeys}{\expandcsonce\ltxkeys@rsvda}% + \csn@edef{@\ltxkeys@hdr#1setkeys}{\expandcsonce\ltxkeys@rsvdb}% + }% + \ifcpt@cl + \globalizecsn{\ltxkeys@hdr#1setkeys}% + \globalizecsn{@\ltxkeys@hdr#1setkeys}% + \fi + }% +} +\robust@def*\ltxkeys@removeppsetkeys#1#2{% + \ifcsndefFT{\ltxkeys@hdr#1setkeys}{% + \ltxkeys@err{No #1set keys defined for prefix '\ltxkeys@ttpref' + and family '\ltxkeys@tfam'}\@ehc + }{% + \def\ltxkeys@rsvda{}\def\ltxkeys@rsvdb{}% + \def\ltxkeys@do##1{% + \ltxkeys@splitkeyval##1=\ltxkeys@nil\ltxkeys@tkey\ltxkeys@tval + \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{% + \ltxkeys@err{Key '\ltxkeys@currtriple' is undefined}\@ehc + }{% + \xifinsetTF{,\cptoxdetok\ltxkeys@tkey=\cptoxdetok\ltxkeys@tval,}% + {,\cptsxdetok{\usename{\ltxkeys@hdr#1setkeys}},}{% + \edef\ltxkeys@rsvda{\cptliststack,\ltxkeys@rsvda + \ltxkeys@tkey\ifcsemptyTF\ltxkeys@tval{} + {=\expandcsonce\ltxkeys@tval}}% + \edef\ltxkeys@rsvdb{\cptliststack,\ltxkeys@rsvdb + \expandcsonce\ltxkeys@tkey}% + }{% + \ltxkeys@err{Key '\ltxkeys@currtriple' not a #1set key}\@ehc + }% + }% + }% + \ltxkeys@kvparse{#2}% + \ifcsemptyTF\ltxkeys@rsvda{}{% + \cptpassexpanded{% + \cptfilterremovekv\noexpandcsn{\ltxkeys@hdr#1setkeys} + {\expandcsonce\ltxkeys@rsvda}\noexpand\nofilter + \cptfilterremovecsv\noexpandcsn{@\ltxkeys@hdr#1setkeys} + {\ltxkeys@rsvdb}\noexpand\nofilter + }% + \ifcpt@cl + \globalizecsn{\ltxkeys@hdr#1setkeys}% + \globalizecsn{@\ltxkeys@hdr#1setkeys}% + \fi + }% + }% +} +\robust@def*\ltxkeys@undefppsetkeys#1{% + \ifcsndefFT{\ltxkeys@hdr#1setkeys}{% + \ltxkeys@err{No #1set keys defined for prefix '\ltxkeys@ttpref' + and family '\ltxkeys@tfam'}\@ehc + }{% + \usename{\ifcpt@cl g\fi undefcsn}{\ltxkeys@hdr#1setkeys}% + \usename{\ifcpt@cl g\fi undefcsn}{@\ltxkeys@hdr#1setkeys}% + }% } \robust@def*\ltxkeys@setmnkey#1{% \xifinsetTF{,}{\detokenize{#1}}{% \ltxkeys@err{\noexpand\ltxkeys@setmnkey doesn't accept key list}\@ehc }{% - \cpt@testopt{\ltxkeys@settmnkey@a#1}{}% + \cpt@testopt{\ltxkeys@s@tmnkey#1}{}% }% } -\robust@def*\ltxkeys@settmnkey@a#1[#2]{% +\robust@def*\ltxkeys@s@tmnkey#1[#2]{% + \begingroup + \let\x\ltxkeys@tkey\let\y\noexpand + \edef\z{\expandcstwice{\csname\ltxkeys@hdr#1\endcsname{}}}% + \cptexpandsecond{\endgroup\ltxkeys@ifinlistTF(1)}{% + {\y\ltxkeys@setmnkey{\x},\y\setmnkey{\x},\y\setaliaskey{\x}}% + {\expandcsonce\z}% + }{% + \ltxkeys@err{\noexpand\ltxkeys@setmnkey or \noexpand\setmnkey + or \noexpand\setaliaskey nested}\@ehc + }{}% \cptexpandsecond\ltxkeys@setkeys{% [\ltxkeys@ttpref]{\ltxkeys@tfam}{% - #1=\ifnullTF{#2}{\expandcsonce\ltxkeys@tval}{\unexpanded{#2}}% + #1=\ifblankTF{#2}{\expandcsonce\ltxkeys@tval}{\unexpanded{#2}}% }% }% } @@ -1377,7 +1556,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ifstrcmpTF{##2}{.}{% \ltxkeys@err{Invalid alternate value list for key '#1'}\@ehc }{% - \cptifmacroTF{##2}{% + \ifmacroTF{##2}{% \edef\ltxkeys@alt{\expandcsonce{##2}}% }{% \edef\ltxkeys@alt{\unexpanded{##2}}% @@ -1397,7 +1576,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% }% } -% \ltxkeys@initializekeys[<prefix>]{<fams>}[<na>] \robust@def*\ltxkeys@initializekeys{% \cpt@testopt\ltxkeys@in@tializekeys{KV}% } @@ -1408,27 +1586,28 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \begingroup \def\ltxkeys@resa{}% \def\ltxkeys@do##1{% - \edef\ltxkeys@resa{% - \cptliststack,\ltxkeys@resa - \ifcsndefFT{#1@##1@initial@keyvals}{}{% - \expandcsnonce{#1@##1@initial@keyvals}% + \def\ltxkeys@do####1{% + \edef\ltxkeys@resa{% + \cptliststack,\ltxkeys@resa + \ifcsndefFT{##1@####1@initial@keyvals}{}{% + \expandcsnonce{##1@####1@initial@keyvals}% + }% }% }% + \ltxkeys@csvparse{#2}% }% - \ltxkeys@csvparse{#2}% + \ltxkeys@csvparse{#1}% \ltxkeys@getkeynames{#3}% \cptexpandsecond{\endgroup\ltxkeys@setkeys*+[#1]{#2}}% {[\ltxkeys@keynames]{\ltxkeys@resa}}% } - -% \ltxkeys@launchkeys[<prefix>]{<fams>}{<curr>} \robust@def*\ltxkeys@launchkeys{\cpt@testopt\ltxkeys@l@unchkeys{KV}} \robust@def*\ltxkeys@l@unchkeys[#1]#2#3{% \ltxkeys@in@ti@lizekeys{#1}{#2}[#3]% + % Don't use the star/plus forms of \ltxkeys@setkeys here, + % otherwise we won't be able to catch undefined keys: \ifblankTF{#3}{}{\ltxkeys@setkeys[#1]{#2}{#3}}% } - -% \ltxkeys@setkeys*+[<prfs>]{<fams>}[<na>]{<curr>} \robust@def*\ltxkeys@setkeys{% \ltxkeys@rmfalse \ltxkeys@teststpl{\ltxkeys@testopt@c\ltxkeys@setkeys@a}% @@ -1442,33 +1621,78 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ {\expandcsnonce{\ltxkeys@hdr rmkeys}}% } \robust@def*\ltxkeys@setkeys@a[#1]#2{% - \cpt@choicefdfalse - \def\siso@do##1{% - \ifstrcmpTF{#2}{##1}\cpt@choicefdtrue\relax - }% - \siso@@loop{.,;:+-=*^_/[()]}% - \ifcpt@choicefd - \ltxkeys@err{Invalid key list '#2'}\@ehc - \fi + \begingroup + \def\x{\ltxkeys@nil}% + \xifinsetTF{\x\detokenize{#2}\x} + {\x.\x,\x;\x:\x+\x-\x=\x*\x^\x_\x/\x|\x[\x(\x)\x]\x}{% + \ltxkeys@err{Invalid key list '#2': Something is wrong}\@ehc + }{}% + \endgroup \ifnum\ltxkeys@keydepth=\z@pt \csn@def{\ltxkeys@hdr rmkeys}{}% \def\ltxkeys@undefinedkeys{}% \fi - \edef\ltxkeys@nakeys{\unexpanded{#1}}% - \ifcsemptyTF\ltxkeys@nakeys{}{% - \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@nakeys + \ltxkeys@getkeynames{#2}% + \let\ltxkeys@naa\ltxkeys@keynames + \ifblankTF{#1}{}{% + \edef\ltxkeys@naa{\cptliststack,\ltxkeys@naa\unexpanded{#1}}% + }% + \ltxkeys@usepresetkeys{pre}% + \ltxkeys@setkeys@b{#1}{#2}% + \ltxkeys@usepresetkeys{post}% + \ltxkeys@exopfalse\ltxkeys@pxopfalse + \ifnumcmpTF\ltxkeys@keydepth=\z@pt{% + \emptifycsset{% + \ltxkeys@keys,\ltxkeys@prefs,\ltxkeys@fams,\ltxkeys@nakeys,% + \ltxkeys@naa,\ltxkeys@tpref,\ltxkeys@ttpref,\ltxkeys@tfam,% + \ltxkeys@tkey,\ltxkeys@tval,\CurrentPref,\CurrentFam,% + \CurrentKeyval,\CurrentKey,\CurrentVal,\ltxkeys@naa + }% + \ifcsemptyTF\ltxkeys@undefinedkeys{}\ltxkeys@logunknownkeys + }{}% +} +\robust@def*\ltxkeys@usepresetkeys#1{% + \ltxkeys@inpresettrue + \begingroup + \toks@{}% + \ltxkeys@vinfo{Looking for #1-set keys}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \ifcsndefFT{\ltxkeys@hdr#1setkeys}{}{% + \cptexpanded{\toks@{\the\toks@\relax\ltxkeys@setkeys@b + {\expandcsonce\ltxkeys@naa} + {\expandcsnonce{\ltxkeys@hdr#1setkeys}}}}% + }% + }% + \ltxkeys@csvloop*\ltxkeys@fams + }% + \ltxkeys@csvloop*\ltxkeys@prefs + \oifblankTF{\the\toks@}{% + \endgroup + \ltxkeys@vinfo{No #1-set keys found}% + }{% + \ltxkeys@vinfo{P\@gobble#1-set keys found. Setting them now}% + \expandafter\endgroup\the\toks@ + \ltxkeys@vinfo{Finished setting #1-set keys}% + }% + \ltxkeys@inpresetfalse +} +\robust@def*\ltxkeys@setkeys@b#1#2{% + \ifblankTF{#1}{% + \def\ltxkeys@nakeys{}% + }{% + \edef\ltxkeys@nakeys{\cptcommanormalize{#1}}% }% \def\ltxkeys@do##1{% \edef\CurrentKeyval{\unexpanded{##1}}% - \ltxkeys@setkeys@b##1=\ltxkeys@nil + \ltxkeys@getkeyvalue##1=\ltxkeys@nil\ltxkeys@tval + \ltxkeys@setkeys@c##1=\ltxkeys@nil }% \ltxkeys@kvparse{#2}% - \emptifycsset{\CurrentPref,\CurrentFam,\CurrentKeyval, - \CurrentKey,\CurrentVal}% - \ltxkeys@exopfalse\ltxkeys@pxopfalse - \ifcsnullTF\ltxkeys@undefinedkeys{}\ltxkeys@logunknownkeys } -\robust@def*\ltxkeys@setkeys@b#1=#2\ltxkeys@nil{% +\robust@def*\ltxkeys@setkeys@c#1=#2\ltxkeys@nil{% \ifinsetTF{\needvalue}{#1}{% \ltxkeys@err{\noexpand\needvalue pointer not allowed \MsgBrk when setting keys}\@ehc @@ -1476,18 +1700,6 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ltxkeys@findpointer\savevalue{#1}\ltxkeys@tkey \ltxkeys@svtrue\ltxkeys@svfalse \let\CurrentKey\ltxkeys@tkey - \ifinsetTF{=\ltxkeys@nil}{#2\ltxkeys@nil}{% - \ltxkeys@novalfalse - \begingroup - \defpass\reserved@a##1=##2\ltxkeys@nil{\endgroup - \edef\ltxkeys@tval{\expandcsonce{\@gobble##1}}% - \let\CurrentVal\ltxkeys@tval - }% - .#2\ltxkeys@nil - }{% - \ltxkeys@novaltrue - \def\ltxkeys@tval{}% - }% \ifcsemptyTF\ltxkeys@tkey{% \ifltxkeys@noval\else \ltxkeys@err{No key specified for value @@ -1496,46 +1708,44 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \fi }{% \xifinsetTF{,\ltxkeys@tkey,}{,\ltxkeys@nakeys,}{}{% - \ltxkeys@setkeys@c + \ltxkeys@setkeys@d }% }% } -\robust@def*\ltxkeys@setkeys@c{% +\robust@def*\ltxkeys@setkeys@d{% \ltxkeys@kffalse - \if@boolTF{ltxkeys@pl}{% - \def\ltxkeys@do##1{% - \def\CurrentPref{##1}% - \ltxkeys@makepf{##1}% - \def\ltxkeys@do####1{% - \def\ltxkeys@tfam{####1}% - \let\CurrentFam\ltxkeys@tfam - \ltxkeys@makehdr\ltxkeys@tfam - \ltxkeys@setkeys@d - }% - \ltxkeys@csvloop*\ltxkeys@fams - }% - \ltxkeys@csvloop*\ltxkeys@prefs + \if@boolTF{ltxkeys@inpreset}{% + \ltxkeys@setkeys@e }{% - \def\ltxkeys@do##1{% - \if@boolTF{ltxkeys@kf}{% - \ltxkeys@break - }{% + \if@boolTF{ltxkeys@pl}{% + \def\ltxkeys@do##1{% \def\CurrentPref{##1}% \ltxkeys@makepf{##1}% \def\ltxkeys@do####1{% - \if@boolTF{ltxkeys@kf}{% - \ltxkeys@break - }{% - \def\ltxkeys@tfam{####1}% - \let\CurrentFam\ltxkeys@tfam - \ltxkeys@makehdr\ltxkeys@tfam - \ltxkeys@setkeys@d - }% + \def\ltxkeys@tfam{####1}% + \let\CurrentFam\ltxkeys@tfam + \ltxkeys@makehdr\ltxkeys@tfam + \ltxkeys@setkeys@e }% \ltxkeys@csvloop*\ltxkeys@fams }% + \ltxkeys@csvloop*\ltxkeys@prefs + }{% + \def\ltxkeys@do##1{% + \def\CurrentPref{##1}% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \def\ltxkeys@tfam{####1}% + \let\CurrentFam\ltxkeys@tfam + \ltxkeys@makehdr\ltxkeys@tfam + \ltxkeys@setkeys@e + \ifltxkeys@kf\loopbreak\fi + }% + \ltxkeys@csvloop*\ltxkeys@fams + \ifltxkeys@kf\loopbreak\fi + }% + \ltxkeys@csvloop*\ltxkeys@prefs }% - \ltxkeys@csvloop*\ltxkeys@prefs }% \if@boolTF{ltxkeys@kf}{% \if@boolFT{ltxkeys@pxop}{}{% @@ -1570,8 +1780,10 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ }% }% } -\robust@def*\ltxkeys@setkeys@d{% - \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{}{% +\robust@def*\ltxkeys@setkeys@e{% + \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{% + \relax + }{% \ltxkeys@kftrue \if@boolTF{ltxkeys@pxop}{% \ltxkeys@testoptionkey{not}% @@ -1594,8 +1806,10 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \s@expandarg\ltxkeys@replacepointers\ltxkeys@tval \if@boolTF{ltxkeys@verbose}{% \ltxkeys@getinnovalnopad - \wlog{Key executed: \ltxkeys@ttpref, \ltxkeys@tfam, - \ltxkeys@tkey, \InnocentVal; on level '\the\ltxkeys@keydepth'.}% + \ltxkeys@vinfo{% + \ifltxkeys@inpreset Preset key\else Key\fi\@space + executed: \ltxkeys@currtriple,\InnocentVal; + on level '\the\ltxkeys@keydepth'}% }{}% \cpt@pushstate\ltxkeys@setkeys\ltxkeys@state\ltxkeys@keydepth \csname\ltxkeys@hdr\ltxkeys@tkey\expandafter @@ -1614,12 +1828,14 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \s@expandarg\ltxkeys@replacepointers\ltxkeys@tval \if@boolTF{ltxkeys@verbose}{% \ltxkeys@getinnovalnopad - \wlog{Key executed: \ltxkeys@ttpref, \ltxkeys@tfam, - \ltxkeys@tkey, \InnocentVal\@space(default); - on level '\the\ltxkeys@keydepth'.}% + \ltxkeys@vinfo{% + \ifltxkeys@inpreset Preset key\else Key\fi\@space + executed: \ltxkeys@currtriple,\InnocentVal(default); + on level '\the\ltxkeys@keydepth' + }% }{}% \cpt@pushstate\ltxkeys@setkeys\ltxkeys@state\ltxkeys@keydepth - \cptifmacroTF{#1}{% + \ifmacroTF{#1}{% \expandafter#1\expandafter{\ltxkeys@tval}\relax }{% \ltxkeys@err{Faulty key macro '\detokenize{#1}'}\@ehc @@ -1637,6 +1853,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ {\ltxkeys@hdr savevalue@keys}#1{\ltxkeys@nil}\ltxkeys@nil } \robust@def*\ltxkeys@replacepointers#1{% + \ltxkeys@vinfo{Replacing pointers of key '\ltxkeys@tkey'}% \def\ltxkeys@resa{}% \@tempswafalse \ifbracedTF{#1}{% @@ -1653,9 +1870,11 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \if@tempswa \ifltxkeys@verbose \ltxkeys@getinnovalnopad - \wlog{Value '\InnocentVal' of key '\ltxkeys@tkey' - inherited from key '\ltxkeys@tempb'.}% + \ltxkeys@vinfo{Value '\InnocentVal' of key '\ltxkeys@tkey' + inherited from key '\ltxkeys@tempb'}% \fi + \else + \ltxkeys@vinfo{No pointers found on key '\ltxkeys@tkey'}% \fi }{% \ltxkeys@getsavedval{#2}{% @@ -1665,10 +1884,9 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \@tempswatrue \def\ltxkeys@tempb{#2}% \oifinset@sp@TF,{#2}\ltxkeys@resa{% - \ltxkeys@err{Dangerous back linking of pointers}{% + \ltxkeys@error{Dangerous back linking of pointers}{% Key pointer replacement terminated due \MsgBrk to possible back linking.}% - \@gobble }{% \edef\ltxkeys@resa{\cptliststack,\ltxkeys@resa#2}% \s@expandarg\ifbracedTF\reserved@a{% @@ -1813,12 +2031,9 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ } \robust@def*\ltxkeys@dis@bl@keys[#1]#2#3{% \endgroup - \def\ltxkeys@prefs{#1}% - \def\ltxkeys@fams{#2}% - \def\ltxkeys@keys{#3}% - \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@prefs - \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@fams - \cpt@sttrue\cpt@csvnormalize[,]\ltxkeys@keys + \edef\ltxkeys@prefs{\cptcommanormalize{#1}}% + \edef\ltxkeys@fams{\cptcommanormalize{#2}}% + \edef\ltxkeys@keys{\cptcommanormalize{#3}}% \def\ltxkeys@do##1{% \ltxkeys@makepf{##1}% \def\ltxkeys@do####1{% @@ -1833,10 +2048,8 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \robust@def\ltxkeys@dis@bl@k@ys{% \def\ltxkeys@do##1{% \ifcsndefFT{\ltxkeys@hdr##1}{% - \ifltxkeys@verbose - \ltxkeys@warn{Key '##1' undefined in families '\ltxkeys@tfam': - \MsgBrk can't be disabled}% - \fi + \ltxkeys@vwarn{Key '##1' undefined in families '\ltxkeys@tfam': + \MsgBrk couldn't be disabled}% }{% \edef\ltxkeys@tempa{% \noexpand\ltxkeys@err{% @@ -1977,7 +2190,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \cpt@choicefdfalse \def\ltxkeys@do##1{% \if@boolTF{cpt@choicefd}{% - \ltxkeys@break + \loopbreak }{% \ltxkeys@makepf{##1}% \ltxkeys@ifk@yd@f @@ -1990,7 +2203,7 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \def\ltxkeys@do##1{% \ltxkeys@makehdr{##1}% \ifcsndefTF{\ltxkeys@hdr\ltxkeys@tkey}{% - \cpt@choicefdtrue\ltxkeys@break + \cpt@choicefdtrue\loopbreak }{}% }% \ltxkeys@csvloop*\ltxkeys@fams @@ -2016,10 +2229,11 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \xifstrcmpTF\answer{x}\ltxkeys@emergencystop\relax } \cpt@cleanup\ltxkeys@processedoptions + \cptonlypreamble{% - \ltxkeys@declareoption,\ltxkeys@declarecmdoption, - \ltxkeys@declarebooloption,\ltxkeys@declarechoiceoption, - \ltxkeys@processoptions,\ltxkeys@executeoptions, + \ltxkeys@declareoption,\ltxkeys@declarecmdoption,% + \ltxkeys@declarebooloption,\ltxkeys@declarechoiceoption,% + \ltxkeys@processoptions,\ltxkeys@executeoptions,% \ltxkeys@unknownoptionhandler,\ltxkeys@unknownkeyhandler } \ltxkeys@declareoption*[KV]<ltxkeys>{% @@ -2029,8 +2243,15 @@ $Id: ltxkeys.sty,v 0.1.0 2011/07/07 09:00:00 Ahmed Musa Exp $ \ltxkeys@declarecmdoption[KV]<ltxkeys>[ltxkeys@]{keyparser}[{;}]{% \stripallouterbracesincs\ltxkeys@keyparser } +\ltxkeys@declarecmdoption[KV]<ltxkeys>[ltxkeys@]{keystacklimit}[4]{% + \ifx\\#1\\% + \ltxkeys@err{Invalid empty value for 'keystacklimit'}\@ehc + \else + \xdef\cpt@optionstacklimit{\number#1}% + \fi +} \ltxkeys@declarebooloption[KV]<ltxkeys>[ltxkeys@]{verbose}[true]{} -\ltxkeys@executeoptions[KV]<ltxkeys>{keyparser}\relax +\ltxkeys@executeoptions[KV]<ltxkeys>{keyparser,keystacklimit}\relax \ltxkeys@processoptions*[KV]<ltxkeys>\relax \endinput |