diff options
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/latex/skeyval/README | 2 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf | bin | 597080 -> 600300 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex | 1035 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/skeyval/skeyval.sty | 677 |
4 files changed, 873 insertions, 841 deletions
diff --git a/Master/texmf-dist/doc/latex/skeyval/README b/Master/texmf-dist/doc/latex/skeyval/README index 97c3cb6d955..0b495132f3d 100644 --- a/Master/texmf-dist/doc/latex/skeyval/README +++ b/Master/texmf-dist/doc/latex/skeyval/README @@ -1,6 +1,6 @@ %+++++++++++++++++++++++++++++++++++ INTRODUCTION +++++++++++++++++++++++++++++++++++% % % -% This is the Readme file for the skeyval package, version 0.7. % +% This is the Readme file for the skeyval package, version 0.71. % % May 2010 % % % % Copyright (c) 2010 Ahmed Musa (a.musa@rocketmail.com). % diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf b/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf Binary files differindex 0f893afa783..a82980a58eb 100644 --- a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf +++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.pdf diff --git a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex b/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex index 919ebfc7d9e..17345d18950 100644 --- a/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex +++ b/Master/texmf-dist/doc/latex/skeyval/skeyval-guide.tex @@ -14,13 +14,13 @@ version~0.5. The \asty{keyreader} is now obsolete and no longer supported.} }{% \titlenote[t2]{The package is available at \url{\@shorttitleurl}.}% } -\subtitle{Version 0.7} +\subtitle{Version 0.71} \titleurl{http://www.ctan.org/tex-archive/macros/latex/contrib/skeyval/} \shorttitleurl{http://www.ctan.org/} \author{Ahmed Musa\Email{a.musa@rocketmail.com}\\Preston, Lancashire, UK} \NewLet\abstname\abstractname -\SKV@redef*\abstractname{\vspace{-\baselineskip}} +\redef*\abstractname{\vspace{-\baselineskip}} \begin{abstract} \frameshade[width=\hsize,fillcolor=yellow!20,framesep=2pt,framerule=2pt, framecolor=brown]{% @@ -31,7 +31,7 @@ version~0.5. The \asty{keyreader} is now obsolete and no longer supported.} \end{abstract} \NewLet\licname\licensename -\SKV@redef*\licensename{\vspace{-\baselineskip}} +\redef*\licensename{\vspace{-\baselineskip}} \begin{license} \frameshade[width=\hsize,fillcolor=white,framesep=2pt,framerule=2pt, framecolor=brown]{\small @@ -68,7 +68,7 @@ version~0.5. The \asty{keyreader} is now obsolete and no longer supported.} \Note A toggle is also a boolean or switch. We refer to it here as \emph{toggle} or \emph{toggle switch} or \emph{toggle boolean}. The term \emph{Knuth/native switch} is reserved here for \tex's legacy boolean or switch. -The \pkg{xkeyval} can't be used to define and set toggle keys. The present package provides facilities for defining and setting toggle keys. The work relies on some of the internal macros from the \pkg{xkeyval}. +The \pkg{xkeyval} can't be used to define and set toggle keys. The present package provides facilities for defining and setting toggle keys. Secondly, the \pkg{xkeyval} can't be used to define and set complementary (bipolar and unipolar) keys, which can be handy in the case of native boolean and toggle keys. Complementary bipolar keys are mutually exclusive keys, \ie, they never assume the same state of a two-valued logic, and they switch states automatically, depending on the state of any one of them. So whenever one of them assumes one of the two states of a two-valued logic, the other one automatically switches its state from whatever state it was previously, such that the two are never in the same state. Simple examples of complementary bipolar keys would be the options \acmd{draft} and \acmd{final} in a document; they are mutually exclusive. Complementary bipolar keys carry equal charge, \ie, each one can equally toggle the other with identical propensity, but the one that represents the default state of a two-valued logic is usually considered the primary, while the other is secondary. In many document classes, for instance, \acmd{final} is considered a default document option and \acmd{draft} would have to be explicitly selected by the user to toggle \acmd{final} to false. @@ -80,7 +80,9 @@ The third motivation for this package relates to economy of tokens in style file Fourthly, macros are introduced for defining all key types without the fear of inadvertently redefining existing keys in the same family and with the same key prefix. This has a philosophy akin to the \acmd{\newcommand} concept in \LaTeX. -The package also provides facilities for disabling, suspending, restoring and removing keys across multiple families of keys. The pointer system of the \pkg{xkeyval} is also extended by the \pkg{skeyval}, and the notion of ``user-value'' keys is introduced. +The package also provides facilities for disabling, suspending, restoring and removing keys across multiple families of keys. The pointer system of the \pkg{xkeyval} is also extended by the \pkg{skeyval}, and the notion of ``user-value'' keys is introduced and operationalized. + +Normally when setting keys, the \pkg{xkeyval} terminates with an error message if any key in the list of keys to be set is currently undefined or unknown. This means that if you have a set of keys to set simultaneously and you misspell a few of them, you would have to make several passes to get all the keys right. The \pkg{skeyval} takes a different approach. For each call to \acmd{\setkeys}, it saves the names of undefined keys (and their associated families and prefixes) in a macro and issues an error message (together with the contents of that macro) if at the end of the call that macro is non-empty. Such undefined keys are not set in the pass. In this way, you can correct all wrongly entered keys in one go, rather than repeat the pass for each of them. The new macros can be used together with the machinery from the \pkg{xkeyval} for efficient and versatile key management. @@ -108,7 +110,7 @@ verbose=false \end{macro} \acmdm*{keyparser,macroprefix,keyprefix,keyfamily,verbose} -The \aang{keyparser} is the separator between the keys in the key list to be defined in one go (see \cref{sec:multkeys-examples}). The \aang{macroprefix}, \aang{keyprefix}, and \aang{keyfamily} are, respectively, the macro prefix, key prefix and key family for all the keys to be defined upon the declaration of these options. All these options can be set or changed dynamically by using the \acmdm{\skvoptions} macro: +The \ang{keyparser} is the separator between the keys in the key list to be defined in one go (see \cref{sec:multkeys-examples}). The \ang{macroprefix}, \ang{keyprefix}, and \ang{keyfamily} are, respectively, the macro prefix, key prefix and key family for all the keys to be defined upon the declaration of these options. All these options can be set or changed dynamically by using the \acmdm{\skvoptions} macro: \begin{macro} \skvoptions{keyparser=;, macroprefix=mp@, keyprefix=KV, keyfamily=fam} @@ -116,7 +118,7 @@ The \aang{keyparser} is the separator between the keys in the key list to be def These options are explained in more detail in subsequent sections. -If, as unlikely as it may seem, a clash arises between package and/or user macros as a result of the use of the defaults for \aang{macroprefix}, \aang{keyprefix} and \aang{keyfamily}, then the user will have to make his own choices for these defaults so as to avoid clashes. +If, as unlikely as it may seem, a clash arises between package and/or user macros as a result of the use of the defaults for \ang{macroprefix}, \ang{keyprefix} and \ang{keyfamily}, then the user will have to make his own choices for these defaults so as to avoid clashes. The \pkg{skeyval} issues a fatal error if it is loaded before (or run without) \acmd{\documentclass}. @@ -130,15 +132,15 @@ As mentioned in \cref{sec:motivation}, complementary bipolar keys are keys that The syntax for creating bipolar native-boolean keys is \begin{macro} -\define@biboolkeys[|cang(keyprefix)]{|cang(family)}[|cang(macroprefix)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(func for primary boolean)} - {|cang(func for secondary boolean)} +\define@biboolkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(func for primary boolean)} + {|vang(func for secondary boolean)} \end{macro} \acmdm*{\define@biboolkeys} -This command is robust and can be used in expansion contexts, but expandable commands may need to be protected. When the user doesn't supply the \aang{keyprefix} and/or \aang{macroprefix}, the package will use \aang{KV} and \aang{mp@}, respectively. When the default value for the primary boolean is not supplied, the package will use \acmd{true}. Infinite loops, which are possible in back-linked key settings, are avoided in the \pkg{skeyval}. The machinery of the \pkg{xkeyval}, such as \acmd{\setkeys}, \acmd{\presetkeys}, \acmd{\savekeys}, \acmd{\savevalue}, \acmd{\usevalue}, \etc, are all applicable to all complementary keys. +This command is robust and can be used in expansion contexts, but expandable commands may need to be protected. When the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary boolean is not supplied, the package will use \acmd{true}. Infinite loops, which are possible in back-linked key settings, are avoided in the \pkg{skeyval}. The machinery of the \pkg{xkeyval}, such as \acmd{\setkeys}, \acmd{\presetkeys}, \acmd{\savekeys}, \acmd{\savevalue}, \acmd{\usevalue}, \etc, are all applicable to all complementary keys. -As an example, we define below two bipolar native-boolean keys \aang{draft} and \aang{final} with different key macros: +As an example, we define below two bipolar native-boolean keys \ang{draft} and \ang{final} with different key macros: \begin{example} \define@biboolkeys[KV]{fam}[mp@]{draft}[true]{final}% {% @@ -160,13 +162,13 @@ The key prefix (default \fx{KV}), macro prefix (default \fx{mp@}), key macros (n \define@biboolkeys{fam}{draft}{final}{}{}. \end{example} -The defined complementary bipolar keys \aang{draft} and \aang{final} can now be set separately as follows: +The defined complementary bipolar keys \ang{draft} and \ang{final} can now be set separately as follows: \begin{example} \setkeys[KV]{fam}{draft=true |makered(or) on} \setkeys[KV]{fam}{final=true |makered(or) on} \end{example} -The second statement above reverses the boolean \aang{draft} to \aang{false}, which had been set in the first statement to \aang{true}. There is no apparent meaning to the following: +The second statement above reverses the boolean \ang{draft} to \ang{false}, which had been set in the first statement to \ang{true}. There is no apparent meaning to the following: \begin{example} \setkeys[KV]{fam}{draft=true,final=true}. \end{example} @@ -176,10 +178,10 @@ In the \pkg{skeyval}, the acceptable values for native-boolean and toggle-boolea The \pkg{skeyval} has the \acmdm{\NewIfs} macro which defines five commands per switch: \begin{macro} -\NewIfs[|cang(optional prefix)]{|cang(boolean list)}[|cang(optional state)] +\NewIfs[|vang(optional prefix)]{|vang(boolean list)}[|vang(optional state)] \end{macro} \acmdm*{\NewIfs} -This provides, for each member of the comma-separated list \bang{boolean list}, a new native-boolean register if the register didn't already exist, otherwise an error is flagged. Each member of \bang{boolean list} is prefixed with \aang{prefix} upon definition. The optional \aang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}; the default is \fx{false}. \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. After declaring +This provides, for each member of the comma-separated list \ang{boolean list}, a new native-boolean register if the register didn't already exist, otherwise an error is flagged. Each member of \ang{boolean list} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}; the default is \fx{false}. The state \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. After declaring \begin{example} \NewIfs[bool]{a,b}[true] \end{example} @@ -189,13 +191,13 @@ you can say \fx{\ifboola}, \fx{\boolaon} and \fx{\boolaoff}, just like you would Unipolar boolean keys are two keys that are always in the same state: when one is true (or false), the other one is also true (or false). In this regard, the key macro is always executed when a key transits to the ``true'' state. The syntax for creating unipolar native-boolean keys is exactly as that for defining bipolar native-boolean keys: \begin{macro} -\define@uniboolkeys[|cang(keyprefix)]{|cang(family)}[|cang(macroprefix)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(func for primary boolean)} - {|cang(func for secondary boolean)} +\define@uniboolkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(func for primary boolean)} + {|vang(func for secondary boolean)} \end{macro} \acmdm*{\define@uniboolkeys} -This command is robust and can be used in expansion contexts, but expandable commands may need to be protected. Again, if the user doesn't supply the \aang{keyprefix} and/or \aang{macroprefix}, the package will use \aang{KV} and \aang{mp@}, respectively. When the default value for the primary boolean is not supplied, the package will assume it to be \fx{true}. +This command is robust and can be used in expansion contexts, but expandable commands may need to be protected. Again, if the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary boolean is not supplied, the package will assume it to be \fx{true}. The following example constructs two unipolar native-boolean keys: \begin{example} @@ -231,10 +233,10 @@ Of course, the primary key can be true only after it has been set. The syntax for establishing biuni boolean keys is exactly like that for creating other complementary boolean keys, except for the optional \RedStar and \RedPlus signs: \begin{macro} -\define@biuniboolkeys|redstar|redplus[|cang(keyprefix)]{|cang(family)}[|cang(macroprefix)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(macro for primary boolean)} - {|cang(macro for secondary boolean)} +\define@biuniboolkeys|redstar|redplus[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(macro for primary boolean)} + {|vang(macro for secondary boolean)} \end{macro} \acmdm*{\define@biuniboolkeys,\define@biuniboolkeys*,\define@biuniboolkeys*+} @@ -287,72 +289,72 @@ The following toggle switches are defined in the \pkg{skeyval}. They largely mim All the commands in this section are robust and can be used in expansion or moving contexts without fear of premature expansion, but fragile arguments would need to be protected in those settings. \begin{macro} -\deftog[|cang(optional prefix)]{|cang(toggle)}[|cang(optional state)] +\deftog[|vang(optional prefix)]{|vang(toggle)}[|vang(optional state)] \end{macro} -This defines a new \aang{toggle}, prefixed with \aang{prefix} upon definition, whether or not \aang{toggle} (with its prefix) is already defined. If \aang{toggle} is already defined, a warning message is logged in the transcript file (if the package option \fx{verbose} is selected) and the new definition is effected. The optional \aang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. +This defines a new \ang{toggle}, prefixed with \ang{prefix} upon definition, whether or not \ang{toggle} (with its prefix) is already defined. If \ang{toggle} is already defined, a warning message is logged in the transcript file (if the package option \acmd{verbose} is selected) and the new definition is effected. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. \begin{macro} -\newtog[|cang(optional prefix)]{|cang(toggle)}[|cang(optional state)] +\newtog[|vang(optional prefix)]{|vang(toggle)}[|vang(optional state)] \end{macro} \acmdm*{\newtog} -This defines a new \aang{toggle}, prefixed with \aang{prefix} upon definition, if \aang{toggle} (with its prefix) is not already defined; otherwise the package issues a fatal error. The optional \aang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. +This defines a new \ang{toggle}, prefixed with \ang{prefix} upon definition, if \ang{toggle} (with its prefix) is not already defined; otherwise the package issues a fatal error. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. You can define a set of toggles by the following command: \begin{macro} -\NewTogs[|cang(optional prefix)]{|cang(toggles)}[|cang(optional state)], +\NewTogs[|vang(optional prefix)]{|vang(toggles)}[|vang(optional state)], \end{macro} \acmdm*{\NewTogs} -where \aang{toggles} is a comma-separated list. Each member of \aang{toggles} is prefixed with \aang{prefix} upon definition. The optional \aang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. For example, we may define new toggles \fx{togx}, \fx{togy}, \fx{togz} by the following: +where \ang{toggles} is a comma-separated list. Each member of \ang{toggles} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. For example, we may define new toggles \fx{togx}, \fx{togy}, \fx{togz} by the following: \begin{example} \NewTogs[tog]{x,y,z}[true] \end{example} \begin{macro} -\providetog{|cang(toggle)} +\providetog{|vang(toggle)} \end{macro} \acmdm*{\providetog} -This defines a new \aang{toggle} if \aang{toggle} is not already defined. If \aang{toggle} is already defined, the command does nothing. Please note that there are no tog prefix here, and that the default state is \fx{false}. +This defines a new \ang{toggle} if \ang{toggle} is not already defined. If \ang{toggle} is already defined, the command does nothing. Please note that there are no tog prefix here, and that the default state is \fx{false}. \begin{macro} -\requiretog{|cang(toggle)} +\requiretog{|vang(toggle)} \end{macro} -\acmdm{\requiretog} takes arguments like \fx{\newtog} and behaves like \fx{\providetog} with the difference: if the toggle is already defined, the command \fx{\requiretog} calls \LaTeX's \acmdm{\CheckCommand} to make sure that the new and existing definitions are identical, whereas \fx{\providetog} assumes that if the toggle is already defined, the existing definition should persist. \fx{\requiretog} assures that a toggle will have the given definition, but (if the package option \fx{verbose} is selected) \fx{\requiretog} also warns the user if there was a previous and different existing definition. For example, if the toggle \aang{toga} is currently \aang{true}, then since all new toggles start out as \aang{false}, a call \fx{\requiretog{toga}} will, if the package option \fx{verbose} is selected, issue a warning in the log file that the new and old definitions of \aang{toga} don't agree and the new definition, therefore, can't go ahead. Note that there are no tog prefix here, and that the default state is \fx{false}. +\acmdm{\requiretog} takes arguments like \fx{\newtog} and behaves like \fx{\providetog} with the difference: if the toggle is already defined, the command \fx{\requiretog} calls \LaTeX's \acmdm{\CheckCommand} to make sure that the new and existing definitions are identical, whereas \fx{\providetog} assumes that if the toggle is already defined, the existing definition should persist. \fx{\requiretog} assures that a toggle will have the given definition, but (if the package option \fx{verbose} is selected) \fx{\requiretog} also warns the user if there was a previous and different existing definition. For example, if the toggle \ang{toga} is currently \ang{true}, then since all new toggles start out as \ang{false}, a call \fx{\requiretog{toga}} will, if the package option \fx{verbose} is selected, issue a warning in the log file that the new and old definitions of \ang{toga} don't agree and the new definition, therefore, can't go ahead. Note that there are no tog prefix here, and that the default state is \fx{false}. The \pkg{skeyval} also provides the command \acmd{\requirecmd}, which has the same logic as \fx{\requiretog} but can be used for general \latex commands, including those with optional arguments (see \cref{sec:misce-commands}). \begin{macro} -\settog{|cang(toggle)}{|cang(true |amdvert false |amdvert on |amdvert off)} +\settog{|vang(toggle)}{|vang(true |amdvert false |amdvert on |amdvert off)} \end{macro} \acmdm*{\settog} -This command sets \aang{toggle} to \aang{value}, where \aang{value} may be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. This statement will issue an error if \aang{toggle} wasn't previously defined. +This command sets \ang{toggle} to \ang{value}, where \ang{value} may be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. This statement will issue an error if \ang{toggle} wasn't previously defined. \begin{macro} -\togon{|cang(toggle)} -\togtrue{|cang(toggle)} +\togon{|vang(toggle)} +\togtrue{|vang(toggle)} \end{macro} \acmdm*{\togon, \togtrue} -These set \aang{toggle} to \aang{true} or \fx{on}. They will issue an error if \aang{toggle} wasn't previously defined. +These set \ang{toggle} to \ang{true} or \fx{on}. They will issue an error if \ang{toggle} wasn't previously defined. \begin{macro} -\togoff{|cang(toggle)} -\togfalse{|cang(toggle)} +\togoff{|vang(toggle)} +\togfalse{|vang(toggle)} \end{macro} \acmdm*{\togoff, \togfalse} -These set \aang{toggle} to \aang{false} or \fx{off}. They will issue an error if \aang{toggle} wasn't previously defined. +These set \ang{toggle} to \ang{false} or \fx{off}. They will issue an error if \ang{toggle} wasn't previously defined. \begin{macro} -\iftogon{|cang(toggle)}{|cang(true)}{|cang(false)} -\iftogtrue{|cang(toggle)}{|cang(true)}{|cang(false)} +\iftogon{|vang(toggle)}{|vang(true)}{|vang(false)} +\iftogtrue{|vang(toggle)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\iftogon, \iftogtrue} -These yield the \aang{true} statement if the boolean \aang{toggle} is currently \aang{true}, and \aang{false} otherwise. They will issue an error if \aang{toggle} wasn't previously defined. +These yield the \ang{true} statement if the boolean \ang{toggle} is currently \ang{true}, and \ang{false} otherwise. They will issue an error if \ang{toggle} wasn't previously defined. \begin{macro} -\iftogoff{|cang(toggle)}{|cang(not true)}{|cang(not false)} -\iftogfalse{|cang(toggle)}{|cang(not true)}{|cang(not false)} +\iftogoff{|vang(toggle)}{|vang(not true)}{|vang(not false)} +\iftogfalse{|vang(toggle)}{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\iftogoff, \iftogfalse} -These behave like \fx{\iftogon} and \fx{\iftogtrue} but reverse the logic of the test. They will issue an error if \aang{toggle} wasn't previously defined. +These behave like \fx{\iftogon} and \fx{\iftogtrue} but reverse the logic of the test. They will issue an error if \ang{toggle} wasn't previously defined. \subsection{Toggle-boolean keys} \label{sec:toggle-keys} @@ -363,19 +365,19 @@ As mentioned earlier, toggles have their own separate namespace. However, the \a The user interfaces for defining toggle keys are \begin{macro} -\define@togkey[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(function)} +\define@togkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(function)} -\define@togkey|redplus[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(function1)}{|cang(function2)} +\define@togkey|redplus[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(function1)}{|vang(function2)} \end{macro} \acmdm*{\define@togkey,\define@togkey+} -If the macro prefix \aang{mp} is not specified, these create a toggle of the form \fnn{prefix}{family}{key}{} using \acmd{\deftog} (which initializes the toggle switch to \fx{false}) and a key macro of the form \bs\fnn{prefix}{family}{key}{} which first checks the validity of the user input. If the value is valid, it uses it to set the toggle and then executes \aang{function}. If the user input wasn't valid (\ie, neither \fx{true} nor \fx{false}), then the toggle will not be set and the package will generate a fatal error to this effect. +If the macro prefix \ang{mp} is not specified, these create a toggle of the form \fnn{prefix}{family}{key}{} using \acmd{\deftog} (which initializes the toggle switch to \fx{false}) and a key macro of the form \bs\fnn{prefix}{family}{key}{} which first checks the validity of the user input. If the value is valid, it uses it to set the toggle and then executes \ang{function}. If the user input wasn't valid (\ie, neither \fx{true} nor \fx{false}), then the toggle will not be set and the package will generate a fatal error to this effect. -If \aang{mp} is specified, then the key definition process will create a toggle of the form \fnm{mp}{key}{}{} and a key macro of the form \bs\fnm{mp}{key}{}{}. The value \aang{default} will be used by the key macro when the user sets the key without a value. +If \ang{mp} is specified, then the key definition process will create a toggle of the form \fnm{mp}{key}{}{} and a key macro of the form \bs\fnm{mp}{key}{}{}. The value \ang{default} will be used by the key macro when the user sets the key without a value. -If the plus (\RedPlus) version of the macro is used, the user can specify two key macros \aang{function1} and \aang{function2}. If user input is valid, the macro will set the toggle and executes \aang{function1}; otherwise, it will not set the boolean but will execute \aang{function2}. +If the plus (\RedPlus) version of the macro is used, the user can specify two key macros \ang{function1} and \ang{function2}. If user input is valid, the macro will set the toggle and executes \ang{function1}; otherwise, it will not set the boolean but will execute \ang{function2}. As an example, consider the following: \begin{example} @@ -398,16 +400,16 @@ As an example, consider the following: } \end{example} -The first example creates the toggle \aang{my@frame} and defines the key macro +The first example creates the toggle \ang{my@frame} and defines the key macro \fx{\KV@fam@frame} to set the boolean (if the input is valid). The second key intimates the user of changed settings, or produces a warning when input was incorrect. It is also possible to define multiple toggle keys with a single command: \begin{macro} -\define@togkeys[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(keys)}[|cang(default)] +\define@togkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)] \end{macro} \acmdm*{\define@togkeys} -This creates a toggle key for every entry in the comma-separated list \aang{keys}. As is the case with the commands \acmd{\define@cmdkeys} and \acmd{\define@boolkeys} from the \pkg{xkeyval}, the individual keys in this case can't have a custom function. See \cref{sec:multiplekeys} for how to define multiple keys with custom functions. +This creates a toggle key for every entry in the comma-separated list \ang{keys}. As is the case with the commands \acmd{\define@cmdkeys} and \acmd{\define@boolkeys} from the \pkg{xkeyval}, the individual keys in this case can't have a custom function. See \cref{sec:def-multiple-keys} for how to define multiple keys with custom functions. As an example of defining multiple toggle keys, consider \begin{example} @@ -433,11 +435,11 @@ Toggle keys can be set in the same way that other key types are set. The status of toggles can be examined by doing \begin{example} -\show\SKV@toggle@|cang(mp)|cang(key) +\show\SKV@toggle@|vang(mp)|vang(key) \end{example} -when the \aang{mp} is present. When the user has specified no \aang{mp} in defining the key, he has to issue +when the \ang{mp} is present. When the user has specified no \ang{mp} in defining the key, he has to issue \begin{example} -\show\SKV@toggle@|cang(prefix)@|cang(family)@|cang(key). +\show\SKV@toggle@|vang(prefix)@|vang(family)@|vang(key). \end{example} \section{Complementary toggle keys} @@ -447,15 +449,15 @@ when the \aang{mp} is present. When the user has specified no \aang{mp} in defin Similar to complementary native-boolean keys of \cref{sec:comp-boolkeys}, the \pkg{skeyval} introduces facilities for creating complementary (bipolar, unipolar and biunipolar) toggle keys. The syntax for defining bipolar toggle keys is identical to that for defining bipolar native-boolean keys: \begin{macro} -\define@bitogkeys[|cang(keyprefix)]{|cang(family)}[|cang(macroprefix)] - {|cang(primary toggle)}[|cang(default value for primary toggle)] - {|cang(secondary toggle)}{|cang(func for primary toggle)} - {|cang(func for secondary toggle)}. +\define@bitogkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)] + {|vang(primary toggle)}[|vang(default value for primary toggle)] + {|vang(secondary toggle)}{|vang(func for primary toggle)} + {|vang(func for secondary toggle)}. \end{macro} \acmdm*{\define@bitogkeys} -This command is robust and can be used in expansion contexts, but non-robust commands have to be protected. When the user doesn't supply the \aang{keyprefix} and/or \aang{macroprefix}, the package will use \aang{KV} and \aang{mp@}, respectively. When the default value for the primary toggle-boolean is not supplied, the package will use \fx{true}. When one of the bipolar toggle keys (primary or secondary) is true, the other is automatically set false; and vice versa: when one toggle key (primary or secondary) is false, the other is automatically set true. +This command is robust and can be used in expansion contexts, but non-robust commands have to be protected. When the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary toggle-boolean is not supplied, the package will use \fx{true}. When one of the bipolar toggle keys (primary or secondary) is true, the other is automatically set false; and vice versa: when one toggle key (primary or secondary) is false, the other is automatically set true. -As an example, we define below two bipolar toggle keys \aang{xdraft} and \aang{xfinal} with different key macros: +As an example, we define below two bipolar toggle keys \ang{xdraft} and \ang{xfinal} with different key macros: \begin{example} \define@bitogkeys[KV]{fam}[mp@]{xdraft}[true]{xfinal}% {\def\gobble##1{}}{\def\firstofone##1{##1}} @@ -465,31 +467,31 @@ The key prefix (default \fx{KV}), macro prefix (default \fx{mp@}), key macros (n \define@bitogkeys{fam}{xdraft}{xfinal}{}{}. \end{example} -The defined bipolar toggle keys \aang{xdraft} and \aang{xfinal} can now be set as follows: +The defined bipolar toggle keys \ang{xdraft} and \ang{xfinal} can now be set as follows: \begin{example} \setkeys[KV]{fam}{xdraft=true} \setkeys[KV]{fam}{xfinal=true} \end{example} \acmd*{\setkeys} -The second statement above reverses the toggle \aang{xdraft} to \aang{false}, which had been set in the first statement to \aang{true}. +The second statement above reverses the toggle \ang{xdraft} to \ang{false}, which had been set in the first statement to \ang{true}. \Note Toggle keys may easily be confused with the conventional boolean keys, especially at the time of key setting. It is, therefore, always safer to use the syntaxes in \cref{sec:redef-keys} for defining keys; they avoid interference between new and existing keys. -If we were to use the key names \acmd{draft} and \acmd{final} as toggle keys above, instead of \fx{xdraft} and \fx{xfinal}, there would have been a clash with the keys \acmd{draft} and \acmd{final} defined as (complementary) native-boolean keys in \cref{sec:comp-boolkeys}---because they share the same family \aang{fam} and prefix \aang{KV}. The names \acmd{draft} and \acmd{final} could safely be used as toggles only if the family \aang{fam} or prefix \aang{KV} is changed. See \cref{sec:avoiding-redef} for further details. +If we were to use the key names \acmd{draft} and \acmd{final} as toggle keys above, instead of \fx{xdraft} and \fx{xfinal}, there would have been a clash with the keys \acmd{draft} and \acmd{final} defined as (complementary) native-boolean keys in \cref{sec:comp-boolkeys}---because they share the same family \ang{fam} and prefix \ang{KV}. The names \acmd{draft} and \acmd{final} could safely be used as toggles only if the family \ang{fam} or prefix \ang{KV} is changed. See \cref{sec:avoiding-redef} for further details. \subsection{Unipolar toggle-boolean keys} The syntax for defining unipolar toggle keys is exactly the same as that for defining bipolar toggle keys: \begin{macro} -\define@unitogkeys[|cang(keyprefix)]{|cang(family)}[|cang(macroprefix)] - {|cang(primary toggle)}[|cang(default value for primary toggle)] - {|cang(secondary toggle)}{|cang(func for primary toggle)} - {|cang(func for secondary toggle)}. +\define@unitogkeys[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)] + {|vang(primary toggle)}[|vang(default value for primary toggle)] + {|vang(secondary toggle)}{|vang(func for primary toggle)} + {|vang(func for secondary toggle)}. \end{macro} \acmdm*{\define@unitogkeys} -Here too, if the user doesn't supply the \aang{keyprefix} and/or \aang{macroprefix}, the package will use \aang{KV} and \aang{mp@}, respectively. When the default value for the primary toggle key is not supplied, the package will use \acmd{true}. +Here too, if the user doesn't supply the \ang{keyprefix} and/or \ang{macroprefix}, the package will use \ang{KV} and \ang{mp@}, respectively. When the default value for the primary toggle key is not supplied, the package will use \acmd{true}. \begin{example} \define@unitogkeys[KV]{fam}[mp@]{draft}[true]{final}% {\def\x##1{}}{\def\y##1{##1}} @@ -501,10 +503,10 @@ Here too, if the user doesn't supply the \aang{keyprefix} and/or \aang{macropref The interface for creating biuni toggle keys is exactly like that for creating other complementary boolean keys, except for the optional \RedStar and \RedPlus signs. The interface is as follows (the meaning of the optional \RedStar and \RedPlus is given in \cref{sec:biuni-boolean}): \begin{macro} -\define@biunitogkeys|redstar|redplus[|cang(keyprefix)]{|cang(family)}[|cang(macroprefix)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(macro for primary boolean)} - {|cang(macro for secondary boolean)} +\define@biunitogkeys|redstar|redplus[|vang(keyprefix)]{|vang(family)}[|vang(macroprefix)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(macro for primary boolean)} + {|vang(macro for secondary boolean)} \end{macro} \acmdm*{\define@biunitogkeys,\define@biunitogkeys*,\define@biunitogkeys*+} @@ -527,21 +529,21 @@ The interface for creating biuni toggle keys is exactly like that for creating o \section[Defining multiple keys by one command] {Defining multiple keys of all genres by one command} -\label{sec:multiplekeys} +\label{sec:def-multiple-keys} -The interface for defining multiple keys of all kinds in one go is the command \acmdm{\define@keylist}, whose syntax is +The user interface for defining multiple keys of all kinds in one go is the command \acmdm{\define@keylist}, whose syntax is \begin{macro} -\define@keylist{|cang(key type/id), |cang(key), |cang(key default value), - |cang(key macro/function); |cang(another set of key specifiers); etc} +\define@keylist{|vang(key type/id), |vang(key), |vang(key default value), + |vang(key macro/function); |vang(another set of key specifiers); etc} \end{macro} -There are five key types: 1 (ordinary key), 2 (command key), 3 (native-boolean key), -4 (toggle-boolean key), and 5 (choice/menu key). The key types can be indicated either in numeral format (\fx{1}~to~\fx{5}) or in alphabetic format (\fx{ord}, \fx{cmd}, \fx{bool}, \fx{tog}, \fx{choice}, \fx{menu}). ``Choice'' and ``menu'' key types imply the same thing (key type~5): the user can pick the name he prefers. The key and its attributes are separated by commas; they constitute one ``object'' or ``instance''. The objects are separated by the \aang{keyparser}, which is the semicolon in the above example. +Here, there are five key types: 1~(ordinary key), 2~(command key), 3~(native-boolean key), +4~(toggle-boolean key), and 5~(choice/menu key). The key types can be indicated either in numeral format (\fx{1}~to~\fx{5}) or in alphabetic format (\fx{ord}, \fx{cmd}, \fx{bool}, \fx{tog}, \fx{choice}, \fx{menu}). ``Choice'' and ``menu'' keys imply the same thing (key type~5): the user can pick the name he prefers. The key and its attributes are separated by commas; they constitute one ``object'' or ``instance''. The objects are separated by the \ang{keyparser}, which is the semicolon in the above example. The \ang{keyparser} is a package option and can be changed dynamically. If the key list is available in a macro, say, \begin{example} -\def\keylist{|cang(key type/id), |cang(key), |cang(key default value), - |cang(key macro/function); |cang(another set of key specifiers); etc}, +\def\keylist{|vang(key type/id), |vang(key), |vang(key default value), + |vang(key macro/function); |vang(another set of key specifiers); etc}, \end{example} then the keys can be defined by the starred form of \fx{\define@keylist}: \begin{example} @@ -557,7 +559,9 @@ The \fx{\define@keylist} macro uses the following commands in the background: \end{example} \acmdm*{\define@cmdkey,\define@boolkey,\define@choicekey,\define@togkey} \acmd*{\define@key} -Therefore, it assumes that it is safe to redefine a previously defined key. If this assumption is unwarranted, then the user should consider using the machinery of \cref{sec:redef-keys}.\footnote{The machinery of \cref{sec:redef-keys} can be utilized to safely define new keys without the fear of inadvertently redefining an existing key within the same family and with the same key prefix.} +Therefore, it assumes that it is safe to redefine a previously defined key. If this assumption is unwarranted, then the user should consider using the machinery of \cref{sec:redef-keys}. The machinery of \cref{sec:redef-keys} can be utilized to safely define new keys without the fear of inadvertently redefining an existing key within the same family and with the same key prefix. + +Keys defined by the tools in this section are amenable to management by pointers of \cref{sec:pointer-mech}. \subsection{Choice key values} \label{sec:choice-key-values} @@ -566,9 +570,9 @@ The \acmdm{\choicekeyvalues} macro is provided for defining choice keys; it list admissible values for a choice key and thus can't be empty when a choice key is being defined via \fx{\define@keylist}. Its syntax is \begin{macro} -\choicekeyvalues|redstar[|cang(prefix)][|cang(family)]{|cang(key)}{|cang(list)}, +\choicekeyvalues|redstar[|vang(prefix)][|vang(family)]{|vang(key)}{|vang(list)}, \end{macro} -where \aang{list} is a comma-separated list of admissible key values. Unless the key prefix or family changes, the unstarred variant of \fx{\choicekeyvalues} wouldn't allow you to set two \fx{\choicekeyvalues} for the same choice key. The starred variant \fx{\choicekeyvalues}\unskip\redstar, on the other hand, allows you to overwrite admissible choice values for a key within a specified family and with the given key prefix. The arguments \aang{prefix} and \aang{family} are optional, provided the key prefix and family have been specified before calling \fx{\choicekeyvalues}, using \fx{\skvoptions}. If \aang{prefix} and \aang{family} are not given, the prevailing key prefix and key family are used internally by \fx{\choicekeyvalues} to build distinct alternate values list for the choice key. Therefore, any number of choice keys are allowed to appear in one \acmd{\define@keylist} or \acmd{\define@keylist}\unskip\redstar\ statement, if their lists of alternate/admissible values have been set by \fx{\choicekeyvalues}. +where \ang{list} is a comma-separated list of admissible key values. Unless the key prefix or family changes, the unstarred variant of \fx{\choicekeyvalues} wouldn't allow you to set two \fx{\choicekeyvalues} for the same choice key. The starred variant \fx{\choicekeyvalues}\unskip\redstar, on the other hand, allows you to overwrite admissible choice values for a key within a specified family and with the given key prefix. The arguments \ang{prefix} and \ang{family} are optional, provided the key prefix and family have been specified before calling \fx{\choicekeyvalues}, using \fx{\skvoptions}. If \ang{prefix} and \ang{family} are not given, the prevailing key prefix and key family are used internally by \fx{\choicekeyvalues} to build distinct alternate values list for the choice key. Therefore, any number of choice keys are allowed to appear in one \acmd{\define@keylist} or \acmd{\define@keylist}\unskip\redstar\ statement, if their lists of alternate/admissible values have been set by \fx{\choicekeyvalues}. It doesn't matter which choice key first gets a \fx{\choicekeyvalues}. To further save tokens, the macro \fx{\choicekeyvalues} may be abbreviated by \acmdm{\CKVS}. It has to be provided for each choice key that is being defined. @@ -726,13 +730,12 @@ The rest of the defined keys can now be set as follows: textheight,textwidth=6cm} \end{example} \acmd*{\setkeys} -Try \fx{\show\ifmp@boolvar} to confirm that \fx{boolvar} is now \aang{true}; it was originally set as \aang{false}. The macro \fx{\KV@fam@paperwidth} holds the function \fx{\funcforpaperwidth}, while \fx{\mp@textheight} holds the value submitted to key \fx{textheight} at any instance of \acmd{\setkeys}. By the above \acmd{\setkeys}, only the default values of \fx{paperheight}, \fx{paperwidth}, and \fx{textheight} are presently available. +Try \fx{\show\ifmp@boolvar} to confirm that \fx{boolvar} is now \ang{true}; it was originally set as \ang{false}. The macro \fx{\KV@fam@paperwidth} holds the function \fx{\funcforpaperwidth}, while \fx{\mp@textheight} holds the value submitted to key \fx{textheight} at any instance of \acmd{\setkeys}. By the above \acmd{\setkeys}, only the default values of \fx{paperheight}, \fx{paperwidth}, and \fx{textheight} are presently available. Instead of using macros to pass key macros and functions, it is also possible to use token list registers. Some examples are provided below: \begin{example} \NewToks[temptoks]{a,b} -|comm(See page |pageref(page:newtoks) for definition of \NewToks and) -|comm(related commands.) +|comm(See page |pageref(page:newtoks) for definition of \NewToks and related commands.) \temptoksa{\ifmp@boola\def\do#1{% \def#1##1##2{\expandafter\expandafter\expandafter\in@ @@ -874,62 +877,6 @@ The examples in \cref{sec:multkeys-examples} would have provided some glimpse of \setkeys[KV]{fam}{boold=true} \end{example} -\subsection{Key commands} -\label{sec:keycommand} -\acmdm*{keycommand} - -The \fx{\define@keylist} macro provides an interface for defining commands using keys, in the manner of the \pkg{keycommand}, but the user interfaces differ between here and the \pkg{keycommand}. Our interface for introducing new key commands is as follows -\begin{macro} -\DeclareKeyCommand|redstar|cang(cmd)[|cang(keyval)][|cang(narg)]{|cang(content)} -\end{macro} -\acmdm*{\DeclareKeyCommand} -Here, \aang{cmd} is the new key command being declared, \aang{keyval} are the default key-value pairs, and \aang{narg} is the number of arguments in \aang{content} plus one. The quantity \aang{narg} has nothing to do with the number of admissible keys, and may also have no relation to the keys themselves. The first argument (\ie, \angledhash{1}) is the \aang{keyval} pairs: this is the reason why in \aang{narg} you have to add one to your number of arguments. In \aang{content} (\ie, the replacement text) the parameter number one \angledhash{1} refers to the \aang{keyval} pairs. You refer to your arguments using parameter number two \angledhash{2} onwards, up to a maximum of \angledhash{9}. This means that \fx{\DeclareKeyCommand} accepts no optional arguments. This is not a limitation, since optional arguments can be entered as keys. Using keys is preferable to using parameters: you don't have to match parameters to arguments and, in principle, there is no limit to the number of keys that are permissible. - -The unstarred variant of \fx{\DeclareKeyCommand} gives long macros, as is usual in \latex. - -In \aang{content}, you refer to the values of the keys using macros whose first three characters (after the escape character) are the first three letters of the declared key command. The fourth character of the key-value macros is the ``at'' sign (\fx{@}), which should have catcode 11. The family name of the keys defined via a key command is the key command name itself (without the escape character). The key prefix is always ``KV''. The ``at'' sign only serves to visually aid the separation of the macro prefix from the key name and may be deprecated in future versions of the package. - -The following examples illustrate these points: - -\begin{example} -|makered(\DeclareKeyCommand*)\demomacro[name=Dummy,height=1.6m, - wieght=60kg,employed=false][3]{% - \edef\x{\dem@name}\def\y{#2}\def\z{#3}} - -|comm(Instruct the user to supply value of `name' in) -|comm(\demomacro key command:) -\uservaluekeys[KV]{demomacro}{name} - -|comm(Now you can use \demomacro. If you don't supply a key value) -|comm(here, the macro will use the above defaults:) -\demomacro[name=John,height=1.55m,wieght=55kg,employed=true] - {data1}{data2} - -|makered(\DeclareKeyCommand)\Rule[raise=.5ex,width=1em,thick=2pt, - proclaim=false][2]{\rule[\Rul@raise]{\Rul@width}{\Rul@thick}% - #2% - \rule[\Rul@raise]{\Rul@width}{\Rul@thick}\hspace*{1em}% - \ifRul@proclaim \color{red}\fi\textdaggerdbl -} - -|makered(\begin{document}) -\parindent\z@ -\begin{tabular*}\textwidth{rr} -\verb+\Rule[width=2em,thick=4pt]{Hello World}+:|ampersand - \Rule[width=2em,thick=4pt]{Hello World}\cr -\verb+\Rule[width=2em,thick=.5pt,proclaim=true]{Hello}+:|ampersand - \Rule[width=2em,thick=.5pt,proclaim=true]{Hello}\cr -\verb+\Rule[thick=2pt,proclaim=true]{Hello World}+:|ampersand - \Rule[thick=2pt,proclaim=true]{Hello World}\cr -\verb+\Rule[raise=1ex,width=2em,thick=1pt]{Hello World}+:|ampersand - \Rule[raise=1ex,width=2em,thick=1pt]{Hello} -\end{tabular*} -|makered(\end{document}) -\end{example} -\acmd*{\begin\{document\}} - -The corresponding \fx{\DeclareKeyEnviron} easily follows. - \subsection{Input error} \label{sec:input-error} @@ -1017,7 +964,7 @@ Suppose we want to define a native-boolean key \fx{mybool} with the following ke where the key prefix \fx{KV}, key family \fx{fam}, and the macro prefix \fx{mp@} are assumed to have been defined previously. Then, instead of hiding the conditional in an intermediate macro, we may adopt the following: \begin{example} \define@keylist{3,mybool,true, - |makered(\skif{|makemac(mp@mybool)})\def\hold##1{\def##1####1{***####1***}}% + |makered(\skif{|mcolor(mp@mybool)})\def\hold##1{\def##1####1{***####1***}}% |makered(\skelse)\def\hold##1{\def##1####1{===####1===}}|makered(\skfi) } @@ -1026,19 +973,19 @@ where the key prefix \fx{KV}, key family \fx{fam}, and the macro prefix \fx{mp@} \end{example} \acmdm*{\skif,\skifx,\skelse,\skfi} \acmd*{\skifcase,\skor,\define@keylist} -Here we have used the pseudo-primitives \fx{\skif{mp@mybool}}, \fx{\skifx}, \fx{\skelse} and \fx{\skfi} for the commands \fx{\ifmp@mybool}, \fx{\ifx}, \fx{\else} and \fx{\fi}, respectively, to hide the latter four from \TeX's scanning and skipping mechanism. It should be noted that \fx{\skif{mp@mybool}} requires that the argument \aang{mp@mybool} be enclosed in braces. Something like \fx{\skifmp@mybool} will be interpreted by \tex as an undefined control sequence when the key \fx{mybool} is being set. Defining the command \fx{\skif{mp@mybool}} to be \fx{\ifmp@mybool} before hand would have failed because \tex's scanner would then get the hint of the assignment. +Here we have used the pseudo-primitives \fx{\skif{mp@mybool}}, \fx{\skifx}, \fx{\skelse} and \fx{\skfi} for the commands \fx{\ifmp@mybool}, \fx{\ifx}, \fx{\else} and \fx{\fi}, respectively, to hide the latter four from \TeX's scanning and skipping mechanism. It should be noted that \fx{\skif{mp@mybool}} requires that the argument \ang{mp@mybool} be enclosed in braces. Something like \fx{\skifmp@mybool} will be interpreted by \tex as an undefined control sequence when the key \fx{mybool} is being set. Defining the command \fx{\skif{mp@mybool}} to be \fx{\ifmp@mybool} before hand would have failed because \tex's scanner would then get the hint of the assignment. \Note We haven't found any package that has defined \fx{\skif}, \fx{\skifx}, \fx{\skelse}, \fx{\skfi}, \fx{\skifcase} or \fx{\skor}. The \pkgm{xifthen}, for example, uses \fx{\OR}, not \fx{\skor}. If the situation changes in the future (\ie, if a package is observed to have defined any of these commands), they will be appropriately modified in the \pkg{skeyval}. Information and feedback from package users is solicited in this regard. We have redefined the \fx{\setkeys} command of the \pkg{xkeyval} to recognize that \fx{\skif{boolean}}, \fx{\skifx}, \fx{\skelse}, \fx{\skfi}, \fx{\skifcase} and \fx{\skor} stand for \fx{\ifboolean}, \fx{\ifx}, \fx{\else}, \fx{\fi}, \fx{\ifcase} and \fx{\or}, respectively. The redefined \fx{\setkeys} command has the same syntaxes as as in \pkg{xkeyval}: \begin{macro} -\setkeys[|cang(prefix)]{|cang(families)}[|cang(na)]{|cang(keys=values)} -\setkeys|redstar[|cang(prefix)]{|cang(families)}[|cang(na)]{|cang(keys=values)} -\setkeys|redplus[|cang(prefix)]{|cang(families)}[|cang(na)]{|cang(keys=values)} -\setkeys|redstar|redplus[|cang(prefix)]{|cang(families)}[|cang(na)]{|cang(keys=values)}. +\setkeys[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)} +\setkeys|redstar[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)} +\setkeys|redplus[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)} +\setkeys|redstar|redplus[|vang(prefix)]{|vang(families)}[|vang(na)]{|vang(keys=values)}. \end{macro} \acmdm*{\setkeys,\setkeys*,\setkeys*+} -No errors are produced if any of the sets \aang{prefix}, \aang{families}, \aang{na}, and \aang{keys=values} is empty. In fact, an instruction such as \fx{\setkeys[]{}[]{}} is completely benign, and so is \fx{\setkeys{}{}}. +No errors are produced if any of the sets \ang{prefix}, \ang{families}, \ang{na}, and \ang{keys=values} is empty. In fact, an instruction such as \fx{\setkeys[]{}[]{}} is completely benign, and so is \fx{\setkeys{}{}}. \paragraph{Conditionals involving \textcolor{xmagenta1}{\@bs ifcase}:} @@ -1073,10 +1020,10 @@ The approaches of \cref{sec:pseudo-primitives} provide a familiar \tex-like synt A new switch can be introduced by using the following command: \begin{macro} -\newswitch[|cang(optional prefix)]{|cang(boolean)}[|cang(optional state)] +\newswitch[|vang(optional prefix)]{|vang(boolean)}[|vang(optional state)] \end{macro} \acmdm*{\newswitch} -This provides a new native-boolean register \fx{\if}\unskip\aang{prefix}\unskip\aang{boolean} if the register didn't already exist; if the register already existed, an error is flagged. The optional \aang{state} can be either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}); the switch will be initialized to that state. With this definition, you can issue \fx{\if}\unskip\aang{switch}, \bs\aang{switch}\unskip\fx{true}, and \bs\aang{switch}\unskip\fx{false}. One advantage of \fx{\newswitch} is that a switch can start off as either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}), unlike the classical \tex's case in which all booleans start off as \fx{false}. Also, switches can be used where primitive \tex conditionals may prove impossible. For example, we know that you can't do \fx{\let\ifabc\iftrue} within the body of a conditional text without hiding the assignment from \tex's scanning mechanism. +This provides a new native-boolean register \fx{\if}\unskip\ang{prefix}\unskip\ang{boolean} if the register didn't already exist; if the register already existed, an error is flagged. The optional \ang{state} can be either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}); the switch will be initialized to that state. With this definition, you can issue \fx{\if}\unskip\ang{switch}, \bs\ang{switch}\unskip\fx{true}, and \bs\ang{switch}\unskip\fx{false}. One advantage of \fx{\newswitch} is that a switch can start off as either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}), unlike the classical \tex's case in which all booleans start off as \fx{false}. Also, switches can be used where primitive \tex conditionals may prove impossible. For example, we know that you can't do \fx{\let\ifabc\iftrue} within the body of a conditional text without hiding the assignment from \tex's scanning mechanism. \begin{example} \newswitch{boola} |tto \newif\ifboola @@ -1090,10 +1037,10 @@ This provides a new native-boolean register \fx{\if}\unskip\aang{prefix}\unskip\ You can define many switches in a row by the following command: \begin{macro} -\NewSwitches[|cang(optional prefix)]{|cang(switches)}[|cang(optional state)] +\NewSwitches[|vang(optional prefix)]{|vang(switches)}[|vang(optional state)] \end{macro} \acmdm*{\NewSwitches} -Each member of \aang{switches} is prefixed with \aang{prefix} upon definition. The optional \aang{state} can be either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}). +Each member of \ang{switches} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true} (or \fx{on}) or \fx{false} (or \fx{off}). Here are some examples: @@ -1108,23 +1055,23 @@ Here are some examples: Switches may be set and tested using the following commands: \begin{macro} -\setswitch{|cang(switch)}{|cang(value/state)} +\setswitch{|vang(switch)}{|vang(value/state)} -\switchon{|cang(switch)} |tto \|cang(switch)true +\switchon{|vang(switch)} |tto \|vang(switch)true -\switchtrue{|cang(switch)} |tto \|cang(switch)true +\switchtrue{|vang(switch)} |tto \|vang(switch)true -\switchoff{|cang(switch)} |tto \|cang(switch)false +\switchoff{|vang(switch)} |tto \|vang(switch)false -\switchfalse{|cang(switch)} |tto \|cang(switch)false +\switchfalse{|vang(switch)} |tto \|vang(switch)false -\ifswitchon{|cang(switch)}{|cang(true text)}{|cang(false text)} +\ifswitchon{|vang(switch)}{|vang(true text)}{|vang(false text)} -\ifswitchtrue{|cang(switch)}{|cang(true text)}{|cang(false text)} +\ifswitchtrue{|vang(switch)}{|vang(true text)}{|vang(false text)} -\ifswitchoff{|cang(switch)}{|cang(not true)}{|cang(not false)} +\ifswitchoff{|vang(switch)}{|vang(not true)}{|vang(not false)} -\ifswitchfalse{|cang(switch)}{|cang(not true)}{|cang(not false)} +\ifswitchfalse{|vang(switch)}{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\newswitch,\setswitch,\switchon,\switchoff,\ifswitchon, \ifswitchoff,\switchtrue,\switchfalse,\ifswitchtrue, @@ -1144,10 +1091,10 @@ Switches may be set and tested using the following commands: \end{example} \begin{macro} -\defswitch[|cang(optional prefix)]{|cang(boolean)}[|cang(optional state)] +\defswitch[|vang(optional prefix)]{|vang(boolean)}[|vang(optional state)] \end{macro} \acmdm*{\defswitch} -This is similar to \fx{\newswitch} but raises no errors even if the register \aang{boolean} already exists. +This is similar to \fx{\newswitch} but raises no errors even if the register \ang{boolean} already exists. Now how do we use switches in \fx{\define@keylist}? Suppose the key prefix is \fx{KV}, the key family is \fx{fam}, and the key macro is \fx{mp@}. Then the following works: \begin{example} @@ -1173,7 +1120,12 @@ Toggle booleans, described in \cref{sec:toggles}, can also be used to circumvent \setkeys[KV]{fam}{toga= true |makered(or) false} \end{example} \acmd*{\define@keylist,\iftogon} -where the key prefix, key family, and macro prefix are still assumed to be \fx{KV}, \fx{fam}, \fx{mp@}, respectively. Recall that toggle keys are type~`4' keys. +where the key prefix, key family, and macro prefix are still assumed to be \fx{KV}, \fx{fam}, \fx{mp@}, respectively. Recall that toggle keys are type~4 keys. + +\section{Key command and key environment} +\label{sec:keycommand} + +The \fx{\define@keylist} macro of \cref{sec:def-multiple-keys}, together with the \fx{\newkeylist} macro of \cref{sec:avoiding-redef}, provides an attractive toolkit for developing a system for defining commands using keys, in the manner of the \pkgm{keycommand} but with a more compact user interface. See the \pkgm{skeycommand} for details. \section{Checking and redefining keys} \label{sec:check-redef-keys} @@ -1184,28 +1136,28 @@ where the key prefix, key family, and macro prefix are still assumed to be \fx{K Three mechanisms have been introduced in the \pkg{skeyval} to ascertain the statuses of keys. These are as follows. \begin{macro} -\ifkeydefined[|cang(prefixes)]{|cang(families)}{|cang(key)}{|cang(true)}{|cang(false)} +\ifkeydefined[|vang(prefixes)]{|vang(families)}{|vang(key)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\ifkeydefined} -This executes \aang{true} if \aang{key} is defined, reserved, or suspended with a prefix in \aang{prefixes} and family in \aang{families}; it returns \aang{false} otherwise. This is similar to -the \pkg{xkeyval}'s \acmdm{\key@ifundefined}, but, apart from reversing the logic of the test, \fx{\ifkeydefined} loops over prefixes (in addition to looping over families) to locate the key, and also considers reserved and suspended keys as defined. The lists \aang{prefixes} and \aang{families} may contain nil, one or more elements. +This executes \ang{true} if \ang{key} is defined, reserved, or suspended with a prefix in \ang{prefixes} and family in \ang{families}; it returns \ang{false} otherwise. This is similar to +the \pkg{xkeyval}'s \acmdm{\key@ifundefined}, but, apart from reversing the logic of the test, \fx{\ifkeydefined} loops over prefixes (in addition to looping over families) to locate the key, and also considers reserved and suspended keys as defined. The lists \ang{prefixes} and \ang{families} may contain nil, one or more elements. \begin{macro} -\ifkeyreserved[|cang(prefixes)]{|cang(families)}{|cang(key)}{|cang(true)}{|cang(false)} +\ifkeyreserved[|vang(prefixes)]{|vang(families)}{|vang(key)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\ifkeyreserved} -This returns \aang{true} if \aang{key} is reserved with a prefix in \aang{prefixes} and family in \aang{families}; it returns \aang{false} otherwise. Reserved keys are introduced in \cref{sec:reserve-keys}. +This returns \ang{true} if \ang{key} is reserved with a prefix in \ang{prefixes} and family in \ang{families}; it returns \ang{false} otherwise. Reserved keys are introduced in \cref{sec:reserve-keys}. \begin{macro} -\ifkeysuspended[|cang(prefixes)]{|cang(families)}{|cang(key)}{|cang(true)}{|cang(false)} +\ifkeysuspended[|vang(prefixes)]{|vang(families)}{|vang(key)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\ifkeysuspended} -This executes \aang{true} if \aang{key} is suspended with a prefix in \aang{prefixes} and family in \aang{families}; it executes \aang{false} otherwise. Suspended keys are introduced in \cref{sec:suspend-keys}. +This executes \ang{true} if \ang{key} is suspended with a prefix in \ang{prefixes} and family in \ang{families}; it executes \ang{false} otherwise. Suspended keys are introduced in \cref{sec:suspend-keys}. \subsection{Unintentional redefinition of keys} \label{sec:redef-keys} -The \pkg{xkeyval}, by default, permits the automatic redefining of keys of the same \aang{prefix} and \aang{family}: at the point of defining a new key, the package doesn't, by default, check whether or not the key had been previously defined with the same \aang{prefix} and \aang{family}. In some circumstances this can be undesirable, and even dangerous, especially if the same key (of the same \aang{prefix} and \aang{family}) is mistakenly redefined with different macros/functions in the same package or across packages. One way to solve this problem is to use \pkg{xkeyval}'s \fx{\key@ifundefined} command (or the \pkg{skeyval}'s \fx{\ifkeydefined}) to confirm the status of a key prior to its definition. However, using these commands before defining every key can be laborious. +The \pkg{xkeyval}, by default, permits the automatic redefining of keys of the same \ang{prefix} and \ang{family}: at the point of defining a new key, the package doesn't, by default, check whether or not the key had been previously defined with the same \ang{prefix} and \ang{family}. In some circumstances this can be undesirable, and even dangerous, especially if the same key (of the same \ang{prefix} and \ang{family}) is mistakenly redefined with different macros/functions in the same package or across packages. One way to solve this problem is to use \pkg{xkeyval}'s \fx{\key@ifundefined} command (or the \pkg{skeyval}'s \fx{\ifkeydefined}) to confirm the status of a key prior to its definition. However, using these commands before defining every key can be laborious. Consider the following two scenarios: \begin{example} @@ -1217,9 +1169,9 @@ Consider the following two scenarios: \setkeys[KV]{fam}{keya=$\textbullet$} \end{example} \acmd*{\setkeys} -Obviously the two definitions of \aang{keya} are valid and will be implemented but the \acmd{\setkeys} command here will issue an unintelligible error message, like \LaTeX's ``You are in trouble here \textellipsis''. The key \aang{keya} has been defined twice and \acmd{\setkeys} has sought to use its latest definition to set its value, which is incorrect. As mentioned in \cref{sec:toggle-keys}, the \acmd{\setkeys} command (and friends) of the \pkg{xkeyval} doesn't know if a key has been redefined in the same \aang{family} and with the same \aang{prefix}. At the high level, it doesn't consider the key type: it uses the latest definition of the key to set its value using the key's macro. This is particularly worrisome in the case of toggle keys, since although toggle keys have their own separate namespace, they can easily be confusing (at least to \acmd{\setkeys}) if they have names identical to other keys within the same family and with the same prefix. In fact, the problem can manifest itself in more ways than the scenario just depicted. +Obviously the two definitions of \ang{keya} are valid and will be implemented but the \acmd{\setkeys} command here will issue an unintelligible error message, like \LaTeX's ``You are in trouble here \textellipsis''. The key \ang{keya} has been defined twice and \acmd{\setkeys} has sought to use its latest definition to set its value, which is incorrect. As mentioned in \cref{sec:toggle-keys}, the \acmd{\setkeys} command (and friends) of the \pkg{xkeyval} doesn't know if a key has been redefined in the same \ang{family} and with the same \ang{prefix}. At the high level, it doesn't consider the key type: it uses the latest definition of the key to set its value using the key's macro. This is particularly worrisome in the case of toggle keys, since although toggle keys have their own separate namespace, they can easily be confusing (at least to \acmd{\setkeys}) if they have names identical to other keys within the same family and with the same prefix. In fact, the problem can manifest itself in more ways than the scenario just depicted. -If the package option \fx{verbose} is enabled, the \pkg{skeyval} provides a warning system (by making an entry in the transcript log file) if an existing key is being redefined (within the same family and with the same prefix) by any of the following commands: +If the package option \acmd{verbose} is enabled, the \pkg{skeyval} provides a warning system (by making an entry in the transcript log file) if an existing key is being redefined (within the same family and with the same prefix) by any of the following commands: \begin{macro} \define@key, \define@cmdkey, \define@cmdkeys, \define@choicekey, \define@boolkey, \define@boolkeys, @@ -1233,7 +1185,7 @@ The machinery of \cref{sec:avoiding-redef} can be used to avoid inadvertently re \subsubsection{Avoiding multiple definitions of same key} \label{sec:avoiding-redef} -For the above reasons, the \pkg{skeyval} introduces the following commands, which have the same syntaxes as their counterparts from the \asty{xkeyval} and \asty{skeyval} packages but which bar the user from repeated definition of keys with identical names within the same \aang{family} and with the same \aang{prefix}: +For the above reasons, the \pkg{skeyval} introduces the following commands, which have the same syntaxes as their counterparts from the \asty{xkeyval} and \asty{skeyval} packages but which bar the user from repeated definition of keys with identical names within the same \ang{family} and with the same \ang{prefix}: \acmd*{\define@boolkey} \acmdm*{\newordkey,\newcmdkey,\newboolkey,\newboolkeys,\newtogkey,\newtogkeys, \newchoicekey,\newbiboolkeys,\newuniboolkeys,\newbiuniboolkeys,\newbitogkeys, @@ -1241,84 +1193,84 @@ For the above reasons, the \pkg{skeyval} introduces the following commands, whic \define@cmdkeys,\define@biboolkeys,\define@uniboolkeys, \define@biuniboolkeys,\define@bitogkeys,\define@unitogkeys,\define@biunitogkeys} \begin{macro} -|comm(The following defines ``ordinary'' keys |LParen:the counterpart) -|comm(of \define@key from the xkeyval package|RParen::) -\newordkey[|cang(prefix)]{|cang(family)}{|cang(key)}[|cang(default)]{|cang(funtion)} +|comm(The following defines ``ordinary'' keys |:the counterpart) +|comm(of \define@key from the xkeyval package|!:) +\newordkey[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(default)]{|vang(funtion)} |comm(Counterpart of \define@cmdkey:) -\newcmdkey[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(funtion)} +\newcmdkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(funtion)} |comm(Counterpart of \define@cmdkeys:) -\newcmdkeys[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(keys)}[|cang(default)] +\newcmdkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)] |comm(Counterparts of \define@boolkey:) -\newboolkey[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(funtion)} -\newboolkey|redplus[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(funtion1)}{|cang(funtion2)} +\newboolkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(funtion)} +\newboolkey|redplus[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(funtion1)}{|vang(funtion2)} |comm(Counterpart of \define@boolkeys:) -\newboolkeys[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(keys)}[|cang(default)] +\newboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)] |comm(Counterpart of \define@biboolkeys:) -\newbiboolkeys[|cang(prefix)]{|cang(family)}[|cang(mp)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(func for primary boolean)} - {|cang(func for secondary boolean)} +\newbiboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(func for primary boolean)} + {|vang(func for secondary boolean)} |comm(Counterpart of \define@uniboolkeys:) -\newuniboolkeys[|cang(prefix)]{|cang(family)}[|cang(mp)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(func for primary boolean)} - {|cang(func for secondary boolean)} +\newuniboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(func for primary boolean)} + {|vang(func for secondary boolean)} |comm(Counterpart of \define@biuniboolkeys:) -\newbiuniboolkeys[|cang(prefix)]{|cang(family)}[|cang(mp)] - {|cang(primary boolean)}[|cang(default value for primary boolean)] - {|cang(secondary boolean)}{|cang(func for primary boolean)} - {|cang(func for secondary boolean)} +\newbiuniboolkeys[|vang(prefix)]{|vang(family)}[|vang(mp)] + {|vang(primary boolean)}[|vang(default value for primary boolean)] + {|vang(secondary boolean)}{|vang(func for primary boolean)} + {|vang(func for secondary boolean)} |comm(Counterparts of \define@togkey:) -\newtogkey[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(funtion)} -\newtogkey|redplus[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(key)}[|cang(default)]% - {|cang(funtion1)}{|cang(funtion2)} +\newtogkey[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(funtion)} +\newtogkey|redplus[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(key)}[|vang(default)]% + {|vang(funtion1)}{|vang(funtion2)} |comm(Counterpart of \define@togkeys:) -\newtogkeys[|cang(prefix)]{|cang(family)}[|cang(mp)]{|cang(keys)}[|cang(default)] +\newtogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)]{|vang(keys)}[|vang(default)] |comm(Counterpart of \define@bitogkeys:) -\newbitogkeys[|cang(prefix)]{|cang(family)}[|cang(mp)] - {|cang(primary toggle)}[|cang(default value for primary toggle)] - {|cang(secondary toggle)}{|cang(func for primary toggle)} - {|cang(func for secondary toggle)} +\newbitogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)] + {|vang(primary toggle)}[|vang(default value for primary toggle)] + {|vang(secondary toggle)}{|vang(func for primary toggle)} + {|vang(func for secondary toggle)} |comm(Counterpart of \define@unitogkeys:) -\newunitogkeys[|cang(prefix)]{|cang(family)}[|cang(mp)] - {|cang(primary toggle)}[|cang(default value for primary toggle)] - {|cang(secondary toggle)}{|cang(func for primary toggle)} - {|cang(func for secondary toggle)} +\newunitogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)] + {|vang(primary toggle)}[|vang(default value for primary toggle)] + {|vang(secondary toggle)}{|vang(func for primary toggle)} + {|vang(func for secondary toggle)} |comm(Counterpart of \define@biunitogkeys:) -\newbiunitogkeys[|cang(prefix)]{|cang(family)}[|cang(mp)] - {|cang(primary toggle)}[|cang(default value for primary toggle)] - {|cang(secondary toggle)}{|cang(func for primary toggle)} - {|cang(func for secondary toggle)} +\newbiunitogkeys[|vang(prefix)]{|vang(family)}[|vang(mp)] + {|vang(primary toggle)}[|vang(default value for primary toggle)] + {|vang(secondary toggle)}{|vang(func for primary toggle)} + {|vang(func for secondary toggle)} |comm(Counterparts of \define@choicekey:) -\newchoicekey[|cang(prefix)]{|cang(family)}{|cang(key)}[|cang(bin)]{|cang(alt)}% - [|cang(default)]{|cang(funtion)} -\newchoicekey|redstar[|cang(prefix)]{|cang(family)}{|cang(key)}[|cang(bin)]{|cang(alt)}% - [|cang(default)]{|cang(funtion)} -\newchoicekey|redplus[|cang(prefix)]{|cang(family)}{|cang(key)}[|cang(bin)]{|cang(alt)}% - [|cang(default)]{|cang(funtion1)}{|cang(funtion2)} -\newchoicekey|redstar|redplus[|cang(prefix)]{|cang(family)}{|cang(key)}[|cang(bin)]{|cang(alt)}% - [|cang(default)]{|cang(funtion1)}{|cang(funtion2)} +\newchoicekey[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}% + [|vang(default)]{|vang(funtion)} +\newchoicekey|redstar[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}% + [|vang(default)]{|vang(funtion)} +\newchoicekey|redplus[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}% + [|vang(default)]{|vang(funtion1)}{|vang(funtion2)} +\newchoicekey|redstar|redplus[|vang(prefix)]{|vang(family)}{|vang(key)}[|vang(bin)]{|vang(alt)}% + [|vang(default)]{|vang(funtion1)}{|vang(funtion2)} |comm(Counterpart of \define@keylist:) -\newkeylist{|cang(key type/id), |cang(key), |cang(key default value), - |cang(key macro/function); |cang(another set of key specifiers); etc}. +\newkeylist{|vang(key type/id), |vang(key), |vang(key default value), + |vang(key macro/function); |vang(another set of key specifiers); etc}. \end{macro} \acmdm*{\define@choicekey,\newchoicekey*,\newchoicekey*+,\newkeylist,\newkeylist*} @@ -1331,9 +1283,9 @@ The following aliases are defined in the \pkg{skeyval}: We could simply have redefined/modified the legacy key definition commands in the \pkg{xkeyval} to make it impossible to define keys of the same name in the same family and with the same prefix, but this approach would be unsafe since there are many packages using the \pkg{xkeyval} and those packages may well have redefined identical keys. Moreover, the legacy key definition commands from the \pkg{xkeyval} may be needed to redefine a disabled key (see \cref{sec:disable-reserv-keys}). -All the commands of the type \NewKey\footnote{We shall refer to keys of the type \NewKey as those of category \ccmdm{\newkey}, and keys of the type \DefineKey as those of category \ccmdm{\definekey}.} are robust and may be used in expansion contexts without fear of premature expansion, although expandable tokens in the definition may need to be protected. +All the commands of the type \textnewkey are robust and may be used in expansion contexts without fear of premature expansion, although expandable tokens in the definition may need to be protected. Commands of the type \textdefinekey are originally, in the \pkg{xkeyval}, non-robust and remain so in the \pkg{skeyval}. -With the above macros, the following will flag an understandable error message, namely that the key \aang{keya} is about being redefined in the same family \aang{fam} and with the same prefix \aang{KV}: +With the above macros, the following will flag an understandable error message, namely that the key \ang{keya} is about being redefined in the same family \ang{fam} and with the same prefix \ang{KV}: \begin{example} \newordkey[KV]{fam}{keya}[$\star$]{\def\tempa##1{##1}} @@ -1352,35 +1304,35 @@ Besides macros for defining keys, the \pkg{skeyval} also introduces mechanisms f The \pkg{skeyval} has modified the definition of \fx{\disable@keys} from the \pkg{xkeyval} to allow for looping over key prefixes and key families and for bespoke warnings and error messages, without engendering any potential conflict with the legacy \fx{\disable@keys}. The new command is still called \fx{\disable@keys} and has the same syntax as the native \fx{\disable@keys} of the \pkg{xkeyval}, except that the new command accepts key prefixes (instead of just one prefix) and key families (instead of just one family): \begin{macro} -\disable@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)}. +\disable@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}. \end{macro} \acmdm*{\disable@keys} -Here \aang{prefixes}, \aang{families}, \aang{keys} are lists of comma-separated entries referring to the keys to be disabled. Each of the lists \aang{prefixes}, \aang{families}, \aang{keys} may contain nil, one or more elements. If any of the members in \aang{keys} can't be located in \aang{families} and with prefix in \aang{prefixes}, an informational (not error) message is logged in respect of this member, but only if the package option \fx{verbose} is selected. +Here \ang{prefixes}, \ang{families}, \ang{keys} are lists of comma-separated entries referring to the keys to be disabled. Each of the lists \ang{prefixes}, \ang{families}, \ang{keys} may contain nil, one or more elements. If any of the members in \ang{keys} can't be located in \ang{families} and with prefix in \ang{prefixes}, an informational (not error) message is logged in respect of this member, but only if the package option \fx{verbose} is selected. The legacy version of \fx{\disable@keys} (\ie, that of the \pkg{xkeyval}) is still available via the starred variant: \begin{macro} -\disable@keys|redstar[|cang(prefix)]{|cang(family)}{|cang(keys)} +\disable@keys|redstar[|vang(prefix)]{|vang(family)}{|vang(keys)} \end{macro} \acmdm*{\disable@keys*} -Note that this doesn't accept key prefixes and families, but only one key prefix and only one key family: the \fx{\disable@keys} command from the \pkg{xkeyval} can only be used to disable keys with the same \aang{prefix} and from the same \aang{family}, but not across prefixes and families. +Note that this doesn't accept key prefixes and families, but only one key prefix and only one key family: the \fx{\disable@keys} command from the \pkg{xkeyval} can only be used to disable keys with the same \ang{prefix} and from the same \ang{family}, but not across prefixes and families. Any attempt to subsequently set or use a disabled key will prompt the following error message. (The \pkg{xkeyval} issues a warning in this case.) The error message can be modified by the user, but the names of the controls \fx{\SKV@disabledkey@err} and \acmd{\SKV@disabledkey} should be retained. \begin{macro} \def\SKV@disabledkey@err{% \PackageError{skeyval}{% - Key |cang(key) with prefix |cang(prefix) in family |cang(family) - was disabled on input line |cang(lineno) + Key |vang(key) with prefix |vang(prefix) in family |vang(family) + was disabled on input line |vang(lineno) }{% - You can't set or reset |cang(key) at this + You can't set or reset |vang(key) at this late stage. Perhaps you're required to set it earlier, within a package or in the document's preamble. }% } \end{macro} \acmdm*{\SKV@disabledkey@err} -If the user attempts to disable an undefined key, the \pkg{xkeyval} issues a fatal error; the \pkg{skeyval}, on the other hand, issues a warning in the transcript log file (if the package option \fx{verbose} is selected), since the situation isn't fatal to the outcome of the \latex pass or the document. +If the user attempts to disable an undefined key, the \pkg{xkeyval} issues a fatal error; the \pkg{skeyval}, on the other hand, issues a warning in the transcript log file (if the package option \acmd{verbose} is selected), since the situation isn't fatal to the outcome of the \latex pass or the document. -Disabled keys can be redefined with commands in the \ccmd{\definekey} category but not with commands in the \ccmd{\newkey} category, since a disabled key remains defined: only its macro has been replaced by an error message signifying the disabling of the key. +Disabled keys can be redefined with commands in the \textdefinekey category but not with commands in the \textnewkey category, since a disabled key remains defined: only its macro has been replaced by an error message signifying the disabling of the key. \textbf{Note:} Reserved and suspended keys can't be disabled, until they are unreserved or restored (see \crefrange{sec:reserve-keys}{sec:suspend-keys}). @@ -1391,70 +1343,70 @@ By localizing a key we mean disabling a key at the end of the current class or p The syntax for localizing keys is exactly like that for disabling keys: \begin{macro} -\localize@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)}. +\localize@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}. \end{macro} \acmdm*{\localize@keys} -If any of the members of the set \aang{keys} is not found in any of the members of \aang{families} and with a prefix from \aang{prefixes}, an informational message is written into the log file (if the package option \fx{verbose} is selected), but no errors are flagged. +If any of the members of the set \ang{keys} is not found in any of the members of \ang{families} and with a prefix from \ang{prefixes}, an informational message is written into the log file (if the package option \fx{verbose} is selected), but no errors are flagged. -The starred variant of \fx{\localize@keys} disables the keys listed in \aang{keys}, not at the end of the package or class file, but right before the start of document (\ie, at the boundary between the document preamble and \acmd{\AtBeginDocument}): +The starred variant of \fx{\localize@keys} disables the keys listed in \ang{keys}, not at the end of the package or class file, but right before the start of document (\ie, at the boundary between the document preamble and \acmd{\AtBeginDocument}): \begin{macro} -\localize@keys|redstar[|cang(prefixes)]{|cang(families)}{|cang(keys)}. +\localize@keys|redstar[|vang(prefixes)]{|vang(families)}{|vang(keys)}. \end{macro} \acmdm*{\localize@keys*} The hook used here is \acmd{\SKV@BeforeDocumentStart}, described in \cref{sec:misce-commands}, \macref{beforedocstart}. A key can be localized as soon as it is defined. In fact, a key can be localized even before it is defined: the actual disablement of the key will take place at the execution of the contents of \acmd{\SKV@BeforeClassEnd} or \acmd{\SKV@BeforePackageEnd} or \acmd{\SKV@BeforeDocumentStart}. -Localized keys can be redefined with commands in the \ccmd{\definekey} category, but not with commands in the \ccmd{\newkey} category. +Localized keys can be redefined with commands in the \textdefinekey category, but not with commands in the \textnewkey category. \subsection{Reserving and unreserving keys} \label{sec:reserve-keys} The \pkg{xkeyval} bars its users from defining new keys with \fx{XKV} as a prefix. The \pkg{skeyval} generalizes this concept via the following three developer macros: \begin{macro} -\ReserveKeyPrefixNames{|cang(list)} +\ReserveKeyPrefixNames{|vang(list)} \end{macro} \acmdm*{\ReserveKeyPrefixNames} -This allows the package developer to bar the future use of names appearing in \aang{list} as key prefixes when defining, disabling, reserving and suspending keys; but not when setting keys. The \aang{list}, whose members are comma-separated, can be populated by the package developer as required. +This allows the package developer to bar the future use of names appearing in \ang{list} as key prefixes when defining, disabling, reserving and suspending keys; but not when setting keys. The \ang{list}, whose members are comma-separated, can be populated by the package developer as required. \begin{macro} -\ReserveMacroPrefixNames{|cang(list)} +\ReserveMacroPrefixNames{|vang(list)} \end{macro} \acmdm*{\ReserveMacroPrefixNames} This has a similar functionality to \fx{\ReserveKeyPrefixNames}, but applies to macro prefixes instead of key prefixes. \begin{macro} -\ReserveFamilyNames{|cang(list)} +\ReserveFamilyNames{|vang(list)} \end{macro} \acmdm*{\ReserveFamilyNames} -This reserves family names \aang{list} and prevents further use of members of \aang{list}. +This reserves family names \ang{list} and prevents further use of members of \ang{list}. \textbf{Note:} The lists in these macros are scanned only when defining, disabling, reserving or suspending keys, and not when setting existing keys. If the lists were also to be scanned when keys are being set, then a situation could arise in which existing keys (including those defined by prior packages) couldn't be set. These macros could be used, for instances, to secure against future use the key prefixes, macro prefixes, and key families that have used in a new style or class file. For example, we have used these facilities to bar users of the \pkg{skeyval} from using the key prefix \fx{SKV}, the family name \fx{skeyval}, and the macro prefix \fx{SKV@} to define new keys in their packages. \begin{macro} -\ReserveKeyPrefixNames|redstar{|cang(list)} -\ReserveMacroPrefixNames|redstar{|cang(list)} -\ReserveFamilyNames|redstar{|cang(list)} +\ReserveKeyPrefixNames|redstar{|vang(list)} +\ReserveMacroPrefixNames|redstar{|vang(list)} +\ReserveFamilyNames|redstar{|vang(list)} \end{macro} %\acmd*{\ReserveKeyPrefixNames} \acmdm*{\ReserveFamilyNames*,\ReserveKeyPrefixNames*,\ReserveMacroPrefixNames*} -These starred variants take effect at end of current package; the unstarred ones above assume immediate effect. If the developer wants to use any member of \aang{list} in his own package, it may be necessary for him to use the starred versions. +These starred variants take effect at end of current package; the unstarred ones above assume immediate effect. If the developer wants to use any member of \ang{list} in his own package, it may be necessary for him to use the starred versions. In addition to the above reservation commands, the \pkg{skeyval} also introduces the following command: \begin{macro} -\reserve@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)}, +\reserve@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}, \end{macro} \acmdm*{\reserve@keys} -where the lists \aang{prefixes}, \aang{families}, \aang{keys} can contain nil, one or more elements. Defined, reserved and suspended keys can't be reserved. +where the lists \ang{prefixes}, \ang{families}, \ang{keys} can contain nil, one or more elements. Defined, reserved and suspended keys can't be reserved. Reserved keys have to be unreserved with the following command before they can be defined and used: \begin{macro} -\unreserve@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)}, +\unreserve@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}, \end{macro} \acmdm*{\unreserve@keys} -where, again, the lists \aang{prefixes}, \aang{families}, \aang{keys} can contain nil, one or more elements. If a key was not previously reserved, this command will simply issue an informational message in the log file (if the package option \fx{verbose} is selected) and ignore that key. Defined keys and suspended keys can also be unreserved, which is equivalent to removing the keys (see \cref{sec:remove-keys}). +where, again, the lists \ang{prefixes}, \ang{families}, \ang{keys} can contain nil, one or more elements. If a key was not previously reserved, this command will simply issue an informational message in the log file (if the package option \fx{verbose} is selected) and ignore that key. Defined keys and suspended keys can also be unreserved, which is equivalent to removing the keys (see \cref{sec:remove-keys}). \subsection{Suspending and restoring keys} \label{sec:suspend-keys} @@ -1463,15 +1415,15 @@ For some keys, it might be preferable to temporarily suspend them from a family The syntax for suspending keys is \begin{macro} -\suspend@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)}, +\suspend@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}, \end{macro} \acmdm*{\suspend@keys} -where the lists \aang{prefixes}, \aang{families}, \aang{keys} can contain nil, one or more elements. +where the lists \ang{prefixes}, \ang{families}, \ang{keys} can contain nil, one or more elements. A key of particular prefix not previously defined in a family can't be suspended from that family. Similarly, a key previously suspended from a family can't be suspended again (for the second time) from the same family without being first restored in that family. Suspended keys can be restored to their frozen states (\name{ex ante} suspension) by the following command: \begin{macro} -\restore@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)}. +\restore@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)}. \end{macro} \acmdm*{\restore@keys} Only keys (with a given prefix) previously suspended from a family can be restored in that family: ``unsuspended'' keys can't be restored. @@ -1481,11 +1433,11 @@ Only keys (with a given prefix) previously suspended from a family can be restor The \pkg{skeyval} provides for removing keys completely, such that any attempt to set or use a removed key will prompt the error message that the key is undefined in the given family and with the given prefix. The command \acmd{\key@ifundefined} from the \pkg{xkeyval} and the macro \acmd{\ifkeydefined} from the \pkg{skeyval} will both identify a removed key as undefined. The syntax for removing keys is: \begin{macro} -\remove@keys[|cang(prefixes)]{|cang(families)}{|cang(keys)} +\remove@keys[|vang(prefixes)]{|vang(families)}{|vang(keys)} \end{macro} \acmdm*{\remove@keys} -Removed keys can't be restored but can be redefined with the commands in both the \ccmd{\newkey} and \ccmd{\definekey} categories. +Removed keys can't be restored but can be redefined with the commands in both the \textnewkey and \textdefinekey categories. \section{User-value keys} \label{sec:uservaluekeys} @@ -1494,10 +1446,10 @@ We define these keys as those for which the user must supply values at key setti The following command can be used to require a user to supply a value for a key at key setting time, whether or not that key has a default value: \begin{macro} -\uservaluekeys[|cang(prefix)]{|cang(family)}{|cang(keys)} +\uservaluekeys[|vang(prefix)]{|vang(family)}{|vang(keys)} \end{macro} \acmdm*{\uservaluekeys} -where \aang{keys} is the list of keys with \aang{prefix} and in \aang{family} for which the user must supply values at key setting time. It is obviously not logical to loop over key prefixes or families in this case. What the command \fx{\uservaluekeys} does is to populate the container \fnl{SKV}{prefix}{family}{uservalue} which is scanned for user-value key names at key setting time. +where \ang{keys} is the list of keys with \ang{prefix} and in \ang{family} for which the user must supply values at key setting time. It is obviously not logical to loop over key prefixes or families in this case. What the command \fx{\uservaluekeys} does is to populate the container \fnl{SKV}{prefix}{family}{uservalue} which is scanned for user-value key names at key setting time. The \fx{\uservaluekeys} macro works incrementally, \ie, new inputs are added to an existing list for the family in question only if they haven't previously been included. @@ -1509,7 +1461,7 @@ The \fx{\uservaluekeys} macro works incrementally, \ie, new inputs are added to \uservaluekeys[KV]{fam}{keya,boola} \setkeys[KV]{fam}{keya,boola=true} - |tto |makered(Error |LParen:no value supplied for `keya'|RParen:) + |tto |makered(Error: no value supplied for `keya') \end{example} \acmd*{\newcmdkey,\newboolkey,\setkeys} %\acmd*{\uservaluekeys} @@ -1520,9 +1472,9 @@ The \fx{\uservaluekeys} macro works incrementally, \ie, new inputs are added to Instead of using the macro \fx{\uservaluekeys} to accumulate user-value keys, there is another way to dynamically specify these keys at key definition time: by using pointers. At key definition time, the pointers \acmdm{\uservalue} and \acmdm{\guservalue} can be associated with a user-value key. In the following statements, the pointer \fx{\uservalue} specifies that the user of the affected key must supply a value at the time of using/setting the key. The pointer \fx{\uservalue} has local effect, \ie, its impact can't escape local groups; on the other hand, \fx{\guservalue} has global effect, \ie, using it within or out of a local group means that the user of the affected key must specify a value for the key at key setting time. \fx{\guservalue} ensures that the internal container \fnl{SKV}{prefix}{family}{uservalue} is defined globally so that the settings can escape local groups. \begin{example} -\newordkey[KV]{fam}{|makered(\uservalue{|makemac(keya)})}[12pt]{\def\x{#1}} +\newordkey[KV]{fam}{|makered(\uservalue{|mcolor(keya)})}[12pt]{\def\x{#1}} -\define@togkey|redplus[KV]{fam}[mp@]{|makered(\guservalue{|makemac(toga)})}[true]% +\define@togkey|redplus[KV]{fam}[mp@]{|makered(\guservalue{|mcolor(toga)})}[true]% {% \iftogon{mp@toga}{\def\x{#1}}{}% }{% @@ -1540,17 +1492,17 @@ The \pkg{xkeyval} introduced a key pointer system. This basically involves the p \acmdm{\savevalue}, \acmdm{\gsavevalue}, and \acmdm{\usevalue}. However, by the mechanism of that package, these pointers could be used only within the \acmd{\setkeys} command or context. In the key definition commands, the \fx{\usevalue} pointer could also be used in default values of keys, as in \begin{example} \define@key{fam}{keya}{\def\keya{#1}} -\define@key{fam}{keyb}[|makered(\usevalue{|makemac(keya)})]{\def\keyb{#1}} -\define@key{fam}{keyc}[|makered(\usevalue{|makemac(keyb)})]{\def\keyc{#1}} +\define@key{fam}{keyb}[|makered(\usevalue{|mcolor(keya)})]{\def\keyb{#1}} +\define@key{fam}{keyc}[|makered(\usevalue{|mcolor(keyb)})]{\def\keyc{#1}} -\setkeys{fam}{|makered(\savevalue{|makemac(keya)})=test} -\setkeys{fam}{|makered(\savevalue{|makemac(keyb)})}|comm(Yes, this also works.) +\setkeys{fam}{|makered(\savevalue{|mcolor(keya)})=test} +\setkeys{fam}{|makered(\savevalue{|mcolor(keyb)})}|comm(Yes, this also works.) \setkeys{fam}{keyc} \end{example} \acmd*{\define@key,\setkeys} The default values of keys are called (invoked) within \acmd{\setkeys}. The pointers can't, however, be used as part of key names outside default values. The following, \eg, fails: \begin{example} -\define@key{fam}{|makered(\savevalue{|makemac(keya)})}{\def\keya{#1}} +\define@key{fam}{|makered(\savevalue{|mcolor(keya)})}{\def\keya{#1}} \end{example} The \pkg{skeyval} has extended the pointer system to be issuable as part of key names within key definition commands in the two scenarios illustrated above (within and outside default values). Moreover, the pointers \fx{\savevalue} and \fx{\gsavevalue} can be deployed concurrently with \acmd{\uservalue} and \acmd{\guservalue} of \cref{sec:uservalue-pointers} within the same key definition command. In combining the two pointer subclasses (\ie, \fx{\savevalue} subclass and \acmd{\uservalue} subclass) in the same key definition command, it doesn't matter which subclass comes first, as the following examples show. @@ -1563,11 +1515,11 @@ The pointers \fx{\savevalue} and \fx{\gsavevalue} make entries into the containe The following provide examples of legacy pointer features of the \pkg{xkeyval} (key pointers at key setting time): \acmdm*{\gsavekeys,\savekeys,\global\{key\}} \begin{example} -\savekeys[KV]{fam}{keya,|makered(\global{|makemac(keyb)})} -\gsavekeys[KV]{fam}{keyc,keyd,|makered(\global{|makemac(keye)})}|label(mac:gsavekeys) +\savekeys[KV]{fam}{keya,|makered(\global{|mcolor(keyb)})} +\gsavekeys[KV]{fam}{keyc,keyd,|makered(\global{|mcolor(keye)})}|label(mac:gsavekeys) -\setkeys[KV]{fam}{|makered(\gsavevalue{|makemac(keyd)})=yyy,|label(mac:setkeyd) - keye=|makered(\usevalue{|makemac(keyd)})} +\setkeys[KV]{fam}{|makered(\gsavevalue{|mcolor(keyd)})=yyy,|label(mac:setkeyd) + keye=|makered(\usevalue{|mcolor(keyd)})} \end{example} If we had included \fx{\global{keyb}} in \fx{\gsavekeys} of \macref{mac:gsavekeys}, its entry in \fx{\savekeys} would have been overwritten, since keys in the container \acmdm{\XKV@KV@fam@save} normally get overwritten if they have the same name. The macro \fx{\gsavekeys} ensures the global definition of \fx{\XKV@KV@fam@save} when the keys \fx{keyc}, \fx{keyd} and \fx{keye} are being included, while \fx{\global{keyb}} ensures that, when \fx{keyb} is used in a \acmd{\setkeys} command, its value will be saved globally to \fx{\KV@fam@keyb@value}. When the keys \fx{keyc} and \fx{keyd} are set, their values will be saved locally, even though the container \fx{\XKV@KV@fam@save} was defined globally when the keys \fx{keyc} and \fx{keyd} were inserted. However, when keys \fx{keyb} and \fx{keye} are set, their values will be saved globally (even though \fx{keyb} appears in \fx{\savekeys} and not in \fx{\gsavekeys}). @@ -1579,31 +1531,31 @@ The pointer \fx{\gsavevalue{keyd}} of \macref{mac:setkeyd} will ensure that the The following provide examples of new pointer features enabled by the \pkg{skeyval} (key pointers at key definition time): \begin{example} -\define@key[KV]{fam}{|makered(\savevalue{|makemac(keya)})}[xxx]{\def\x{*#1*}} +\define@key[KV]{fam}{|makered(\savevalue{|mcolor(keya)})}[xxx]{\def\x{*#1*}} -\newordkey[KV]{fam}{|makered(\gsavevalue{|makemac(keyb)})}[zzz]{\def\x{=#1=}}|label(mac:pointers:a) +\newordkey[KV]{fam}{|makered(\gsavevalue{|mcolor(keyb)})}[zzz]{\def\x{=#1=}}|label(mac:pointers:a) -\newtogkey|redplus[KV]{fam}[mp@]{|makered(\savevalue\uservalue{|makemac(toga)})}[true]% +\newtogkey|redplus[KV]{fam}[mp@]{|makered(\savevalue\uservalue{|mcolor(toga)})}[true]% { \iftogon{mp@toga}{\def\x{#1}}{}% }{% \@latex@error{Value `#1' not valid}\@ehc } -\define@cmdkey[KV]{fam}[mp@]{|makered(\uservalue\savevalue{|makemac(keyc)})}% +\define@cmdkey[KV]{fam}[mp@]{|makered(\uservalue\savevalue{|mcolor(keyc)})}% [www]{\def\x{#1}} -\newboolkey|redplus[KV]{fam}[mp@]{|makered(\gsavevalue\uservalue{|makemac(boola)})}% +\newboolkey|redplus[KV]{fam}[mp@]{|makered(\gsavevalue\uservalue{|mcolor(boola)})}% [true]{% \ifmp@boola\def\x{#1}\fi }{% \@latex@error{Value `#1' not valid}\@ehc } -\define@cmdkey[KV]{fam}[mp@]{|makered(\guservalue\savevalue{|makemac(keyd)})}% +\define@cmdkey[KV]{fam}[mp@]{|makered(\guservalue\savevalue{|mcolor(keyd)})}% [www]{\def\x{#1}} -\newchoicekey|redstar|redplus[KV]{fam}{|makered(\guservalue\gsavevalue{|makemac(align)})}% +\newchoicekey|redstar|redplus[KV]{fam}{|makered(\guservalue\gsavevalue{|mcolor(align)})}% [\val\nr]{center,right,left}[center]% {% \ifcase\nr\relax @@ -1617,7 +1569,7 @@ The following provide examples of new pointer features enabled by the \pkg{skeyv \@latex@error{Inadmissible value `#1' for align}\@ehc } -\setkeys[KV]{fam}{keya=Hello World,keyb=|makered(\usevalue{|makemac(keya)})} +\setkeys[KV]{fam}{keya=Hello World,keyb=|makered(\usevalue{|mcolor(keya)})} \end{example} \acmd*{\define@key,\define@cmdkey,\newchoicekey,\newordkey, \newtogkey,\setkeys,\iftogon} @@ -1653,48 +1605,48 @@ This package is predominantly about \latex keys and their efficient creation and The following are provided in the \pkg{skeyval} but you're advised to use the \fx{\TestProvidedCommand} macro (described below) to test that you are really using the \fx{\newdef} of the \pkg{skeyval}: \begin{macro} -\SKV@newdef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} -\newdef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} +\SKV@newdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} +\newdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} \end{macro} \acmdm*{\SKV@newdef,\SKV@newdef*,\newdef,\newdef*} -These commands adopt \tex's syntax and accept parameter delimiters. They are both robust. The unstarred variant produces long macros. The command \fx{\newdef} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@newdef}, on the other hand, is always available. If \bang{cs} was previously defined, both \fx{\SKV@newdef} and \fx{\newdef} will issue an error. +These commands adopt \tex's syntax and accept parameter delimiters. They are both robust. The unstarred variant produces long macros. The command \fx{\newdef} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@newdef}, on the other hand, is always available. If \ang{cs} was previously defined, both \fx{\SKV@newdef} and \fx{\newdef} will issue an error. \macrosubsection{Defining robust commands} \begin{macro} -\SKV@robustdef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} -\robustdef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} +\SKV@robustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} +\robustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} \end{macro} \acmdm*{\SKV@robustdef,\SKV@robustdef*,\robustdef,\robustdef*} -These use \etex's \acmd{\protected} prefix to provide something resembling \latex's \acmdm{\DeclareRobustCommand} whilst conforming to \tex's \fx{\def} interface. The unstarred variants produce long macros. These commands accept parameter delimiters and are all robust. The command \fx{\robustdef} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@robustdef}, on the other hand, is always available. If \bang{cs} was previously defined, both \fx{\SKV@robustdef} and \fx{\robustdef} will issue an error. You can use the above \fx{\TestProvidedCommand} to check whether or not you are using the \fx{\robustdef} of the \pkg{skeyval}. +These use \etex's \acmd{\protected} prefix to provide something resembling \latex's \acmdm{\DeclareRobustCommand} whilst conforming to \tex's \fx{\def} interface. The unstarred variants produce long macros. These commands accept parameter delimiters and are all robust. The command \fx{\robustdef} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@robustdef}, on the other hand, is always available. If \ang{cs} was previously defined, both \fx{\SKV@robustdef} and \fx{\robustdef} will issue an error. You can use the above \fx{\TestProvidedCommand} to check whether or not you are using the \fx{\robustdef} of the \pkg{skeyval}. \macrosubsection{\tex-like \@bs providecommand} \begin{macro} -\SKV@providedef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} -\providedef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} -\SKV@providerobustdef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} -\providerobustdef|redstar|cang(cs)|cang(parameters){|cang(replacement text)} +\SKV@providedef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} +\providedef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} +\SKV@providerobustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} +\providerobustdef|redstar|vang(cs)|vang(parameters){|vang(replacement text)} \end{macro} \acmdm*{\SKV@providedef,\SKV@providerobustdef,\providerobustdef, \SKV@providedef*,\SKV@providerobustdef*,\providerobustdef*} \acmds*\providedef\SKV@providedef -These emulate \latex's \acmdm{\providecommand}, but they conform to \tex's \fx{\def} interface. The unstarred variants produce long macros. These commands accept parameter delimiters and are all robust. The commands \fx{\providedef} and \fx{\providerobustdef} are defined in the \pkg{skeyval} only if they haven't been defined by a previously loaded package; the commands \fx{\SKV@providedef} and \fx{\SKV@providerobustdef}, on the other hand, are always available. Macros defined by \fx{\SKV@providerobustdef} and \fx{\providerobustdef} are robust, while those defined by \fx{\SKV@providedef} and \fx{\providedef} are nonrobust. If \aang{cs} was previously defined, all these commands will simply ignore the new definition and enter a message to this effect in the log file (if the package option \fx{verbose} is selected). +These emulate \latex's \acmdm{\providecommand}, but they conform to \tex's \fx{\def} interface. The unstarred variants produce long macros. These commands accept parameter delimiters and are all robust. The commands \fx{\providedef} and \fx{\providerobustdef} are defined in the \pkg{skeyval} only if they haven't been defined by a previously loaded package; the commands \fx{\SKV@providedef} and \fx{\SKV@providerobustdef}, on the other hand, are always available. Macros defined by \fx{\SKV@providerobustdef} and \fx{\providerobustdef} are robust, while those defined by \fx{\SKV@providedef} and \fx{\providedef} are nonrobust. If \ang{cs} was previously defined, all these commands will simply ignore the new definition and enter a message to this effect in the log file (if the package option \fx{verbose} is selected). \macrosubsection{\@bs requirecmd} \begin{macro} -\requirecmd{|cang(cs)}[|cang(number of args)][|cang(default)]% - {|cang(replacement text)} +\requirecmd{|vang(cs)}[|vang(number of args)][|vang(default)]% + {|vang(replacement text)} \end{macro} -This is explained in \cref{sec:toggle-booleans}. If \aang{cs} is already defined, \acmdm{\requirecmd} checks if the new and old definitions are identical. If they aren't, a warning message is logged in the transcript file (if the package option \fx{verbose} is selected) and the new definition is aborted. +This is explained in \cref{sec:toggle-booleans}. If \ang{cs} is already defined, \acmdm{\requirecmd} checks if the new and old definitions are identical. If they aren't, a warning message is logged in the transcript file (if the package option \fx{verbose} is selected) and the new definition is aborted. -\macrosubsection{Testing ``provided'' commands} +\macrosubsection{Testing \emph{provided} commands} \begin{macro} -\TestProvidedCommand|cang(cs){|cang(true text)}{|cang(false text)}|label(mac:testprovide) +\TestProvidedCommand|vang(cs){|vang(true text)}{|vang(false text)}|label(mac:testprovide) \end{macro} -This can be used to test whether or not one is using the \fx{\newdef} (or any other ``provided'' command) of the \pkg{skeyval}. Here \aang{cs} is either \fx{\newdef} or any ``provided'' command. In fact, if you define any command using the macro \fx{\SKV@providedef} or \fx{\SKV@providerobustdef} (see below), you can verify by \fx{\TestProvidedCommand} whether or not the new definition is the one in effect. +This can be used to test whether or not one is using the \fx{\newdef} (or any other ``provided'' command) of the \pkg{skeyval}. Here \ang{cs} is either \fx{\newdef} or any ``provided'' command. In fact, if you define any command using the macro \fx{\SKV@providedef} or \fx{\SKV@providerobustdef} (see below), you can verify by \acmdm{\TestProvidedCommand} whether or not the new definition is the one in effect. \begin{example} \SKV@providerobustdef*\newcmd{\newcommand} @@ -1707,15 +1659,21 @@ This can be used to test whether or not one is using the \fx{\newdef} (or any ot } \end{example} +\begin{example} +\SKV@providedef*\declarecommand{\newcommand} +\TestProvidedCommand\declarecommand{}% + {\let\declarecommand\newcommand} +\end{example} + \macrosection{Declaring new unique variables collectively} New definable variables can be introduced in sets by the following commands. \begin{macro} -\NewBooleans[|cang(optional prefix)]{|cang(boolean list)}[|cang(optional state)] +\NewBooleans[|vang(optional prefix)]{|vang(boolean list)}[|vang(optional state)] \end{macro} \acmdm*{\NewBooleans} -This provides, for each member of the comma-separated list \bang{boolean list}, a new native-boolean register if the register didn't already exist, otherwise an error is flagged. Each member of \bang{boolean list} is prefixed with \aang{prefix} upon definition. The optional \aang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. +This provides, for each member of the comma-separated list \ang{boolean list}, a new native-boolean register if the register didn't already exist, otherwise an error is flagged. Each member of \ang{boolean list} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. \begin{example} \NewBooleans[bool]{a,b,c}[true] |tto \newif\ifboola \newif\ifboolb \newif\ifboolc @@ -1723,13 +1681,13 @@ This provides, for each member of the comma-separated list \bang{boolean list}, \NewBooleans{boold} |tto \newif\ifboold \end{example} -Notice that members of the list \bang{boolean list} don't have \fx{\if} in their names. +Notice that members of the list \ang{boolean list} don't have \fx{\if} in their names. \begin{macro} -\NewTogs[|cang(optional prefix)]{|cang(tog list)}[|cang(optional state)] +\NewTogs[|vang(optional prefix)]{|vang(tog list)}[|vang(optional state)] \end{macro} \acmdm*{\NewTogs} -This provides a new toggle register for each member of the comma-separated list \bang{tog list} if the register didn't already exist, otherwise an error is flagged. Each member of \bang{tog list} is prefixed with \aang{prefix} upon definition. The optional \aang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. +This provides a new toggle register for each member of the comma-separated list \ang{tog list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{tog list} is prefixed with \ang{prefix} upon definition. The optional \ang{state} can be either \fx{true}, \fx{false}, \fx{on} or \fx{off}. \fx{on} is synonymous with \fx{true}, whilst \fx{off} is equivalent to \fx{false}. \begin{example} \NewTogs[tog]{a,b,c}[true] |tto \newtog{toga} \newtog{togb} \newtog{togc} @@ -1739,10 +1697,10 @@ This provides a new toggle register for each member of the comma-separated list \end{example} \begin{macro} -\NewToks[|cang(optional prefix)]{|cang(toks list)} +\NewToks[|vang(optional prefix)]{|vang(toks list)} \end{macro} \acmdm*{\NewToks}\label{page:newtoks} -This provides a new token list register for each member of the comma-separated list \bang{toks list} if the register didn't already exist, otherwise an error is flagged. Each member of \bang{toks list} is prefixed with \aang{prefix} upon definition. +This provides a new token list register for each member of the comma-separated list \ang{toks list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{toks list} is prefixed with \ang{prefix} upon definition. \begin{example} \NewToks[toks]{a,b,c} |tto \newtoks\toksa \newtoks\toksb \newtoks\toksc @@ -1751,22 +1709,22 @@ This provides a new token list register for each member of the comma-separated l \end{example} \begin{macro} -\NewCounts[|cang(optional prefix)]{|cang(counter list)} +\NewCounts[|vang(optional prefix)]{|vang(counter list)} \end{macro} \acmdm*{\NewCounts} -This provides a new counter register for each member of the comma-separated list \bang{counter list} if the register didn't already exist, otherwise an error is flagged. Each member of \bang{counter list} is prefixed with \aang{prefix} upon definition. +This provides a new counter register for each member of the comma-separated list \ang{counter list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{counter list} is prefixed with \ang{prefix} upon definition. \begin{macro} -\NewDimens[|cang(optional prefix)]{|cang(dimen list)} +\NewDimens[|vang(optional prefix)]{|vang(dimen list)} \end{macro} \acmdm*{\NewDimens} -This provides a new dimension register for each member of the comma-separated list \bang{dimen list} if the register didn't already exist, otherwise an error is flagged. Each member of \bang{dimen list} is prefixed with \aang{prefix} upon definition. +This provides a new dimension register for each member of the comma-separated list \ang{dimen list} if the register didn't already exist, otherwise an error is flagged. Each member of \ang{dimen list} is prefixed with \ang{prefix} upon definition. \begin{macro} -\NewBoxes[|cang(optional prefix)]{|cang(box list)} +\NewBoxes[|vang(optional prefix)]{|vang(box list)} \end{macro} \acmdm*{\NewBoxes} -This allocates a new box register for each member of the comma-separated list \bang{box list} if the box register didn't already exist, otherwise an error is flagged. Each member of \bang{box list} is prefixed with \aang{prefix} upon definition. +This allocates a new box register for each member of the comma-separated list \ang{box list} if the box register didn't already exist, otherwise an error is flagged. Each member of \ang{box list} is prefixed with \ang{prefix} upon definition. \begin{example} \NewBoxes[box]{a,b,c} @@ -1776,10 +1734,10 @@ This allocates a new box register for each member of the comma-separated list \b \end{example} \begin{macro} -\NewWrites[|cang(optional prefix)]{|cang(stream list)} +\NewWrites[|vang(optional prefix)]{|vang(stream list)} \end{macro} \acmdm*{\NewWrites} -This allocates a new output stream for each member of the comma-separated list \bang{stream list} if the stream didn't already exist, otherwise an error is flagged. Each member of \bang{stream list} is prefixed with \aang{prefix} upon definition. +This allocates a new output stream for each member of the comma-separated list \ang{stream list} if the stream didn't already exist, otherwise an error is flagged. Each member of \ang{stream list} is prefixed with \ang{prefix} upon definition. \begin{example} \NewWrites[write]{a,b,c} |tto \newwrite\writea \newwrite\writeb \newwrite\writec @@ -1787,48 +1745,58 @@ This allocates a new output stream for each member of the comma-separated list \ \NewWrites{writed} |tto \newwrite\writed \end{example} -The macros \fx{\NewBooleans}, \fx{\NewToks}, \fx{\NewCounts}, \fx{\NewDimens}, \fx{\NewBoxes}, and \fx{\NewWrites} are non-outer, unlike their primitive counterparts. +\begin{macro} +\NewReads[|vang(optional prefix)]{|vang(stream list)} +\end{macro} +\acmdm*{\NewReads} + +This allocates a new input stream for each member of the comma-separated list \ang{stream list} if the stream didn't already exist, otherwise an error is flagged. Each member of \ang{stream list} is prefixed with \ang{prefix} upon definition. + +The macros \fx{\NewBooleans}, \fx{\NewToks}, \fx{\NewCounts}, \fx{\NewDimens}, \fx{\NewBoxes}, \fx{\NewWrites}, and \fx{\NewReads} are non-outer, unlike their primitive counterparts. \macrosection{Defining new names} \begin{macro} -\SKV@csdef|redplus{|cang(name)}{|cang(definition)} -\SKV@csgdef|redplus{|cang(name)}{|cang(definition)} -\SKV@csedef|redplus{|cang(name)}{|cang(definition)} -\SKV@csxdef|redplus{|cang(name)}{|cang(definition)} +\SKV@csdef|redstar|redplus{|vang(name)}{|vang(definition)} +\SKV@csgdef|redstar|redplus{|vang(name)}{|vang(definition)} +\SKV@csedef|redstar|redplus{|vang(name)}{|vang(definition)} +\SKV@csxdef|redstar|redplus{|vang(name)}{|vang(definition)} \end{macro} -\acmdm*{\SKV@csdef,\SKV@csgdef,\SKV@csedef,\SKV@csxdef} -The unsigned variants of these turn \aang{name} into a control sequence in terms of \aang{definition} whether or not the control was already defined. No error or warning messages are issued. The plus (\RedPlus) variants turn \aang{name} into a control sequence if it wasn't already defined; if it is already defined, an error message is flagged. These derive from a concept based on that of \acmd{\newcommand}, but (i)~\relaxed\ commands are considered undefined in this regard, and (ii)~these commands retain the powerful machinery of plain \tex.\footnote{The \pkg{skeyval} contains other undocumented tools for defining new commands.} +\acmdm*{\SKV@csdef,\SKV@csgdef,\SKV@csedef,\SKV@csxdef, +\SKV@csdef*,\SKV@csgdef*,\SKV@csedef*,\SKV@csxdef*, +\SKV@csdef*+,\SKV@csgdef*+,\SKV@csedef*+,\SKV@csxdef*+} + +The variants of these commands without the plus (\RedPlus) sign turn \ang{name} into a control sequence in terms of \ang{definition} whether or not the control was already defined. No error or warning messages are issued. The variants with plus (\RedPlus) sign turn \ang{name} into a control sequence if it wasn't already defined; if it is already defined, an error message is flagged. The starred (\RedStar) variants give ``short'' macros, while the unstarred variants yield ``long'' definitions. These derive from a concept based on that of \acmd{\newcommand}, but (i)~\textrelaxed\ commands are considered undefined in this regard, and (ii)~these commands retain the powerful machinery of plain \tex.\footnote{The \pkg{skeyval} contains other undocumented tools for defining new commands.} \macrosection{Name use} \begin{macro} -\SKV@csuse{|cang(name)} +\SKV@csuse{|vang(name)} \end{macro} \acmdm*{\SKV@csuse} -This is similar to \LaTeX's legacy \acmdm{\@nameuse} but returns \fx{\@empty} (instead of an error) if \aang{name} is undefined. This is due originally to \pkg{etoolbox}. +This is similar to \LaTeX's legacy \acmdm{\@nameuse} but returns \fx{\@empty} (instead of an error) if \ang{name} is undefined. This is due originally to \pkg{etoolbox}. \macrosection{\texttt{\@bs let} assignments} \begin{macro} -\SKV@newlet{|cang(cs1)}{|cang(cs2)} -\NewLet{|cang(cs1)}{|cang(cs2)} +\SKV@newlet{|vang(cs1)}{|vang(cs2)} +\NewLet{|vang(cs1)}{|vang(cs2)} \end{macro} \acmdm*{\SKV@newlet,\NewLet} -These assign \aang{cs2} to \aang{cs1} if \aang{cs2} exists and if \aang{cs1} isn't already defined, otherwise an error is flagged. The command \fx{\NewLet} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@newlet}, on the other hand, is always available. You can use \acmd{\TestProvidedCommand} (\macref{mac:testprovide}) to test whether or not you are using the \fx{\NewLet} command of the \pkg{skeyval}. +These assign \ang{cs2} to \ang{cs1} if \ang{cs2} exists and if \ang{cs1} isn't already defined, otherwise an error is flagged. The command \fx{\NewLet} is defined in the \pkg{skeyval} only if it hasn't been defined by a previously loaded package; the command \fx{\SKV@newlet}, on the other hand, is always available. You can use \acmd{\TestProvidedCommand} (\macref{mac:testprovide}) to test whether or not you are using the \fx{\NewLet} command of the \pkg{skeyval}. \begin{macro} -\SKV@cslet{|cang(name)}{|cang(cs)} -\SKV@letcs{|cang(cs)}{|cang(name)} -\SKV@csletcs{|cang(name)}{|cang(name)} +\SKV@cslet{|vang(name)}{|vang(cs)} +\SKV@letcs{|vang(cs)}{|vang(name)} +\SKV@csletcs{|vang(name)}{|vang(name)} \end{macro} \acmdm*{\SKV@cslet,\SKV@letcs,\SKV@csletcs} -These perform \fx{\let} assignments if the second argument is defined, otherwise an error message is flagged. The notation \aang{cs} means a control sequence, and \aang{name} means a control sequence name. +These perform \fx{\let} assignments if the second argument is defined, otherwise an error message is flagged. The notation \ang{cs} means a control sequence, and \ang{name} means a control sequence name. \begin{macro} -\SKV@cslet|redstar{|cang(name)}{|cang(cs)} -\SKV@letcs|redstar{|cang(cs)}{|cang(name)} -\SKV@csletcs|redstar{|cang(name)}{|cang(name)} +\SKV@cslet|redstar{|vang(name)}{|vang(cs)} +\SKV@letcs|redstar{|vang(cs)}{|vang(name)} +\SKV@csletcs|redstar{|vang(name)}{|vang(name)} \end{macro} \acmdm*{\SKV@cslet*,\SKV@letcs*,\SKV@csletcs*} These perform \fx{\let} assignments whether or not the second argument is defined. If the second argument is undefined, the first remains undefined and the hash table is not filled. @@ -1836,87 +1804,87 @@ These perform \fx{\let} assignments whether or not the second argument is define \macrosection{Number and dimension expressions} \begin{macro} -\SKV@numdef|redplus|redask{|cang(num)}{|cang(expression)} +\SKV@numdef|redplus|redask{|vang(num)}{|vang(expression)} \end{macro} -\acmdm{\SKV@numdef} defines \aang{num} from \aang{expression} using \etex's \acmd{\numexpr}. If \aang{num} was previously undefined, it is first initialized with \acmd{\newcount} before the expression is built. If you do \fx{\SKV@numdef\x{1+2+3}}, you would need to prefix \fx{\x} with \fx{\the} or \acmd{\number} in expressions. Expressions defined by \fx{\SKV@numdef} can be used with \tex's operators such as \fx{\advance} or \fx{\multiply} and \etex's \acmd{\numexpr} operator. +\acmdm{\SKV@numdef} defines \ang{num} from \ang{expression} using \etex's \acmd{\numexpr}. If \ang{num} was previously undefined, it is first initialized with \acmd{\newcount} before the expression is built. If you do \fx{\SKV@numdef\x{1+2+3}}, you would need to prefix \fx{\x} with \fx{\the} or \acmd{\number} in expressions. Expressions defined by \fx{\SKV@numdef} can be used with \tex's operators such as \fx{\advance} or \fx{\multiply} and \etex's \acmd{\numexpr} operator. The plus sign (\RedPlus) means that \fx{\SKV@numdef} takes a control sequence name instead of a control sequence, while the question mark (\RedAsk) implies that the macro \fx{\SKV@numdef} effects a global assignment which can thus escape local groups. \begin{macro} -\SKV@dimdef|redplus|redask{|cang(dim)}{|cang(expression)} +\SKV@dimdef|redplus|redask{|vang(dim)}{|vang(expression)} \end{macro} -\acmdm{\SKV@dimdef} defines \aang{dim} from \aang{expression} using \etex's \acmd{\dimexpr}. If \aang{dim} was previously undefined, it is first initialized with \acmd{\newdimen} before the expression is built. If you do \fx{\SKV@dimdef\x{1pt+2pt+3pt}}, you would need to prefix \fx{\x} with \fx{\the} in expressions. Expressions defined by \fx{\SKV@dimdef} can be used with \etex's \acmd{\dimexpr} operator. +\acmdm{\SKV@dimdef} defines \ang{dim} from \ang{expression} using \etex's \acmd{\dimexpr}. If \ang{dim} was previously undefined, it is first initialized with \acmd{\newdimen} before the expression is built. If you do \fx{\SKV@dimdef\x{1pt+2pt+3pt}}, you would need to prefix \fx{\x} with \fx{\the} in expressions. Expressions defined by \fx{\SKV@dimdef} can be used with \etex's \acmd{\dimexpr} operator. The plus sign (\RedPlus) means that \fx{\SKV@dimdef} takes a control sequence name instead of a control sequence, while the question mark (\RedAsk) implies that the macro \fx{\SKV@dimdef} effects a global assignment which can thus escape local groups. \macrosection{Verifying definability} \begin{macro} -\SKV@ifdefinable|cang(cs){|cang(function)} -\SKV@csifdefinable|cang(cs name){|cang(function)} +\SKV@ifdefinable|vang(cs){|vang(function)} +\SKV@csifdefinable|vang(cs name){|vang(function)} \end{macro} -\acmdm*{\SKV@ifdefinable} -\latex kernel's \fx{\@ifdefinable} fills up the hash table and also considers commands that are \fx{\relax}'ed as defined. Moreover, if the command being tested (\aang{cs} in the above example) is definable, the \fx{\@ifdefinable} macro begins executing \aang{function} while still in the \fx{\if} \textellipsis \fx{\fi} conditional. You can't do \fx{\let\ifabc\iftrue} in such conditionals. The command \fx{\SKV@ifdefinable}, which is robust, seeks to avoid these problems. +\acmdm*{\SKV@ifdefinable, \SKV@csifdefinable} +\latex kernel's \fx{\@ifdefinable} fills up the hash table and also considers commands that are \fx{\relax}'ed as defined. Moreover, if the command being tested (\ang{cs} in the above example) is definable, the \fx{\@ifdefinable} macro begins executing \ang{function} while still in the \fx{\if} \textellipsis \fx{\fi} conditional. You can't do \fx{\let\ifabc\iftrue} in such conditionals. The command \fx{\SKV@ifdefinable}, which is robust, seeks to avoid these problems. \fx{\SKV@csifdefinable} expects a control sequence name instead of a control sequence. \begin{macro} -\SKV@ifdefinable@n{|cang(list)} +\SKV@ifdefinable@n{|vang(list)} \end{macro} -The macro \acmdm{\SKV@ifdefinable@n} accepts a comma-separated list of control sequence \emph{names} whose definability are to be tested. It should be noted that the macro \fx{\SKV@ifdefinable@n} doesn't accept \aang{function}, unlike the above \fx{\SKV@ifdefinable}. The aim of \fx{\SKV@ifdefinable@n} is simply to test the definability of instances/members of \aang{list}. +The macro \acmdm{\SKV@ifdefinable@n} accepts a comma-separated list of control sequence \emph{names} whose definability are to be tested. It should be noted that the macro \fx{\SKV@ifdefinable@n} doesn't accept \ang{function}, unlike the above \fx{\SKV@ifdefinable}. The aim of \fx{\SKV@ifdefinable@n} is simply to test the definability of instances/members of \ang{list}. \begin{example} \SKV@ifdefinable@n{ax,ay,az} \end{example} \begin{macro} -\SKV@ifnew|redstar|redplus[|cang(optional parser)]{|cang(list)} +\SKV@ifnewcmd|redstar|redplus[|vang(optional parser)]{|vang(list)} \end{macro} -\acmdm*{\SKV@ifnew,\SKV@ifnew*,\SKV@ifnew*+} +\acmdm*{\SKV@ifnewcmd,\SKV@ifnewcmd*,\SKV@ifnewcmd*+} -The macro \fx{\SKV@ifnew} is similar to, but more versatile, than the command \fx{\SKV@ifdefinable@n}. The star sign (\RedStar) in \fx{\SKV@ifnew} indicates that \aang{list} is available in a macro, say \fx{\mylist}; and the plus sign (\RedPlus) shows \fx{\SKV@ifnew} that members of \aang{list} (or \fx{\mylist}) are control sequence names, otherwise they are control sequences (see examples below). The default value of the optional \aang{parser} is ``,'' (comma). The macro \fx{\SKV@ifnew} doesn't execute any \aang{function}. Both \fx{\SKV@ifdefinable@n} and \fx{\SKV@ifnew} are robust. +The macro \fx{\SKV@ifnewcmd} is similar to, but more versatile, than the command \fx{\SKV@ifdefinable@n}. The star sign (\RedStar) in \fx{\SKV@ifnewcmd} indicates that \ang{list} is available in a macro, say \fx{\mylist}; and the plus sign (\RedPlus) shows \fx{\SKV@ifnewcmd} that members of \ang{list} (or \fx{\mylist}) are control sequence names, otherwise they are control sequences (see examples below). The default value of the optional \ang{parser} is ``,'' (comma). The macro \fx{\SKV@ifnewcmd}, like \fx{\SKV@ifdefinable@n} but unlike \fx{\SKV@ifdefinable}, doesn't execute any \ang{function}. Both \fx{\SKV@ifdefinable@n} and \fx{\SKV@ifnewcmd} are robust. \begin{example} \def\mylist{ax,ay,az} -\SKV@ifnew|redstar|redplus[,]\mylist -\SKV@ifnew|redstar|redplus\mylist -\SKV@ifnew|redplus{ax,ay,az} -\SKV@ifnew{\ax\ay\az} +\SKV@ifnewcmd|redstar|redplus[,]\mylist +\SKV@ifnewcmd|redstar|redplus\mylist +\SKV@ifnewcmd|redplus{ax,ay,az} +\SKV@ifnewcmd{\ax\ay\az} \def\my@list{\ax\ay\az} -\SKV@ifnew|redstar\my@list +\SKV@ifnewcmd|redstar\my@list \def\my@@list{ax;ay;az} -\SKV@ifnew|redstar|redplus[;]\my@@list -\SKV@ifnew\ax |tto \SKV@ifnew|redplus{ax} |tto \SKV@ifdefinable@n{ax} +\SKV@ifnewcmd|redstar|redplus[;]\my@@list +\SKV@ifnewcmd\ax |tto \SKV@ifnewcmd|redplus{ax} |tto \SKV@ifdefinable@n{ax} \end{example} \macrosection{Verifying the status of variables} \begin{macro} -\SKV@ifdef|cang(cs){|cang(true)}{|cang(false)} -\SKV@ifcsdef{|cang(name)}{|cang(true)}{|cang(false)} -\SKV@ifundef|cang(cs){|cang(true)}{|cang(false)} -\SKV@ifcsundef{|cang(name)}{|cang(true)}{|cang(false)} +\SKV@ifdef|vang(cs){|vang(true)}{|vang(false)} +\SKV@ifcsdef{|vang(name)}{|vang(true)}{|vang(false)} +\SKV@ifundef|vang(cs){|vang(true)}{|vang(false)} +\SKV@ifcsundef{|vang(name)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\SKV@ifdef,\SKV@ifcsdef,\SKV@ifundef,\SKV@ifcsundef} -These use \etex's facilities to test the existence of the control sequence \aang{cs} or control sequence name \aang{name}. These commands aren't robust and may be used to determine the current state of the macro replacement text, if such replacement text contains these commands. \relaxed\ macros are considered undefined by \emph{all} these commands. To test if a macro is \relaxed, use the following commands: +These use \etex's facilities to test the existence of the control sequence \ang{cs} or control sequence name \ang{name}. These commands aren't robust and may be used to determine the current state of the macro replacement text, if such replacement text contains these commands. \textrelaxed\ macros are considered undefined by \emph{all} these commands. To test if a macro is \textrelaxed, use the following commands: \begin{macro} -\SKV@ifrelax|cang(cs){|cang(true)}{|cang(false)} -\SKV@ifcsrelax{|cang(name)}{|cang(true)}{|cang(false)} +\SKV@ifrelax|vang(cs){|vang(true)}{|vang(false)} +\SKV@ifcsrelax{|vang(name)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\SKV@ifrelax,\SKV@ifcsrelax} \begin{macro} -\SKV@ifdefax|cang(cs){|cang(defined)}{|cang(relaxed)}{|cang(undefined)} -\SKV@ifcsdefax{|cang(name)}{|cang(defined)}{|cang(relaxed)}{|cang(undefined)} +\SKV@ifdefax|vang(cs){|vang(defined)}{|vang(relaxed)}{|vang(undefined)} +\SKV@ifcsdefax{|vang(name)}{|vang(defined)}{|vang(relaxed)}{|vang(undefined)} \end{macro} \acmdm*{\SKV@ifdefax,\SKV@ifcsdefax} -These test if \aang{cs} or \aang{name} is defined, relaxed, or undefined. In using these three-valued logical tests, it is often easy to forget to include the null state (\ie, \aang{undefined}) because \tex is dominated by two-valued logical tests. +These test if \ang{cs} or \ang{name} is defined, relaxed, or undefined. In using these three-valued logical tests, it is often easy to forget to include the null state (\ie, \ang{undefined}) because \tex is dominated by two-valued logical tests. \macrosection{Undefining macros} \begin{macro} -\SKV@Undef|redstar|redplus|redask[|cang(optional parser)]{|cang(cs)} +\SKV@Undef|redstar|redplus|redask[|vang(optional parser)]{|vang(cs)} \end{macro} \acmdm*{\SKV@Undef,\SKV@Undef*,\SKV@Undef*+,\SKV@Undef*+?} -This undefines the macros or control sequence names in the list \aang{cs} (of nil, one or more elements) such that \tex will subsequently consider each element undefined. The star sign (\RedStar) indicates that \aang{cs} is given as a macro whose \emph{contents} are to be individually undefined, and the plus sign (\RedPlus) shows that \aang{cs} is made up of \emph{control sequence names} instead of control sequences. The question mark (\RedAsk) directs \fx{\SKV@Undef} to \emph{globally} undefine all the control sequences or names in \aang{cs}. Control sequence names are to be separated by the parser; control sequences shouldn't be separated. The default value of the \aang{parser} is ``,'' (comma). The command \fx{\SKV@Undef} is robust (it will thus not expand in expansion contexts), but fragile arguments would need to be protected in expansion contexts.\footnote{Macros such as \acmdm{\@ifnextchar}, \acmdm{\@ifstar}, and those involving optional arguments normally can't be evaluated in expansion contexts. The same applies to the \pkg{skeyval} macros with optional arguments. The \pkgm{etextools} introduced expandable variants of these commands, but in the contexts these commands are employed in the \pkg{skeyval}, the expandable variants aren't particularly advantageous. The main reason is that some of our internal macros (\eg, looping macros) aren't amenable to full expansion anyway. Actually, the \pkg{skeyval} provides the fully expandable variants (\acmdm{\SKV@TestOpt}, \acmdm{\SKV@IfStar}, \acmdm{\SKV@IfPlus}, and \acmdm{\SKV@IfAsk}) of the non-expandable commands \acmdm{\SKV@testopt}, \acmdm{\SKV@ifstar}, \acmdm{\SKV@ifplus}, and \acmdm{\SKV@ifask}. The commands \fx{\SKV@ifask} and \fx{\SKV@IfAsk} look for an optional question mark (\RedAsk).} +This undefines the macros or control sequence names in the list \ang{cs} (of nil, one or more elements) such that \tex will subsequently consider each element undefined. The star sign (\RedStar) indicates that \ang{cs} is given as a macro whose \emph{contents} are to be individually undefined, and the plus sign (\RedPlus) shows that \ang{cs} is made up of \emph{control sequence names} instead of control sequences. The question mark (\RedAsk) directs \fx{\SKV@Undef} to \emph{globally} undefine all the control sequences or names in \ang{cs}. Control sequence names are to be separated by the parser; control sequences shouldn't be separated. The default value of the \ang{parser} is ``,'' (comma). The command \fx{\SKV@Undef} is robust (it will thus not expand in expansion contexts), but fragile arguments would need to be protected in expansion contexts.\footnote{Macros such as \acmdm{\@ifnextchar}, \acmdm{\@ifstar}, and those involving optional arguments normally can't be evaluated in expansion contexts. The same applies to the \pkg{skeyval} macros with optional arguments. The \pkgm{etextools} introduced expandable variants of these commands, but in the contexts these commands are employed in the \pkg{skeyval}, the expandable variants aren't particularly advantageous. The main reason is that some of our internal macros (\eg, looping macros) aren't amenable to full expansion anyway. Actually, the \pkg{skeyval} provides the fully expandable variants (\acmdm{\SKV@TestOpt}, \acmdm{\SKV@IfStar}, \acmdm{\SKV@IfPlus}, and \acmdm{\SKV@IfAsk}) of the non-expandable commands \acmdm{\SKV@testopt}, \acmdm{\SKV@ifstar}, \acmdm{\SKV@ifplus}, and \acmdm{\SKV@ifask}. The commands \fx{\SKV@ifask} and \fx{\SKV@IfAsk} look for an optional question mark (\RedAsk).} \begin{example} \def\unwanted{tempa,tempb,tempc,temp1} @@ -1944,52 +1912,52 @@ This undefines the macros or control sequence names in the list \aang{cs} (of ni The following non-generic variants avoid the above complications of signs, but they don't take lists: \begin{macro} -\SKV@undef{|cang(cs)} |tto \SKV@Undef{|cang(cs)} -\SKV@gundef{|cang(cs)} |tto \SKV@Undef|redask{|cang(cs)} -\SKV@csundef{|cang(cs name)} |tto \SKV@Undef|redplus{|cang(cs)} -\SKV@csgundef{|cang(cs name)} |tto \SKV@Undef|redplus|redask{|cang(cs)} +\SKV@undef{|vang(cs)} |tto \SKV@Undef{|vang(cs)} +\SKV@gundef{|vang(cs)} |tto \SKV@Undef|redask{|vang(cs)} +\SKV@csundef{|vang(cs name)} |tto \SKV@Undef|redplus{|vang(cs)} +\SKV@csgundef{|vang(cs name)} |tto \SKV@Undef|redplus|redask{|vang(cs)} \end{macro} \acmdm*{\SKV@undef,\SKV@gundef,\SKV@csundef,\SKV@csgundef} \macrosection{Expansion control} \begin{macro} -\SKV@expox{|cang(cs)} +\SKV@expox{|vang(cs)} \end{macro} \acmdm*{\SKV@expox} -This expands its argument \aang{cs} once and forbids further expansion. +This expands its argument \ang{cs} once and forbids further expansion. \begin{macro} -\SKV@expcsox{|cang(name)} +\SKV@expcsox{|vang(name)} \end{macro} \acmdm*{\SKV@expcsox} -This is similar to \fx{\SKV@expox} but accepts control sequence name \aang{name} instead of control sequence. +This is similar to \fx{\SKV@expox} but accepts control sequence name \ang{name} instead of control sequence. \begin{macro} -\SKV@exptx{|cang(cs)} +\SKV@exptx{|vang(cs)} \end{macro} \acmdm*{\SKV@exptx} -This expands its argument \aang{cs} twice and forbids further expansion. +This expands its argument \ang{cs} twice and forbids further expansion. \begin{macro} -\SKV@expcstx{|cang(name)} +\SKV@expcstx{|vang(name)} \end{macro} \acmdm*{\SKV@expcstx} -This is similar to \fx{\SKV@exptx} but accepts control sequence name \aang{name} instead of control sequence. +This is similar to \fx{\SKV@exptx} but accepts control sequence name \ang{name} instead of control sequence. \begin{macro} -\SKV@expargs|cang(n)|cang(function)|cang(arg1)|cang(arg2)\@nil +\SKV@expargs|vang(n)|vang(function)|vang(arg1)|vang(arg2)\@nil \end{macro} \acmdm*{\SKV@expargs} -\LaTeX's \acmdm{\@expandtwoargs} is often used as a utility macro to expand two arguments \aang{arg1} and \aang{arg2} in order to execute \aang{function}. The command \fx{\SKV@expargs}, on the other hand, accepts up to four expansion types, signified by \aang{n}, which runs \mbox{from 0 to 3}: +\LaTeX's \acmdm{\@expandtwoargs} is often used as a utility macro to expand two arguments \ang{arg1} and \ang{arg2} in order to execute \ang{function}. The command \fx{\SKV@expargs}, on the other hand, accepts up to four expansion types, signified by \ang{n}, which runs \mbox{from 0 to 3}: \begin{enum} -\item If \aang{n} is 0, then \aang{arg2} is empty and only \aang{arg1} will be expanded before \aang{function} is executed. -\item If \aang{n} is 1, then both \aang{arg1} and \aang{arg2} are nonempty but only \aang{arg2} will be expanded before \aang{function} is executed. -\item When \aang{n} is 2, then both \aang{arg1} and \aang{arg2} are nonempty and both will be expanded before \aang{function} is executed. This is equivalent to \LaTeX's \fx{\@expandtwoargs}. -\item If \aang{n} is 3, then both \aang{arg1} and \aang{arg2} are nonempty but only \aang{arg1} is expanded before \aang{function} is executed. -\item If \aang{n} isn't in the list \hv{0,1,2,3}, then an error message is flagged. +\item If \ang{n} is 0, then \ang{arg2} is empty and only \ang{arg1} will be expanded before \ang{function} is executed. +\item If \ang{n} is 1, then both \ang{arg1} and \ang{arg2} are nonempty but only \ang{arg2} will be expanded before \ang{function} is executed. +\item When \ang{n} is 2, then both \ang{arg1} and \ang{arg2} are nonempty and both will be expanded before \ang{function} is executed. This is equivalent to \LaTeX's \fx{\@expandtwoargs}. +\item If \ang{n} is 3, then both \ang{arg1} and \ang{arg2} are nonempty but only \ang{arg1} is expanded before \ang{function} is executed. +\item If \ang{n} isn't in the list \fnv{0,1,2,3}, then an error message is flagged. \end{enum} -Because \aang{arg2} is delimited, it can be empty. The command \fx{\SKV@expargs} can be used to save \fx{\expandafter}'s, but caution should be exercised in deploying it: for example, the \fx{\edef} it uses may expand too deeply in some cases. Also, precaution may be necessary when the expanded arguments (\aang{arg1} and/or \aang{arg2}) involve the \tex primitive \fx{\if}. When invoking \fx{\SKV@expargs}, the macros \fx{\SKV@expox} and \fx{\SKV@exptx} can be used to control the level of expansion. +Because \ang{arg2} is delimited, it can be empty. The command \fx{\SKV@expargs} can be used to save \fx{\expandafter}'s, but caution should be exercised in deploying it: for example, the \fx{\edef} it uses may expand too deeply in some cases. Also, precaution may be necessary when the expanded arguments (\ang{arg1} and/or \ang{arg2}) involve the \tex primitive \fx{\if}. When invoking \fx{\SKV@expargs}, the macros \fx{\SKV@expox} and \fx{\SKV@exptx} can be used to control the level of expansion. Some trivial examples follow: \begin{example} @@ -2005,13 +1973,15 @@ These expressions show how \fx{\SKV@expargs} can be used to economize on chains \macrosection{Checking values of \texttt{choice} keys} -Choice keys should, by definition, have preordained values. This requirement can be useful even for non-choice keys. +Choice keys should, by definition, have preordained values. This requirement can be useful even for non-choice keys, as we illustrate below. \begin{macro} -\SKV@checkchoice{|cang(value)}{|cang(altlist)}{|cang(true)}{|cang(false)} +\SKV@checkchoice{|vang(value)}{|vang(altlist)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\SKV@checkchoice} -This is an enhanced form of \pkg{xkeyval}'s \fx{\XKV@checkchoice}. It checks if the user-submitted \aang{value} of a key (say, \aang{keya}) is in the list \aang{altlist}. It executes \aang{true} if \aang{value} is found in \aang{altlist} and \aang{false} otherwise. Additionally, it returns \acmd{\val} for the expanded value of \aang{value} and \acmd{\nr} for the numerical order of \acmd{\val} in the list \aang{altlist}. If \aang{value} isn't found in \aang{altlist}, then \acmd{\nr} will return $-1$. If \aang{value} and \aang{altlist} are buried in macros, the macros are fully expanded before the search for \aang{value} in the list \aang{altlist} is effected. In that case, \acmd{\val} will hold the expanded form of \aang{value} and can be used in subsequent computations. Choice keys do accept macros as values, but such values aren't directly suitable for matching against the contents of \aang{altlist}. For example, \aang{altlist} may be the set \fx{{left,right,center}}, but given as a macro \fx{\@altlist}, while \aang{value} is given as \fx{\def\@value{center}}. Obviously, \fx{\@value} contains one of the elements of \aang{altlist}, but choice keys won't know this without the expansion of both \fx{\@altlist} and \fx{\@value}. This is \name{raison d'\^e tre} of the \fx{\SKV@checkchoice} macro. +This is an enhanced form of \pkg{xkeyval}'s \fx{\XKV@checkchoice}. It checks if the user-submitted \ang{value} of a key (say, \ang{keya}) is in the list \ang{altlist}. It executes \ang{true} if \ang{value} is found in \ang{altlist} and \ang{false} otherwise. Additionally, it returns \acmd{\val} for the expanded value of \ang{value} and \acmd{\nr} for the numerical order of \acmd{\val} in the list \ang{altlist}. If \ang{value} isn't found in \ang{altlist}, then \acmd{\nr} will return $-1$. If \ang{value} and \ang{altlist} are buried in macros, the macros are fully expanded before the search for \ang{value} in the list \ang{altlist} is effected. In that case, \acmd{\val} will hold the expanded form of \ang{value} and can be used in subsequent computations. + +Choice keys do accept macros as values, but such values aren't directly suitable for matching against the contents of \ang{altlist}. For example, \ang{altlist} may be the set \fx{{left,right,center}}, but given as a macro \fx{\@altlist}, while \ang{value} is given as \fx{\def\@value{center}}. Obviously, \fx{\@value} contains one of the elements of \ang{altlist}, but choice keys won't know this without the expansion of both \fx{\@altlist} and \fx{\@value}. This is \name{raison d'\^e tre} of the \fx{\SKV@checkchoice} macro. Moreover, \fx{\SKV@checkchoice} can be used in the definition of non-choice keys. In the following example we check the value of an \emph{ordinary} key by means of \fx{\SKV@checkchoice}: \begin{example} @@ -2038,65 +2008,77 @@ The reader may wish to do \fx{\show\tempa} to see what \fx{\tempa} gets upon set \macrosection{Testing for substring} \begin{macro} -\SKV@in@{|cang(substring)}{|cang(string)} +\SKV@in@{|vang(substring)}{|vang(string)} \end{macro} \acmdm*{\SKV@in@} -This is similar to the \latex kernel's \hy{\in@}{substring}{string} which tests if \aang{substring} is in \aang{string}, but the present test avoids the problem of false result, which is typified by the following test: +This is similar to the \latex kernel's \fny{\in@}{substring}{string} which tests if \ang{substring} is in \ang{string}, but the present test avoids the problem of false result, which is typified by the following test: \begin{example} \in@{aa}{ababba} \end{example} This incorrectly returns \acmdm{\ifin@} as \fx{\iftrue}. The macro \fx{\SKV@in@}, on the other hand, correctly gives \fx{\ifin@} as \fx{\iffalse} in this case. The command \fx{\SKV@in@} is robust. \begin{macro} -\SKV@in@o{|cang(substring)}{|cang(string)}{|cang(true text)}{|cang(false text)} +\SKV@in@n{|vang(substring)}{|vang(string)}{|vang(true text)}{|vang(false text)} +\end{macro} +\acmdm*{\SKV@in@n} +This is similar to \fx{\SKV@in@} but, as shown here, the returned result has a different syntax. + +\begin{macro} +\SKV@in@o{|vang(substring)}{|vang(string)}{|vang(true text)}{|vang(false text)} \end{macro} \acmdm*{\SKV@in@o} -This is similar to \fx{\SKV@in@} but the returned result has a different syntax. +This expands each of its two arguments once before the test. + +\begin{macro} +\SKV@in@x{|vang(substring)}{|vang(string)}{|vang(true text)}{|vang(false text)} +\end{macro} +\acmdm*{\SKV@in@x} +This expands each of its two arguments fully before the test. \begin{macro} -\in@tog{|cang(substring)}{|cang(string)} +\in@tog{|vang(substring)}{|vang(string)} \end{macro} \acmdm*{\in@tog} -In this case the returned boolean is the toggle switch \aang{in@} instead of the kernel's \aang{in@} switch which is used as \fx{\ifin@}. The toggle \aang{in@} can be used in the following way and in other manners that toggles can be employed: +In this case the returned boolean is the toggle switch \ang{in@} instead of the kernel's \ang{in@} switch which is used as \fx{\ifin@}. The toggle \ang{in@} can be used in the following way and in other manners that toggles can be employed: \begin{example} -\iftogon{in@}{|cang(true text)}{|cang(false text)}. +\iftogon{in@}{|vang(true text)}{|vang(false text)}. \end{example} \acmd*{\iftogon} The command \fx{\in@tog} is robust. \begin{macro} -\in@tok{|cang(substring)}{|cang(string)} +\in@tok{|vang(substring)}{|vang(string)} \end{macro} \acmdm*{\in@tok} -Sometimes you want to use the \latex kernel's \hy{\in@}{substring}{string} to test if \aang{substring} is in \aang{string} irrespective of their catcodes. The robust command \hy{\in@tok}{substring}{string} makes this possible, and eliminates the tokens that would have been necessary if the user was required to first detokenize the two arguments. It returns the same switch \fx{\ifin@} as the kernel's \hy{\in@}{substring}{string}. Actually, it calls \fx{\SKV@in@} to avoid false returns. +Sometimes you want to use the \latex kernel's \fny{\in@}{substring}{string} to test if \ang{substring} is in \ang{string} irrespective of their catcodes. The robust command \fny{\in@tok}{substring}{string} makes this possible, and eliminates the tokens that would have been necessary if the user was required to first detokenize the two arguments. It returns the same switch \fx{\ifin@} as the kernel's \fny{\in@}{substring}{string}. Actually, it calls \fx{\SKV@in@} to avoid false returns. \macrosection{Testing equality of strings} \begin{macro} -\SKV@ifstrequal{|cang(string1)}{|cang(string2)}{|cang(true)}{|cang(false)} -\SKV@ifstrnotequal{|cang(string1)}{|cang(string2)}{|cang(not true)}{|cang(not false)} -\SKV@oifstrequal{|cang(string1)}{|cang(string2)}{|cang(true)}{|cang(false)} -\SKV@xifstrequal{|cang(string1)}{|cang(string2)}{|cang(true)}{|cang(false)} +\SKV@ifstrequal{|vang(string1)}{|vang(string2)}{|vang(true)}{|vang(false)} +\SKV@ifstrnotequal{|vang(string1)}{|vang(string2)}{|vang(not true)}{|vang(not false)} +\SKV@oifstrequal{|vang(string1)}{|vang(string2)}{|vang(true)}{|vang(false)} +\SKV@xifstrequal{|vang(string1)}{|vang(string2)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\SKV@ifstrequal,\SKV@ifstrnotequal,\SKV@oifstrequal,\SKV@xifstrequal} -In order to properly test the equality of strings, it may be necessary to remove leading and trailing spaces before the test. Such spaces may have cropped into the strings from input or from pre-processing and may invalidate the test. The macro \fx{\SKV@ifstrequal} takes care of such situations. It executes \aang{true} if \aang{string1} is equal (character code wise) to \aang{string2}, and \aang{false} otherwise. Both \aang{string1} and \aang{string2} are detokenized before the test. The macro \fx{\SKV@oifstrequal} is similar to \fx{\SKV@ifstrequal} but first expands its arguments (the two strings \aang{string1} and \aang{string2}) once before the test. The macro \fx{\SKV@xifstrequal} first expands its arguments fully before the test. +In order to properly test the equality of strings, it may be necessary to remove leading and trailing spaces before the test. Such spaces may have cropped into the strings from input or from pre-processing and may invalidate the test. The macro \fx{\SKV@ifstrequal} takes care of such situations. It executes \ang{true} if \ang{string1} is equal (character code wise) to \ang{string2}, and \ang{false} otherwise. Both \ang{string1} and \ang{string2} are detokenized before the test. The macro \fx{\SKV@oifstrequal} is similar to \fx{\SKV@ifstrequal} but first expands its arguments (the two strings \ang{string1} and \ang{string2}) once before the test. The macro \fx{\SKV@xifstrequal} first expands its arguments fully before the test. \macrosection{Testing for empty or blank} \begin{macro} -\SKV@ifempty{|cang(token)}{|cang(true)}{|cang(false)} -\SKV@ifnotempty{|cang(token)}{|cang(not true)}{|cang(not false)} -\SKV@oifempty{|cang(token)}{|cang(true)}{|cang(false)} -\SKV@xifempty{|cang(token)}{|cang(true)}{|cang(false)} +\SKV@ifempty{|vang(token)}{|vang(true)}{|vang(false)} +\SKV@ifnotempty{|vang(token)}{|vang(not true)}{|vang(not false)} +\SKV@oifempty{|vang(token)}{|vang(true)}{|vang(false)} +\SKV@xifempty{|vang(token)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\SKV@ifempty,\SKV@ifnotempty,\SKV@oifempty,\SKV@xifempty} -These yield \aang{true} if \aang{token} is empty, and \aang{false} otherwise. In the command \fx{\SKV@ifempty}, \aang{token} isn't expanded before the test; in the command \fx{\SKV@oifempty}, \aang{token} is expanded once before the test; in the command \fx{\SKV@xifempty}, \aang{token} is fully expanded before the test. +These yield \ang{true} if \ang{token} is empty, and \ang{false} otherwise. In the command \fx{\SKV@ifempty}, \ang{token} isn't expanded before the test; in the command \fx{\SKV@oifempty}, \ang{token} is expanded once before the test; in the command \fx{\SKV@xifempty}, \ang{token} is fully expanded before the test. \begin{macro} -\SKV@ifblank{|cang(token)}{|cang(true)}{|cang(false)} -\SKV@ifnotblank{|cang(token)}{|cang(not true)}{|cang(not false)} -\SKV@oifblank{|cang(token)}{|cang(true)}{|cang(false)} -\SKV@xifblank{|cang(token)}{|cang(true)}{|cang(false)} +\SKV@ifblank{|vang(token)}{|vang(true)}{|vang(false)} +\SKV@ifnotblank{|vang(token)}{|vang(not true)}{|vang(not false)} +\SKV@oifblank{|vang(token)}{|vang(true)}{|vang(false)} +\SKV@xifblank{|vang(token)}{|vang(true)}{|vang(false)} \end{macro} \acmdm*{\SKV@ifblank,\SKV@ifnotblank,\SKV@oifblank,\SKV@xifblank} @@ -2105,44 +2087,44 @@ These macros test if the argument is blank or not. The first of these is from \p \macrosection{Verifying \texttt{draft} and \texttt{final} options} \begin{macro} -\SKV@ifdraft{|cang(true)}{|cang(false)} -\SKV@ifnotdraft{|cang(not true)}{|cang(not false)} -\SKV@iffinal{|cang(true)}{|cang(false)} -\SKV@ifnotfinal{|cang(not true)}{|cang(not false)} -\iftogon{draft}{|cang(true)}{|cang(false)} -\iftogoff{draft}{|cang(not true)}{|cang(not false)} -\iftogon{final}{|cang(true)}{|cang(false)} -\iftogoff{final}{|cang(not true)}{|cang(not false)} +\SKV@ifdraft{|vang(true)}{|vang(false)} +\SKV@ifnotdraft{|vang(not true)}{|vang(not false)} +\SKV@iffinal{|vang(true)}{|vang(false)} +\SKV@ifnotfinal{|vang(not true)}{|vang(not false)} +\iftogon{draft}{|vang(true)}{|vang(false)} +\iftogoff{draft}{|vang(not true)}{|vang(not false)} +\iftogon{final}{|vang(true)}{|vang(false)} +\iftogoff{final}{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\SKV@ifdraft,\SKV@ifnotdraft,\SKV@iffinal,\SKV@ifnotfinal,\iftogon\{draft\}, \iftogoff\{draft\},\iftogon\{final\},\iftogoff\{final\}} -These execute \aang{true} or \aang{false} depending on whether \fx{draft} or \fx{final} appears as \fx{true} in the options list of \acmd{\documentclass} or \hx{\usepackage}{skeyval}. +These execute \ang{true} or \ang{false} depending on whether \fx{draft} or \fx{final} appears as \fx{true} in the options list of \acmd{\documentclass} or \fnx{\usepackage}{skeyval}. The default is that \fx{final} is true, which implies that \fx{draft} is false by default. The keys \fx{draft} and \fx{final} are complementary native-boolean keys (see \cref{sec:comp-boolkeys}), which reduces the risk of mixing them. These commands are robust. \begin{macro} -\ifdraft{|cang(true)}{|cang(false)} -\ifnotdraft{|cang(not true)}{|cang(not false)} -\iffinal{|cang(true)}{|cang(false)} -\ifnotfinal{|cang(not true)}{|cang(not false)} +\ifdraft{|vang(true)}{|vang(false)} +\ifnotdraft{|vang(not true)}{|vang(not false)} +\iffinal{|vang(true)}{|vang(false)} +\ifnotfinal{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\ifdraft,\ifnotdraft,\iffinal,\ifnotfinal} -These are also defined in the \pkg{skeyval}, but because packages such as \pkgm{ifdraft} already exist, the \pkg{skeyval} defines them only if they haven't already been defined. If they existed before \pkg{skeyval} is loaded, they aren't redefined, and (if the package option \fx{verbose} is selected) a warning is logged in the transcript file to indicate that the definition being used isn't from the \pkg{skeyval}. The warning is logged only once. I am aware of the existence of only \fx{\ifdraft} outside the \pkg{skeyval}: therefore, the definition of \fx{\ifdraft} is deferred until \acmd{\AtBeginDocument}. You can use \acmd{\TestProvidedCommand} to check the version of the \fx{\ifdraft} that you are using. +These are also defined in the \pkg{skeyval}, but because packages such as \pkgm{ifdraft} already exist, the \pkg{skeyval} defines them only if they haven't already been defined. If they existed before \pkg{skeyval} is loaded, they aren't redefined, and (if the package option \acmd{verbose} is selected) a warning is logged in the transcript file to indicate that the definition being used isn't from the \pkg{skeyval}. The warning is logged only once. I am aware of the existence of only \fx{\ifdraft} outside the \pkg{skeyval}: therefore, the definition of \fx{\ifdraft} is deferred until \acmd{\AtBeginDocument}. You can use \acmd{\TestProvidedCommand} to check the version of the \fx{\ifdraft} that you are using. \macrosection{Verifying \texttt{dvi} and \texttt{pdf} modes} \begin{macro} -\SKV@ifpdf{|cang(true)}{|cang(false)} -\SKV@ifnotpdf{|cang(not true)}{|cang(not false)} -\iftogon{pdf}{|cang(true)}{|cang(false)} -\iftogoff{pdf}{|cang(not true)}{|cang(not false)} +\SKV@ifpdf{|vang(true)}{|vang(false)} +\SKV@ifnotpdf{|vang(not true)}{|vang(not false)} +\iftogon{pdf}{|vang(true)}{|vang(false)} +\iftogoff{pdf}{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\SKV@ifpdf,\SKV@ifnotpdf,\iftogon\{pdf\},\iftogoff\{pdf\}} -These execute \aang{true} or \aang{false} depending on whether \fx{dvi} or \fx{pdf} output is being produced. These commands are robust and may be used in expansion contexts. +These execute \ang{true} or \ang{false} depending on whether \fx{dvi} or \fx{pdf} output is being produced. These commands are robust and may be used in expansion contexts. \begin{macro} -\ifpdf{|cang(true)}{|cang(false)} -\ifnotpdf{|cang(not true)}{|cang(not false)} +\ifpdf{|vang(true)}{|vang(false)} +\ifnotpdf{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\ifpdf,\ifnotpdf} These are available only if they haven't been previously defined by another package. If they existed outside the \pkg{skeyval}, a warning is logged in the transcript log file (if the package option \fx{verbose} is selected), but only once, and the commands are not redefined. In particular, the above \fx{\ifpdf} is available only at \acmd{\AtBeginDocument} and is defined only if it doesn't already exist. The reason is that the popular \pkg{hyperref} loads the \pkg{ifpdf} and the \pkg{ifpdf} will abort if it detects that \fx{\ifpdf} has been defined by a package loaded earlier. @@ -2152,32 +2134,32 @@ These are available only if they haven't been previously defined by another pack \macrosection{Tests related to package loading} \begin{macro} -\@ifpackagecurrent{|cang(package)}{|cang(date)}{|cang(true)}{|cang(false)} -\@ifpackagenotcurrent{|cang(package)}{|cang(date)}{|cang(not true)}{|cang(not false)} +\@ifpackagecurrent{|vang(package)}{|vang(date)}{|vang(true)}{|vang(false)} +\@ifpackagenotcurrent{|vang(package)}{|vang(date)}{|vang(not true)}{|vang(not false)} \end{macro} \acmdm*{\@ifpackagecurrent,\@ifpackagenotcurrent} -These executes \aang{true} if the date of the current/loaded version \aang{package} is greater than or equal to \aang{date}. This is similar to \latex's \acmdm{\@ifpackagelater} but, unlike the latter, both \fx{\@ifpackagecurrent} and \fx{\@ifpackagenotcurrent} are robust. My main reason for these commands is that the nomenclature \fx{\@ifpackagelater} is subject to the wrong interpretation of being space (rather than time) related. +These executes \ang{true} if the date of the current/loaded version \ang{package} is greater than or equal to \ang{date}. This is similar to \latex's \acmdm{\@ifpackagelater} but, unlike the latter, both \fx{\@ifpackagecurrent} and \fx{\@ifpackagenotcurrent} are robust. My main reason for these commands is that the nomenclature \fx{\@ifpackagelater} is subject to the wrong interpretation of being space (rather than time) related. \begin{macro} -\@afterpackageloaded{|cang(package)}{|cang(code)} +\@afterpackageloaded{|vang(package)}{|vang(code)} \end{macro} \acmdm*{\@afterpackageloaded} -This executes \aang{code} only after \aang{package} has been loaded. This has been optimized from the \pkgm{afterpackage} to avoid filling up the hash table with hooks that are \fx{relax}'ed or indeed undefined, and to warn the user if \aang{package} was not eventually loaded. If at the start of document, \aang{package} has not been loaded, a warning message is entered in the log file. Use the following \fx{\@ensurepackageloaded} macro if you really need an error message in this case. +This executes \ang{code} only after \ang{package} has been loaded. This has been optimized from the \pkgm{afterpackage} to avoid filling up the hash table with hooks that are \fx{relax}'ed or indeed undefined, and to warn the user if \ang{package} was not eventually loaded. If at the start of document, \ang{package} has not been loaded, a warning message is entered in the log file. Use the following \fx{\@ensurepackageloaded} macro if you really need an error message in this case. \begin{macro} -\@ensurepackageloaded{|cang(packages)} +\@ensurepackageloaded{|vang(packages)} \end{macro} \acmdm*{\@ensurepackageloaded} -This will issue an error at start of document if any member of the comma-separated list \aang{packages} wasn't loaded before then. This command can be used to signpost those packages that must be loaded later. +This will issue an error at start of document if any member of the comma-separated list \ang{packages} wasn't loaded before then. This command can be used to signpost those packages that must be loaded later. \macrosection{Commands restricted to package and preamble} \begin{macro} -\SKV@onlypreamble{|cang(list)} +\SKV@onlypreamble{|vang(list)} \SKV@onlypackage \end{macro} \acmdm*{\SKV@onlypreamble,\SKV@onlypackage} -The \latex kernel's macro \fx{\@onlypreamble} accepts only one command at a time (\ie, you can't give it a list of preamble commands in one go), and the error message \acmdm{\@notprerr} is not that precise, since it doesn't indicate the command that has been wrongly placed in the document's body. The use of \fx{\@onlypreamble} in a style or class file can be monotonous if the file has many preamble commands. The macro \fx{\SKV@onlypreamble} takes a no-comma \aang{list} of commands at once and gives precise error messages related to the incorrectly located commands. The \aang{list} may be populated with nil, one, or more control sequences, \eg, +The \latex kernel's macro \fx{\@onlypreamble} accepts only one command at a time (\ie, you can't give it a list of preamble commands in one go), and the error message \acmdm{\@notprerr} is not that precise, since it doesn't indicate the command that has been wrongly placed in the document's body. The use of \fx{\@onlypreamble} in a style or class file can be monotonous if the file has many preamble commands. The macro \fx{\SKV@onlypreamble} takes a no-comma \ang{list} of commands at once and gives precise error messages related to the incorrectly located commands. The \ang{list} may be populated with nil, one, or more control sequences, \eg, \begin{example} \SKV@onlypreamble{\macroa \macrob \macroc} \end{example} @@ -2191,14 +2173,14 @@ The function \fx{\SKV@onlypackage} may be used to restrict commands to packages \macrosection{Extended \texttt{\@bs aftergroup} and \texttt{\@bs afterassignment}} \begin{macro} -\SKV@aftergroup{|cang(code)} -\SKV@aftergroup|redstar{|cang(code)} -\SKV@afterassignment{|cang(code)} -\SKV@afterassignment|redstar{|cang(code)} +\SKV@aftergroup{|vang(code)} +\SKV@aftergroup|redstar{|vang(code)} +\SKV@afterassignment{|vang(code)} +\SKV@afterassignment|redstar{|vang(code)} \end{macro} \acmdm*{\SKV@aftergroup,\SKV@aftergroup*,\SKV@afterassignment,\SKV@afterassignment*} -\tex's \fx{\aftergroup} and \fx{\afterassignment} don't accept arbitrary code. The commands \fx{\SKV@aftergroup} and \fx{\SKV@afterassignment} execute the arbitrary \aang{code} after a group or assignment. The starred variants expand \aang{code} once before the assignment or before exiting the group. These commands don't accumulate the group and assignment counters indefinitely: the counters are initialized after each group or each assignment. +\tex's \fx{\aftergroup} and \fx{\afterassignment} don't accept arbitrary code. The commands \fx{\SKV@aftergroup} and \fx{\SKV@afterassignment} execute the arbitrary \ang{code} after a group or assignment. The starred variants expand \ang{code} once before the assignment or before exiting the group. These commands don't accumulate the group and assignment counters indefinitely: the counters are initialized after each group or each assignment. Some examples follow: \begin{example} @@ -2231,27 +2213,27 @@ Some examples follow: \macrosection{List processing} \begin{macro} -\SKV@for@a{|cang(list)}|cang(cmd){|cang(function)} -\SKV@for@b|cang(listcmd)|cang(cmd){|cang(function)} +\SKV@for@a{|vang(list)}|vang(cmd){|vang(function)} +\SKV@for@b|vang(listcmd)|vang(cmd){|vang(function)} \end{macro} \acmdm*{\SKV@for@a,\SKV@for@b} -These are fast for-loops that accept general list parsers and allow for list breaks, as well as give the remainder of the list if a break occurs within the list. Elements of \aang{list} are stored in \aang{cmd}, and \aang{function} is executed for each element of \aang{list}. \aang{list}, which is populated by parser-separated elements, is not expanded before the iteration; \aang{listcmd}, on the other hand, is expanded once before the commencement of the loop. The list parser is dynamically declarable via +These are fast for-loops that accept general list parsers and allow for list breaks, as well as give the remainder of the list if a break occurs within the list. Elements of \ang{list} are stored in \ang{cmd}, and \ang{function} is executed for each element of \ang{list}. \ang{list}, which is populated by parser-separated elements, is not expanded before the iteration; \ang{listcmd}, on the other hand, is expanded once before the commencement of the loop. The list parser is dynamically declarable via \begin{macro} -\SKV@CommandGenParser{|cang(parser)} |orr -\skvoptions{genparser=|cang(parser)} +\SKV@CommandGenParser{|vang(parser)} |orr +\skvoptions{genparser=|vang(parser)} \end{macro} \acmdm*{\SKV@CommandGenParser} -Also, these iteration macros use the more powerful \acmd{\SKV@ifblank} to check whether or not \aang{list} is empty or blank. The commands \fx{\SKV@for@a} and \fx{\SKV@for@b} are robust, but in expansion contexts, both \aang{cmd} and \aang{function} will need to be protected. The \aang{parser} persists in effect until it is changed by another call to \fx{\SKV@CommandGenParser} or \acmd{\skvoptions} as above. +Also, these iteration macros use the more powerful \acmd{\SKV@ifblank} to check whether or not \ang{list} is empty or blank. The commands \fx{\SKV@for@a} and \fx{\SKV@for@b} are robust, but in expansion contexts, both \ang{cmd} and \ang{function} will need to be protected. The \ang{parser} persists in effect until it is changed by another call to \fx{\SKV@CommandGenParser} or \acmd{\skvoptions} as above. \Note One snag with a generic list parser like \fx{\SKV@CommandGenParser} is that the user must always remember to call it and set the right parser before beginning an iteration, otherwise there might be unpleasant results, since a previous call to \fx{\SKV@CommandGenParser} might have set a parser that is no longer valid. To obviate this type of situation, the following commands are also provided in the \pkg{skeyval}: \begin{macro} -\SKV@for[|cang(parser)]{|cang(list)}|cang(cmd){|cang(function)} -\SKV@for|redstar[|cang(parser)]|cang(listcmd)|cang(cmd){|cang(function)} +\SKV@for[|vang(parser)]{|vang(list)}|vang(cmd){|vang(function)} +\SKV@for|redstar[|vang(parser)]|vang(listcmd)|vang(cmd){|vang(function)} \end{macro} \acmdm*{\SKV@for,\SKV@for*} -The \aang{parser} appears as an optional argument in these commands and its default value is ``\fx{,}'' (comma). These commands allow the user to provide the \aang{parser} with every call. The unstarred and starred versions of \fx{\SKV@for} are equivalent to \fx{\SKV@for@a} and \fx{\SKV@for@b}, respectively. Both sets (\fx{\SKV@for@a} and \fx{\SKV@for@b} \amdvert\ \fx{\SKV@for} and \fx{\SKV@for}\redstar) may be needed in different circumstances. In applications where the \aang{parser} is fixed, the commands \fx{\SKV@for@a} and \fx{\SKV@for@b} are faster than \fx{\SKV@for} and \fx{\SKV@for}\redstar\ because in the former cases the \aang{parser} would then need to be set only once: each call to \fx{\SKV@for} or \fx{\SKV@for}\redstar, whether or not the optional \aang{parser} is provided, resets the \aang{parser}. +The \ang{parser} appears as an optional argument in these commands and its default value is ``\fx{,}'' (comma). These commands allow the user to provide the \ang{parser} with every call. The unstarred and starred versions of \fx{\SKV@for} are equivalent to \fx{\SKV@for@a} and \fx{\SKV@for@b}, respectively. Both sets (\fx{\SKV@for@a} and \fx{\SKV@for@b} \amdvert\ \fx{\SKV@for} and \fx{\SKV@for}\redstar) may be needed in different circumstances. In applications where the \ang{parser} is fixed, the commands \fx{\SKV@for@a} and \fx{\SKV@for@b} are faster than \fx{\SKV@for} and \fx{\SKV@for}\redstar\ because in the former cases the \ang{parser} would then need to be set only once: each call to \fx{\SKV@for} or \fx{\SKV@for}\redstar, whether or not the optional \ang{parser} is provided, resets the \ang{parser}. -The list parser itself is available in \acmd{\parser}, which can be used in \aang{function}. An example follows: +The list parser itself is available in \acmd{\parser}, which can be used in \ang{function}. An example follows: \begin{example} \SKV@CommandGenParser{;} \SKV@for@a{a;b;c;d}\cmd{\if a\cmd `\cmd'\ is `a'\parser @@ -2266,19 +2248,19 @@ isn't `a'\parser\fi}, upon which the remainder of the list is accessible from \acmd{\SKV@remainder}. \begin{macro} -\SKV@tfor@a{|cang(list)}|cang(cmd){|cang(function)} -\SKV@tfor@b|cang(listcmd)|cang(cmd){|cang(function)} +\SKV@tfor@a{|vang(list)}|vang(cmd){|vang(function)} +\SKV@tfor@b|vang(listcmd)|vang(cmd){|vang(function)} \end{macro} \acmdm*{\SKV@tfor@a,\SKV@tfor@b} -The first of these (\ie, \fx{\SKV@tfor@a}) is equivalent to \latex kernel's \acmdm{\@tfor}, which loops over \aang{list} token-wise (character or control sequence token), but these two macros have been prompted by the following rationale. Note that \aang{list} is not a comma-separated list! In \fx{\SKV@tfor@b}, \aang{listcmd} is expanded once before the commencement of the loop. The two commands \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} are both robust. +The first of these (\ie, \fx{\SKV@tfor@a}) is equivalent to \latex kernel's \acmdm{\@tfor}, which loops over \ang{list} token-wise (character or control sequence token), but these two macros have been prompted by the following rationale. Note that \ang{list} is not a comma-separated list! In \fx{\SKV@tfor@b}, \ang{listcmd} is expanded once before the commencement of the loop. The two commands \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} are both robust. -The \acmdm{\@break@tfor} of the \latex kernel allows the user to break out of the \fx{\@tfor} loop but provides no mechanism for saving the remainder of the \aang{list} upon breaking the list. Secondly, I have had trouble breaking out of simple \fx{\@tfor} loops. For example, the following fails: \latex complains of ``extra \string\fi'', the reason being obvious. +The \acmdm{\@break@tfor} of the \latex kernel allows the user to break out of the \fx{\@tfor} loop but provides no mechanism for saving the remainder of the \ang{list} upon breaking the list. Secondly, I have had trouble breaking out of simple \fx{\@tfor} loops. For example, the following fails: \latex complains of ``extra \string\fi'', the reason being obvious. \begin{example} \def\one{One}\def\two{Two}\def\three{Three} \@tfor\x:=\one\two|makered(\@break@tfor)\three\do{\x} \end{example} -Thirdly, if the content of \fx{\x} above is sanitized/detokenized in the loop before being used in \aang{function} (or sanitized in the \aang{function} itself), then \fx{\@break@tfor} can't break the loop. Consider the following: +Thirdly, if the content of \fx{\x} above is sanitized/detokenized in the loop before being used in \ang{function} (or sanitized in the \ang{function} itself), then \fx{\@break@tfor} can't break the loop. Consider the following: \begin{example} \@tfor\x:=\one\two|makered(\@break@tfor)\three\do{% \edef\x{\detokenize\expandafter{\x}}% @@ -2286,7 +2268,7 @@ Thirdly, if the content of \fx{\x} above is sanitized/detokenized in the loop be \end{example} Clearly, \fx{\@break@tfor} can't break this loop. The macros \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} circumvent these problems. Additionally, they \begin{inenum}[(a)] -\item reorder the arguments such that \aang{list} comes before \aang{cmd}, and +\item reorder the arguments such that \ang{list} comes before \ang{cmd}, and \item remove the need for the usual delimitating tokens, thereby making their syntaxes mimic those of \acmd{\SKV@for@a} and \acmd{\SKV@for@b}. \end{inenum} @@ -2298,8 +2280,8 @@ In the following, the remainder of the list (namely, \fx{\three}) can be accesse \end{example} \begin{macro} -\SKV@tfor{|cang(list)}|cang(cmd){|cang(function)} -\SKV@tfor|redstar|cang(listcmd)|cang(cmd){|cang(function)} +\SKV@tfor{|vang(list)}|vang(cmd){|vang(function)} +\SKV@tfor|redstar|vang(listcmd)|vang(cmd){|vang(function)} \end{macro} \acmdm*{\SKV@tfor,\SKV@tfor*} These are equivalent to \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} respectively. @@ -2308,81 +2290,81 @@ These are equivalent to \fx{\SKV@tfor@a} and \fx{\SKV@tfor@b} respectively. \macrosubsection{Hooking to user-defined macros} \begin{macro} -\SKV@appto|redstar|redplus|redask|cang(cs){|cang(content)} +\SKV@appto|redstar|redplus|redask|vang(cs){|vang(content)} \end{macro} \acmdm*{\SKV@appto,\SKV@appto*,\SKV@appto*+,\SKV@appto*+?} -This appends \aang{content} to \aang{cs}. If \aang{cs} was previously undefined, it is initialized with \aang{content}. The star (\RedStar) sign directs \fx{\SKV@appto} to expand \aang{content} once before appending \aang{content} to \aang{cs}. The plus (\RedPlus) sign means that \aang{cs} is a control sequence name instead of a control sequence, while the question mark (\RedAsk) instructs \fx{\SKV@appto} to append \aang{content} to \aang{cs} globally (to escape local groups). This command is robust, but fragile arguments must be protected in expansion contexts. +This appends \ang{content} to \ang{cs}. If \ang{cs} was previously undefined, it is initialized with \ang{content}. The star (\RedStar) sign directs \fx{\SKV@appto} to expand \ang{content} once before appending \ang{content} to \ang{cs}. The plus (\RedPlus) sign means that \ang{cs} is a control sequence name instead of a control sequence, while the question mark (\RedAsk) instructs \fx{\SKV@appto} to append \ang{content} to \ang{cs} globally (to escape local groups). This command is robust, but fragile arguments must be protected in expansion contexts. -Except for the initialization of undefined \aang{cs}, \fx{\SKV@appto}\redask\ is equivalent to \latex's \acmdm{\g@addto@macro}. +Except for the initialization of undefined \ang{cs}, \fx{\SKV@appto}\redask\ is equivalent to \latex's \acmdm{\g@addto@macro}. The following non-generic, less powerful, forms of \fx{\SKV@appto} are also available, but they don't have the starred (\RedStar) variants: \begin{macro} -\apptomac|cang(cs){|cang(content)} - |tto \SKV@appto|cang(cs){|cang(content)} -\gapptomac|cang(cs){|cang(content)} - |tto \SKV@appto|redask|cang(cs){|cang(content)} -\csapptomac{|cang(name)}{|cang(content)} - |tto \SKV@appto|redplus{|cang(name)}{|cang(content)} -\csgapptomac{|cang(name)}{|cang(content)} - |tto \SKV@appto|redplus|redask{|cang(name)}{|cang(content)} +\apptomac|vang(cs){|vang(content)} + |tto \SKV@appto|vang(cs){|vang(content)} +\gapptomac|vang(cs){|vang(content)} + |tto \SKV@appto|redask|vang(cs){|vang(content)} +\csapptomac{|vang(name)}{|vang(content)} + |tto \SKV@appto|redplus{|vang(name)}{|vang(content)} +\csgapptomac{|vang(name)}{|vang(content)} + |tto \SKV@appto|redplus|redask{|vang(name)}{|vang(content)} \end{macro} \acmdm*{\apptomac,\gapptomac,\csapptomac,\csgapptomac} \bigskip \begin{macro} -\SKV@prepto|redstar|redplus|redask|cang(cs){|cang(content)} +\SKV@prepto|redstar|redplus|redask|vang(cs){|vang(content)} \end{macro} \acmdm*{\SKV@prepto,\SKV@prepto*,\SKV@prepto*+,\SKV@prepto*+?} -This prepends \aang{content} to \aang{cs}. If \aang{cs} was previously undefined, it is initialized with \aang{content}. The star (\RedStar) sign directs \fx{\SKV@prepto} to expand \aang{content} once before prepending it to \aang{cs}. The plus (\RedPlus) sign means that \aang{cs} is a control sequence name instead of a control sequence, while the question mark (\RedAsk) instructs \fx{\SKV@prepto} to prepend \aang{content} to \aang{cs} globally (to escape local groups). This command is robust, but fragile arguments must be protected in expansion contexts. +This prepends \ang{content} to \ang{cs}. If \ang{cs} was previously undefined, it is initialized with \ang{content}. The star (\RedStar) sign directs \fx{\SKV@prepto} to expand \ang{content} once before prepending it to \ang{cs}. The plus (\RedPlus) sign means that \ang{cs} is a control sequence name instead of a control sequence, while the question mark (\RedAsk) instructs \fx{\SKV@prepto} to prepend \ang{content} to \ang{cs} globally (to escape local groups). This command is robust, but fragile arguments must be protected in expansion contexts. Again, the following non-generic versions of \fx{\SKV@prepto} are available, but they don't have the starred (\RedStar) variants: \begin{macro} -\preptomac|cang(cs){|cang(content)} - |tto \SKV@prepto|cang(cs){|cang(content)} -\gpreptomac|cang(cs){|cang(content)} - |tto \SKV@prepto|redask|cang(cs){|cang(content)} -\cspreptomac{|cang(name)}{|cang(content)} - |tto \SKV@prepto|redplus{|cang(name)}{|cang(content)} -\csgpreptomac{|cang(name)}{|cang(content)} - |tto \SKV@prepto|redplus|redask{|cang(name)}{|cang(content)} +\preptomac|vang(cs){|vang(content)} + |tto \SKV@prepto|vang(cs){|vang(content)} +\gpreptomac|vang(cs){|vang(content)} + |tto \SKV@prepto|redask|vang(cs){|vang(content)} +\cspreptomac{|vang(name)}{|vang(content)} + |tto \SKV@prepto|redplus{|vang(name)}{|vang(content)} +\csgpreptomac{|vang(name)}{|vang(content)} + |tto \SKV@prepto|redplus|redask{|vang(name)}{|vang(content)} \end{macro} \acmdm*{\preptomac,\gpreptomac,\cspreptomac,\csgpreptomac} \bigskip \begin{macro} -\SKV@addtolist|redplus|redask[|cang(parser)]|cang(csa)|cang(csb) +\SKV@addtolist|redplus|redask|redleft[|vang(parser)]|vang(csa)|vang(csb) \end{macro} -\acmdm*{\SKV@addtolist,\SKV@addtolist+,\SKV@addtolist+?} -This adds the contents of the macro \aang{csb} to the list in the container \aang{csa}. The plus sign~(\RedPlus) means that \aang{csa} is a control sequence name, and the question mark~(\RedAsk) directs \fx{\SKV@addtolist} to add the contents of \aang{csb} to \aang{csa} globally (to escape local groups). The optional argument \aang{parser} is the list parser, ie, the separator of the instances in \aang{csa}. Its default value is ``,'' (comma). +\acmdm*{\SKV@addtolist,\SKV@addtolist+,\SKV@addtolist+?,\SKV@addtolist+?<} +This adds the contents of the macro \ang{csb} to the list in the container \ang{csa}. The plus sign~(\RedPlus) means that \ang{csa} is a control sequence name (instead of a control sequence); the question mark~(\RedAsk) directs \fx{\SKV@addtolist} to add the contents of \ang{csb} to \ang{csa} globally (to escape local groups); and the left angle (\RedLeft), if present, instructs \fx{\SKV@addtolist} to prepend the contents of \ang{csb} to the left of the contents of \ang{csa}, instead of appending to the right by default. The optional argument \ang{parser} is the list parser, ie, the separator of the instances in \ang{csa}. Its default value is ``,'' (comma). \macrosubsection{Package and document hooks} \begin{macro} -\SKV@AtPackageEnd{|cang(code)} -\SKV@AtClassEnd{|cang(code)} +\SKV@AtPackageEnd{|vang(code)} +\SKV@AtClassEnd{|vang(code)} \end{macro} \acmdm*{\SKV@AtPackageEnd,\SKV@AtClassEnd} These are the robust versions of the well-known \latex hooks \acmd{\AtEndOfPackage} and \acmd{\AtEndOfClass}. \begin{macro} -\SKV@BeforePackageEnd{|cang(code)} |label(befpkgend) -\SKV@BeforeClassEnd{|cang(code)} |label(befclsend) -\SKV@AfterPackageEnd{|cang(code)} -\SKV@AfterClassEnd{|cang(code)} +\SKV@BeforePackageEnd{|vang(code)} |label(befpkgend) +\SKV@BeforeClassEnd{|vang(code)} |label(befclsend) +\SKV@AfterPackageEnd{|vang(code)} +\SKV@AfterClassEnd{|vang(code)} \end{macro} \acmdm*{\SKV@BeforePackageEnd,\SKV@BeforeClassEnd,\SKV@AfterPackageEnd, \SKV@AfterClassEnd} The first two of these hook to just before \acmd{\AtEndOfPackage} or \acmd{\AtEndOfClass}; the third and fourth hook to just after \fx{\AtEndOfPackage} or \acmd{\AtEndOfClass}. They are all robust. These commands have been necessitated by some tasks in the \pkg{skeyval}, but may be useful in some other contexts. \begin{macro} -\SKV@AtDocumentStart{|cang(code)} +\SKV@AtDocumentStart{|vang(code)} \end{macro} \acmdm*{\SKV@AtDocumentStart} This is the robust version of the \latex hook \acmdm{\AtBeginDocument}. It can be used in expansion contexts without protection, but fragile arguments within it must be protected. \begin{macro} -\SKV@BeforeDocumentStart{|cang(code)}|label(beforedocstart) -\SKV@AfterDocumentStart{|cang(code)}|label(afterdocstart) +\SKV@BeforeDocumentStart{|vang(code)}|label(beforedocstart) +\SKV@AfterDocumentStart{|vang(code)}|label(afterdocstart) \end{macro} \acmdm*{\SKV@BeforeDocumentStart,\SKV@AfterDocumentStart} These provide two more document hooks. They are both robust. The command \fx{\SKV@BeforeDocumentStart} differs from \fx{\AtBeginDocument} in that the former is executed right at @@ -2393,28 +2375,28 @@ to write to the auxiliary file at the point \fx{\SKV@BeforeDocumentStart} is exe \fx{\SKV@AfterDocumentStart} differs from \fx{\AtBeginDocument} in the sense that the former is executed at the tag end of \acmd{\begin\{document\}}, after the execution of any \fx{\AtBeginDocument} code. Commands whose scope are restricted to the document's preamble with \acmd{\@onlypreamble} or \acmd{\SKV@onlypreamble} are no longer committable when \fx{\SKV@AfterDocumentStart} is being executed. \begin{macro} -\SKV@AtDocumentEnd{|cang(code)} -\SKV@BeforeLastPage{|cang(code)} -\SKV@AfterLastPage{|cang(code)} -\SKV@AfterDocumentEnd{|cang(code)} +\SKV@AtDocumentEnd{|vang(code)} +\SKV@BeforeLastPage{|vang(code)} +\SKV@AfterLastPage{|vang(code)} +\SKV@AfterDocumentEnd{|vang(code)} \end{macro} \acmdm*{\SKV@AtDocumentEnd,\SKV@BeforeLastPage,\SKV@AfterLastPage, \SKV@AfterDocumentEnd} The last three of these are wrappers developed based on the \pkgm{atveryend}, which provides a consistent mechanism for \acmd{\enddocument} methods. The macro -\fx{\SKV@AtDocumentEnd} is the robust equivalent of \acmd{\AtEndDocument}. The macro \fx{\SKV@BeforeLastPage} appends \aang{code} after the \acmd{\@enddocumenthook} but before the last \acmd{\clearpage}, and thus before the last shipout. The command \fx{\SKV@AfterLastPage} executes \aang{code} after the last \acmd{\clearpage} invoked within \acmd{\enddocument}, \ie, after the last shipout but before the main auxiliary file is closed. This is, \eg, the right instance to record the last document page in the auxiliary file. +\fx{\SKV@AtDocumentEnd} is the robust equivalent of \acmd{\AtEndDocument}. The macro \fx{\SKV@BeforeLastPage} appends \ang{code} after the \acmd{\@enddocumenthook} but before the last \acmd{\clearpage}, and thus before the last shipout. The command \fx{\SKV@AfterLastPage} executes \ang{code} after the last \acmd{\clearpage} invoked within \acmd{\enddocument}, \ie, after the last shipout but before the main auxiliary file is closed. This is, \eg, the right instance to record the last document page in the auxiliary file. -The command \fx{\SKV@AfterDocumentEnd} appends \aang{code} to the very end of the document, after all of the end-of-document codes have been executed (\ie, after the main .aux file of the current pass has been read and all \acmd{\AtEndDocument} codes have been effected, except font and label/reference warnings). +The command \fx{\SKV@AfterDocumentEnd} appends \ang{code} to the very end of the document, after all of the end-of-document codes have been executed (\ie, after the main .aux file of the current pass has been read and all \acmd{\AtEndDocument} codes have been effected, except font and label/reference warnings). \macrosection{Inputting files} \begin{macro} -\InputFileOnce[|cang(path)]{|cang(file)} -\InputFileOnce|redstar[|cang(path)]{|cang(file)} +\InputFileOnce[|vang(path)]{|vang(file)} +\InputFileOnce|redstar[|vang(path)]{|vang(file)} \end{macro} \acmdm*{\InputFileOnce} -The unstarred variant of this command inputs \aang{file} on \aang{path} but only once in one \latex pass. The argument \aang{path} is optional and its default value is the current/document's environment/directory. If \aang{file} had previously been read, a warning message is entered in the transcript log file (if the package option \fx{verbose} is selected) and the input is aborted. If \aang{file} doesn't exist on \aang{path}, as many as desired opportunities are given to the user to type in the correct filename on the screen, or enter ``no'' to continue with the \latex pass without inputting the file. +The unstarred variant of this command inputs \ang{file} on \ang{path} but only once in one \latex pass. The argument \ang{path} is optional and its default value is the current/document's environment/directory. If \ang{file} had previously been read, a warning message is entered in the transcript log file (if the package option \acmd{verbose} is selected) and the input is aborted. If \ang{file} doesn't exist on \ang{path}, as many as desired opportunities are given to the user to type in the correct filename on the screen, or enter ``no'' to continue with the \latex pass without inputting the file. -If the user wants to input \aang{file} more than once in one document, then he should use the starred (\RedStar) variant of \fx{\InputFileOnce}. +If the user wants to input \ang{file} more than once in one document, then he should use the starred (\RedStar) variant of \fx{\InputFileOnce}. \section{References} @@ -2426,14 +2408,14 @@ All the \texorlatex packages cited in this guide are available on \ctan. The following change history highlights significant changes that affect user utilities and interfaces; mutations of technical nature are not documented in this section. The numbers on the right-hand side of the following lists are section numbers; the star sign (\RedStar) means the subject features in the package but is not reflected anywhere in this user guide. \begin{versionhist} -\begin{version}{0.1}{2010/01/01} + \begin{version}{0.1}{2010/01/01} \item First public release under the name \pkg{keyreader}\xsecref \item Introduced complementary native-boolean keys \secref{sec:comp-boolkeys} - \item Provided machinery for reading multiple keys of all kinds from just one command \secref{sec:multiplekeys} -\end{version} + \item Provided machinery for reading multiple keys of all kinds from just one command \secref{sec:def-multiple-keys} + \end{version} \begin{version}{0.2}{2010/01/10} - \item Fixed a bug and optimized the \acmd{\define@keylist} loop \secref{sec:multiplekeys} + \item Fixed a bug and optimized the \acmd{\define@keylist} loop \secref{sec:def-multiple-keys} \end{version} \begin{version}{0.3}{2010/01/20} @@ -2509,7 +2491,7 @@ The following change history highlights significant changes that affect user uti \item Introduced ``user-value'' keys \secref{sec:uservaluekeys} \item Extended the pointer system of the \pkg{xkeyval} \secref{sec:pointer-mech} - \item Corrected a bug in the \pkg{xkeyval} which, if \acmd{\setkeys} are nested in a class file, gives non-empty \acmdm{\@unusedoptionlist} even if all the options of \acmd{\documentclass} have been used \xsecref + \item Corrected a bug in the \pkg{xkeyval} which, if \acmd{\setkeys} is nested in a class file, gives non-empty \acmdm{\@unusedoptionlist} even if all the options of \acmd{\documentclass} have been used \xsecref \end{version} \begin{version}{0.7}{2010/05/05} @@ -2517,8 +2499,15 @@ The following change history highlights significant changes that affect user uti in addition to \fx{true} and \fx{false} \secref*{sec:toggle-booleans}{sec:switches} \item Replaced the former \acmd{\NewIfs} with \acmd{\NewBooleans} and redefined \fx{\NewIfs} \secref{sec:biboolkeys} - - \item Introduced \acmd{\DeclareKeyCommand} \secref{sec:keycommand} + + \item Introduced \acmd{\DeclareKeyCommand} \xsecref + + \end{version} + + \begin{version}{0.71}{2010/05/06} + \item Corrected a bug in one of the internal conditional tests \xsecref + + \item Removed \fx{\DeclareKeyCommand} to create a separate \pkg{skeycommand} \xsecref \end{version} diff --git a/Master/texmf-dist/tex/latex/skeyval/skeyval.sty b/Master/texmf-dist/tex/latex/skeyval/skeyval.sty index 3178e0be5e4..78727c65eb1 100644 --- a/Master/texmf-dist/tex/latex/skeyval/skeyval.sty +++ b/Master/texmf-dist/tex/latex/skeyval/skeyval.sty @@ -1,6 +1,6 @@ %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% % % -% This is file 'skeyval.sty', version 0.7. % +% This is file 'skeyval.sty', version 0.71. % % % % This package and accompanying files may be distributed and/or % % modified under the conditions of the LaTeX Project Public License, % @@ -70,9 +70,10 @@ \SKV@setcode{096}{12}% ` \SKV@setcode{126}{13}% ~ \def\SKV@rcsid$#1: #2 #3 #4 #5${#4 v#3} -\ProvidesPackage{skeyval}% - [\SKV@rcsid $Id: skeyval.sty,v 0.7 2010/05/05 09:00:00 Ahmed Musa $ - Extensions to the xkeyval parser (AM)] +\ProvidesPackage{skeyval}[% + \SKV@rcsid $Id: skeyval.sty,v 0.71 2010/05/05 09:00:00 Ahmed Musa $ + Extensions to the xkeyval parser (AM) +] \NeedsTeXFormat{LaTeX2e}[1996/12/01] \ifnum0=0% \ifx\eTeXversion\SKV@undefined1\else\ifnum\eTeXversion<\tw@1\fi\fi @@ -85,16 +86,16 @@ \newcount\SKV@depth \protected\def\@nil{\@nil} \def\@nnil{\@nil} +\long\def\@firstofthree#1#2#3{#1} +\long\def\@secondofthree#1#2#3{#2} +\long\def\@thirdofthree#1#2#3{#3} \long\def\@gobblethree#1#2#3{} \long\def\SKV@car#1#2\@nil{#1} \long\def\SKV@cdr#1#2\@nil{#2} \long\def\SKV@carcube#1#2#3#4\@nil{#1#2#3} -\long\def\@firstofthree#1#2#3{#1} -\long\def\@secondofthree#1#2#3{#2} -\long\def\@thirdofthree#1#2#3{#3} -\def\SKV@threeafter{\expandafter\expandafter\expandafter} +\def\SKV@threexp{\expandafter\expandafter\expandafter} \def\SKV@aftercs#1#2{\expandafter#1\csname#2\endcsname} -\def\SKV@xaftercs#1#2{\SKV@threeafter#1\csname#2\endcsname} +\def\SKV@xaftercs#1#2{\SKV@threexp#1\csname#2\endcsname} \SKV@aftercs\let{SKV@1of1}\@firstofone \SKV@aftercs\let{SKV@1of2}\@firstoftwo \SKV@aftercs\let{SKV@2of2}\@secondoftwo @@ -112,11 +113,15 @@ \def\SKV@unifxcs#1#2{\begingroup\expandafter\endgroup\expandafter \SKV@unifx\expandafter#1\csname#2\endcsname} \def\SKV@ifdefined#1{\@nameuse{SKV@\ifdefined#11\else2\fi of2}} +\def\SKV@oifdefined#1{\@nameuse{SKV@\expandafter\SKV@ifdefined#1{1}{2}of2}} \def\SKV@unifdefined#1{\@nameuse{SKV@\SKV@ifdefined{#1}{2}{1}of2}} \def\SKV@ifcsname#1{\@nameuse{SKV@\ifcsname#1\endcsname1\else2\fi of2}} \def\SKV@unifcsname#1{\@nameuse{SKV@\SKV@ifcsname{#1}{2}{1}of2}} -\def\SKV@iftest#1#2{\@nameuse{SKV@\@nameuse{if#1}#21\else2\fi of2}} -\def\SKV@uniftest#1#2{\@nameuse{SKV@\SKV@iftest{#1}{#2}{2}{1}of2}} +\def\SKV@iftest#1#2{\@nameuse{if#1}#2\relax\expandafter\@firstoftwo + \else\expandafter\@secondoftwo\fi} +\def\SKV@uniftest#1#2{\SKV@iftest{#1}{#2}\@secondoftwo\@firstoftwo} +\protected\def\SKV@AtEndAfterPackageEnd#1{\AtEndOfPackage + {\SKV@AfterPackageEnd{#1}}} \begingroup \def\SKV@tempa{% \def\SKV@nodocerr{% @@ -152,27 +157,36 @@ \SKV@ifx\SKV@documentclass\SKV@undefined\SKV@nodocerr\relax } \SKV@tempa\endgroup +\def\SKV@notdefinable{% + \PackageError{skeyval}% + {Command '\@backslashchar\resvd@a' not definable, + \MessageBreak or name '\@backslashchar\@qend...' illegal}% + {Command '\@backslashchar\resvd@a' already defined.}% +} \def\SKV@ifdefinable#1{% - \begingroup\escapechar92\afterassignment\endgroup - \xdef\reserved@a{\expandafter\@gobble\string#1}% - \edef\resvd@a{\expandafter\SKV@car\string#1\@nil}% - \SKV@ifx\resvd@a\@backslashchar{}{% + \begingroup + \escapechar92\relax + \xdef\resvd@a{\expandafter\@gobble\string#1}% + \edef\resvd@b{\expandafter\SKV@car\string#1\@nil}% + \SKV@ifx\resvd@b\@backslashchar{}{% \PackageError{skeyval}{Backslash required}{Backslash required in argument of '\string\SKV@ifdefinable'.}% }% - \let\resvd@a\SKV@undefined \SKV@ifdefined#1{% - \SKV@ifx{#1}\relax\@firstofone\@notdefinable + \SKV@ifx{#1}\relax{\aftergroup\@firstofone}% + {\aftergroup\SKV@notdefinable}% }{% - \edef\reserved@b{\expandafter\SKV@carcube\reserved@a xxx\@nil}% - \SKV@ifx\reserved@b\@qend\@notdefinable - {\SKV@ifx\reserved@a\@qrelax\@notdefinable\@firstofone}% + \edef\resvd@b{\expandafter\SKV@carcube\resvd@a xxx\@nil}% + \SKV@ifx\resvd@b\@qend{\aftergroup\SKV@notdefinable}% + {\SKV@ifx\resvd@a\@qrelax{\aftergroup\SKV@notdefinable}% + {\aftergroup\@firstofone}}% }% + \endgroup } \def\SKV@csifdefinable#1{\begingroup\expandafter\endgroup \expandafter\SKV@ifdefinable\csname#1\endcsname} \newcommand*\@ifpackagecurrent[2]{% - \@nameuse{SKV@\SKV@iftest{num}{\SKV@threeafter\@parse@version + \@nameuse{SKV@\SKV@iftest{num}{\SKV@threexp\@parse@version \csname ver@#1.\@pkgextension\endcsname//00\@nil <\expandafter\@parse@version#2//00\@nil}{2}{1}of2}} \newcommand*\@ifpackagenotcurrent[2]{% @@ -186,10 +200,10 @@ \endinput }% }{\RequirePackage{xkeyval}[2008/08/13]} -\newcommand\SKV@ifdefinable@n[1]{% +\newcommand*\SKV@ifdefinable@n[1]{% \XKV@sp@deflist\SKV@tempa{#1}% \XKV@for@o\SKV@tempa\SKV@tempa{% - \edef\resvd@a{\SKV@threeafter\SKV@car + \edef\resvd@a{\SKV@threexp\SKV@car \expandafter\string\SKV@tempa\@nil}% \SKV@unifx\resvd@a\@backslashchar{}{% \PackageError{skeyval}{Backslash not allowed}{Backslash not @@ -251,8 +265,9 @@ }{}% \endgroup } -\define@boolkeys[KV]{skeyval@i}[SKV@]{st,pl,ask,sk,loc,uv}[true] -\setkeys[KV]{skeyval@i}{st,pl,ask,sk,loc,uv} +\define@boolkeys[KV]{skeyval@i}[SKV@]{tempsw,st,pl,ask,rt, + lt,sk,loc,uv}[true] +\setkeys[KV]{skeyval@i}{tempsw,st,pl,ask,rt,lt,sk,loc,uv} \define@boolkey+[KV]{skeyval}[SKV@]{verbose}[true]{}{% \SKV@inputerr{#1}{verbose}% } @@ -270,7 +285,7 @@ ifXKV@pl,ifXKV@knf,CurrentOption,ifSKV@sk}% \SKV@ifempty{#3}{\advance\XKV@depth\@ne}{}% \or - \def\SKV@ste{ifSKV@st,ifSKV@pl,ifSKV@ask}% + \def\SKV@ste{ifSKV@st,ifSKV@pl,ifSKV@ask,ifSKV@rt,ifSKV@lt}% \SKV@ifempty{#3}{\advance\SKV@depth\@ne}{}% \else \SKV@err{Unknown state identifier}% @@ -290,59 +305,53 @@ \SKV@def*\SKV@savstate{\SKV@state{1}{@\romannumeral\SKV@depth}{}} \SKV@def*\SKV@resstate{\SKV@state{1}{}{@\romannumeral\SKV@depth}} \def\XKV@srstate#1#2{\SKV@state{0}{#1}{#2}} -\def\SKV@scantoksa#1#2{% - \begingroup - \edef\SKV@tempa{\endgroup - \unexpanded{% - #1\everyeof{\noexpand}\endlinechar\m@ne - \makeatletter\scantokens - }{#2}% - \catcode`\noexpand\@=\the\catcode`\@\relax - \everyeof{\the\everyeof}% - \noexpand\endlinechar\the\endlinechar\relax +\SKV@def*\SKV@scantoksa{\SKV@testopt\SKV@sc@ntoksa{,}} +\SKV@def\SKV@sc@ntoksa[#1]#2{% + \SKV@for[#1]{#2}\SKV@resvda{% + \SKV@expnext\SKV@ensurescape\SKV@resvda + \begingroup + \let\@xp\expandafter + \edef\SKV@resvdb##1##2{##1{##2{\SKV@expox\SKV@resvda}}}% + \everyeof{\noexpand}\endlinechar\m@ne + \SKV@resvdb{\@xp\xdef\SKV@resvda}{\scantokens\@xp}% + \endgroup }% - \SKV@tempa } -\def\SKV@scantoksb#1{% - \begingroup - \everyeof{\noexpand}% - \endlinechar\m@ne - \xdef#1{\scantokens\expandafter{#1}}% - \endgroup +\SKV@def*\SKV@emptycmds{\SKV@savstate\SKV@testoptd\SKV@em@tycmds} +\SKV@def\SKV@em@tycmds[#1]#2{% + \ifSKV@st\let\glob@lrel@x\global\else\let\glob@lrel@x\relax\fi + \SKV@for[#1]{#2}\SKV@resvda{% + \SKV@expnext\SKV@ensurescape\SKV@resvda + \glob@lrel@x\expandafter\let\SKV@resvda\@empty + }% + \SKV@resstate } +\SKV@pdef*\SKV@csdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\def}} +\SKV@pdef*\SKV@csgdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\gdef}} +\SKV@pdef*\SKV@csedef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\edef}} +\SKV@pdef*\SKV@csxdef{\SKV@savstate\SKV@t@stoptb{\SKV@newcs\xdef}} \SKV@def*\SKV@newcs#1#2{% - \SKV@ifcsname{#2}{% - \SKV@csifx{#2}\relax{}{\def\reserved@a{#2}\@notdefinable}% - }{\SKV@aftercs{#1}{#2}}% -} -\SKV@def*\SKV@n@wcs#1#2{% + \ifSKV@st\let\l@ngrel@x\relax\else\let\l@ngrel@x\long\fi \ifSKV@pl - \let\SKV@next\SKV@newcs + \let\SKV@next\SKV@n@wcs \else - \let\SKV@next\SKV@aftercs + \def\SKV@next{\l@ngrel@x\SKV@aftercs}% \fi \SKV@resstate\SKV@next#1{#2}% } -\SKV@pdef*\SKV@csdef{\SKV@savstate\SKV@t@st@pta\SKV@@csdef} -\SKV@def*\SKV@@csdef#1{\SKV@n@wcs\def{#1}} -\SKV@pdef*\SKV@csgdef{\SKV@savstate\SKV@t@st@pta\SKV@@csgdef} -\SKV@def*\SKV@@csgdef#1{\SKV@n@wcs\gdef{#1}} -\SKV@pdef*\SKV@csedef{\SKV@savstate\SKV@t@st@pta\SKV@@csedef} -\SKV@def*\SKV@@csedef#1{\SKV@n@wcs\edef{#1}} -\SKV@pdef*\SKV@csxdef{\SKV@savstate\SKV@t@st@pta\SKV@@csxdef} -\SKV@def*\SKV@@csxdef#1{\SKV@n@wcs\xdef{#1}} +\SKV@def*\SKV@n@wcs#1#2{% + \SKV@ifcsname{#2}% + {\SKV@csifx{#2}\relax{}{\def\resvd@a{#2}\SKV@notdefinable}}% + {\l@ngrel@x\SKV@aftercs{#1}{#2}}% +} \SKV@def*\SKV@csuse#1{\SKV@ifcsname{#1}{\@nameuse{#1}}{}} \SKV@pdef\SKV@expargs#1#2#3#4\@nil{% \begingroup \protected@edef\SKV@tempa{\endgroup - \ifcase#1\relax - \unexpanded{#2}{#3}% - \or - \unexpanded{#2#3}{#4}% - \or - \unexpanded{#2}{#3}{#4}% - \or - \unexpanded{#2}#3\unexpanded{#4}% + \ifcase#1\relax\unexpanded{#2}{#3}% + \or\unexpanded{#2#3}{#4}% + \or\unexpanded{#2}{#3}{#4}% + \or\unexpanded{#2}#3\unexpanded{#4}% \else \SKV@err{Unknown expansion type '\string#1' for \string\SKV@expargs}{I expected your first @@ -377,21 +386,19 @@ \SKV@def*\SKV@ifnextch@r{% \ifx\@temptoks\SKV@nxc\let\SKV@nxb\SKV@nxa\fi\SKV@nxb } -\SKV@pdef\SKV@ifstar#1#2{% - \SKV@ifnextchar*{\begingroup - \def\SKV@tempa*{\endgroup #1}\SKV@tempa}{#2}% -} -\SKV@pdef\SKV@ifplus#1#2{% - \SKV@ifnextchar+{\begingroup - \def\SKV@tempa+{\endgroup #1}\SKV@tempa}{#2}% -} -\SKV@pdef\SKV@ifask#1#2{% - \SKV@ifnextchar?{\begingroup - \def\SKV@tempa?{\endgroup #1}\SKV@tempa}{#2}% -} -\SKV@pdef\SKV@ifbrack#1#2{\SKV@ifnextchar[{#1}{#2}} -\SKV@pdef\SKV@ifparen#1#2{\SKV@ifnextchar({#1}{#2}} -\SKV@pdef*\SKV@testopt#1#2{\SKV@ifbrack{#1}{#1[{#2}]}} +\SKV@pdef\SKV@ifchar#1#2#3{% + \SKV@ifnextchar#1{\begingroup + \def\SKV@tempa#1{\endgroup#2}\SKV@tempa}{#3}% +} +\SKV@pdef*\SKV@ifstar{\SKV@ifchar{*}} +\SKV@pdef*\SKV@ifplus{\SKV@ifchar{+}} +\SKV@pdef*\SKV@ifask{\SKV@ifchar{?}} +\SKV@pdef*\SKV@ifright{\SKV@ifchar{>}} +\SKV@pdef*\SKV@ifleft{\SKV@ifchar{<}} +\SKV@pdef*\SKV@if@brack#1#2{\SKV@ifnextchar[{#1}{#2}} +\SKV@pdef*\SKV@if@paren#1#2{\SKV@ifnextchar({#1}{#2}} +\SKV@pdef*\SKV@if@left#1#2{\SKV@ifnextchar<{#1}{#2}} +\SKV@pdef*\SKV@testopt#1#2{\SKV@if@brack{#1}{#1[{#2}]}} \SKV@pdef*\SKV@testopta#1{\SKV@t@stopta{\SKV@t@st@pta{#1}}} \SKV@pdef*\SKV@t@stopta#1{\SKV@ifstar{\SKV@sttrue#1}{\SKV@stfalse#1}} \SKV@pdef*\SKV@t@st@pta#1{\SKV@ifplus{\SKV@pltrue#1}{\SKV@plfalse#1}} @@ -403,27 +410,49 @@ \SKV@pdef*\SKV@testopte#1{\SKV@testoptb{\SKV@testopt#1{,}}} \SKV@pdef*\SKV@t@stopte#1{\SKV@t@stoptb{\SKV@testopt#1{,}}} \SKV@pdef*\SKV@testoptf#1{\SKV@testoptc{\SKV@testopt#1{,}}} +\SKV@pdef*\SKV@testoptg#1{\SKV@ifright{\SKV@rttrue#1}{\SKV@rtfalse#1}} +\SKV@pdef*\SKV@t@stoptg#1{\SKV@ifleft{\SKV@lttrue#1}{\SKV@ltfalse#1}} +\SKV@pdef*\SKV@testopth#1#2{\SKV@if@left{#1}{#1<{#2}>}} +\SKV@pdef*\SKV@testoptp#1#2{\SKV@if@paren{#1}{#1({#2})}} \SKV@def*\SKV@Test@pt#1{\@nameuse{SKV@\SKV@ifempty{#1}{1}{2}of2}} -\SKV@def*\SKV@TestOpt#1#2#3{\SKV@@TestOpt#1&[&{#2#1}{#2[{#3}]{#1}}} -\SKV@def*\SKV@@TestOpt#1[#2#{\SKV@Test@pt{#1#2}} -\SKV@def*\SKV@IfStar#1#2#3{\SKV@@IfStar#1&*&{#2}{#3{#1}}} -\SKV@def*\SKV@@IfStar#1*#2#{\SKV@Test@pt{#1#2}} -\SKV@def*\SKV@IfPlus#1#2#3{\SKV@@IfPlus#1&+&{#2}{#3{#1}}} -\SKV@def*\SKV@@IfPlus#1+#2#{\SKV@Test@pt{#1#2}} -\SKV@def*\SKV@IfAsk#1#2#3{\SKV@@IfAsk#1&?&{#2}{#3{#1}}} -\SKV@def*\SKV@@IfAsk#1?#2#{\SKV@Test@pt{#1#2}} +\SKV@def*\SKV@IfBrack#1#2#3{\SKV@IfBr@ck#1&[&{#2}{#3{#1}}} +\SKV@def*\SKV@IfBr@ck#1[#2#{\SKV@Test@pt{#1#2}} +\SKV@def*\SKV@TestOpt#1#2#3{\SKV@IfBr@ck#1&[&{#2#1}{#2[{#3}]{#1}}} +\SKV@def*\SKV@IfStar#1#2#3{\SKV@IfSt@r#1&*&{#2}{#3{#1}}} +\SKV@def*\SKV@IfSt@r#1*#2#{\SKV@Test@pt{#1#2}} +\SKV@def*\SKV@IfPlus#1#2#3{\SKV@IfPl@s#1&+&{#2}{#3{#1}}} +\SKV@def*\SKV@IfPl@s#1+#2#{\SKV@Test@pt{#1#2}} +\SKV@def*\SKV@IfAsk#1#2#3{\SKV@IfA@k#1&?&{#2}{#3{#1}}} +\SKV@def*\SKV@IfA@k#1?#2#{\SKV@Test@pt{#1#2}} +\SKV@def*\SKV@csalloc#1{\@nameuse{new#1\SKV@aftercs}} +\SKV@pdef*\csnewif{\SKV@csalloc{if}} +\SKV@pdef*\csnewtoks{\SKV@csalloc{toks}} +\SKV@pdef*\csnewcount{\SKV@csalloc{count}} +\SKV@pdef*\csnewdimen{\SKV@csalloc{dimen}} +\SKV@pdef*\csnewbox{\SKV@csalloc{box}} +\SKV@pdef*\csnewwrite{\SKV@csalloc{write}} +\SKV@pdef*\csnewread{\SKV@csalloc{read}} \SKV@pdef*\NewWrites{\SKV@testopt\SKV@NewWrites{}} -\SKV@pdef*\SKV@NewWrites[#1]#2{% +\SKV@def*\SKV@NewWrites[#1]#2{% + \SKV@for[,]{#2}\SKV@tempa{% + \SKV@expnext\SKV@ensurenoscape\SKV@tempa + \SKV@csifdefinable{#1\SKV@tempa}{% + \csnewwrite{#1\SKV@tempa}% + }% + }% +} +\SKV@pdef*\NewReads{\SKV@testopt\SKV@NewReads{}} +\SKV@def*\SKV@NewReads[#1]#2{% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa \SKV@csifdefinable{#1\SKV@tempa}{% - \@nameuse{newwrite\SKV@aftercs}{#1\SKV@tempa}% + \csnewread{#1\SKV@tempa}% }% }% } \SKV@pdef*\NewIfs{\SKV@testopt\SKV@NewIfs{}} -\SKV@pdef*\SKV@NewIfs[#1]#2{\SKV@testopt{\SKV@New@Ifs[#1]{#2}}{false}} -\SKV@pdef*\SKV@New@Ifs[#1]#2[#3]{% +\SKV@def*\SKV@NewIfs[#1]#2{\SKV@testopt{\SKV@N@wIfs[#1]{#2}}{false}} +\SKV@def*\SKV@N@wIfs[#1]#2[#3]{% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa \begingroup @@ -434,12 +463,12 @@ {\SKV@oifstrequal{\SKV@tempa}{switch}{\SKV@swnameerr{switch}}% {}}}}}\endgroup \SKV@csifdefinable{if#1\SKV@tempa}{% - \SKV@aftercs\SKV@New@If@{if#1\SKV@tempa}% + \SKV@aftercs\SKV@N@wIf@{if#1\SKV@tempa}% \@nameuse{#1\SKV@tempa#3}% }% }% } -\def\SKV@New@If@#1{% +\SKV@def*\SKV@N@wIf@#1{% \@tempcnta\escapechar\escapechar\m@ne \let#1\iffalse \SKV@If#1\iftrue @@ -454,15 +483,10 @@ \SKV@aftercs\def{\expandafter\@gobbletwo\string#1% \expandafter\@gobbletwo\string#2}{\let#1#2}% } -\SKV@pdef*\csnewif{\SKV@aftercs\newif} -\SKV@pdef*\csnewtoks{\SKV@aftercs\newtoks} -\SKV@pdef*\csnewcount{\SKV@aftercs\newcount} -\SKV@pdef*\csnewdimen{\SKV@aftercs\newdimen} -\SKV@pdef*\csnewbox{\SKV@aftercs\newbox} \SKV@pdef*\NewBooleans{\SKV@testopt\SKV@NewBooleans{}} -\SKV@pdef*\SKV@NewBooleans[#1]#2{% - \SKV@testopt{\SKV@New@Booleans[#1]{#2}}{false}} -\SKV@pdef*\SKV@New@Booleans[#1]#2[#3]{% +\SKV@def*\SKV@NewBooleans[#1]#2{% + \SKV@testopt{\SKV@N@wBooleans[#1]{#2}}{false}} +\SKV@def*\SKV@N@wBooleans[#1]#2[#3]{% \SKV@getswstate\NewBooleans{#3}% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa @@ -480,8 +504,8 @@ }% } \SKV@pdef*\NewTogs{\SKV@testopt\SKV@NewTogs{}} -\SKV@pdef*\SKV@NewTogs[#1]#2{\SKV@testopt{\SKV@NewT@gs[#1]{#2}}{false}} -\SKV@pdef*\SKV@NewT@gs[#1]#2[#3]{% +\SKV@def*\SKV@NewTogs[#1]#2{\SKV@testopt{\SKV@NewT@gs[#1]{#2}}{false}} +\SKV@def*\SKV@NewT@gs[#1]#2[#3]{% \SKV@getswstate\NewTogs{#3}% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa @@ -491,7 +515,7 @@ }% } \SKV@pdef*\NewToks{\SKV@testopt\SKV@NewToks{}} -\SKV@pdef*\SKV@NewToks[#1]#2{% +\SKV@def*\SKV@NewToks[#1]#2{% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa \SKV@csifdefinable{#1\SKV@tempa}{% @@ -500,7 +524,7 @@ }% } \SKV@pdef*\NewCounts{\SKV@testopt\SKV@NewCounts{}} -\SKV@pdef*\SKV@NewCounts[#1]#2{% +\SKV@def*\SKV@NewCounts[#1]#2{% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa \SKV@csifdefinable{#1\SKV@tempa}{% @@ -509,7 +533,7 @@ }% } \SKV@pdef*\NewDimens{\SKV@testopt\SKV@NewDimens{}} -\SKV@pdef*\SKV@NewDimens[#1]#2{% +\SKV@def*\SKV@NewDimens[#1]#2{% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa \SKV@csifdefinable{#1\SKV@tempa}{% @@ -518,7 +542,7 @@ }% } \SKV@pdef*\NewBoxes{\SKV@testopt\SKV@NewBoxes{}} -\SKV@pdef*\SKV@NewBoxes[#1]#2{% +\SKV@def*\SKV@NewBoxes[#1]#2{% \SKV@for[,]{#2}\SKV@tempa{% \SKV@expnext\SKV@ensurenoscape\SKV@tempa \SKV@csifdefinable{#1\SKV@tempa}{% @@ -533,7 +557,7 @@ \SKV@ifblank{#2}{% \SKV@err{Arguments of '\string\SKV@expnext' can't be empty}\@ehc }{% - \SKV@iftest{}{@\detokenize\expandafter{\SKV@cdr#1\@nil}@}{% + \SKV@iftest{cat}{$\detokenize\expandafter{\SKV@cdr#1\@nil}$}{% \expandafter#1\expandafter{#2}% }{% \SKV@err{Invalid arguments '\string#1' for @@ -542,8 +566,8 @@ }% }% } -\SKV@pdef*\SKV@ifnew{\SKV@savstate\SKV@t@stopte\SKV@@ifnew} -\SKV@def*\SKV@@ifnew[#1]#2{% +\SKV@pdef*\SKV@ifnewcmd{\SKV@savstate\SKV@t@stopte\SKV@ifn@wcmd} +\SKV@def*\SKV@ifn@wcmd[#1]#2{% \ifSKV@st \ifSKV@pl \def\SKV@ndl{\SKV@for*[#1]#2}% @@ -559,9 +583,8 @@ \fi \SKV@ndl\SKV@ndl{% \ifSKV@pl - \SKV@despace\SKV@ndl - \SKV@expargs{1}\SKV@aftercs - \SKV@ifdefinable{\SKV@ndl}\@nil\relax + \SKV@despacectt\SKV@ndl + \SKV@csifdefinable\SKV@ndl\relax \else \expandafter\SKV@ifdefinable\SKV@ndl\relax \fi @@ -570,7 +593,8 @@ } \let\SKV@no\z@ \SKV@pdef*\SKV@aftergroup{% - \SKV@ifstar{\SKV@aft@rgroup\@firstofone}{\SKV@aft@rgroup\unexpanded}% + \SKV@ifstar{\SKV@aft@rgroup\@firstofone}% + {\SKV@aft@rgroup\unexpanded}% } \SKV@def\SKV@aft@rgroup#1#2{% \edef\SKV@no{\the\numexpr\SKV@no+1}% @@ -606,19 +630,21 @@ \SKV@def*\SKV@@sp@d@f#1{\romannumeral-`\q#1} \SKV@def*\SKV@expox#1{\unexpanded\expandafter{#1}} \SKV@def*\SKV@expcsox#1{\SKV@aftercs\SKV@expox{#1}} -\SKV@def*\SKV@exptx#1{\unexpanded\SKV@threeafter{#1}} +\SKV@def*\SKV@exptx#1{\unexpanded\SKV@threexp{#1}} \SKV@def*\SKV@expcstx#1{\SKV@aftercs\SKV@exptx{#1}} +\SKV@def\SKV@noexpcs#1{\unexpanded\expandafter{\csname#1\endcsname}} \SKV@pdef*\SKV@undef#1{\let#1\SKV@undefined} -\SKV@pdef\SKV@gundef{\global\SKV@undef} +\SKV@pdef*\SKV@gundef{\global\SKV@undef} \SKV@pdef*\SKV@csundef#1{\SKV@aftercs\SKV@undef{#1}} \SKV@pdef*\SKV@csgundef{\global\SKV@csundef} -\SKV@pdef*\SKV@undeflist/#1/#2/{% - \SKV@ifempty{#1}% - {\let\glob@lrel@x\relax}{\let\glob@lrel@x\global}% - \XKV@for@n{#2}\SKV@resvd{% +\SKV@def*\SKV@undeflist{\SKV@savstate\SKV@t@st@p@a\SKV@und@flist} +\SKV@def*\SKV@und@flist#1{% + \ifSKV@ask\let\glob@lrel@x\global\else\let\glob@lrel@x\relax\fi + \XKV@for@n{#1}\SKV@resvd{% \SKV@expnext\SKV@ensurescape\SKV@resvd \glob@lrel@x\expandafter\SKV@undef\SKV@resvd }% + \SKV@resstate } \SKV@pdef*\SKV@Undef{\SKV@savstate\SKV@testopte\SKV@@Undef} \SKV@def*\SKV@@Undef[#1]#2{% @@ -637,9 +663,9 @@ \fi \SKV@ndl\SKV@ndl{% \ifSKV@pl - \SKV@despace\SKV@ndl + \SKV@despacectt\SKV@ndl \ifSKV@ask\expandafter\global\fi - \SKV@threeafter\let + \SKV@threexp\let \expandafter\csname\SKV@ndl\endcsname\SKV@undefined \else \ifSKV@ask\expandafter\global\fi @@ -659,22 +685,28 @@ \relax{2}{1}of2}}\@secondoftwo } \SKV@def*\SKV@ifcsundef#1{\@nameuse{SKV@\SKV@ifcsdef{#1}{2}{1}of2}} -\SKV@pdef*\SKV@AtEndAfterPackageEnd#1{% - \AtEndOfPackage{\SKV@AfterPackageEnd{#1}}} +\SKV@def*\SKV@ifonedef#1{% + \def\SKV@resvda{#1}\SKV@tempswtrue + \XKV@whilist\SKV@resvda\SKV@resvdb\ifSKV@tempsw\fi{% + \SKV@oifdefined\SKV@resvdb\SKV@tempswfalse\SKV@tempswtrue + }% + \@nameuse{SKV@\ifSKV@tempsw2\else1\fi of2}% +} \SKV@def\DeclarePackageCommand#1#2{% \SKV@ensurescape{#2}% \SKV@ifdef#2{% \edef\resvd@a{\expandafter\@gobble\string#2}% \SKV@cslet{Saved\resvd@a}#2% - \edef\resvd@a##1{% - \SKV@AtEndAfterPackageEnd{##1Saved\resvd@a\noexpand\endcsname}}% + \edef\resvd@a##1{\SKV@AtEndAfterPackageEnd% + {##1Saved\resvd@a\noexpand\endcsname}}% \resvd@a{\expandafter\let\expandafter#2\csname}% \SKV@undef\resvd@a }{\SKV@AtEndAfterPackageEnd{\SKV@Undef?#2}}% #1#2% } -\SKV@pdef*\SKV@providedef{\@star@or@long\SKV@@providedef} -\SKV@def\SKV@@providedef#1{% +\SKV@pdef*\SKV@providedef{\@star@or@long\SKV@pr@videdef} +\SKV@def\SKV@pr@videdef#1{% + \SKV@ensurescape{#1}% \edef\SKV@prov@d{\expandafter\@gobble\string#1}% \SKV@aftercs\let{SKV@test@\SKV@prov@d}\SKV@undefined \SKV@ifdef#1{% @@ -690,8 +722,9 @@ \l@ngrel@x\def#1% }% } -\SKV@pdef*\SKV@providerobustdef{\@star@or@long\SKV@@providerobustdef} -\SKV@def\SKV@@providerobustdef#1{% +\SKV@pdef*\SKV@providerobustdef{\@star@or@long\SKV@pr@viderobustdef} +\SKV@def\SKV@pr@viderobustdef#1{% + \SKV@ensurescape{#1}% \edef\SKV@prov@d{\expandafter\@gobble\string#1}% \SKV@aftercs\let{SKV@test@\SKV@prov@d}\SKV@undefined \SKV@ifdef#1{% @@ -708,6 +741,7 @@ }% } \SKV@def\TestProvidedCommand#1{% + \SKV@ensurescape{#1}% \begingroup \SKV@ifmacro#1{% \edef\SKV@resvd@a{\expandafter\@gobble\string#1}% @@ -721,30 +755,25 @@ } \SKV@pdef*\SKV@newdef{\SKV@def} \SKV@providerobustdef*\newdef{\SKV@def} +\SKV@providerobustdef*\redef{\SKV@redef} \SKV@pdef*\SKV@robustdef{\SKV@pdef} \SKV@providerobustdef*\robustdef{\SKV@pdef} +\SKV@providerobustdef*\robustredef{\SKV@predef} \SKV@providerobustdef*\providedef{\SKV@providedef} \SKV@providerobustdef*\providerobustdef{\SKV@providerobustdef} +\SKV@providerobustdef*\aftercommission{\SKV@afterassignment} +\SKV@providerobustdef*\aftercoterie{\SKV@aftergroup} \SKV@def\SKV@ifmacro#1{% \begingroup - \edef\SKV@ifmacro##1{\def##1####1\detokenize{macro}:####2&}% - \SKV@ifmacro\@ifmacro{\expandafter\aftergroup + \edef\SKV@tempa##1{\def##1####1\detokenize{macro}:####2&}% + \SKV@tempa\SKV@tempa{\expandafter\aftergroup \csname SKV@\SKV@ifblank{##2}{2}{1}of2\endcsname}% - \edef\SKV@ifmacro##1{##1\detokenize{macro}:&}% - \SKV@ifmacro{\expandafter\@ifmacro\meaning#1}% + \edef\SKV@tempb##1{##1\detokenize{macro}:&}% + \SKV@tempb{\expandafter\SKV@tempa\meaning#1}% \endgroup } +\SKV@def\SKV@csifmacro{\SKV@aftercs\SKV@ifmacro} \SKV@def\SKV@ifnotmacro#1{\SKV@ifmacro{#1}\@secondoftwo\@firstoftwo} -\SKV@def\SKV@ifparamacro#1{% - \begingroup - \edef\SKV@ifparamacro##1{% - \def##1####1\detokenize{macro}:####2->####3&}% - \SKV@ifparamacro\@ifparam{\expandafter\aftergroup - \csname SKV@\SKV@ifblank{##2}{2}{1}of2\endcsname}% - \edef\SKV@ifparamacro##1{##1\detokenize{macro}:->&}% - \SKV@ifparamacro{\expandafter\@ifparam\meaning#1}% - \endgroup -} \SKV@def*\SKV@ifrelax#1{% \SKV@ensurescape{#1}% \SKV@ifdefined{#1}% @@ -767,12 +796,14 @@ {\@nameuse{SKV@\expandafter\SKV@ifx\csname#1\endcsname \relax{2}{1}of3}}\@thirdofthree } -\SKV@def*\SKV@despace#1{% +\SKV@def*\SKV@despacectt#1{% \SKV@ensurescape{#1}% \SKV@expnext\SKV@sp@def{#1}#1% } \SKV@def\SKV@detokdespace#1{% - \edef#1{\detokenize\expandafter{#1}}\SKV@despace#1} + \edef#1{\detokenize\expandafter{#1}}% + \SKV@despacectt#1% +} \SKV@def\SKV@ifblank#1{\SKV@ifbl@nk#1&&\@secondoftwo\@firstoftwo:} \SKV@def\SKV@ifbl@nk#1#2#4#5:{#4} \SKV@def\SKV@ifnotblank#1{\SKV@ifbl@nk#1&&\@firstoftwo\@secondoftwo:} @@ -786,7 +817,8 @@ \csname SKV@\SKV@ifx\resvd@a\resvd@b{1}{2}of2\endcsname \endgroup } -\SKV@def\SKV@ifstrnotequal#1#2{\SKV@ifstrequal{#1}{#2}\@secondoftwo\@firstoftwo} +\SKV@def\SKV@ifstrnotequal#1#2{% + \SKV@ifstrequal{#1}{#2}\@secondoftwo\@firstoftwo} \SKV@def\SKV@oifstrequal#1#2{% \@expandtwoargs\SKV@ifstrequal{\SKV@expox{#1}}{\SKV@expox{#2}}} \SKV@def\SKV@xifstrequal#1#2{\@expandtwoargs\SKV@ifstrequal{#1}{#2}} @@ -814,26 +846,27 @@ \fi \endgroup } -\SKV@pdef*\SKV@appto{\SKV@savstate\SKV@testoptb{\SKV@apprepto{appto}}} -\SKV@pdef*\SKV@prepto{\SKV@savstate\SKV@testoptb{\SKV@apprepto{prepto}}} +\SKV@pdef*\SKV@appto{\SKV@savstate\SKV@testoptb{\SKV@apprepto{>}}} +\SKV@pdef*\SKV@prepto{\SKV@savstate\SKV@testoptb{\SKV@apprepto{<}}} \SKV@def\SKV@apprepto#1#2#3{% - \def\tempa##1{\def\tempb####1{\SKV@aftercs##1{####1}}}% - \ifSKV@st\let\tempc\SKV@expox\else\let\tempc\unexpanded\fi + \def\SKV@tapa##1{\def\SKV@tapb####1{\SKV@aftercs##1{####1}}}% + \ifSKV@st\let\SKV@tapc\SKV@expox\else\let\SKV@tapc\unexpanded\fi \ifSKV@pl - \let\@ifundef\SKV@ifcsundef\let\tempd\SKV@expcsox - \ifSKV@ask\tempa\xdef\else\tempa\edef\fi + \let\@ifundef\SKV@ifcsundef\let\SKV@tapd\SKV@expcsox + \ifSKV@ask\SKV@tapa\xdef\else\SKV@tapa\edef\fi \else - \let\@ifundef\SKV@ifundef\let\tempd\SKV@expox - \ifSKV@ask\def\tempb##1{\xdef##1}\else\def\tempb##1{\edef##1}\fi + \let\@ifundef\SKV@ifundef\let\SKV@tapd\SKV@expox + \ifSKV@ask\def\SKV@tapb##1{\xdef##1}\else + \def\SKV@tapb##1{\edef##1}\fi \fi \@ifundef{#2}{% - \tempb{#2}{\tempc{#3}}% + \SKV@tapb{#2}{\SKV@tapc{#3}}% }{% - \SKV@ifstrequal{#1}{appto}% - {\tempb{#2}{\tempd{#2}\tempc{#3}}}% - {\tempb{#2}{\tempc{#3}\tempd{#2}}}% + \SKV@ifstrequal{#1}{>}% + {\SKV@tapb{#2}{\SKV@tapd{#2}\SKV@tapc{#3}}}% + {\SKV@tapb{#2}{\SKV@tapc{#3}\SKV@tapd{#2}}}% }% - \SKV@undeflist//\tempa,\tempb,\tempc,\tempd/% + \SKV@undeflist?{\SKV@tapa,\SKV@tapb,\SKV@tapc,\SKV@tapd}% \SKV@resstate } \SKV@pdef\apptomac#1#2{% @@ -850,27 +883,33 @@ \SKV@pdef*\gpreptomac{\global\preptomac} \SKV@pdef*\cspreptomac{\SKV@aftercs\preptomac} \SKV@pdef*\csgpreptomac{\global\cspreptomac} -\SKV@pdef*\SKV@addtolist{\SKV@savstate\SKV@testoptf\SKV@@addtolist} -\SKV@def*\SKV@@addtolist[#1]{% +\SKV@pdef*\SKV@addtolist{\SKV@savstate\SKV@testoptc{% + \SKV@t@stoptg{\SKV@testopt\SKV@addt@list{,}}}} +\SKV@def*\SKV@addt@list[#1]{% \def\parser{#1}% - \ifSKV@ask - \let\glob@l@or@def\xdef - \else - \let\glob@l@or@def\edef - \fi + \ifSKV@ask\let\glob@l@def\xdef\else\let\glob@l@def\edef\fi \ifSKV@pl - \def\SKV@next##1{\SKV@aftercs\SKV@addt@list{##1}}% + \def\SKV@next##1{\SKV@aftercs\SKV@addt@l@st{##1}}% \else - \let\SKV@next\SKV@addt@list + \let\SKV@next\SKV@addt@l@st \fi - \SKV@resstate\SKV@next + \SKV@next } -\SKV@def\SKV@addt@list#1#2{% +\SKV@def\SKV@addt@l@st#1#2{% \SKV@ifundef{#1}{% - \glob@l@or@def#1{\SKV@expox{#2}}% + \glob@l@def#1{\SKV@expox{#2}}% }{% - \glob@l@or@def#1{\SKV@expox{#1}\parser\SKV@expox{#2}}% + \SKV@ifx#1\@empty{% + \glob@l@def#1{\SKV@expox{#2}}% + }{% + \ifSKV@lt + \glob@l@def#1{\SKV@expox{#2}\parser\SKV@expox{#1}}% + \else + \glob@l@def#1{\SKV@expox{#1}\parser\SKV@expox{#2}}% + \fi + }% }% + \SKV@resstate } \SKV@pdef*\SKV@relax#1{\let#1\relax} \SKV@pdef*\SKV@grelax{\global\SKV@relax} @@ -1004,8 +1043,7 @@ } \SKV@pdef*\SKV@for@b{\SKV@testopt\SKV@@for@b{,}} \SKV@def\SKV@@for@b[#1]#2{% - \SKV@CommandGenParser{#1}% - \SKV@expnext\SKV@for@a{#2}% + \SKV@CommandGenParser{#1}\SKV@expnext\SKV@for@a{#2}% } \SKV@pdef*\SKV@tfor{\SKV@ifstar\SKV@tfor@b\SKV@tfor@a} \SKV@pdef*\SKV@tfor@a#1#2#3{% @@ -1063,7 +1101,7 @@ } \SKV@def*\SKV@CommandKeyParser#1{% \long\def\SKV@define@keylist##1{% - \SKV@undeflist/g/\skif,\skifx,\skifcase,\skor,\skelse,\skfi/% + \SKV@undeflist?{\skif,\skifx,\skifcase,\skor,\skelse,\skfi}% \ifswitchon{SKV@st}{% \long\edef\@keylist{\SKV@expox{##1}}% }{% @@ -1098,8 +1136,8 @@ \SKV@err{Erroneous value '#1' for key '#2'}% {Please use the correct value for key '#2'.}% } -\SKV@def*\SKV@despacelist{\SKV@savstate\SKV@testoptd\SKV@despac@list} -\SKV@def*\SKV@despac@list[#1]#2{% +\SKV@def*\SKV@despacelist{\SKV@savstate\SKV@testoptd\SKV@desp@celist} +\SKV@def*\SKV@desp@celist[#1]#2{% \begingroup \let\SKV@resa\@empty \ifSKV@st @@ -1108,7 +1146,7 @@ \def\SKV@dsl{\SKV@for[#1]{#2}}% \fi \SKV@dsl\SKV@dsl{% - \SKV@despace\SKV@dsl + \SKV@despacectt\SKV@dsl \SKV@appto*\SKV@resa{\expandafter#1\SKV@dsl}% }% \ifx\SKV@resa\@empty\else\SKV@remparser[#1]\SKV@resa\fi @@ -1117,7 +1155,7 @@ \SKV@resstate } \SKV@def*\SKV@tdespacelt#1{% - \SKV@tfor{#1}\SKV@dsl{\expandafter\SKV@despace\SKV@dsl}% + \SKV@tfor{#1}\SKV@dsl{\expandafter\SKV@despacectt\SKV@dsl}% } \SKV@pdef*\ReserveKeyPrefixNames{\SKV@ifstar\SKV@rkpn@mes\SKV@rkpn@m@s} \SKV@def*\SKV@rkpn@mes#1{\SKV@AfterPackageEnd{\gapptomac\SKV@rkpnames{,#1}}} @@ -1200,14 +1238,10 @@ \fi \SKV@resstate\SKV@next } -\SKV@pdef*\SKV@numdef{\SKV@savstate\SKV@testoptc{\SKV@numdimdef{num}}} -\SKV@pdef*\SKV@dimdef{\SKV@savstate\SKV@testoptc{\SKV@numdimdef{dim}}} -\SKV@def*\SKV@numdimdef#1{% - \ifSKV@ask - \let\glob@lrel@x\global - \else - \let\glob@lrel@x\relax - \fi +\SKV@pdef*\SKV@numdef{\SKV@savstate\SKV@testoptc{\SKV@expr{num}}} +\SKV@pdef*\SKV@dimdef{\SKV@savstate\SKV@testoptc{\SKV@expr{dim}}} +\SKV@def*\SKV@expr#1{% + \ifSKV@ask\let\glob@lrel@x\global\else\let\glob@lrel@x\relax\fi \ifSKV@pl \def\SKV@next##1{% \edef\resvd@a####1{####1{#1}\SKV@expcsox{##1}}% @@ -1220,11 +1254,8 @@ } \SKV@def*\SKV@numdimd@f#1#2#3{% \SKV@ensurescape@notempty{#2}{#3}% - \SKV@ifstrequal{#1}{num}{% - \def\resvd@a{count}% - }{% - \def\resvd@a{dimen}% - }% + \SKV@ifstrequal{#1}{num}% + {\def\resvd@a{count}}{\def\resvd@a{dimen}}% \SKV@ifundef{#2}{% \@nameuse{new\resvd@a}#2% \glob@lrel@x#2=\@nameuse{#1expr}#3\relax @@ -1234,7 +1265,8 @@ } \SKV@def*\SKV@ensurescape@notempty#1#2{% \SKV@ensurescape{#1}% - \SKV@ifempty{#2}{\SKV@err{Argument '\string#1' is empty}\@ehc}{}% + \SKV@ifempty{#2}% + {\SKV@err{Argument '\string#1' is empty}\@ehc}{}% } \SKV@def*\SKV@keylistparser@err{% \SKV@err{Key list parser '\SKV@keyparser' not allowed}% @@ -1245,13 +1277,13 @@ } \define@cmdkey[KV]{skeyval}[SKV@]{genparser}[,]{% \@onelevel@sanitize\SKV@genparser - \SKV@despace\SKV@genparser + \SKV@despacectt\SKV@genparser \SKV@expargs{0}\SKV@CommandGenParser\SKV@genparser\@nil } \define@cmdkey[KV]{skeyval}[SKV@]{keyparser}[;]{% \@onelevel@sanitize\SKV@keyparser \SKV@xifblank\SKV@keyparser\SKV@keylistparser@err\relax - \SKV@despace\SKV@keyparser + \SKV@despacectt\SKV@keyparser \begingroup \def\SKV@tempa{,}\SKV@detokdespace\SKV@tempa \SKV@ifx\SKV@keyparser\SKV@tempa @@ -1265,7 +1297,7 @@ } \define@cmdkey[KV]{skeyval}[SKV@]{keyprefix}[KV]{% \SKV@xifblank\SKV@keyprefix\SKV@keyprefix@err\relax - \SKV@despace\SKV@keyprefix + \SKV@despacectt\SKV@keyprefix \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rkpnames}}% \SKV@tempa\@nil \SKV@for*[,]\SKV@tempa\SKV@tempa{% @@ -1278,7 +1310,7 @@ } \define@cmdkey[KV]{skeyval}[SKV@]{keyfamily}[fam]{% \SKV@xifblank\SKV@keyfamily\SKV@keyfamily@err\relax - \SKV@despace\SKV@keyfamily + \SKV@despacectt\SKV@keyfamily \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rfnames}}% \SKV@tempa\@nil \SKV@for*[,]\SKV@tempa\SKV@tempa{% @@ -1291,7 +1323,7 @@ } \define@cmdkey[KV]{skeyval}[SKV@]{macroprefix}[mp@]{% \SKV@xifblank\SKV@macroprefix\SKV@macroprefix@err\relax - \SKV@despace\SKV@macroprefix + \SKV@despacectt\SKV@macroprefix \SKV@expargs{3}\XKV@checksanitizeb{{\SKV@rmpnames}}% \SKV@tempa\@nil \SKV@for*[,]\SKV@tempa\SKV@tempa{% @@ -1331,10 +1363,18 @@ \def\in@@##1#1##2##3\in@@{\ifx\in@##2\in@false\else\in@true\fi}% \in@@#2\@mil#1\in@\in@@ } -\SKV@pdef*\SKV@in@o#1#2{% +\SKV@pdef*\SKV@in@n#1#2{% \SKV@in@{#1}{#2}% \@nameuse{SKV@\ifin@1\else2\fi of2}% } +\SKV@pdef*\SKV@in@o#1#2{% + \@expandtwoargs\SKV@in@{\SKV@expox{#1}}{\SKV@expox{#2}}% + \@nameuse{SKV@\ifin@1\else2\fi of2}% +} +\SKV@pdef*\SKV@in@x#1#2{% + \@expandtwoargs\SKV@in@{#1}{#2}% + \@nameuse{SKV@\ifin@1\else2\fi of2}% +} \SKV@pdef*\in@tog#1#2{% \SKV@in@{#1}{#2}% \ifin@\togon{in@}\else\togoff{in@}\fi @@ -1373,7 +1413,7 @@ \SKV@ifdefined{#1}% {\CheckCommand\@star@or@none}{\newcommand\@star@or@none}{#1}% } -\def\@check@eq#1#2{% +\SKV@redef\@check@eq#1#2{% \SKV@ifx{#1}{#2}{}{% \SKV@vbsmsg{warn}{% Previous definition of '\string#1'\SKV@MB @@ -1389,9 +1429,9 @@ {\SKV@swvalerr{#1}{#2}}}}}% } \SKV@pdef*\newswitch{\SKV@testopt\SKV@newswitch{}} -\SKV@pdef*\SKV@newswitch[#1]#2{\SKV@testopt{\SKV@n@wswitch[#1]{#2}}{false}} -\SKV@pdef*\SKV@n@wswitch[#1]#2[#3]{% - \SKV@in@o{,}{#2}{% +\SKV@def*\SKV@newswitch[#1]#2{\SKV@testopt{\SKV@n@wswitch[#1]{#2}}{false}} +\SKV@def*\SKV@n@wswitch[#1]#2[#3]{% + \SKV@in@n{,}{#2}{% \SKV@err{Command '\string\newswitch' doesn't accept list}% {Please submit only one switch to '\string\newswitch' at a time.}% }{}% @@ -1407,10 +1447,10 @@ }% } \SKV@pdef*\defswitch{\SKV@testopt\SKV@defswitch{}} -\SKV@pdef*\SKV@defswitch[#1]#2{\SKV@testopt{\SKV@d@fswitch[#1]{#2}}{false}} -\SKV@pdef*\SKV@d@fswitch[#1]#2[#3]{% +\SKV@def*\SKV@defswitch[#1]#2{\SKV@testopt{\SKV@d@fswitch[#1]{#2}}{false}} +\SKV@def*\SKV@d@fswitch[#1]#2[#3]{% \SKV@ensurenoscape{#2}% - \SKV@in@o{,}{#2}{% + \SKV@in@n{,}{#2}{% \SKV@err{Command '\string\defswitch' doesn't accept list}% {Please submit only one switch to '\string\defswitch' at a time.}% }{}% @@ -1474,9 +1514,9 @@ {You need to first define '#1' before use.}% } \SKV@pdef*\newtog{\SKV@testopt\SKV@newtog{}} -\SKV@pdef*\SKV@newtog[#1]#2{\SKV@testopt{\SKV@n@wtog[#1]{#2}}{false}} -\SKV@pdef*\SKV@n@wtog[#1]#2[#3]{% - \SKV@in@o{,}{#2}{% +\SKV@def*\SKV@newtog[#1]#2{\SKV@testopt{\SKV@n@wtog[#1]{#2}}{false}} +\SKV@def*\SKV@n@wtog[#1]#2[#3]{% + \SKV@in@n{,}{#2}{% \SKV@err{Command '\string\newtog' doesn't accept list}% {Please submit only one tog to '\string\newtog' at a time.}% }{}% @@ -1487,9 +1527,9 @@ }{\SKV@csletcs{SKV@toggle@#1#2}{SKV@t@ggle#3}}% } \SKV@pdef*\deftog{\SKV@testopt\SKV@deftog{}} -\SKV@pdef*\SKV@deftog[#1]#2{\SKV@testopt{\SKV@d@ftog[#1]{#2}}{false}} -\SKV@pdef*\SKV@d@ftog[#1]#2[#3]{% - \SKV@in@o{,}{#2}{% +\SKV@def*\SKV@deftog[#1]#2{\SKV@testopt{\SKV@d@ftog[#1]{#2}}{false}} +\SKV@def*\SKV@d@ftog[#1]#2[#3]{% + \SKV@in@n{,}{#2}{% \SKV@err{Command '\string\deftog' doesn't accept list}% {Please submit only one tog to '\string\deftog' at a time.}% }{}% @@ -1640,7 +1680,7 @@ \SKV@expnext\SKV@definedkey@err\SKV@resa \begingroup \edef\SKV@tempa{\endgroup - \SKV@ifbrack{\noexpand\XKV@d@fine@key{\SKV@resa}}% + \SKV@if@brack{\noexpand\XKV@d@fine@key{\SKV@resa}}% {\noexpand\SKV@d@fine@key{\SKV@resa}}% }% \SKV@tempa @@ -1911,7 +1951,7 @@ \SKV@for*[,]#1\SKV@tempa{% \edef\SKV@tempa{\detokenize\expandafter{\SKV@tempa}\space}% \edef\SKV@tempa{\expandafter\zap@space\SKV@tempa\@empty}% - \SKV@csxdef{SKV@zsp@\expandafter\@gobble\SKV@tempa}% + \SKV@csxdef*{SKV@zsp@\expandafter\@gobble\SKV@tempa}% {\SKV@expox{\SKV@tempa}}% }% \endgroup @@ -1921,24 +1961,30 @@ \begingroup \SKV@for*[,]#1\SKV@tempa{% \edef\SKV@tempa{\detokenize\expandafter{\SKV@tempa}}% - \SKV@despace\SKV@tempa - \SKV@csxdef{SKV@dsp@\expandafter\@gobble\SKV@tempa}% + \SKV@despacectt\SKV@tempa + \SKV@csxdef*{SKV@dsp@\expandafter\@gobble\SKV@tempa}% {\SKV@expox{\SKV@tempa}}% }% \endgroup } -\SKV@def*\SKV@exceplist{\par,\if,\ifcase,\or,\else,\skif,\iftog,\ifswitch} +\SKV@def*\SKV@exceplist{% + \par,\if,\ifcase,\or,\else,\skif,\iftog,\ifswitch} \SKV@detok@dsp\SKV@exceplist \SKV@def*\SKV@noiferr#1#2{% - \SKV@err{You can't use '\@backslashchar #1' in key macro within keylist}% + \SKV@err{You can't use '\@backslashchar #1' in\SKV@MB + key macro within keylist}% {Use '\@backslashchar #2' instead of '\@backslashchar #1'.}% } +\SKV@pdef*\uservalue{\uservalue} +\SKV@pdef*\guservalue{\guservalue} +\SKV@pdef*\savevalue{\savevalue} +\SKV@pdef*\gsavevalue{\gsavevalue} \SKV@def\SKV@define@multkeys#1,#2,#3,#4\@nil{% \let\SKV@altlisterr\z@ \SKV@sp@def{#1}\SKV@tempa \SKV@checkchoice{\SKV@tempa}{ord,cmd,bool,tog,choice,menu}{% - \SKV@iftest{num}{\nr=6}{% - \edef\SKV@keytype{\the\numexpr\nr-1}% + \SKV@iftest{num}{\nr=5}{% + \let\SKV@keytype\nr }{% \edef\SKV@keytype{\the\numexpr\nr+1}% }% @@ -2109,7 +2155,7 @@ \SKV@expnext\SKV@suspkey@err\SKV@resa \begingroup \edef\SKV@tempa{\endgroup - \SKV@ifbrack{\noexpand\XKV@d@fine@key{\SKV@resa}}% + \SKV@if@brack{\noexpand\XKV@d@fine@key{\SKV@resa}}% {\noexpand\SKV@d@fine@key{\SKV@resa}}% }% \SKV@tempa @@ -2136,7 +2182,7 @@ \begingroup \def\SKV@tempa{% \expandafter\def\csname\XKV@header\SKV@resa\endcsname####1}% - \SKV@threeafter\endgroup\expandafter\SKV@tempa\expandafter% + \SKV@threexp\endgroup\expandafter\SKV@tempa\expandafter% {\expandafter\def\csname#1\SKV@resa\endcsname{##1}#4}% } \def\XKV@define@choicekey#1{% @@ -2239,7 +2285,7 @@ \SKV@MB In that case, you can use '\string\remove@keys'. }% }{% - \SKV@csedef{\XKV@header\SKV@tempa}{% + \SKV@csedef*{\XKV@header\SKV@tempa}{% \SKV@err{% Key '\SKV@tempa' with prefix '\SKV@pref' in family '\XKV@tfam'\SKV@MB was reserved\on@line @@ -2247,7 +2293,7 @@ Unreserve '\SKV@tempa' before use. }% }% - \@namedef{\XKV@header\SKV@tempa @reser}{}% + \SKV@csdef*{\XKV@header\SKV@tempa @reser}{}% }% }% } @@ -2453,7 +2499,7 @@ }{% \edef\SKV@suspkey{#1}% \global\SKV@csletcs{\XKV@header#1@susp}{\XKV@header#1}% - \SKV@csedef{\XKV@header#1}{\SKV@suspkey@e@r}% + \SKV@csedef*{\XKV@header#1}{\SKV@suspkey@e@r}% \SKV@vbsmsg{info}{Key '\SKV@suspkey' with prefix '\SKV@pref' in \SKV@MB family '\XKV@tfam' was suspended\on@line}% }% @@ -2546,7 +2592,7 @@ \XKV@header#1@reser }% \SKV@for@b\SKV@tempa\SKV@tempa{% - \SKV@despace\SKV@tempa + \SKV@despacectt\SKV@tempa \SKV@csgundef{\SKV@tempa}% }% \endgroup @@ -2558,12 +2604,19 @@ \SKV@def*\SKV@uservaluekeys#1{% \SKV@ifcsundef{SKV@\XKV@header uservalue}{% \XKV@checksanitizeb{#1}\SKV@tempa - \SKV@csxdef{SKV@\XKV@header uservalue}{\SKV@expox{\SKV@tempa}}% + \SKV@csxdef*{SKV@\XKV@header uservalue}{\SKV@expox{\SKV@tempa}}% }{% \SKV@aftercs\XKV@merge{SKV@\XKV@header uservalue}{#1}\XKV@getsg }% } -\protected\def\setkeys{% +\SKV@def*\SKV@undefinedkeys#1#2#3{% + \edef\SKV@resvd##1{\SKV@addtolist?[;]##1{(#1:#2:#3)}}% + \SKV@resvd\SKV@und@finedkeys +} +\SKV@predef*\ExecuteOptionsX{% + \SKV@sktrue\XKV@stfalse\XKV@plfalse\XKV@t@stopte\XKV@setkeys} +\SKV@predef*\setkeys{\SKV@sktrue\XKV@testopta{\XKV@testoptc\XKV@setkeys}} +\SKV@redef*\XKV@setkeys[#1]#2{% \def\skif##1{% \SKV@ensurenoscape{##1}% \SKV@ifcsdef{if##1}{}{% @@ -2574,9 +2627,7 @@ }% \let\skifx\ifx\let\skifcase\ifcase\let\skor\or \let\skelse\else\let\skfi\fi - \SKV@sktrue\XKV@testopta{\XKV@testoptc\XKV@setkeys}% -} -\def\XKV@setkeys[#1]#2{% + \let\SKV@und@finedkeys\@empty \XKV@checksanitizea{#2}\XKV@resb \SKV@normalizea\XKV@resb \let\XKV@naa\@empty @@ -2590,10 +2641,69 @@ \XKV@usepresetkeys{#1}{presett}% \let\CurrentOption\@empty \SKV@skfalse + \SKV@ifx\SKV@und@finedkeys\@empty{}{% + \SKV@warn{*** Unknown keys: \SKV@expox\SKV@und@finedkeys}% + \typein[\answer]{^^JThere were undefined keys: see list above. + ^^JEnter 'stop' or 'go' and <return> to continue.}% + \SKV@oifstrequal{\answer}{stop}{\stop}{}% + }% +} +\SKV@redef*\XKV@s@tk@ys#1=#2=#3\@nil{% + \XKV@g@tkeyname#1=\@nil\XKV@tkey + \SKV@expnext\SKV@sp@def\XKV@tkey\XKV@tkey + \SKV@ifx\XKV@tkey\@empty{% + \SKV@ifempty{#2}{}{% + \SKV@err{No key specified for value '#2'}% + {You have supplied a value '#2' without key name.\SKV@MB + This is certainly an error on your part.\SKV@MB + Please correct the error and rerun.} + }% + }{% + \@expandtwoargs\in@{,\XKV@tkey,}{,\XKV@na,}% + \unless\ifin@ + \XKV@knftrue + \SKV@sp@def{#2}\XKV@tempa + \ifXKV@preset + \XKV@s@tk@ys@{#3}% + \else + \ifXKV@pl + \XKV@for@eo\XKV@fams\XKV@tfam{% + \XKV@makehd\XKV@tfam\XKV@s@tk@ys@{#3}% + }% + \else + \XKV@whilist\XKV@fams\XKV@tfam\ifXKV@knf\fi{% + \XKV@makehd\XKV@tfam\XKV@s@tk@ys@{#3}% + }% + \fi + \fi + \ifXKV@knf + \ifXKV@inpox + \SKV@ifx\XKV@doxs\relax{% + \unless\ifx\@currext\@clsextension + \let\CurrentOption\XKV@tkey\@unknownoptionerror + \fi + }{% + \XKV@doxs + }% + \else + \ifXKV@st + \XKV@addtolist@o\XKV@rm\CurrentOption + \else + \SKV@undefinedkeys{\SKV@pref}{\XKV@fams}{\XKV@tkey}% + \fi + \fi + \else + \ifXKV@inpox\ifx\XKV@testclass\XKV@documentclass + \SKV@expnext\XKV@useoption\CurrentOption + \fi\fi + \fi + \fi + }% } -\def\XKV@s@tk@ys@#1{% +\SKV@redef*\XKV@s@tk@ys@#1{% \SKV@ifcsundef{\XKV@header\XKV@tkey}{% - \SKV@vbsmsg{warn}{No key macro for key '\XKV@tkey'}% + \SKV@vbsmsg{warn}{No key macro for key '\XKV@tkey'\SKV@MB + in families '\XKV@fams'}% }{% \XKV@knffalse \SKV@ifcsundef{SKV@\XKV@header uservalue}{}{% @@ -2602,8 +2712,11 @@ \ifSKV@uv \SKV@ifnotblank{#1}{}{% \SKV@err{You're required to supply a value\SKV@MB - for key '\XKV@tkey'}% - {Supply a value for key '\XKV@tkey' and rerun.}% + for key '\XKV@tkey' in families '\XKV@fams'}% + {Please supply a value for key '\XKV@tkey'\SKV@MB + of families '\XKV@fams' and rerun.\SKV@MB + The originator of this key meant it to\SKV@MB + require a user value.}% }% \fi }% @@ -2633,11 +2746,10 @@ }% } \SKV@def*\SKV@testuservaluekey#1#2{% - \let\SKV@staux\ifSKV@st\SKV@sttrue\SKV@uvfalse - \XKV@whilist#1\SKV@tempa\ifSKV@st\fi{% - \ifx#2\SKV@tempa\SKV@uvtrue\SKV@stfalse\fi + \SKV@tempswtrue\SKV@uvfalse + \XKV@whilist#1\SKV@tempa\ifSKV@tempsw\fi{% + \ifx#2\SKV@tempa\SKV@uvtrue\SKV@tempswfalse\fi }% - \let\ifSKV@st\SKV@staux\SKV@undef\SKV@staux } \SKV@def*\SKV@remspaceletter#1#2{% \begingroup @@ -2720,7 +2832,7 @@ \ifnum\escapechar<0\else \expandafter\expandafter \csname @gobble\ifnum\escapechar=32 space\fi - \SKV@threeafter\endcsname + \SKV@threexp\endcsname \fi\fi \string% } @@ -2767,13 +2879,13 @@ \SKV@cslet{##2@read}\@empty \let\SKV@inp@tfile\relax }{% - \typein[\Answer]{^^J! File '\string##2' does not exist.^^J + \typein[\answer]{^^J! File '\string##2' does not exist.^^J Enter filename or 'no' and <return> to continue.}% - \SKV@oifstrequal{\Answer}{no}{% + \SKV@oifstrequal{\answer}{no}{% \let\SKV@inp@tfile\relax }{% \def\SKV@inp@tfile{% - \SKV@expargs{0}{\SKV@InputFileOnce[##1]}\Answer\@nil + \SKV@expargs{0}{\SKV@InputFileOnce[##1]}\answer\@nil }}}}% \let\SKV@no\z@ \SKV@save\input@path @@ -2815,77 +2927,6 @@ \SKV@notloaded \global\let\SKV@do@b\@gobble } -\SKV@pdef*\DeclareKeyCommand{\@star@or@long\SKV@keycommand} -\SKV@def\SKV@keycommand#1{% - \SKV@ifdefinable#1\relax - \def\SKV@keycmdname{#1}% - \edef\resvd@a{\expandafter\@gobble\string#1}% - \edef\resvd@b{\expandafter\expandafter\expandafter\SKV@carcube - \expandafter\@gobble\string#1\@nil}% - \SKV@scantoksb\resvd@a - \SKV@scantoksb\resvd@b - \edef\resvd##1{\skvoptions{##1,keyfamily=\resvd@a,macroprefix=\resvd@b @}}% - \resvd{keyparser=;,keyprefix=KV}% - \SKV@testopt\SKV@k@ycommand{}% -} -\def\SKV@keycmdlist{}\def\SKV@k@ycmdlist{} -\SKV@def\SKV@k@ycommand[#1]{% - \SKV@ifnotempty{#1}{}{% - \SKV@err{\string\DeclareKeyCommand\space error: no keys declared}\@ehc - }% - \SKV@k@yc@mmand{#1}% - \define@keylist*\SKV@keycmdlist - \edef\resvd{\setkeys[KV]{\resvd@a}{\SKV@k@ycmdlist}}% - \resvd - \SKV@testopt\SKV@k@yc@mm@nd{1}% -} -\SKV@def\SKV@k@yc@mmand#1{% - \def\SKV@keycmdlist{}\def\SKV@k@ycmdlist{}% - \XKV@checksanitizea{#1}\SKV@tempa - \SKV@normalizea\SKV@tempa - \SKV@for*[,]\SKV@tempa\SKV@tempa{% - \expandafter\SKV@getkeyname\SKV@tempa==\@nil - \SKV@addtokeycmdlist\SKV@tkey\SKV@tval - }% -} -\SKV@def\SKV@k@yc@mm@nd[#1]#2{% - \edef\resvd##1##2{##1{\setkeys[KV]{\resvd@a}{####1}##2}}% - \ifx\l@ngrel@x\relax - \def\resvd@b{\newcommand*}% - \else - \let\resvd@b\newcommand - \fi - \resvd{\expandafter\resvd@b\SKV@keycmdname[#1][]}{#2}% -} -\SKV@def\SKV@getkeyname#1=#2=#3\@nil{% - \XKV@g@tkeyname#1=\@nil\SKV@tkey - \SKV@expnext\SKV@sp@def\SKV@tkey\SKV@tkey - \def\SKV@tval{#2}% - \ifx\SKV@tkey\@empty - \SKV@ifnotempty{#2}{}% - {\XKV@err{No key specified for value '#2'}\@ehc}% - \fi - \SKV@ifnotempty{#3}{}% - {\XKV@err{No value specified for key '#1'}\@ehc}% -} -\SKV@def\SKV@addtokeycmdlist#1#2{% - \SKV@oifstrequal{#2}{true}{% - \def\tempa{bool}% - }{% - \SKV@oifstrequal{#2}{false}{% - \def\tempa{bool}% - }{% - \def\tempa{cmd}% - }% - }% - \SKV@oifempty{#1}{}{% - \edef\resvd##1{\gapptomac##1{\tempa,\SKV@expox{#1},\SKV@expox{#2},;}}% - \resvd\SKV@keycmdlist - \edef\resvd##1{\gapptomac##1{\SKV@expox{#1}=\SKV@expox{#2},}}% - \resvd\SKV@k@ycmdlist - }% - \SKV@undef\tempa -} \SKV@onlypreamble{% \SKV@preamblecmds\SKV@onlypreamble \@afterpackageloaded\@ifpackagecurrent\@ifpackagenotcurrent @@ -2895,6 +2936,8 @@ \SKV@AfterLastPage\SKV@AfterDocumentEnd } +%\InputIfFileExists{skeyval-x.sty}{}{} + \endinput %%% End of file skeyval.sty %%% |